mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-03-26 12:14:35 -05:00
Add commands to list stages, challenges, weapon stats, hero stats, battles and stage schedules from SplatNet 2
This commit is contained in:
parent
28b3468835
commit
f1d262bfa7
|
|
@ -17,7 +17,8 @@ export function builder(yargs: Argv<ParentArguments>) {
|
|||
return yargs.option('znc-proxy-url', {
|
||||
describe: 'URL of Nintendo Switch Online app API proxy server to use',
|
||||
type: 'string',
|
||||
}).option('auto-update-iksm-session', {
|
||||
}).option('auto-update-session', {
|
||||
alias: ['auto-update-iksm-session'],
|
||||
describe: 'Automatically obtain and refresh the iksm_session cookie',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
|
|
|
|||
92
src/cli/splatnet2/battles.ts
Normal file
92
src/cli/splatnet2/battles.ts
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import createDebug from 'debug';
|
||||
// @ts-expect-error
|
||||
import Table from 'cli-table/lib/index.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import { ArgumentsCamelCase, Argv, initStorage, YargsArguments } from '../../util.js';
|
||||
import { getIksmToken } from './util.js';
|
||||
|
||||
const debug = createDebug('cli:splatnet2:battles');
|
||||
|
||||
export const command = 'battles';
|
||||
export const desc = 'List the last 50 regular/ranked/private/festival battles';
|
||||
|
||||
export function builder(yargs: Argv<ParentArguments>) {
|
||||
return yargs.option('user', {
|
||||
describe: 'Nintendo Account ID',
|
||||
type: 'string',
|
||||
}).option('token', {
|
||||
describe: 'Nintendo Account session token',
|
||||
type: 'string',
|
||||
}).option('json', {
|
||||
describe: 'Output raw JSON',
|
||||
type: 'boolean',
|
||||
}).option('json-pretty-print', {
|
||||
describe: 'Output pretty-printed JSON',
|
||||
type: 'boolean',
|
||||
});
|
||||
}
|
||||
|
||||
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.' + usernsid);
|
||||
const {splatnet} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateSession);
|
||||
|
||||
const results = await splatnet.getResults();
|
||||
|
||||
if (argv.jsonPrettyPrint) {
|
||||
console.log(JSON.stringify(results, null, 4));
|
||||
return;
|
||||
}
|
||||
if (argv.json) {
|
||||
console.log(JSON.stringify(results));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Summary', results.summary);
|
||||
|
||||
const table = new Table({
|
||||
head: [
|
||||
'#',
|
||||
'Type',
|
||||
'Mode',
|
||||
'Rule',
|
||||
'Stage',
|
||||
'Result',
|
||||
'Inked',
|
||||
'K (A)',
|
||||
'D',
|
||||
'S',
|
||||
'Timestamp',
|
||||
],
|
||||
});
|
||||
|
||||
results.results.sort((a, b) => a.start_time > b.start_time ? 1 : a.start_time < b.start_time ? -1 : 0);
|
||||
|
||||
for (const result of results.results) {
|
||||
table.push([
|
||||
result.battle_number,
|
||||
result.type,
|
||||
(result.game_mode.key === 'regular' ? '\u001b[32m' :
|
||||
result.game_mode.key === 'ranked' ? '\u001b[33m' :
|
||||
result.game_mode.key === 'league' ? '\u001b[31m' :
|
||||
result.game_mode.key === 'private' ? '\u001b[35m' : '') +
|
||||
result.game_mode.name + '\u001b[0m',
|
||||
result.rule.key,
|
||||
result.stage.name,
|
||||
(result.my_team_result.key === 'victory' ? '\u001b[32m' : '\u001b[31m') +
|
||||
result.my_team_result.name + '\u001b[0m',
|
||||
result.player_result.game_paint_point + 'p',
|
||||
result.player_result.kill_count + ' (' + result.player_result.assist_count + ')',
|
||||
result.player_result.death_count,
|
||||
result.player_result.special_count,
|
||||
new Date(result.start_time * 1000).toISOString(),
|
||||
]);
|
||||
}
|
||||
|
||||
console.log(table.toString());
|
||||
}
|
||||
92
src/cli/splatnet2/challenges.ts
Normal file
92
src/cli/splatnet2/challenges.ts
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import createDebug from 'debug';
|
||||
// @ts-expect-error
|
||||
import Table from 'cli-table/lib/index.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import { ArgumentsCamelCase, Argv, initStorage, YargsArguments } from '../../util.js';
|
||||
import { getIksmToken } from './util.js';
|
||||
|
||||
const debug = createDebug('cli:splatnet2:challenges');
|
||||
|
||||
export const command = 'challenges';
|
||||
export const desc = 'List lifetime inkage challenges';
|
||||
|
||||
export function builder(yargs: Argv<ParentArguments>) {
|
||||
return yargs.option('user', {
|
||||
describe: 'Nintendo Account ID',
|
||||
type: 'string',
|
||||
}).option('token', {
|
||||
describe: 'Nintendo Account session token',
|
||||
type: 'string',
|
||||
}).option('json', {
|
||||
describe: 'Output raw JSON',
|
||||
type: 'boolean',
|
||||
}).option('json-pretty-print', {
|
||||
describe: 'Output pretty-printed JSON',
|
||||
type: 'boolean',
|
||||
});
|
||||
}
|
||||
|
||||
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.' + usernsid);
|
||||
const {splatnet} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateSession);
|
||||
|
||||
const records = await splatnet.getRecords();
|
||||
|
||||
if (argv.jsonPrettyPrint) {
|
||||
console.log(JSON.stringify(records.challenges, null, 4));
|
||||
return;
|
||||
}
|
||||
if (argv.json) {
|
||||
console.log(JSON.stringify(records.challenges));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const [text, season, challenges, next, total_paint_point] of [
|
||||
[
|
||||
'Lifetime inkage challenges season 1', 1,
|
||||
records.challenges.archived_challenges, records.challenges.next_challenge,
|
||||
records.challenges.total_paint_point,
|
||||
] as const,
|
||||
[
|
||||
'Lifetime inkage challenges season 2 (Octoling)', 2,
|
||||
records.challenges.archived_challenges_octa, records.challenges.next_challenge_octa,
|
||||
records.challenges.total_paint_point_octa,
|
||||
] as const,
|
||||
]) {
|
||||
const table = new Table({
|
||||
head: [
|
||||
'ID',
|
||||
'Name',
|
||||
'Turf covered',
|
||||
'Completion',
|
||||
],
|
||||
});
|
||||
|
||||
for (const challenge of challenges) {
|
||||
table.push([
|
||||
challenge.key,
|
||||
challenge.name,
|
||||
challenge.paint_points + 'p',
|
||||
'100%',
|
||||
]);
|
||||
}
|
||||
|
||||
if (next) {
|
||||
table.push([
|
||||
'???',
|
||||
'???',
|
||||
next.paint_points + 'p',
|
||||
(Math.round((total_paint_point / next.paint_points) * 10000) / 100) + '%',
|
||||
]);
|
||||
}
|
||||
|
||||
console.log(text);
|
||||
console.log(table.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -67,7 +67,7 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
const usernsid = argv.user ?? await storage.getItem('SelectedUser');
|
||||
const token: string = argv.token ||
|
||||
await storage.getItem('NintendoAccountToken.' + usernsid);
|
||||
const {splatnet} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateIksmSession);
|
||||
const {splatnet} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateSession);
|
||||
|
||||
await mkdirp(argv.directory);
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
const usernsid = argv.user ?? await storage.getItem('SelectedUser');
|
||||
const token: string = argv.token ||
|
||||
await storage.getItem('NintendoAccountToken.' + usernsid);
|
||||
const {splatnet} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateIksmSession);
|
||||
const {splatnet} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateSession);
|
||||
|
||||
await mkdirp(argv.directory);
|
||||
|
||||
|
|
@ -123,13 +123,16 @@ export async function dumpResults(
|
|||
await fs.writeFile(image_file, image);
|
||||
}
|
||||
|
||||
const skipped = [];
|
||||
const skipped_images = [];
|
||||
|
||||
for (const item of results.results) {
|
||||
const filename = 'splatnet2-result-' + results.unique_id + '-' + item.battle_number + '-' + item.type + '.json';
|
||||
const file = path.join(directory, filename);
|
||||
|
||||
try {
|
||||
await fs.stat(file);
|
||||
debug('Skipping battle result %d, file already exists', item.battle_number);
|
||||
skipped.push(item.battle_number);
|
||||
} catch (err) {
|
||||
debug('Fetching battle result %d', item.battle_number);
|
||||
const result = await splatnet.getResult(item.battle_number);
|
||||
|
|
@ -159,26 +162,36 @@ export async function dumpResults(
|
|||
try {
|
||||
await fs.stat(file);
|
||||
await fs.stat(image_file);
|
||||
debug('Skipping battle result image %d, file already exists', item.battle_number);
|
||||
skipped_images.push(item.battle_number);
|
||||
} catch (err) {
|
||||
debug('Fetching battle results summary image URL');
|
||||
debug('Fetching battle results image URL');
|
||||
const share = await splatnet.shareResult(item.battle_number);
|
||||
|
||||
debug('Fetching battle results summary image');
|
||||
debug('Fetching battle results image');
|
||||
const image_response = await fetch(share.url);
|
||||
const image = await image_response.buffer();
|
||||
|
||||
debug('Writing battle results summary image data %s', filename);
|
||||
debug('Writing battle results image data %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
share,
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
||||
debug('Writing battle results summary image %s', filename);
|
||||
debug('Writing battle results image %s', filename);
|
||||
await fs.writeFile(image_file, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (skipped.length) {
|
||||
if (skipped.length === 1) debug('Skipped battle result %d, file already exists', skipped[0]);
|
||||
else debug('Skipped battle results %s, files already exist', skipped.join(', '));
|
||||
}
|
||||
if (skipped_images.length) {
|
||||
if (skipped_images.length === 1) debug('Skipped battle result image %d, file already exists',
|
||||
skipped_images[0]);
|
||||
else debug('Skipped battle result images %s, files already exist', skipped_images.join(', '));
|
||||
}
|
||||
|
||||
await fs.writeFile(latest_file, JSON.stringify({timestamp}, null, 4) + '\n', 'utf-8');
|
||||
}
|
||||
|
||||
|
|
@ -207,13 +220,15 @@ export async function dumpCoopResults(splatnet: SplatNet2Api, directory: string,
|
|||
debug('Writing summary %s', summary_filename);
|
||||
await fs.writeFile(summary_file, JSON.stringify(results, null, 4) + '\n', 'utf-8');
|
||||
|
||||
const skipped = [];
|
||||
|
||||
for (const item of results.results) {
|
||||
const filename = 'splatnet2-coop-result-' + user_id + '-' + item.job_id + '.json';
|
||||
const file = path.join(directory, filename);
|
||||
|
||||
try {
|
||||
await fs.stat(file);
|
||||
debug('Skipping coop result %d, file already exists', item.job_id);
|
||||
skipped.push(item.job_id);
|
||||
continue;
|
||||
} catch (err) {}
|
||||
|
||||
|
|
@ -234,5 +249,10 @@ export async function dumpCoopResults(splatnet: SplatNet2Api, directory: string,
|
|||
}, null, 4) + '\n', 'utf-8');
|
||||
}
|
||||
|
||||
if (skipped.length) {
|
||||
if (skipped.length === 1) debug('Skipped coop result %d, file already exists', skipped[0]);
|
||||
else debug('Skipped coop results %s, files already exist', skipped.join(', '));
|
||||
}
|
||||
|
||||
await fs.writeFile(latest_file, JSON.stringify({timestamp}, null, 4) + '\n', 'utf-8');
|
||||
}
|
||||
|
|
|
|||
97
src/cli/splatnet2/hero.ts
Normal file
97
src/cli/splatnet2/hero.ts
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
import createDebug from 'debug';
|
||||
// @ts-expect-error
|
||||
import Table from 'cli-table/lib/index.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import { ArgumentsCamelCase, Argv, initStorage, YargsArguments } from '../../util.js';
|
||||
import { getIksmToken } from './util.js';
|
||||
|
||||
const debug = createDebug('cli:splatnet2:hero');
|
||||
|
||||
export const command = 'hero';
|
||||
export const desc = 'Show hero (Octo Canyon) records';
|
||||
|
||||
export function builder(yargs: Argv<ParentArguments>) {
|
||||
return yargs.option('user', {
|
||||
describe: 'Nintendo Account ID',
|
||||
type: 'string',
|
||||
}).option('token', {
|
||||
describe: 'Nintendo Account session token',
|
||||
type: 'string',
|
||||
}).option('json', {
|
||||
describe: 'Output raw JSON',
|
||||
type: 'boolean',
|
||||
}).option('json-pretty-print', {
|
||||
describe: 'Output pretty-printed JSON',
|
||||
type: 'boolean',
|
||||
});
|
||||
}
|
||||
|
||||
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.' + usernsid);
|
||||
const {splatnet} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateSession);
|
||||
|
||||
const hero = await splatnet.getHeroRecords();
|
||||
|
||||
if (argv.jsonPrettyPrint) {
|
||||
console.log(JSON.stringify(hero, null, 4));
|
||||
return;
|
||||
}
|
||||
if (argv.json) {
|
||||
console.log(JSON.stringify(hero));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Summary', hero.summary);
|
||||
|
||||
const table = new Table({
|
||||
head: [
|
||||
'Mission',
|
||||
'Hero Shot',
|
||||
'Hero Roller',
|
||||
'Hero Charger',
|
||||
'Hero Dualies',
|
||||
'Hero Brella',
|
||||
'Hero Splatling',
|
||||
'Hero Blaster',
|
||||
'Hero Slosher',
|
||||
'Herobrush',
|
||||
],
|
||||
});
|
||||
|
||||
for (const stage of hero.stage_infos) {
|
||||
table.push([
|
||||
stage.stage.area + '-' + (stage.stage.is_boss ? 'B' : stage.stage.id),
|
||||
stage.clear_weapons[0] ? 'Level ' + stage.clear_weapons[0].weapon_level + ', ' +
|
||||
hrduration(stage.clear_weapons[0].clear_time) : '',
|
||||
stage.clear_weapons[1] ? hrduration(stage.clear_weapons[1].clear_time) : '',
|
||||
stage.clear_weapons[2] ? hrduration(stage.clear_weapons[2].clear_time) : '',
|
||||
stage.clear_weapons[3] ? hrduration(stage.clear_weapons[3].clear_time) : '',
|
||||
stage.clear_weapons[4] ? hrduration(stage.clear_weapons[4].clear_time) : '',
|
||||
stage.clear_weapons[5] ? hrduration(stage.clear_weapons[5].clear_time) : '',
|
||||
stage.clear_weapons[6] ? hrduration(stage.clear_weapons[6].clear_time) : '',
|
||||
stage.clear_weapons[7] ? hrduration(stage.clear_weapons[7].clear_time) : '',
|
||||
stage.clear_weapons[8] ? hrduration(stage.clear_weapons[8].clear_time) : '',
|
||||
]);
|
||||
}
|
||||
|
||||
console.log('Stages');
|
||||
console.log(table.toString());
|
||||
}
|
||||
|
||||
function hrduration(duration: number) {
|
||||
const minutes = Math.floor(duration / 60);
|
||||
const seconds = duration - (minutes * 60);
|
||||
|
||||
if (minutes >= 1) {
|
||||
return minutes + 'm' +
|
||||
(seconds ? ' ' + seconds + 's' : '');
|
||||
} else {
|
||||
return seconds + 's';
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,10 @@
|
|||
export * as user from './user.js';
|
||||
export * as stages from './stages.js';
|
||||
export * as challenges from './challenges.js';
|
||||
export * as weapons from './weapons.js';
|
||||
export * as hero from './hero.js';
|
||||
export * as battles from './battles.js';
|
||||
export * as schedule from './schedule.js';
|
||||
export * as dumpResults from './dump-results.js';
|
||||
export * as dumpRecords from './dump-records.js';
|
||||
export * as monitor from './monitor.js';
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
|
||||
i.cached_records = records;
|
||||
|
||||
i.auto_update_iksm_session = argv.autoUpdateSession;
|
||||
|
||||
console.log('Player %s (Splatoon 2 ID %s, NSA ID %s) level %d',
|
||||
records.records.player.nickname,
|
||||
records.records.unique_id,
|
||||
|
|
@ -120,6 +122,8 @@ export class SplatNet2RecordsMonitor {
|
|||
/** Prevents redownloading user records on the first loop run */
|
||||
cached_records: Records | null = null;
|
||||
|
||||
auto_update_iksm_session = true;
|
||||
|
||||
constructor(
|
||||
public storage: persist.LocalStorage,
|
||||
public token: string,
|
||||
|
|
|
|||
78
src/cli/splatnet2/schedule.ts
Normal file
78
src/cli/splatnet2/schedule.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import createDebug from 'debug';
|
||||
// @ts-expect-error
|
||||
import Table from 'cli-table/lib/index.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import { ArgumentsCamelCase, Argv, initStorage, YargsArguments } from '../../util.js';
|
||||
import { getIksmToken } from './util.js';
|
||||
|
||||
const debug = createDebug('cli:splatnet2:schedule');
|
||||
|
||||
export const command = 'schedule';
|
||||
export const desc = 'Show stage schedules';
|
||||
|
||||
export function builder(yargs: Argv<ParentArguments>) {
|
||||
return yargs.option('user', {
|
||||
describe: 'Nintendo Account ID',
|
||||
type: 'string',
|
||||
}).option('token', {
|
||||
describe: 'Nintendo Account session token',
|
||||
type: 'string',
|
||||
}).option('json', {
|
||||
describe: 'Output raw JSON',
|
||||
type: 'boolean',
|
||||
}).option('json-pretty-print', {
|
||||
describe: 'Output pretty-printed JSON',
|
||||
type: 'boolean',
|
||||
});
|
||||
}
|
||||
|
||||
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.' + usernsid);
|
||||
const {splatnet} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateSession);
|
||||
|
||||
const schedules = await splatnet.getSchedules();
|
||||
|
||||
if (argv.jsonPrettyPrint) {
|
||||
console.log(JSON.stringify(schedules, null, 4));
|
||||
return;
|
||||
}
|
||||
if (argv.json) {
|
||||
console.log(JSON.stringify(schedules));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const [text, schedule] of [
|
||||
['Regular Battle', schedules.regular],
|
||||
['Ranked Battle', schedules.gachi],
|
||||
['League Battle', schedules.league],
|
||||
] as const) {
|
||||
const table = new Table({
|
||||
head: [
|
||||
'ID',
|
||||
'Start',
|
||||
'Rule',
|
||||
'Stage',
|
||||
'Stage',
|
||||
],
|
||||
});
|
||||
|
||||
for (const item of schedule) {
|
||||
table.push([
|
||||
item.id,
|
||||
new Date(item.start_time * 1000).toISOString(),
|
||||
item.rule.name,
|
||||
item.stage_a.name,
|
||||
item.stage_b.name,
|
||||
]);
|
||||
}
|
||||
|
||||
console.log(text);
|
||||
console.log(table.toString());
|
||||
}
|
||||
}
|
||||
67
src/cli/splatnet2/stages.ts
Normal file
67
src/cli/splatnet2/stages.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import createDebug from 'debug';
|
||||
// @ts-expect-error
|
||||
import Table from 'cli-table/lib/index.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import { ArgumentsCamelCase, Argv, initStorage, YargsArguments } from '../../util.js';
|
||||
import { getIksmToken } from './util.js';
|
||||
|
||||
const debug = createDebug('cli:splatnet2:stages');
|
||||
|
||||
export const command = 'stages';
|
||||
export const desc = 'List stages';
|
||||
|
||||
export function builder(yargs: Argv<ParentArguments>) {
|
||||
return yargs.option('user', {
|
||||
describe: 'Nintendo Account ID',
|
||||
type: 'string',
|
||||
}).option('token', {
|
||||
describe: 'Nintendo Account session token',
|
||||
type: 'string',
|
||||
}).option('json', {
|
||||
describe: 'Output raw JSON',
|
||||
type: 'boolean',
|
||||
}).option('json-pretty-print', {
|
||||
describe: 'Output pretty-printed JSON',
|
||||
type: 'boolean',
|
||||
});
|
||||
}
|
||||
|
||||
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.' + usernsid);
|
||||
const {splatnet} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateSession);
|
||||
|
||||
const stages = await splatnet.getStages();
|
||||
|
||||
if (argv.jsonPrettyPrint) {
|
||||
console.log(JSON.stringify(stages, null, 4));
|
||||
return;
|
||||
}
|
||||
if (argv.json) {
|
||||
console.log(JSON.stringify(stages));
|
||||
return;
|
||||
}
|
||||
|
||||
const table = new Table({
|
||||
head: [
|
||||
'ID',
|
||||
'Name',
|
||||
],
|
||||
});
|
||||
|
||||
stages.stages.sort((a, b) => parseInt(a.id) > parseInt(b.id) ? 1 : parseInt(a.id) < parseInt(b.id) ? -1 : 0);
|
||||
|
||||
for (const stage of stages.stages) {
|
||||
table.push([
|
||||
stage.id,
|
||||
stage.name,
|
||||
]);
|
||||
}
|
||||
|
||||
console.log(table.toString());
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
const usernsid = argv.user ?? await storage.getItem('SelectedUser');
|
||||
const token: string = argv.token ||
|
||||
await storage.getItem('NintendoAccountToken.' + usernsid);
|
||||
const {splatnet} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateIksmSession);
|
||||
const {splatnet, data} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateSession);
|
||||
|
||||
const [records, stages, activefestivals, timeline] = await Promise.all([
|
||||
splatnet.getRecords(),
|
||||
|
|
@ -42,4 +42,6 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|||
records.records.player.principal_id,
|
||||
records.records.player.player_rank,
|
||||
records.records.player.player_type);
|
||||
|
||||
console.log(data.iksm_session);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export async function getIksmToken(storage: persist.LocalStorage, token: string,
|
|||
|
||||
const existingToken: SavedIksmSessionToken | undefined = await storage.getItem('IksmToken.' + token);
|
||||
|
||||
const td = 2 * 24 * 60 * 60 * 1000; // 2 days in ms
|
||||
const td = 24 * 60 * 60 * 1000; // 1 day in ms
|
||||
const last_used_days_ago = existingToken?.last_used && (existingToken.last_used + td) <= Date.now();
|
||||
const expired = existingToken && existingToken.expires_at <= Date.now();
|
||||
|
||||
|
|
|
|||
82
src/cli/splatnet2/weapons.ts
Normal file
82
src/cli/splatnet2/weapons.ts
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import createDebug from 'debug';
|
||||
// @ts-expect-error
|
||||
import Table from 'cli-table/lib/index.js';
|
||||
import type { Arguments as ParentArguments } from '../splatnet2.js';
|
||||
import { ArgumentsCamelCase, Argv, initStorage, YargsArguments } from '../../util.js';
|
||||
import { getIksmToken } from './util.js';
|
||||
|
||||
const debug = createDebug('cli:splatnet2:weapons');
|
||||
|
||||
export const command = 'weapons';
|
||||
export const desc = 'Show weapon stats';
|
||||
|
||||
export function builder(yargs: Argv<ParentArguments>) {
|
||||
return yargs.option('user', {
|
||||
describe: 'Nintendo Account ID',
|
||||
type: 'string',
|
||||
}).option('token', {
|
||||
describe: 'Nintendo Account session token',
|
||||
type: 'string',
|
||||
}).option('json', {
|
||||
describe: 'Output raw JSON',
|
||||
type: 'boolean',
|
||||
}).option('json-pretty-print', {
|
||||
describe: 'Output pretty-printed JSON',
|
||||
type: 'boolean',
|
||||
});
|
||||
}
|
||||
|
||||
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.' + usernsid);
|
||||
const {splatnet} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateSession);
|
||||
|
||||
const records = await splatnet.getRecords();
|
||||
|
||||
if (argv.jsonPrettyPrint) {
|
||||
console.log(JSON.stringify(records.records.weapon_stats, null, 4));
|
||||
return;
|
||||
}
|
||||
if (argv.json) {
|
||||
console.log(JSON.stringify(records.records.weapon_stats));
|
||||
return;
|
||||
}
|
||||
|
||||
const table = new Table({
|
||||
head: [
|
||||
'ID',
|
||||
'Name',
|
||||
'Sub',
|
||||
'Special',
|
||||
'Wins',
|
||||
'Losses',
|
||||
'Meter',
|
||||
'H. meter',
|
||||
'Turf inked',
|
||||
'Last used',
|
||||
],
|
||||
});
|
||||
|
||||
for (const weaponstats of Object.values(records.records.weapon_stats)) {
|
||||
table.push([
|
||||
weaponstats.weapon.id,
|
||||
weaponstats.weapon.name,
|
||||
weaponstats.weapon.sub.name,
|
||||
weaponstats.weapon.special.name,
|
||||
weaponstats.win_count,
|
||||
weaponstats.lose_count,
|
||||
weaponstats.win_meter,
|
||||
weaponstats.max_win_meter,
|
||||
weaponstats.total_paint_point + 'p',
|
||||
new Date(weaponstats.last_use_time * 1000).toISOString(),
|
||||
]);
|
||||
}
|
||||
|
||||
console.log('Weapon stats');
|
||||
console.log(table.toString());
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user