class Tumugi::Plugin::GoogleDrive::FileSystem
Constants
- MIME_TYPE_FOLDER
Public Class Methods
new(config)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 13 def initialize(config) save_config(config) end
Public Instance Methods
copy(src_file_id, dest_name, dest_parents: nil)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 62 def copy(src_file_id, dest_name, dest_parents: nil) dest_parents = [dest_parents] if dest_parents.is_a?(String) dest_file_metadata = Google::Apis::DriveV3::File.new({ name: dest_name, parents: dest_parents }) file = client.copy_file(src_file_id, dest_file_metadata, options: request_options) wait_until { exist?(file.id) } file rescue process_error($!) end
directory?(file_id)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 49 def directory?(file_id) file = get_file_metadata(file_id) file.mime_type == MIME_TYPE_FOLDER rescue process_error($!) end
download(file_id, download_path: nil, mode: 'r', mime_type: nil, &block)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 95 def download(file_id, download_path: nil, mode: 'r', mime_type: nil, &block) if !exist?(file_id) raise Tumugi::FileSystemError.new("#{file_id} does not exist") end if download_path.nil? download_path = Tempfile.new('tumugi_google_drive_file_system').path end file = get_file_metadata(file_id) if google_drive_document?(file.mime_type) # If file is Google Drive Document, use export_file # https://developers.google.com/drive/v3/web/manage-downloads#downloading_google_documents if mime_type.nil? raise Tumugi::FileSystemError.new("mime_type is required because file #{file_id} is Google Drive Document") end client.export_file(file_id, mime_type, download_dest: download_path, options: request_options) else # If file is not Google Drive Document, use get_file # https://developers.google.com/drive/v3/web/manage-downloads#downloading_a_file client.get_file(file_id, download_dest: download_path, options: request_options) end wait_until { File.exist?(download_path) } if block_given? File.open(download_path, mode, &block) else File.open(download_path, mode) end file rescue process_error($!) end
exist?(file_id)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 17 def exist?(file_id) get_file_metadata(file_id, fields: 'id') true rescue => e return false if e.respond_to?(:status_code) && e.status_code == 404 process_error(e) end
generate_file_id()
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 130 def generate_file_id client.generate_file_ids(count: 1, options: request_options).ids.first rescue process_error($!) end
get_file_metadata(file_id, fields: "*")
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 144 def get_file_metadata(file_id, fields: "*") client.get_file(file_id, fields: fields, options: request_options) end
google_drive_document?(mime_type)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 148 def google_drive_document?(mime_type) !!(mime_type && mime_type.start_with?("application/vnd.google-apps.")) end
list_files(query:, order_by: "name", spaces: "drive", fields: "next_page_token, files(id, name, parents, mime_type)", page_size: 100, page_token: nil)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 136 def list_files(query:, order_by: "name", spaces: "drive", fields: "next_page_token, files(id, name, parents, mime_type)", page_size: 100, page_token: nil) # https://developers.google.com/drive/v3/reference/files/list # https://developers.google.com/drive/v3/web/search-parameters client.list_files(q: query, order_by: order_by, spaces: spaces, fields: fields, page_size: page_size, page_token: page_token) rescue process_error($!) end
mkdir(name, folder_id: nil, parents: nil)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 35 def mkdir(name, folder_id: nil, parents: nil) file_metadata = Google::Apis::DriveV3::File.new({ name: name, mime_type: MIME_TYPE_FOLDER, parents: parents, id: folder_id }) file = client.create_file(file_metadata, fields: "*", options: request_options) wait_until { exist?(file.id) } file rescue process_error($!) end
move(src_file_id, dest_name, dest_parents: nil)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 56 def move(src_file_id, dest_name, dest_parents: nil) file = copy(src_file_id, dest_name, dest_parents: dest_parents) remove(src_file_id) file end
put_string(contents, name, content_type: 'text/plain', file_id: nil, parents: nil)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 90 def put_string(contents, name, content_type: 'text/plain', file_id: nil, parents: nil) media = StringIO.new(contents) upload(media, name, content_type: content_type, file_id: file_id, parents: parents) end
remove(file_id)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 25 def remove(file_id) return unless exist?(file_id) client.delete_file(file_id, options: request_options) wait_until { !exist?(file_id) } file_id rescue process_error($!) end
upload(media, name, content_type: nil, file_id: nil, parents: nil, mime_type: nil)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 75 def upload(media, name, content_type: nil, file_id: nil, parents: nil, mime_type: nil) parents = [parents] if parents.is_a?(String) file_metadata = Google::Apis::DriveV3::File.new({ id: file_id, name: name, parents: parents, mime_type: mime_type }) file = client.create_file(file_metadata, fields: "*", upload_source: media, content_type: content_type, options: request_options) wait_until { exist?(file.id) } file rescue process_error($!) end
Private Instance Methods
client()
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 171 def client return @cached_client if @cached_client && @cached_client_expiration > Time.now client = Google::Apis::DriveV3::DriveService.new scope = Google::Apis::DriveV3::AUTH_DRIVE if @key[:client_email] && @key[:private_key] options = { json_key_io: StringIO.new(JSON.generate(@key)), scope: scope } auth = Google::Auth::ServiceAccountCredentials.make_creds(options) else auth = Google::Auth.get_application_default([scope]) end auth.fetch_access_token! client.authorization = auth @cached_client_expiration = Time.now + (auth.expires_in / 2) @cached_client = client end
process_error(err)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 199 def process_error(err) if err.respond_to?(:body) begin if err.body.nil? reason = err.status_code.to_s errors = "HTTP Status: #{err.status_code}, Headers: #{err.header.inspect}" else jobj = JSON.parse(err.body) error = jobj["error"] errors = "HTTP Status: #{err.status_code}, Headers: #{err.header.inspect}, Body: " if error["errors"] reason = error["errors"].map{|e| e["reason"]}.join(",") errors += error["errors"].map{|e| e["message"] }.join(". ") else errors += error["message"] end end rescue JSON::ParserError reason = err.status_code.to_s errors = "HTTP Status: #{err.status_code}, Headers: #{err.header.inspect}, Body: #{err.body}" end raise Tumugi::FileSystemError.new(errors, reason) else raise err end end
request_options()
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 226 def request_options { retries: 5, timeout_sec: 60 } end
save_config(config)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 154 def save_config(config) if config.private_key_file.nil? @project_id = config.project_id client_email = config.client_email private_key = config.private_key elsif config.private_key_file json = JSON.parse(File.read(config.private_key_file)) @project_id = json['project_id'] client_email = json['client_email'] private_key = json['private_key'] end @key = { client_email: client_email, private_key: private_key } end
wait_until(&block)
click to toggle source
# File lib/tumugi/plugin/google_drive/file_system.rb, line 193 def wait_until(&block) while not block.call sleep 3 end end