mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-04-24 15:07:05 -05:00
Add separate Discord client for Nintendo Switch/Nintendo Switch 2
This commit is contained in:
parent
8a05e4c6ef
commit
7666191600
|
|
@ -209,6 +209,7 @@ function getActivityFromPresence(
|
|||
proxy_response,
|
||||
nsaid: argv.friendNsaid ?? user?.nsaId,
|
||||
user,
|
||||
// platform: presence.platform,
|
||||
};
|
||||
|
||||
const discordpresence = 'name' in presence.game ?
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ class ZncDiscordPresenceClient {
|
|||
monitors: [...this.monitors.values()],
|
||||
nsaid: this.m.presence_user!,
|
||||
user,
|
||||
// platform: presence.platform,
|
||||
};
|
||||
|
||||
const discord_presence = 'name' in presence.game ?
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import persist from 'node-persist';
|
||||
import DiscordRPC from 'discord-rpc';
|
||||
import { BankaraMatchMode, CoopRule, CoopSetting_schedule, DetailVotingStatusResult, FestMatchMode, FestTeam_schedule, FestTeam_votingStatus, Fest_schedule, FriendListResult, FriendOnlineState, GraphQLSuccessResponse, StageScheduleResult, VsMode, VsSchedule_regular } from 'splatnet3-types/splatnet3';
|
||||
import { Game } from '../../api/coral-types.js';
|
||||
import SplatNet3Api, { SplatNet3GraphQLErrorResponse } from '../../api/splatnet3.js';
|
||||
|
|
@ -10,8 +9,8 @@ import { ExternalMonitorPresenceInterface } from '../../common/presence.js';
|
|||
import createDebug from '../../util/debug.js';
|
||||
import { EmbeddedLoop, LoopResult } from '../../util/loop.js';
|
||||
import { ArgumentsCamelCase } from '../../util/yargs.js';
|
||||
import { product } from '../../util/product.js';
|
||||
import { DiscordPresenceContext, ErrorResult } from '../types.js';
|
||||
import { DiscordActivity } from '../util.js';
|
||||
|
||||
const debug = createDebug('nxapi:discord:splatnet3');
|
||||
|
||||
|
|
@ -299,7 +298,7 @@ interface PresenceUrlResponse {
|
|||
splatoon3_fest?: Fest_schedule | null;
|
||||
}
|
||||
|
||||
export function callback(activity: DiscordRPC.Presence, game: Game, context?: DiscordPresenceContext) {
|
||||
export function callback(activity: DiscordActivity, game: Game, context?: DiscordPresenceContext) {
|
||||
const monitor = context?.monitors?.find(m => m instanceof SplatNet3Monitor) as SplatNet3Monitor | undefined;
|
||||
const presence_proxy_data = context?.proxy_response ? context.proxy_response as PresenceUrlResponse : null;
|
||||
|
||||
|
|
@ -351,9 +350,7 @@ export function callback(activity: DiscordRPC.Presence, game: Game, context?: Di
|
|||
null;
|
||||
|
||||
if (proxy_stage_image) {
|
||||
activity.largeImageKey = proxy_stage_image;
|
||||
activity.largeImageText = fest.tricolorStage.name +
|
||||
' | ' + product;
|
||||
activity.setLargeImage(proxy_stage_image, fest.tricolorStage.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -366,15 +363,12 @@ export function callback(activity: DiscordRPC.Presence, game: Game, context?: Di
|
|||
// (friend.vsMode.id === 'VnNNb2RlLTg=')
|
||||
// );
|
||||
|
||||
activity.largeImageKey = 'https://fancy.org.uk/api/nxapi/s3/image?' + new URLSearchParams({
|
||||
activity.setLargeImage('https://fancy.org.uk/api/nxapi/s3/image?' + new URLSearchParams({
|
||||
a: setting.vsStages[0].id,
|
||||
b: setting.vsStages[1].id,
|
||||
// ...(possibly_tricolour ? {t: fest?.tricolorStage.id} : {}),
|
||||
v: '2022092400',
|
||||
}).toString();
|
||||
activity.largeImageText = setting.vsStages.map(s => s.name).join('/') +
|
||||
// (possibly_tricolour ? '/' + fest?.tricolorStage.name : '') +
|
||||
' | ' + product;
|
||||
}).toString(), setting.vsStages.map(s => s.name).join('/'));
|
||||
}
|
||||
|
||||
// REGULAR, BANKARA, X_MATCH, LEAGUE, PRIVATE, FEST
|
||||
|
|
@ -391,8 +385,9 @@ export function callback(activity: DiscordRPC.Presence, game: Game, context?: Di
|
|||
friend.vsMode.mode === 'PRIVATE' ? 'mode-vs-private-1' :
|
||||
undefined;
|
||||
|
||||
activity.smallImageKey = mode_image;
|
||||
activity.smallImageText = mode_name ?? friend.vsMode.name;
|
||||
if (mode_image) {
|
||||
activity.setSmallImage(mode_image, mode_name ?? friend.vsMode.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (friend.onlineState === FriendOnlineState.COOP_MODE_MATCHING ||
|
||||
|
|
@ -415,23 +410,18 @@ export function callback(activity: DiscordRPC.Presence, game: Game, context?: Di
|
|||
null;
|
||||
|
||||
if (proxy_stage_image) {
|
||||
activity.largeImageKey = proxy_stage_image;
|
||||
activity.largeImageText = setting.coopStage.name +
|
||||
' | ' + product;
|
||||
activity.setLargeImage(proxy_stage_image, setting.coopStage.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (friend.coopRule === CoopRule.REGULAR) {
|
||||
activity.smallImageKey = 'mode-coop-regular-1';
|
||||
activity.smallImageText = 'Salmon Run';
|
||||
activity.setSmallImage('mode-coop-regular-1', 'Salmon Run');
|
||||
}
|
||||
if (friend.coopRule === CoopRule.BIG_RUN) {
|
||||
activity.smallImageKey = 'mode-coop-bigrun-1';
|
||||
activity.smallImageText = 'Big Run';
|
||||
activity.setSmallImage('mode-coop-bigrun-1', 'Big Run');
|
||||
}
|
||||
if (friend.coopRule === CoopRule.TEAM_CONTEST) {
|
||||
activity.smallImageKey = 'mode-coop-teamcontest-1';
|
||||
activity.smallImageText = 'Eggstra Work';
|
||||
activity.setSmallImage('mode-coop-teamcontest-1', 'Eggstra Work');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Title } from './types.js';
|
||||
import * as publishers from './titles/index.js';
|
||||
import { PresencePlatform } from '../api/coral-types.js';
|
||||
|
||||
export const defaultTitle: Title = {
|
||||
id: '0000000000000000',
|
||||
|
|
@ -9,6 +10,11 @@ export const defaultTitle: Title = {
|
|||
showActiveEvent: true,
|
||||
};
|
||||
|
||||
export const platform_clients: Record<PresencePlatform, string> = {
|
||||
[PresencePlatform.NINTENDO_SWITCH]: '950883021165330493',
|
||||
// [PresencePlatform.NINTENDO_SWITCH_2]: '1358060657957928970',
|
||||
};
|
||||
|
||||
export const titles: Title[] = [];
|
||||
|
||||
for (const [publisher, m] of Object.entries(publishers)) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import DiscordRPC from 'discord-rpc';
|
||||
import { ActiveEvent, CurrentUser, Friend, Game } from '../api/coral-types.js';
|
||||
import { ActiveEvent, CurrentUser, Friend, Game, PresencePlatform } from '../api/coral-types.js';
|
||||
import { ExternalMonitorPresenceInterface, ZncDiscordPresence, ZncProxyDiscordPresence } from '../common/presence.js';
|
||||
import { EmbeddedLoop } from '../util/loop.js';
|
||||
import { DiscordActivity } from './util.js';
|
||||
|
||||
export interface DiscordPresenceContext {
|
||||
friendcode?: CurrentUser['links']['friendCode'];
|
||||
|
|
@ -12,6 +13,7 @@ export interface DiscordPresenceContext {
|
|||
monitors?: ExternalMonitor[];
|
||||
nsaid?: string;
|
||||
user?: CurrentUser | Friend;
|
||||
platform?: PresencePlatform;
|
||||
}
|
||||
|
||||
export interface DiscordPresence {
|
||||
|
|
@ -104,7 +106,7 @@ export interface Title<M extends ExternalMonitor = ExternalMonitor> {
|
|||
/**
|
||||
* A function to call to customise the Discord activity.
|
||||
*/
|
||||
callback?: (activity: DiscordRPC.Presence, game: Game, context?: DiscordPresenceContext, monitor?: M) => void;
|
||||
callback?: (activity: DiscordActivity, game: Game, context?: DiscordPresenceContext, monitor?: M) => void;
|
||||
}
|
||||
|
||||
export enum DiscordPresencePlayTime {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import DiscordRPC from 'discord-rpc';
|
||||
import { PresenceGame, PresenceState } from '../api/coral-types.js';
|
||||
import { defaultTitle, titles } from './titles.js';
|
||||
import { defaultTitle, platform_clients, titles } from './titles.js';
|
||||
import createDebug from '../util/debug.js';
|
||||
import { product, version } from '../util/product.js';
|
||||
import { getTitleIdFromEcUrl, hrduration } from '../util/misc.js';
|
||||
|
|
@ -42,24 +42,28 @@ export function getDiscordPresence(
|
|||
const nintendo_eshop_redirect_url = titleid ?
|
||||
'https://fancy.org.uk/api/nxapi/title/' + titleid + '/redirect?source=nxapi-' + version + '-discord' : null;
|
||||
|
||||
const activity: DiscordRPC.Presence = {
|
||||
details: text[0],
|
||||
state: text[1],
|
||||
largeImageKey: title.largeImageKey ?? game.imageUri,
|
||||
largeImageText: title.largeImageText ? title.largeImageText + ' | ' + product : product,
|
||||
smallImageKey: title.smallImageKey || (context?.friendcode ? context?.user?.imageUri : undefined),
|
||||
smallImageText: title.smallImageKey ? title.smallImageText :
|
||||
context?.friendcode && context?.user?.imageUri ? 'SW-' + context.friendcode.id : undefined,
|
||||
buttons: game.shopUri ? [
|
||||
{
|
||||
label: 'Nintendo eShop',
|
||||
url: nintendo_eshop_redirect_url ?? game.shopUri,
|
||||
},
|
||||
] : [],
|
||||
};
|
||||
const activity = new DiscordActivity();
|
||||
|
||||
activity.details = text[0];
|
||||
activity.state = text[1];
|
||||
|
||||
activity.setLargeImage(title.largeImageKey ?? game.imageUri, title.largeImageText);
|
||||
|
||||
if (title.smallImageKey) {
|
||||
activity.setSmallImage(title.smallImageKey, title.smallImageText);
|
||||
} else if (context?.friendcode && context.user?.imageUri) {
|
||||
activity.setSmallImage(context.user.imageUri, 'SW-' + context.friendcode.id);
|
||||
}
|
||||
|
||||
if (game.shopUri) {
|
||||
activity.buttons.push({
|
||||
label: 'Nintendo eShop',
|
||||
url: nintendo_eshop_redirect_url ?? game.shopUri,
|
||||
});
|
||||
}
|
||||
|
||||
if (online && title.showActiveEvent) {
|
||||
activity.buttons!.push({
|
||||
activity.buttons.push({
|
||||
label: context?.activeevent?.shareUri ? 'Join' : 'Join via Nintendo Switch',
|
||||
url: context?.activeevent?.shareUri ?? 'https://lounge.nintendo.com',
|
||||
});
|
||||
|
|
@ -72,7 +76,9 @@ export function getDiscordPresence(
|
|||
}
|
||||
|
||||
return {
|
||||
id: title.client || defaultTitle.client,
|
||||
id: title.client ||
|
||||
(typeof context?.platform !== 'undefined' && platform_clients[context.platform]) ||
|
||||
defaultTitle.client,
|
||||
title: titleid,
|
||||
config: title,
|
||||
activity,
|
||||
|
|
@ -80,6 +86,30 @@ export function getDiscordPresence(
|
|||
};
|
||||
}
|
||||
|
||||
export class DiscordActivity implements DiscordRPC.Presence {
|
||||
details?: string = undefined;
|
||||
state?: string = undefined;
|
||||
largeImageKey?: string = undefined;
|
||||
largeImageText?: string = undefined;
|
||||
smallImageKey?: string = undefined;
|
||||
smallImageText?: string = undefined;
|
||||
buttons: { label: string; url: string; }[] = [];
|
||||
|
||||
constructor() {
|
||||
//
|
||||
}
|
||||
|
||||
setLargeImage(key: string, text?: string) {
|
||||
this.largeImageKey = key;
|
||||
this.largeImageText = text ? text + ' | ' + product : product;
|
||||
}
|
||||
|
||||
setSmallImage(key: string, text?: string) {
|
||||
this.smallImageKey = key;
|
||||
this.smallImageText = text;
|
||||
}
|
||||
}
|
||||
|
||||
function getPlayTimeText(type: DiscordPresencePlayTime, game: PresenceGame) {
|
||||
if (type === DiscordPresencePlayTime.NINTENDO) {
|
||||
const days = Math.floor(Date.now() / 1000 / 86400) - Math.floor(game.firstPlayedAt / 86400);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user