nxapi/src/cli/pctl/dump-summaries.ts
2022-05-29 19:16:54 +01:00

107 lines
4.0 KiB
TypeScript

import * as path from 'node:path';
import * as fs from 'node:fs/promises';
import createDebug from 'debug';
import mkdirp from 'mkdirp';
import type { Arguments as ParentArguments } from '../pctl.js';
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
import { initStorage } from '../../util/storage.js';
import { getPctlToken } from '../../common/auth/moon.js';
import { DailySummaryResult } from '../../api/moon-types.js';
import MoonApi from '../../api/moon.js';
const debug = createDebug('cli:pctl:dump-summaries');
export const command = 'dump-summaries [directory]';
export const desc = 'Download all daily and monthly summaries';
export function builder(yargs: Argv<ParentArguments>) {
return yargs.positional('directory', {
describe: 'Directory to write summary data to',
type: 'string',
}).option('user', {
describe: 'Nintendo Account ID',
type: 'string',
}).option('token', {
describe: 'Nintendo Account session token',
type: 'string',
}).option('device', {
describe: 'Nintendo Switch device ID',
type: 'array',
});
}
type Arguments = YargsArguments<ReturnType<typeof builder>>;
export async function handler(argv: ArgumentsCamelCase<Arguments>) {
const storage = await initStorage(argv.dataPath);
const usernsid = argv.user ?? await storage.getItem('SelectedUser');
const token: string = argv.token ||
await storage.getItem('NintendoAccountToken-pctl.' + usernsid);
const {moon, data} = await getPctlToken(storage, token);
const directory = argv.directory ?? path.join(argv.dataPath, 'summaries');
await mkdirp(directory);
const devices = await moon.getDevices();
for (const id of argv.device ?? []) {
if (!devices.items.find(d => d.deviceId === id)) {
console.warn('Device %s does not exist or is not linked to the authenticated user');
}
}
for (const device of devices.items) {
if (argv.device && !argv.device.includes(device.deviceId)) continue;
console.warn('Downloading summaries for device %s (%s)', device.label, device.deviceId);
await dumpMonthlySummariesForDevice(moon, directory, device.deviceId);
await dumpDailySummariesForDevice(moon, directory, device.deviceId);
}
}
async function dumpMonthlySummariesForDevice(moon: MoonApi, directory: string, device: string) {
debug('Fetching monthly summaries for device %s', device);
const monthlySummaries = await moon.getMonthlySummaries(device);
for (const item of monthlySummaries.items) {
const filename = 'pctl-monthly-' + item.deviceId + '-' + item.month + '.json';
const file = path.join(directory, filename);
try {
await fs.stat(file);
debug('Skipping monthly summary %s for device %s, file already exists', item.month, item.deviceId);
continue;
} catch (err) {}
debug('Fetching monthly summary %s for device %s', item.month, item.deviceId);
const summary = await moon.getMonthlySummary(item.deviceId, item.month);
debug('Writing %s', filename);
await fs.writeFile(file, JSON.stringify(summary, null, 4) + '\n', 'utf-8');
}
}
async function dumpDailySummariesForDevice(moon: MoonApi, directory: string, device: string) {
debug('Fetching daily summaries for device %s', device);
const summaries = await moon.getDailySummaries(device);
const timestamp = Date.now();
for (const summary of summaries.items) {
const filename = 'pctl-daily-' + summary.deviceId + '-' + summary.date +
(summary.result === DailySummaryResult.ACHIEVED ? '' : '-' + timestamp) + '.json';
const file = path.join(directory, filename);
try {
await fs.stat(file);
debug('Skipping daily summary %s for device %s, file already exists', summary.date, summary.deviceId);
continue;
} catch (err) {}
debug('Writing %s', filename);
await fs.writeFile(file, JSON.stringify(summary, null, 4) + '\n', 'utf-8');
}
}