mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-03-22 02:14:10 -05:00
210 lines
8.2 KiB
TypeScript
210 lines
8.2 KiB
TypeScript
import * as path from 'path';
|
|
import createDebug from 'debug';
|
|
import persist from 'node-persist';
|
|
import notifier from 'node-notifier';
|
|
import type { Arguments as ParentArguments } from '../nso.js';
|
|
import { ArgumentsCamelCase, Argv, initStorage, YargsArguments } from '../../util.js';
|
|
import { getToken } from '../../common/auth/nso.js';
|
|
import { getIksmToken } from '../../common/auth/splatnet2.js';
|
|
import { EmbeddedSplatNet2Monitor, NotificationManager, ZncNotifications } from '../../common/notify.js';
|
|
import { CurrentUser, Friend, Game } from '../../api/znc-types.js';
|
|
|
|
const debug = createDebug('cli:nso:notify');
|
|
|
|
export const command = 'notify';
|
|
export const desc = 'Show notifications when friends come online without starting Discord Rich Presence';
|
|
|
|
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('user-notifications', {
|
|
describe: 'Show notification for your own user',
|
|
type: 'boolean',
|
|
default: false,
|
|
}).option('friend-notifications', {
|
|
describe: 'Show notification for friends',
|
|
type: 'boolean',
|
|
default: true,
|
|
}).option('update-interval', {
|
|
describe: 'Update interval in seconds',
|
|
type: 'number',
|
|
default: 30,
|
|
}).option('splatnet2-monitor', {
|
|
describe: 'Download new SplatNet 2 data when you are playing Splatoon 2 online',
|
|
type: 'boolean',
|
|
default: false,
|
|
}).option('splatnet2-monitor-directory', {
|
|
alias: ['sn2-path'],
|
|
describe: 'Directory to write SplatNet 2 record data to',
|
|
type: 'string',
|
|
}).option('splatnet2-monitor-profile-image', {
|
|
alias: ['sn2-profile-image'],
|
|
describe: 'Include profile image',
|
|
type: 'boolean',
|
|
default: false,
|
|
}).option('splatnet2-monitor-favourite-stage', {
|
|
alias: ['sn2-favourite-stage'],
|
|
describe: 'Favourite stage to include on profile image',
|
|
type: 'string',
|
|
}).option('splatnet2-monitor-favourite-colour', {
|
|
alias: ['sn2-favourite-colour'],
|
|
describe: 'Favourite colour to include on profile image',
|
|
type: 'string',
|
|
}).option('splatnet2-monitor-battles', {
|
|
alias: ['sn2-battles'],
|
|
describe: 'Include regular/ranked/private/festival battle results',
|
|
type: 'boolean',
|
|
default: true,
|
|
}).option('splatnet2-monitor-battle-summary-image', {
|
|
alias: ['sn2-battle-summary-image'],
|
|
describe: 'Include regular/ranked/private/festival battle summary image',
|
|
type: 'boolean',
|
|
default: false,
|
|
}).option('splatnet2-monitor-battle-images', {
|
|
alias: ['sn2-battle-images'],
|
|
describe: 'Include regular/ranked/private/festival battle result images',
|
|
type: 'boolean',
|
|
default: false,
|
|
}).option('splatnet2-monitor-coop', {
|
|
alias: ['sn2-coop'],
|
|
describe: 'Include coop (Salmon Run) results',
|
|
type: 'boolean',
|
|
default: true,
|
|
}).option('splatnet2-monitor-update-interval', {
|
|
alias: ['sn2-update-interval'],
|
|
describe: 'Update interval in seconds',
|
|
type: 'number',
|
|
// 3 minutes - the monitor is only active while the authenticated user is playing Splatoon 2 online
|
|
default: 3 * 60,
|
|
}).option('splatnet2-auto-update-session', {
|
|
alias: ['sn2-auto-update-session'],
|
|
describe: 'Automatically obtain and refresh the iksm_session cookie',
|
|
type: 'boolean',
|
|
default: true,
|
|
});
|
|
}
|
|
|
|
type Arguments = YargsArguments<ReturnType<typeof builder>>;
|
|
|
|
export async function handler(argv: ArgumentsCamelCase<Arguments>) {
|
|
if (!argv.userNotifications && !argv.friendNotifications && !argv.splatnet2Monitor) {
|
|
throw new Error('Must enable either user notifications, friend notifications, or SplatNet 2 monitoring');
|
|
}
|
|
|
|
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 {nso, data} = await getToken(storage, token, argv.zncProxyUrl);
|
|
|
|
const i = new ZncNotifications(storage, token, nso, data);
|
|
|
|
i.user_notifications = argv.userNotifications;
|
|
i.friend_notifications = argv.friendNotifications;
|
|
i.update_interval = argv.updateInterval;
|
|
|
|
console.warn('Authenticated as Nintendo Account %s (NA %s, NSO %s)',
|
|
data.user.screenName, data.user.nickname, data.nsoAccount.user.name);
|
|
|
|
if (argv.splatnet2Monitor) {
|
|
console.warn('SplatNet 2 monitoring enabled for %s (NA %s, NSO %s) - SplatNet 2 records will be ' +
|
|
'downloaded when this user is playing Splatoon 2 online.',
|
|
data.user.screenName, data.user.nickname, data.nsoAccount.user.name);
|
|
i.splatnet2_monitors.set(data.nsoAccount.user.nsaId, handleEnableSplatNet2Monitoring(argv, storage, token));
|
|
}
|
|
|
|
await i.loop(true);
|
|
|
|
while (true) {
|
|
await i.loop();
|
|
}
|
|
}
|
|
|
|
export class TerminalNotificationManager extends NotificationManager {
|
|
onFriendOnline(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
|
|
const currenttitle = friend.presence.game as Game;
|
|
|
|
notifier.notify({
|
|
title: friend.name,
|
|
message: 'Playing ' + currenttitle.name +
|
|
(currenttitle.sysDescription ? '\n' + currenttitle.sysDescription : ''),
|
|
// icon: currenttitle.imageUri,
|
|
icon: friend.imageUri,
|
|
});
|
|
}
|
|
|
|
onFriendOffline(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
|
|
notifier.notify({
|
|
title: friend.name,
|
|
message: 'Offline',
|
|
icon: friend.imageUri,
|
|
});
|
|
}
|
|
|
|
onFriendPlayingChangeTitle(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
|
|
const currenttitle = friend.presence.game as Game;
|
|
|
|
notifier.notify({
|
|
title: friend.name,
|
|
message: 'Playing ' + currenttitle.name +
|
|
(currenttitle.sysDescription ? '\n' + currenttitle.sysDescription : ''),
|
|
// icon: currenttitle.imageUri,
|
|
icon: friend.imageUri,
|
|
});
|
|
}
|
|
|
|
onFriendTitleStateChange(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
|
|
const currenttitle = friend.presence.game as Game;
|
|
|
|
notifier.notify({
|
|
title: friend.name,
|
|
message: 'Playing ' + currenttitle.name +
|
|
(currenttitle.sysDescription ? '\n' + currenttitle.sysDescription : ''),
|
|
// icon: currenttitle.imageUri,
|
|
icon: friend.imageUri,
|
|
});
|
|
}
|
|
}
|
|
|
|
export function handleEnableSplatNet2Monitoring(
|
|
argv: ArgumentsCamelCase<Arguments>, storage: persist.LocalStorage, token: string
|
|
) {
|
|
return async () => {
|
|
const directory = argv.splatnet2MonitorDirectory ?? path.join(argv.dataPath, 'splatnet2');
|
|
|
|
const {splatnet, data} = await getIksmToken(storage, token, argv.zncProxyUrl, argv.splatnet2AutoUpdateSession);
|
|
|
|
const records = await splatnet.getRecords();
|
|
const stages = await splatnet.getStages();
|
|
|
|
const i = new EmbeddedSplatNet2Monitor(storage, token, splatnet, stages, directory, argv.zncProxyUrl);
|
|
|
|
i.update_interval = argv.splatnet2MonitorUpdateInterval;
|
|
|
|
i.profile_image = argv.splatnet2MonitorProfileImage;
|
|
i.favourite_stage = argv.splatnet2MonitorFavouriteStage;
|
|
i.favourite_colour = argv.splatnet2MonitorFavouriteColour;
|
|
|
|
i.results = argv.splatnet2MonitorBattles;
|
|
i.results_summary_image = argv.splatnet2MonitorBattleSummaryImage;
|
|
i.result_images = argv.splatnet2MonitorBattleImages;
|
|
i.coop_results = argv.splatnet2MonitorCoop;
|
|
|
|
i.cached_records = records;
|
|
|
|
console.log('Player %s (Splatoon 2 ID %s, NSA ID %s) level %d',
|
|
records.records.player.nickname,
|
|
records.records.unique_id,
|
|
records.records.player.principal_id,
|
|
records.records.player.player_rank,
|
|
records.records.player.player_type);
|
|
|
|
return i;
|
|
};
|
|
}
|