import { SessionState, GoogleSheetsGetOptions, VariableWithValue, ChatLog, } from '@typebot.io/schemas' import { isNotEmpty, byId, isDefined } from '@typebot.io/lib' import { getAuthenticatedGoogleDoc } from './helpers/getAuthenticatedGoogleDoc' import { ExecuteIntegrationResponse } from '../../../types' import { matchFilter } from './helpers/matchFilter' import { deepParseVariables } from '@typebot.io/variables/deepParseVariables' import { updateVariablesInSession } from '@typebot.io/variables/updateVariablesInSession' export const getRow = async ( state: SessionState, { outgoingEdgeId, options, }: { outgoingEdgeId?: string; options: GoogleSheetsGetOptions } ): Promise => { const logs: ChatLog[] = [] const { variables } = state.typebotsQueue[0].typebot const { sheetId, cellsToExtract, filter, ...parsedOptions } = deepParseVariables(variables)(options) if (!sheetId) return { outgoingEdgeId } const doc = await getAuthenticatedGoogleDoc({ credentialsId: options.credentialsId, spreadsheetId: options.spreadsheetId, }) try { await doc.loadInfo() const sheet = doc.sheetsById[Number(sheetId)] const rows = await sheet.getRows() const filteredRows = getTotalRows( options.totalRowsToExtract, rows.filter((row) => 'referenceCell' in parsedOptions && parsedOptions.referenceCell ? row.get(parsedOptions.referenceCell?.column as string) === parsedOptions.referenceCell?.value : matchFilter(row, filter) ) ) if (filteredRows.length === 0) { logs.push({ status: 'info', description: `Couldn't find any rows matching the filter`, details: JSON.stringify(filter, null, 2), }) return { outgoingEdgeId, logs } } const extractingColumns = cellsToExtract ?.map((cell) => cell.column) .filter(isNotEmpty) const selectedRows = filteredRows .map((row) => extractingColumns?.reduce<{ [key: string]: string }>( (obj, column) => ({ ...obj, [column]: row.get(column) }), {} ) ) .filter(isDefined) if (!selectedRows) return { outgoingEdgeId } const newVariables = options.cellsToExtract?.reduce( (newVariables, cell) => { const existingVariable = variables.find(byId(cell.variableId)) const value = selectedRows.map((row) => row[cell.column ?? '']) if (!existingVariable) return newVariables return [ ...newVariables, { ...existingVariable, value: value.length === 1 ? value[0] : value, }, ] }, [] ) if (!newVariables) return { outgoingEdgeId } const newSessionState = updateVariablesInSession(state)(newVariables) return { outgoingEdgeId, newSessionState, } } catch (err) { logs.push({ status: 'error', description: `An error occurred while fetching the spreadsheet data`, details: err, }) } return { outgoingEdgeId, logs } } const getTotalRows = ( totalRowsToExtract: GoogleSheetsGetOptions['totalRowsToExtract'], rows: T[] ): T[] => { switch (totalRowsToExtract) { case 'All': case undefined: return rows case 'First': return rows.slice(0, 1) case 'Last': return rows.slice(-1) case 'Random': return [rows[Math.floor(Math.random() * rows.length)]] } }