-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsheetsHandler.js
More file actions
253 lines (230 loc) · 8.92 KB
/
Copy pathsheetsHandler.js
File metadata and controls
253 lines (230 loc) · 8.92 KB
1
2
3
4
5
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/**
* Google Sheets integration for tracking Elite Dangerous activities
*/
import { google } from 'googleapis';
import { readFileSync, existsSync } from 'fs';
import * as config from './config.js';
export class SheetsHandler {
constructor() {
this.spreadsheetId = config.SPREADSHEET_ID;
this.credentials = null;
this.auth = null;
this.sheets = null;
}
/**
* Authenticate with Google Sheets API
* @returns {Promise<boolean>}
*/
async authenticate() {
try {
// Try to use service account credentials
if (existsSync(config.CREDENTIALS_FILE)) {
const credentialsContent = readFileSync(config.CREDENTIALS_FILE, 'utf8');
const credentials = JSON.parse(credentialsContent);
this.auth = new google.auth.GoogleAuth({
credentials: credentials,
scopes: ['https://www.googleapis.com/auth/spreadsheets']
});
this.sheets = google.sheets({ version: 'v4', auth: this.auth });
console.log('✓ Authenticated with Google Sheets using service account');
return true;
} else {
console.log('✗ credentials.json not found. Please set up Google Sheets API credentials.');
return false;
}
} catch (error) {
console.error('✗ Authentication error:', error.message);
return false;
}
}
/**
* Connect to the specified spreadsheet
* @returns {Promise<boolean>}
*/
async connectSpreadsheet() {
try {
const response = await this.sheets.spreadsheets.get({
spreadsheetId: this.spreadsheetId
});
console.log(`✓ Connected to spreadsheet: ${response.data.properties.title}`);
return true;
} catch (error) {
console.error('✗ Error connecting to spreadsheet:', error.message);
return false;
}
}
/**
* Create or verify worksheets exist with proper headers
* @returns {Promise<boolean>}
*/
async setupWorksheets() {
try {
// Get existing sheets
const spreadsheet = await this.sheets.spreadsheets.get({
spreadsheetId: this.spreadsheetId
});
const existingSheets = spreadsheet.data.sheets.map(sheet => sheet.properties.title);
// Setup BGS tracking sheet
await this._getOrCreateWorksheet(config.WORKSHEETS.BGS, existingSheets);
await this._ensureHeaders(config.WORKSHEETS.BGS, config.BGS_COLUMNS);
console.log('✓ Set up BGS tracking sheet');
// Setup Powerplay tracking sheet
await this._getOrCreateWorksheet(config.WORKSHEETS.POWERPLAY, existingSheets);
await this._ensureHeaders(config.WORKSHEETS.POWERPLAY, config.POWERPLAY_COLUMNS);
console.log('✓ Set up Powerplay tracking sheet');
// Setup Summary sheet
await this._getOrCreateWorksheet(config.WORKSHEETS.SUMMARY, existingSheets);
console.log('✓ Worksheets ready');
return true;
} catch (error) {
console.error('✗ Error setting up worksheets:', error.message);
return false;
}
}
/**
* Get existing worksheet or create new one
* @private
*/
async _getOrCreateWorksheet(title, existingSheets) {
if (!existingSheets.includes(title)) {
await this.sheets.spreadsheets.batchUpdate({
spreadsheetId: this.spreadsheetId,
requestBody: {
requests: [{
addSheet: {
properties: {
title: title,
gridProperties: {
rowCount: 1000,
columnCount: 20
}
}
}
}]
}
});
console.log(`✓ Created worksheet: ${title}`);
}
}
/**
* Ensure worksheet has proper headers
* @private
*/
async _ensureHeaders(sheetName, headers) {
try {
// Check if first row has data
const response = await this.sheets.spreadsheets.values.get({
spreadsheetId: this.spreadsheetId,
range: `${sheetName}!A1:Z1`
});
// If no data or wrong headers, write headers
if (!response.data.values || response.data.values.length === 0) {
await this.sheets.spreadsheets.values.update({
spreadsheetId: this.spreadsheetId,
range: `${sheetName}!A1`,
valueInputOption: 'RAW',
requestBody: {
values: [headers]
}
});
}
} catch (error) {
console.error(`Error ensuring headers for ${sheetName}:`, error.message);
}
}
/**
* Append BGS data to tracking sheet
* @param {Array} data - Row data to append
* @returns {Promise<boolean>}
*/
async appendBGSData(data) {
try {
await this.sheets.spreadsheets.values.append({
spreadsheetId: this.spreadsheetId,
range: `${config.WORKSHEETS.BGS}!A:N`,
valueInputOption: 'RAW',
requestBody: {
values: [data]
}
});
console.log(`✓ Added BGS data for ${data[1]} in ${data[2]}`);
return true;
} catch (error) {
console.error('✗ Error appending BGS data:', error.message);
return false;
}
}
/**
* Append Powerplay data to tracking sheet
* @param {Array} data - Row data to append
* @returns {Promise<boolean>}
*/
async appendPowerplayData(data) {
try {
await this.sheets.spreadsheets.values.append({
spreadsheetId: this.spreadsheetId,
range: `${config.WORKSHEETS.POWERPLAY}!A:F`,
valueInputOption: 'RAW',
requestBody: {
values: [data]
}
});
console.log(`✓ Added Powerplay data for ${data[1]}: ${data[3]} merits`);
return true;
} catch (error) {
console.error('✗ Error appending Powerplay data:', error.message);
return false;
}
}
/**
* Get summary statistics for a commander
* @param {string} commanderName - Commander name to look up
* @returns {Promise<Object|null>}
*/
async getCommanderSummary(commanderName) {
try {
const summary = {
bgs: { total_inf: 0, total_bounties: 0, systems: new Set() },
powerplay: { total_merits: 0, systems: new Set() }
};
// Get BGS data
const bgsResponse = await this.sheets.spreadsheets.values.get({
spreadsheetId: this.spreadsheetId,
range: `${config.WORKSHEETS.BGS}!A2:N`
});
if (bgsResponse.data.values) {
for (const row of bgsResponse.data.values) {
if (row[1] && row[1].toLowerCase() === commanderName.toLowerCase()) {
summary.bgs.total_inf += parseInt(row[4]) || 0;
summary.bgs.total_bounties += parseInt(row[5]) || 0;
if (row[2]) {
summary.bgs.systems.add(row[2]);
}
}
}
}
// Get Powerplay data
const ppResponse = await this.sheets.spreadsheets.values.get({
spreadsheetId: this.spreadsheetId,
range: `${config.WORKSHEETS.POWERPLAY}!A2:F`
});
if (ppResponse.data.values) {
for (const row of ppResponse.data.values) {
if (row[1] && row[1].toLowerCase() === commanderName.toLowerCase()) {
summary.powerplay.total_merits += parseInt(row[3]) || 0;
if (row[2]) {
summary.powerplay.systems.add(row[2]);
}
}
}
}
// Convert sets to arrays
summary.bgs.systems = Array.from(summary.bgs.systems);
summary.powerplay.systems = Array.from(summary.powerplay.systems);
return summary;
} catch (error) {
console.error('✗ Error getting commander summary:', error.message);
return null;
}
}
}