class GoogleDriveProcessor

Public Class Methods

load_localizables(platform_options, options) click to toggle source
# File lib/localio/processors/google_drive_processor.rb, line 7
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
  login = options[:login]
  raise ArgumentError, ':login is deprecated. You should use :client_id and :client_secret for secure OAuth2 authentication.' unless login.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]

  # We need client_id / client_secret
  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?

  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
    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://docs.google.com/feeds/" +
            "https://www.googleapis.com/auth/drive " +
            "https://spreadsheets.google.com/feeds/"
    auth.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"

    config = ConfigStore.new

    access_token = nil

    if options.has_key?(:client_token)
      puts 'Refreshing auth token...'
      auth.refresh_token = options[:client_token]
      auth.refresh!
      access_token = auth.access_token
    elsif config.has? :refresh_token
      puts 'Refreshing auth token...'
      auth.refresh_token = config.get :refresh_token
      auth.refresh!
      access_token = auth.access_token
    else
      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
    end

  if !options.has_key?(:client_token)
    puts 'Store auth data...'
    config.store :refresh_token, auth.refresh_token
    config.store :access_token, auth.access_token
    config.persist
  end

    # Creates a session
    session = GoogleDrive.login_with_oauth(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 (#{matching_spreadsheets.join ', '}). You have to be more specific!"
  end

  sheet = options[:sheet]
  worksheet = if sheet.is_a? Integer
                matching_spreadsheets[0].worksheets[sheet]
              elsif sheet.is_a? String
                matching_spreadsheets[0].worksheets.detect { |s| s.title == sheet }
              end


  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.gsub('*', '') if col_text.include? '*'
      lang = col_text.gsub('*', '')

      unless platform_options[:avoid_lang_downcase]
        default_language = default_language.downcase
        lang = lang.downcase
       end

      unless col_text.to_s == ''
        languages.store lang, column
      end
    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