import { SplidClient } from 'splid-js'; import { google } from "googleapis"; import { NAME_ALIASES, ALIAS_TO_EMOJI, SPREADSHEET_ID, SHEETS_CONFIG, SHEET_RANGES, TABLE_RESET_ROW_COUNT, TABLE_COLUMN_COUNT, SHEET_ID, COLUMN_INDICES } from './constants.js'; async function setAliasesFromSheet() { const response = await getSheetData(SPREADSHEET_ID, SHEET_RANGES.ALIASES); const emojis = response[0]; for (let col = 0; col < emojis.length; col++) { const emoji = emojis[col]; NAME_ALIASES[emoji] = []; for (let row = 1; row < response.length; row++) { const alias = response[row][col]; if (alias && alias.trim() !== '') { const normalized = alias.toLowerCase(); NAME_ALIASES[emoji].push(alias); ALIAS_TO_EMOJI[normalized] = emoji; } } } } function getNameFromAlias(alias) { return ALIAS_TO_EMOJI[alias.toLowerCase()] || NAME_ALIASES['default']; } // Create a reusable sheets API client async function createSheetsClient() { const auth = new google.auth.GoogleAuth(SHEETS_CONFIG); return google.sheets({ version: 'v4', auth }); } // Get data from Google Sheets async function getSheetData(spreadsheetId, range) { try { const sheets = await createSheetsClient(); const response = await sheets.spreadsheets.values.get({ spreadsheetId, range }); return response.data.values; } catch (err) { console.error('Error getting sheet data:', err); throw err; } } // Update data in Google Sheets async function updateSheetData(spreadsheetId, range, values) { try { const sheets = await createSheetsClient(); const response = sheets.spreadsheets.values.update({ spreadsheetId, range, valueInputOption: 'USER_ENTERED', resource: { values }, }); return response.data; } catch (err) { console.error('Error updating sheet data:', err); throw err; } } async function getSplidData(splidCode) { const splid = new SplidClient(); const groupRes = await splid.group.getByInviteCode(splidCode); const groupId = groupRes.result.objectId; const groupInfo = await splid.groupInfo.getOneByGroup(groupId); const members = await splid.person.getAllByGroup(groupId); const expensesAndPayments = await splid.entry.getAllByGroup(groupId); const balance = SplidClient.getBalance( members, expensesAndPayments, groupInfo ); // Create a map of member IDs to their names/initials const memberMap = {}; for (const member of members) { memberMap[member.GlobalId] = { name: member.name, emoji: getNameFromAlias(member.name) }; } // Enhance the balance object with member information const enhancedBalance = {}; for (const [memberId, balanceInfo] of Object.entries(balance)) { enhancedBalance[memberId] = { ...balanceInfo, memberInfo: memberMap[memberId] || { name: 'Unknown', emoji: NAME_ALIASES['default'] }, }; } return { balance: enhancedBalance, groupName: groupInfo.name }; } async function resetTableData() { // Create an array of arrays with "-" for each cell const dashData = Array(TABLE_RESET_ROW_COUNT).fill().map(() => Array(TABLE_COLUMN_COUNT).fill("-")); try { await updateSheetData(SPREADSHEET_ID, SHEET_RANGES.DATA_RESET, dashData); } catch (err) { console.error('Error resetting table data:', err); throw err; } } async function autoResizeColumns(spreadsheetId, sheetId, startColumnIndex, endColumnIndex) { try { const sheets = await createSheetsClient(); const request = { spreadsheetId: spreadsheetId, resource: { requests: [ { autoResizeDimensions: { dimensions: { sheetId: sheetId, dimension: 'COLUMNS', startIndex: startColumnIndex, endIndex: endColumnIndex + 1 } } } ] } }; const response = await sheets.spreadsheets.batchUpdate(request); console.log('Columns auto-resized successfully'); return response.data; } catch (err) { console.error('Error auto-resizing columns:', err); throw err; } } async function main() { let RAW = []; await setAliasesFromSheet(); const splidCodes = await getSheetData(SPREADSHEET_ID, SHEET_RANGES.SPLID_CODES); const userTags = await getSheetData(SPREADSHEET_ID, SHEET_RANGES.USER_TAGS); console.log(splidCodes); console.log("Resetting table data.") await resetTableData(); const groupNames = []; // Array to collect group names for (let i = 0; i < splidCodes.length; i++) { const splidCodeString = splidCodes[i][0]; if (!splidCodeString) { groupNames.push(['-']); // Add placeholder for empty rows continue; } console.log(`Processing Splid code: ${splidCodeString}`); const splidData = await getSplidData(splidCodeString); const balance = splidData.balance; // Add group name to our collection groupNames.push([splidData.groupName]); const rowData = []; for (const tag of userTags[0]) { const matchingMembers = Object.entries(balance).filter(([_, info]) => info.memberInfo.emoji === tag); const totalBalance = matchingMembers.reduce((sum, [_, info]) => sum + parseFloat(info.balance), 0); const balanceValue = matchingMembers.length > 0 ? String(totalBalance.toFixed(2)).replace('.', ',') : '-'; rowData.push(balanceValue); } // Update the sheet with the row data await updateSheetData(SPREADSHEET_ID, SHEET_RANGES.DATA_ROW(i), [rowData]); RAW.push([`Row ${i} Data:`, JSON.stringify(rowData)]); RAW.push([`Balance ${i}:`, JSON.stringify(balance, null, 2)]); } // Update column B with group names if (groupNames.length > 0) { const columnBRange = `B2:B${groupNames.length + 1}`; // B2 to B(2+count-1) await updateSheetData(SPREADSHEET_ID, columnBRange, groupNames); console.log(`Updated column B with ${groupNames.length} group names`); } console.log("Sheets updated, adjusting column width.") try { await autoResizeColumns(SPREADSHEET_ID, SHEET_ID, COLUMN_INDICES.F, COLUMN_INDICES.N); } catch (err) { console.error('Failed to auto-resize columns, but data was updated successfully:', err); } RAW.push(['Splid Codes:', JSON.stringify(splidCodes)]); RAW.push(['User Tags:', JSON.stringify(userTags)]); await updateSheetData(SPREADSHEET_ID, SHEET_RANGES.RAW, RAW); } main().catch(console.error);