mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-04-25 15:43:51 -05:00
Show if playing online even for games that don't set a description
This commit is contained in:
parent
4736fe55d4
commit
0839ff520b
|
|
@ -5,7 +5,8 @@ import fetch from 'node-fetch';
|
||||||
import { CurrentUser, Friend, Presence, PresenceState } from '../../api/znc-types.js';
|
import { CurrentUser, Friend, Presence, PresenceState } from '../../api/znc-types.js';
|
||||||
import ZncApi from '../../api/znc.js';
|
import ZncApi from '../../api/znc.js';
|
||||||
import type { Arguments as ParentArguments } from '../nso.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 { ZncNotifications } from './notify.js';
|
||||||
import ZncProxyApi from '../../api/znc-proxy.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 fc = this.argv.friendCode === '' || this.argv.friendCode === '-' ? friendcode : this.forceFriendCode;
|
||||||
const discordpresence = 'name' in presence.game ?
|
const discordpresence = 'name' in presence.game ?
|
||||||
getDiscordPresence(presence.game, fc) :
|
getDiscordPresence(presence.state, presence.game, fc) :
|
||||||
getInactiveDiscordPresence(fc);
|
getInactiveDiscordPresence(presence.state, presence.logoutAt, fc);
|
||||||
|
|
||||||
if (this.rpc && this.rpc.id !== discordpresence.id) {
|
if (this.rpc && this.rpc.id !== discordpresence.id) {
|
||||||
const client = this.rpc.client;
|
const client = this.rpc.client;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ export const defaultTitle: Title = {
|
||||||
id: '0000000000000000',
|
id: '0000000000000000',
|
||||||
client: '950883021165330493',
|
client: '950883021165330493',
|
||||||
titleName: true,
|
titleName: true,
|
||||||
|
showPlayingOnline: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const titles: Title[] = [
|
const titles: Title[] = [
|
||||||
|
|
@ -12,18 +13,21 @@ const titles: Title[] = [
|
||||||
id: '0100f8f0000a2000',
|
id: '0100f8f0000a2000',
|
||||||
client: '950886725398429726',
|
client: '950886725398429726',
|
||||||
largeImageKey: '0100f8f0000a2000',
|
largeImageKey: '0100f8f0000a2000',
|
||||||
|
showPlayingOnline: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Splatoon 2 [The Americas]
|
// Splatoon 2 [The Americas]
|
||||||
id: '01003bc0000a0000',
|
id: '01003bc0000a0000',
|
||||||
client: '950886725398429726',
|
client: '950886725398429726',
|
||||||
largeImageKey: '0100f8f0000a2000',
|
largeImageKey: '0100f8f0000a2000',
|
||||||
|
showPlayingOnline: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Splatoon 2 [Japan]
|
// Splatoon 2 [Japan]
|
||||||
id: '01003c700009c000',
|
id: '01003c700009c000',
|
||||||
client: '950886725398429726',
|
client: '950886725398429726',
|
||||||
largeImageKey: '01003c700009c000',
|
largeImageKey: '01003c700009c000',
|
||||||
|
showPlayingOnline: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
93
src/discord/util.ts
Normal file
93
src/discord/util.ts
Normal 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;
|
||||||
|
}
|
||||||
79
src/util.ts
79
src/util.ts
|
|
@ -2,14 +2,12 @@ import * as path from 'path';
|
||||||
import * as yargs from 'yargs';
|
import * as yargs from 'yargs';
|
||||||
import type * as yargstypes from '../node_modules/@types/yargs/index.js';
|
import type * as yargstypes from '../node_modules/@types/yargs/index.js';
|
||||||
import createDebug from 'debug';
|
import createDebug from 'debug';
|
||||||
import DiscordRPC from 'discord-rpc';
|
|
||||||
import persist from 'node-persist';
|
import persist from 'node-persist';
|
||||||
import getPaths from 'env-paths';
|
import getPaths from 'env-paths';
|
||||||
import { FlapgApiResponse } from './api/f.js';
|
import { FlapgApiResponse } from './api/f.js';
|
||||||
import { NintendoAccountToken, NintendoAccountUser } from './api/na.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 ZncApi from './api/znc.js';
|
||||||
import titles, { defaultTitle } from './titles.js';
|
|
||||||
import ZncProxyApi from './api/znc-proxy.js';
|
import ZncProxyApi from './api/znc-proxy.js';
|
||||||
import MoonApi from './api/moon.js';
|
import MoonApi from './api/moon.js';
|
||||||
|
|
||||||
|
|
@ -50,6 +48,14 @@ export async function initStorage(dir: string) {
|
||||||
return storage;
|
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) {
|
export async function getToken(storage: persist.LocalStorage, token: string, proxy_url?: string) {
|
||||||
if (!token) {
|
if (!token) {
|
||||||
console.error('No token set. Set a Nintendo Account session token using the `--token` option or by running `nxapi nso 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;
|
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) {
|
export function hrduration(duration: number, short = false) {
|
||||||
const hours = Math.floor(duration / 60);
|
const hours = Math.floor(duration / 60);
|
||||||
const minutes = duration - (hours * 60);
|
const minutes = duration - (hours * 60);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user