diff --git a/app/lib/r3x/client/google_sheets.rb b/app/lib/r3x/client/google_sheets.rb new file mode 100644 index 00000000..a07a71b6 --- /dev/null +++ b/app/lib/r3x/client/google_sheets.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module R3x + module Client + class GoogleSheets + def initialize(spreadsheet_id:, credentials:) + @spreadsheet_id = spreadsheet_id + @credentials = credentials + @service = build_service + end + + def read_rows(range:, headers: true) + response = service.get_spreadsheet_values(spreadsheet_id, range) + rows = response.values || [] + return [] if rows.empty? + + return rows unless headers + + header_row = rows.first + unique_headers = make_unique_headers(header_row) + data_rows = rows.drop(1) + + data_rows.map { |row| row_to_hash(unique_headers, row) } + end + + private + + attr_reader :spreadsheet_id, :credentials, :service + + def build_service + service = Google::Apis::SheetsV4::SheetsService.new + service.authorization = R3x::Client::GoogleAuth.from_json( + credentials, + scope: Google::Apis::SheetsV4::AUTH_SPREADSHEETS_READONLY + ) + service + end + + def make_unique_headers(headers) + seen = Hash.new(0) + headers.map do |header| + seen[header] += 1 + (seen[header] > 1) ? "#{header}_#{seen[header]}" : header + end + end + + def row_to_hash(headers, row) + padded_row = row + Array.new([ 0, headers.length - row.length ].max, nil) + headers.zip(padded_row).to_h + end + end + end +end diff --git a/docs/todo/plan-google-sheets-client.md b/docs/todo/plan-google-sheets-client.md index 5558a6b1..79158bf6 100644 --- a/docs/todo/plan-google-sheets-client.md +++ b/docs/todo/plan-google-sheets-client.md @@ -24,14 +24,13 @@ gem "google-apis-sheets_v4" ## 2. `app/lib/r3x/client/google_sheets.rb` -### Class: `R3x::Client::GoogleSheets::Client` +### Class: `R3x::Client::GoogleSheets` ```ruby module R3x module Client - module GoogleSheets - class Client - def initialize(spreadsheet_id:, credentials:) + class GoogleSheets + def initialize(spreadsheet_id:, credentials:) @spreadsheet_id = spreadsheet_id @credentials = credentials @service = build_service @@ -52,7 +51,7 @@ module R3x def build_service service = Google::Apis::SheetsV4::SheetsService.new - service.authorization = GoogleAuth.from_json( + service.authorization = R3x::Client::GoogleAuth.from_json( credentials, scope: Google::Apis::SheetsV4::AUTH_SPREADSHEETS_READONLY ) @@ -94,24 +93,14 @@ Add inside `ClientProxy` class, after `llm` method: ```ruby def google_sheets(spreadsheet_id:, credentials_env:) - credentials = fetch_google_credentials(credentials_env) - R3x::Client::GoogleSheets::Client.new( + R3x::Client::GoogleSheets.new( spreadsheet_id: spreadsheet_id, - credentials: credentials + credentials: MultiJson.load(R3x::Env.secure_fetch(credentials_env, prefix: "GOOGLE_CREDENTIALS_")) ) end ``` -Add as private method on `ClientProxy`: -```ruby -private - -def fetch_google_credentials(credentials_env) - json = R3x::Env.secure_fetch(credentials_env, prefix: "GOOGLE_CREDENTIALS_") - MultiJson.load(json) -end -``` --- diff --git a/lib/r3x/workflow/context.rb b/lib/r3x/workflow/context.rb index 01b290ea..db201088 100644 --- a/lib/r3x/workflow/context.rb +++ b/lib/r3x/workflow/context.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module R3x module Workflow class Context @@ -39,6 +41,13 @@ def llm(api_key_env:) ) end + def google_sheets(spreadsheet_id:, credentials_env:) + R3x::Client::GoogleSheets.new( + spreadsheet_id: spreadsheet_id, + credentials: MultiJson.load(R3x::Env.secure_fetch(credentials_env, prefix: "GOOGLE_CREDENTIALS_")) + ) + end + private attr_reader :workflow_class