Show if playing online even for games that don't set a description

This commit is contained in:
Samuel Elliott 2022-03-22 20:07:21 +00:00
parent 4736fe55d4
commit 0839ff520b
No known key found for this signature in database
GPG Key ID: 8420C7CDE43DC4D6
4 changed files with 110 additions and 73 deletions

View File

@ -5,7 +5,8 @@ import fetch from 'node-fetch';
import { CurrentUser, Friend, Presence, PresenceState } from '../../api/znc-types.js';
import ZncApi from '../../api/znc.js';
import type { Arguments as ParentArguments } from '../nso.js';
import { ArgumentsCamelCase, Argv, getDiscordPresence, getInactiveDiscordPresence, getToken, initStorage, SavedToken, YargsArguments } from '../../util.js';
import { ArgumentsCamelCase, Argv, getToken, initStorage, SavedToken, YargsArguments } from '../../util.js';
import { getDiscordPresence, getInactiveDiscordPresence } from '../../discord/util.js';
import { ZncNotifications } from './notify.js';
import ZncProxyApi from '../../api/znc-proxy.js';
@ -188,8 +189,8 @@ class ZncDiscordPresence extends ZncNotifications {
const fc = this.argv.friendCode === '' || this.argv.friendCode === '-' ? friendcode : this.forceFriendCode;
const discordpresence = 'name' in presence.game ?
getDiscordPresence(presence.game, fc) :
getInactiveDiscordPresence(fc);
getDiscordPresence(presence.state, presence.game, fc) :
getInactiveDiscordPresence(presence.state, presence.logoutAt, fc);
if (this.rpc && this.rpc.id !== discordpresence.id) {
const client = this.rpc.client;

View File

@ -4,6 +4,7 @@ export const defaultTitle: Title = {
id: '0000000000000000',
client: '950883021165330493',
titleName: true,
showPlayingOnline: true,
};
const titles: Title[] = [
@ -12,18 +13,21 @@ const titles: Title[] = [
id: '0100f8f0000a2000',
client: '950886725398429726',
largeImageKey: '0100f8f0000a2000',
showPlayingOnline: true,
},
{
// Splatoon 2 [The Americas]
id: '01003bc0000a0000',
client: '950886725398429726',
largeImageKey: '0100f8f0000a2000',
showPlayingOnline: true,
},
{
// Splatoon 2 [Japan]
id: '01003c700009c000',
client: '950886725398429726',
largeImageKey: '01003c700009c000',
showPlayingOnline: true,
},
{

93
src/discord/util.ts Normal file
View File

@ -0,0 +1,93 @@
import DiscordRPC from 'discord-rpc';
import { CurrentUser, Game, PresenceState } from '../api/znc-types.js';
import titles, { defaultTitle } from './titles.js';
import { getTitleIdFromEcUrl, hrduration } from '../util.js';
export function getDiscordPresence(
state: PresenceState, game: Game,
friendcode?: CurrentUser['links']['friendCode']
): DiscordPresence {
const titleid = getTitleIdFromEcUrl(game.shopUri);
const title = titles.find(t => t.id === titleid) || defaultTitle;
const text = [];
if (title.titleName === true) text.push(game.name);
else if (title.titleName) text.push(title.titleName);
if (game.sysDescription) text.push(game.sysDescription);
else if (state === PresenceState.PLAYING && title.showPlayingOnline === true) text.push('Playing online');
else if (state === PresenceState.PLAYING && title.showPlayingOnline) text.push(title.showPlayingOnline as string);
if (game.totalPlayTime >= 60) {
text.push('Played for ' + hrduration(game.totalPlayTime) +
' since ' + (game.firstPlayedAt ? new Date(game.firstPlayedAt * 1000).toLocaleDateString('en-GB') : 'now'));
}
const activity: DiscordRPC.Presence = {
details: text[0],
state: text[1],
largeImageKey: title.largeImageKey ?? game.imageUri,
largeImageText: friendcode ? 'SW-' + friendcode.id : undefined,
smallImageKey: title.smallImageKey,
buttons: game.shopUri ? [
{
label: 'Nintendo eShop',
url: game.shopUri,
},
] : [],
};
title.callback?.call(null, activity, game);
return {
id: title.client || defaultTitle.client,
title: titleid,
activity,
showTimestamp: title.showTimestamp,
};
}
export function getInactiveDiscordPresence(
state: PresenceState, logoutAt: number,
friendcode?: CurrentUser['links']['friendCode']
): DiscordPresence {
return {
id: defaultTitle.client,
title: null,
activity: {
state: 'Not playing',
largeImageKey: 'nintendoswitch',
largeImageText: friendcode ? 'SW-' + friendcode.id : undefined,
},
};
}
export interface DiscordPresence {
id: string;
title: string | null;
activity: DiscordRPC.Presence;
showTimestamp?: boolean;
}
export function getTitleConfiguration(game: Game, id: string) {
return titles.find(title => {
if (title.id !== id) return false;
return true;
});
}
export interface Title {
/** Lowercase hexadecimal title ID */
id: string;
/** Discord client ID */
client: string;
titleName?: string | boolean;
largeImageKey?: string;
smallImageKey?: string;
showTimestamp?: boolean;
/** Show "Playing online" if playing online and the game doesn't set activity details */
showPlayingOnline?: string | boolean;
}

View File

@ -2,14 +2,12 @@ import * as path from 'path';
import * as yargs from 'yargs';
import type * as yargstypes from '../node_modules/@types/yargs/index.js';
import createDebug from 'debug';
import DiscordRPC from 'discord-rpc';
import persist from 'node-persist';
import getPaths from 'env-paths';
import { FlapgApiResponse } from './api/f.js';
import { NintendoAccountToken, NintendoAccountUser } from './api/na.js';
import { AccountLogin, CurrentUser, Game } from './api/znc-types.js';
import { AccountLogin } from './api/znc-types.js';
import ZncApi from './api/znc.js';
import titles, { defaultTitle } from './titles.js';
import ZncProxyApi from './api/znc-proxy.js';
import MoonApi from './api/moon.js';
@ -50,6 +48,14 @@ export async function initStorage(dir: string) {
return storage;
}
export async function getToken(storage: persist.LocalStorage, token: string, proxy_url: string): Promise<{
nso: ZncProxyApi;
data: SavedToken;
}>
export async function getToken(storage: persist.LocalStorage, token: string, proxy_url?: string): Promise<{
nso: ZncApi;
data: SavedToken;
}>
export async function getToken(storage: persist.LocalStorage, token: string, proxy_url?: string) {
if (!token) {
console.error('No token set. Set a Nintendo Account session token using the `--token` option or by running `nxapi nso token`.');
@ -127,73 +133,6 @@ export function getTitleIdFromEcUrl(url: string) {
return match?.[1] ?? null;
}
export function getDiscordPresence(game: Game, friendcode?: CurrentUser['links']['friendCode']): DiscordPresence {
const titleid = getTitleIdFromEcUrl(game.shopUri);
const title = titles.find(t => t.id === titleid) || defaultTitle;
const text = [];
if (title.titleName === true) text.push(game.name);
else if (title.titleName) text.push(title.titleName);
if (game.sysDescription) text.push(game.sysDescription);
if (game.totalPlayTime >= 60) {
text.push('Played for ' + hrduration(game.totalPlayTime) +
' since ' + (game.firstPlayedAt ? new Date(game.firstPlayedAt * 1000).toLocaleDateString('en-GB') : 'now'));
}
return {
id: title.client || defaultTitle.client,
title: titleid,
activity: {
details: text[0],
state: text[1],
largeImageKey: title.largeImageKey ?? game.imageUri,
largeImageText: friendcode ? 'SW-' + friendcode.id : undefined,
smallImageKey: title.smallImageKey,
buttons: game.shopUri ? [
{
label: 'Nintendo eShop',
url: game.shopUri,
},
] : [],
},
showTimestamp: title.showTimestamp,
};
}
export function getInactiveDiscordPresence(friendcode?: CurrentUser['links']['friendCode']): DiscordPresence {
return {
id: defaultTitle.client,
title: null,
activity: {
state: 'Not playing',
largeImageKey: 'nintendoswitch',
largeImageText: friendcode ? 'SW-' + friendcode.id : undefined,
},
};
}
export interface DiscordPresence {
id: string;
title: string | null;
activity: DiscordRPC.Presence;
showTimestamp?: boolean;
}
export interface Title {
/** Lowercase hexadecimal title ID */
id: string;
/** Discord client ID */
client: string;
titleName?: string | true;
largeImageKey?: string;
smallImageKey?: string;
showTimestamp?: boolean;
}
export function hrduration(duration: number, short = false) {
const hours = Math.floor(duration / 60);
const minutes = duration - (hours * 60);