From 39bfc8ab393d6f822d1f45288a43e737b22b9237 Mon Sep 17 00:00:00 2001 From: Samuel Elliott Date: Sun, 26 Jun 2022 16:14:02 +0100 Subject: [PATCH] Add a command to get a SplatNet 2 iksm_session cookie --- src/api/splatnet2.ts | 9 +++++-- src/app/main/menu.ts | 2 +- src/cli/splatnet2/index.ts | 1 + src/cli/splatnet2/token.ts | 51 ++++++++++++++++++++++++++++++++++++ src/cli/splatnet2/user.ts | 2 -- src/common/auth/splatnet2.ts | 7 +++++ 6 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 src/cli/splatnet2/token.ts diff --git a/src/api/splatnet2.ts b/src/api/splatnet2.ts index b287bfc..eeb6a0b 100644 --- a/src/api/splatnet2.ts +++ b/src/api/splatnet2.ts @@ -268,7 +268,7 @@ ${colour} const expires = decodeURIComponent(match[8] || '') .replace(/(\b)(\d{1,2})-([a-z]{3})-(\d{4})(\b)/gi, '$1$2 $3 $4$5'); - debug('iksm_session %s, expires %s', iksm_session, expires); + debug('iksm_session %s, expires %s', iksm_session.replace(/^(.{6}).*/, '$1****'), expires); const expires_at = expires ? Date.parse(expires) : Date.now() + 24 * 60 * 60 * 1000; @@ -278,7 +278,12 @@ ${colour} const mn = body.match(/]*))?)*\s+data-nsa-id=(?:"([^"]*)"|([^\s>]*))/i); const [language, region, user_id, nsa_id] = [ml, mr, mu, mn].map(m => m?.[1] || m?.[2] || null); - debug('SplatNet 2 user', {language, region, user_id, nsa_id}); + debug('SplatNet 2 user', { + language, + region, + user_id: user_id?.replace(/^(.{6}).*/, '$1****'), + nsa_id: nsa_id?.replace(/^(.{6}).*/, '$1****'), + }); return { webserviceToken, diff --git a/src/app/main/menu.ts b/src/app/main/menu.ts index 6831a20..b2acfef 100644 --- a/src/app/main/menu.ts +++ b/src/app/main/menu.ts @@ -59,7 +59,7 @@ export default class MenuApp { checked: monitor?.user_notifications, enabled: !!monitor?.user_notifications, click: () => this.setUserNotificationsActive(data.user.id, !monitor?.user_notifications)}, - {label: 'Enable notifications for this friends of this user\'s presence', type: 'checkbox', + {label: 'Enable notifications for friends of this user\'s presence', type: 'checkbox', checked: monitor?.friend_notifications, click: () => this.setFriendNotificationsActive(data.user.id, !monitor?.friend_notifications)}, {label: 'Update now', enabled: !!monitor, click: () => monitor?.skipIntervalInCurrentLoop(true)}, diff --git a/src/cli/splatnet2/index.ts b/src/cli/splatnet2/index.ts index b87bca9..185b0dd 100644 --- a/src/cli/splatnet2/index.ts +++ b/src/cli/splatnet2/index.ts @@ -1,4 +1,5 @@ export * as user from './user.js'; +export * as token from './token.js'; export * as stages from './stages.js'; export * as challenges from './challenges.js'; export * as weapons from './weapons.js'; diff --git a/src/cli/splatnet2/token.ts b/src/cli/splatnet2/token.ts new file mode 100644 index 0000000..c073fc7 --- /dev/null +++ b/src/cli/splatnet2/token.ts @@ -0,0 +1,51 @@ +import createDebug from 'debug'; +import type { Arguments as ParentArguments } from '../splatnet2.js'; +import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js'; +import { initStorage } from '../../util/storage.js'; +import { getIksmToken } from '../../common/auth/splatnet2.js'; + +const debug = createDebug('cli:splatnet2:token'); + +export const command = 'token'; +export const desc = 'Get the authenticated Nintendo Account\'s SplatNet 2 user data and iksm_session cookie'; + +export function builder(yargs: Argv) { + 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>; + +export async function handler(argv: ArgumentsCamelCase) { + 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, data} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.autoUpdateSession); + + if (argv.json || argv.jsonPrettyPrint) { + const result = { + iksm_session: data.iksm_session, + language: data.language, + region: data.region, + user_id: data.user_id, + nsa_id: data.nsa_id, + }; + + console.log(JSON.stringify(result, null, argv.jsonPrettyPrint ? 4 : 0)); + return; + } + + console.log(data.iksm_session); +} diff --git a/src/cli/splatnet2/user.ts b/src/cli/splatnet2/user.ts index d413195..640f6f9 100644 --- a/src/cli/splatnet2/user.ts +++ b/src/cli/splatnet2/user.ts @@ -43,6 +43,4 @@ export async function handler(argv: ArgumentsCamelCase) { records.records.player.principal_id, records.records.player.player_rank, records.records.player.player_type); - - console.log(data.iksm_session); } diff --git a/src/common/auth/splatnet2.ts b/src/common/auth/splatnet2.ts index 6fa4f08..26d4f17 100644 --- a/src/common/auth/splatnet2.ts +++ b/src/common/auth/splatnet2.ts @@ -13,6 +13,13 @@ export interface SavedIksmSessionToken { url: string; cookies: string; + body: string; + language: string | null; + region: string | null; + /** Splatoon 2 player ID aka. unique_id */ + user_id: string | null; + nsa_id: string | null; + iksm_session: string; expires_at: number; useragent: string;