Class: Dbtools::Google_Drive::Google_drive_api

Inherits:
Object
  • Object
show all
Defined in:
lib/dbtools/google_drive/google_drive_api.rb

Constant Summary collapse

OOB_URI =
'urn:ietf:wg:oauth:2.0:oob'
APPLICATION_NAME =
'Dbtools'
CLIENT_SECRETS_PATH =
File.join(Dbtools::Constants::ROOT_DIR, 'config', 'client_secret_dbtools.json')
CREDENTIALS_PATH =
File.join(Dir.home, '.credentials', "dbtools_geophy.yaml")
SCOPE =
Google::Apis::DriveV3::AUTH_DRIVE
QUERY_FIELDS =
'nextPageToken, files(id,name,mimeType,size,fileExtension,iconLink,createdTime,' +
'modifiedTime,webContentLink,webViewLink,parents,description,properties,trashed)'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(auth = authorize) ⇒ Google_drive_api

Constructor for this class. You should pass the authorization object if you want to use another way to authenticate the user. Check the googleauth documentation for more info.



25
26
27
28
29
# File 'lib/dbtools/google_drive/google_drive_api.rb', line 25

def initialize(auth=authorize)
  @service = Google::Apis::DriveV3::DriveService.new
  @service.client_options.application_name = APPLICATION_NAME
  @service.authorization = auth
end

Instance Attribute Details

#serviceObject (readonly)

Returns the value of attribute service.



11
12
13
# File 'lib/dbtools/google_drive/google_drive_api.rb', line 11

def service
  @service
end

Class Method Details

.get_file_id(access_url) ⇒ Object



200
201
202
203
# File 'lib/dbtools/google_drive/google_drive_api.rb', line 200

def self.get_file_id(access_url)
  match = access_url.match(/.*google.*(id=|d\/)\b(?<file_id>[a-zA-Z0-9_-]+)\b/)
  match['file_id']
end

.get_url_from_id(drive_id) ⇒ Object

Returns the url from the drive id



206
207
208
# File 'lib/dbtools/google_drive/google_drive_api.rb', line 206

def self.get_url_from_id(drive_id)
  return "https://drive.google.com/open?id=#{drive_id}"
end

Instance Method Details

#authorizeGoogle::Auth::UserRefreshCredentials

Ensure valid credentials, either by restoring from the saved credentials files or intitiating an OAuth2 authorization. If authorization is required, the user’s default browser will be launched to approve the request.

Returns:

  • (Google::Auth::UserRefreshCredentials)

    OAuth2 credentials



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/dbtools/google_drive/google_drive_api.rb', line 36

def authorize
  unless File.exist?(CLIENT_SECRETS_PATH)
    puts "#{CLIENT_SECRETS_PATH} not found."
    puts "Create Google Drive API OAuth 2.0 credentials to allow access. "
    exit(1)
  end

  FileUtils.mkdir_p(File.dirname(CREDENTIALS_PATH))
  client_id = Google::Auth::ClientId.from_file(CLIENT_SECRETS_PATH)
  token_store = Google::Auth::Stores::FileTokenStore.new(file: CREDENTIALS_PATH)
  authorizer = Google::Auth::UserAuthorizer.new(
      client_id, SCOPE, token_store)
  user_id = 'default'
  credentials = authorizer.get_credentials(user_id)
  if credentials.nil?
    url = authorizer.get_authorization_url(
        base_url: OOB_URI)
    puts "Open the following URL in the browser and enter the " +
             "resulting code after authorization: "
    puts url
    code = gets
    credentials = authorizer.get_and_store_credentials_from_code(
        user_id: user_id, code: code, base_url: OOB_URI)
  end
  credentials
end

#get_changes(page_token) ⇒ Object

Return the changes that happened from a point given by the page token. The page token for the current state can be retrieved by calling @service.get_changes_start_page_token.

Parameters:

  • page_token

    Last saved token

Returns:

  • changed_files, removed_files, saved_start_page_token An array with three elements. The first element containing a hash with the file_id as the key, and the file object containing the attributes as value, for all changed files. The second element contains the file_ids for all files that were removed. The third element contains the new page token.



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/dbtools/google_drive/google_drive_api.rb', line 149

def get_changes(page_token)
  changed_files = {}
  removed_files = []
  saved_start_page_token = page_token
  while !page_token.nil?
    response = @service.list_changes(page_token,
                                     spaces: 'drive',
                                     page_size: 1000,
                                     restrict_to_my_drive: true,
                                     fields: 'nextPageToken, newStartPageToken, changes')
    response.changes.each do |change|
      if change.file
        changed_files[change.file_id] = change.file
      else
        removed_files << change.file_id
      end
    end
    # Last page, save this token for the next polling interval
    saved_start_page_token = response.new_start_page_token if response.new_start_page_token
    page_token = response.next_page_token
  end
  return changed_files, removed_files, saved_start_page_token
end

#get_children_files(parent_folder, optional_query = '') ⇒ Google::Apis::DriveV3::FileList

Retrieves the children of the parent folder.

Parameters:

  • parent_folder (Google::Apis::DriveV3::File)

    Parent folder to get the children from.

Returns:

  • (Google::Apis::DriveV3::FileList)

    List of all files in the parent_folder.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/dbtools/google_drive/google_drive_api.rb', line 68

def get_children_files(parent_folder, optional_query = '')
  page_token = nil
  children = Google::Apis::DriveV3::FileList.new
  begin
    query = "'#{parent_folder.id}' in parents and trashed = false"
    query << " and " << optional_query if !optional_query.empty?
    result = @service.list_files(q: query,
                                 spaces: 'drive',
                                 page_size: 1000,
                                 page_token: page_token,
                                 fields: QUERY_FIELDS)
    page_token = result.next_page_token
    result.files.concat(children.files) unless children.files.nil?
    children = result
  end while !page_token.nil?
  return children
end

#get_tree(optional_query = "", verbose: false) ⇒ Object

Queries all the files and returns an Hash with all files. All files have a reference to their parent and children if applicable.



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/dbtools/google_drive/google_drive_api.rb', line 104

def get_tree(optional_query = "", verbose: false)
  files = []
  count = 0
  # Query for all files. Loops until no next_page_tokens are given.
  # Returns 1000 files per query (Google Drive API limitation).
  page_token = nil
  begin
    query = "trashed = false"
    query << " and " << optional_query if !optional_query.nil? && !optional_query.empty?
    result = @service.list_files(q: query,
                                 spaces: 'drive',
                                 page_size: 1000,
                                 page_token: page_token,
                                 fields: QUERY_FIELDS)

    page_token = result.next_page_token
    files.concat(result.files) unless result.files.nil?
    count += result.files.size
    STDERR.puts "Count: #{count} \t\t\r" if verbose
  end while !page_token.nil?

  # Convert array into key-value pairs, using ID as key.
  # ID is unique for every file.
  files = files.map! { |f| [f.id, f] } if not files.empty?
  files = files.to_h

  # Add two-way reference for all children-parents.
  # files.each do |id, file|
  #   file.parents.each do |parent|
  #     next if files[parent].nil?
  #     files[parent].children = [] if files[parent].children.nil?
  #     files[parent].children << file.id
  #   end unless file.parents.nil?
  # end
  return files
end

Prints the children of the parent folder.

Parameters:

  • drive_service (Google::Apis::DriveV3::DriveService)

    An authenticated Google Drive service.

  • parent_folder (Google::Apis::DriveV3::File)

    Parent folder to get the children from.

Returns:

  • (String)

    String representing the folder structure.



180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/dbtools/google_drive/google_drive_api.rb', line 180

def print_child_files(parent_folder, depth = 0, optional_query = '')
  output = ''
  children = get_children_files(parent_folder, optional_query)
  children.files.each do |file|
    prefix = '  ' * depth
    if file.mime_type == 'application/vnd.google-apps.folder'
      output << "#{prefix} - #{file.name} (#{file.id})" << "\n"
      output << print_child_files(file, depth + 1)
    else
      output << "#{prefix} * #{file.name} (#{file.id})" << "\n"
    end
  end
  return output
end

#update_file(file_id, attributes = {}) ⇒ Google::Apis::DriveV3::File

Updates the metadata of a Google Drive File.

Parameters:

  • file_id

    Google Drive File ID for the file to be updated.

  • attributes (defaults to: {})

    Hash containing all the attributes to be updated.

Returns:

  • (Google::Apis::DriveV3::File)

    Returns File object with the updated metadata.



93
94
95
96
97
98
99
100
# File 'lib/dbtools/google_drive/google_drive_api.rb', line 93

def update_file(file_id, attributes={})
  attributes.stringify_keys!
  file_object = {}
  file_object[:description] = attributes.delete('description') if attributes['description']
  file_object[:properties] = attributes
  fields = file_object.keys.join(',')
  return @service.update_file(file_id, file_object, fields: fields)
end