Class: GoogleDriveProcessor

Inherits:
Object
  • Object
show all
Defined in:
lib/localio/processors/google_drive_processor.rb

Class Method Summary collapse

Class Method Details

.load_localizables(platform_options, options) ⇒ Object

Raises:

  • (ArgumentError)


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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/localio/processors/google_drive_processor.rb', line 6

def self.load_localizables(platform_options, options)

  # Parameter validations
  spreadsheet = options[:spreadsheet]
  raise ArgumentError, ':spreadsheet required for Google Drive source!' if spreadsheet.nil?

  # Deprecate :login & :password
   = options[:login]
  raise ArgumentError, ':login is deprecated. You should use :client_id and :client_secret for secure OAuth2 authentication.' unless .nil?
  password = options[:password]
  raise ArgumentError, ':password is deprecated. You should use :client_id and :client_secret for secure OAuth2 authentication.' unless password.nil?

  # New authentication way
  client_id = options[:client_id]
  client_secret = options[:client_secret]
  access_token = options[:access_token]

  # We need client_id / client_secret if we dont have an access token
  if access_token.nil?
    raise ArgumentError, ':client_id required for Google Drive. Check how to get it here: https://developers.google.com/drive/web/auth/web-server' if client_id.nil?
    raise ArgumentError, ':client_secret required for Google Drive. Check how to get it here: https://developers.google.com/drive/web/auth/web-server' if client_secret.nil?
  end

  override_default = nil
  override_default = platform_options[:override_default] unless platform_options.nil? or platform_options[:override_default].nil?

  # Log in and get spreadsheet
  puts 'Logging in to Google Drive...'
  begin
    if access_token.nil?
      puts "No :access_token found. Let\'s proceed to get one!".red
      client = Google::APIClient.new application_name: 'Localio', application_version: Localio::VERSION
      auth = client.authorization
      auth.client_id = client_id
      auth.client_secret = client_secret
      auth.scope =
          "https://www.googleapis.com/auth/drive " +
              "https://spreadsheets.google.com/feeds/"
      auth.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
      puts "1. Open this page in your browser:\n#{auth.authorization_uri}\n\n"
      puts "2. Enter the authorization code shown in the page: "
      auth.code = $stdin.gets.chomp
      auth.fetch_access_token!
      access_token = auth.access_token
      puts '\n**IMPORTANT** You can store your access_token in the Locfile :source parameter for avoiding this step in the future:\n'
      puts ":access_token => '#{access_token}'".yellow
      puts '\n\n'
    end
    # Creates a session
    session = GoogleDrive.(access_token)
  rescue => e
    puts "Error: #{e.inspect}"
    raise 'Couldn\'t access Google Drive. Check your values for :client_id and :client_secret, and delete :access_token if present (you might need to refresh its value so please remove it)'
  end
  puts 'Logged in!'

  matching_spreadsheets = []
  session.spreadsheets.each do |s|
    matching_spreadsheets << s if s.title.include? spreadsheet
  end

  case matching_spreadsheets.count
    when 1
      puts 'Spreadsheet found. Analyzing...'
    when 0
      abort "Unable to find any spreadsheet matching your criteria: #{spreadsheet}"
    else
      abort 'More than one match found. You have to be more specific!'
  end


  # TODO we could pass a :page_index in the options hash and get that worksheet instead, defaulting to zero?
  worksheet = matching_spreadsheets[0].worksheets[0]
  raise 'Unable to retrieve the first worksheet from the spreadsheet. Are there any pages?' if worksheet.nil?

  # At this point we have the worksheet, so we want to store all the key / values
  first_valid_row_index = nil
  last_valid_row_index = nil

  for row in 1..worksheet.max_rows
    first_valid_row_index = row if worksheet[row, 1].downcase == '[key]'
    last_valid_row_index = row if worksheet[row, 1].downcase == '[end]'
  end

  raise IndexError, 'Invalid format: Could not find any [key] keyword in the A column of the worksheet' if first_valid_row_index.nil?
  raise IndexError, 'Invalid format: Could not find any [end] keyword in the A column of the worksheet' if last_valid_row_index.nil?
  raise IndexError, 'Invalid format: [end] must not be before [key] in the A column' if first_valid_row_index > last_valid_row_index

  languages = Hash.new('languages')
  default_language = nil

  for column in 2..worksheet.max_cols
    col_all = worksheet[first_valid_row_index, column]
    col_all.each_line(' ') do |col_text|
      default_language = col_text.downcase.gsub('*', '') if col_text.include? '*'
      languages.store col_text.downcase.gsub('*', ''), column unless col_text.to_s == ''
    end
  end

  abort 'There are no language columns in the worksheet' if languages.count == 0

  default_language = languages[0] if default_language.to_s == ''
  default_language = override_default unless override_default.nil?

  puts "Languages detected: #{languages.keys.join(', ')} -- using #{default_language} as default."

  puts 'Building terminology in memory...'

  terms = []
  first_term_row = first_valid_row_index+1
  last_term_row = last_valid_row_index-1

  for row in first_term_row..last_term_row
    key = worksheet[row, 1]
    unless key.to_s == ''
      term = Term.new(key)
      languages.each do |lang, column_index|
        term_text = worksheet[row, column_index]
        term.values.store lang, term_text
      end
      terms << term
    end
  end

  puts 'Loaded!'

  # Return the array of terms, languages and default language
  res = Hash.new
  res[:segments] = terms
  res[:languages] = languages
  res[:default_language] = default_language

  res
end