Add an option to show event data

This commit is contained in:
Samuel Elliott 2022-04-08 19:57:45 +01:00
parent a53eccd91e
commit 77a32e1b5e
No known key found for this signature in database
GPG Key ID: 8420C7CDE43DC4D6
7 changed files with 80 additions and 32 deletions

View File

@ -113,9 +113,9 @@ export interface WebServiceAttribute {
}
/** /v1/Event/GetActiveEvent */
export type ActiveEvent = _ActiveEvent | {};
export type GetActiveEventResult = ActiveEvent | {};
export interface _ActiveEvent extends Event {
export interface ActiveEvent extends Event {
activateId: string;
}

View File

@ -2,7 +2,7 @@ import fetch from 'node-fetch';
import { v4 as uuidgen } from 'uuid';
import createDebug from 'debug';
import { flapg, FlapgIid, genfc } from './f.js';
import { AccountLogin, ActiveEvent, Announcements, CurrentUser, CurrentUserPermissions, Event, Friends, PresencePermissions, User, WebServices, WebServiceToken, ZncResponse, ZncStatus } from './znc-types.js';
import { AccountLogin, Announcements, CurrentUser, CurrentUserPermissions, Event, Friends, GetActiveEventResult, PresencePermissions, User, WebServices, WebServiceToken, ZncResponse, ZncStatus } from './znc-types.js';
import { getNintendoAccountToken, getNintendoAccountUser, NintendoAccountUser } from './na.js';
import { ErrorResponse, JwtPayload } from './util.js';
@ -84,7 +84,7 @@ export default class ZncApi {
}
async getActiveEvent() {
return this.fetch<ActiveEvent>('/v1/Event/GetActiveEvent', 'POST', '{"parameter":{}}');
return this.fetch<GetActiveEventResult>('/v1/Event/GetActiveEvent', 'POST', '{"parameter":{}}');
}
async getEvent(id: number) {

View File

@ -4,7 +4,7 @@ import bodyParser from 'body-parser';
import * as net from 'net';
import persist from 'node-persist';
import { v4 as uuidgen } from 'uuid';
import { ActiveEvent, Announcement, CurrentUser, Friend, Presence, WebService } from '../../api/znc-types.js';
import { ActiveEvent, Announcement, CurrentUser, Friend, GetActiveEventResult, Presence, WebService } from '../../api/znc-types.js';
import ZncApi from '../../api/znc.js';
import type { Arguments as ParentArguments } from '../nso.js';
import { ArgumentsCamelCase, Argv, getToken, initStorage, SavedToken, YargsArguments } from '../../util.js';
@ -268,7 +268,7 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
//
const cached_friendsdata = new Map<string, [Friend[], number]>();
const cached_appdata = new Map<string, [WebService[], ActiveEvent, number]>();
const cached_appdata = new Map<string, [WebService[], GetActiveEventResult, number]>();
const getFriendsData: express.RequestHandler = async (req, res, next) => {
const cache = cached_friendsdata.get(req.zncAuth!.user.id);

View File

@ -198,7 +198,8 @@ export class ZncNotifications extends Loop {
result.webservices = (await this.nso.getWebServices()).result;
}
if (req.includes('event')) {
result.activeevent = (await this.nso.getActiveEvent()).result;
const activeevent = (await this.nso.getActiveEvent()).result;
result.activeevent = 'id' in activeevent ? activeevent : undefined;
}
if (req.includes('user')) {
result.user = (await this.nso.getCurrentUser()).result;

View File

@ -3,7 +3,7 @@ import createDebug from 'debug';
import persist from 'node-persist';
import DiscordRPC from 'discord-rpc';
import fetch from 'node-fetch';
import { CurrentUser, Presence, PresenceState, ZncErrorResponse } from '../../api/znc-types.js';
import { ActiveEvent, CurrentUser, Presence, PresenceState, ZncErrorResponse } from '../../api/znc-types.js';
import ZncApi from '../../api/znc.js';
import type { Arguments as ParentArguments } from '../nso.js';
import { ArgumentsCamelCase, Argv, getToken, initStorage, LoopResult, SavedToken, YargsArguments } from '../../util.js';
@ -29,6 +29,10 @@ export function builder(yargs: Argv<ParentArguments>) {
describe: 'Show Discord presence if your console is online but you are not playing (only enable if you are the only user on all consoles your account exists on)',
type: 'boolean',
default: false,
}).option('show-event', {
describe: 'Show event (Online Lounge/voice chat) details - this shows the number of players in game (experimental)',
type: 'boolean',
default: false,
}).option('friend-nsaid', {
alias: ['friend-naid'],
describe: 'Friend\'s Nintendo Switch account ID',
@ -110,6 +114,7 @@ type Arguments = YargsArguments<ReturnType<typeof builder>>;
export async function handler(argv: ArgumentsCamelCase<Arguments>) {
if (argv.presenceUrl) {
if (argv.showEvent) throw new Error('--presence-url not compatible with --show-event');
if (argv.friendNsaid) throw new Error('--presence-url not compatible with --friend-nsaid');
if (argv.userNotifications) throw new Error('--presence-url not compatible with --user-notifications');
if (argv.friendNotifications) throw new Error('--presence-url not compatible with --user-notifications');
@ -148,6 +153,8 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
return;
}
if (argv.showEvent && argv.friendNsaid) throw new Error('--show-event not compatible with --friend-nsaid');
const storage = await initStorage(argv.dataPath);
const usernsid = argv.user ?? await storage.getItem('SelectedUser');
@ -180,11 +187,12 @@ export class ZncDiscordPresence extends ZncNotifications {
show_friend_code = false;
force_friend_code: CurrentUser['links']['friendCode'] | undefined = undefined;
show_console_online = false;
show_active_event = true;
constructor(
argv: Pick<ArgumentsCamelCase<Arguments>,
'userNotifications' | 'friendNotifications' | 'updateInterval' |
'friendCode' | 'showInactivePresence' | 'friendNsaid'
'friendCode' | 'showInactivePresence' | 'showEvent' | 'friendNsaid'
>,
storage: persist.LocalStorage,
token: string,
@ -199,31 +207,35 @@ export class ZncDiscordPresence extends ZncNotifications {
{id: match[2] + '-' + match[3] + '-' + match[4], regenerable: false, regenerableAt: 0} : undefined;
this.show_friend_code = !!this.force_friend_code || argv.friendCode === '' || argv.friendCode === '-';
this.show_console_online = argv.showInactivePresence;
this.show_active_event = argv.showEvent;
this.presence_user = argv.friendNsaid ?? data.nsoAccount.user.nsaId;
}
async init() {
const {friends, user} = await this.fetch([
const {friends, user, activeevent} = await this.fetch([
'announcements',
this.presence_user ?
this.presence_user === this.data.nsoAccount.user.nsaId ? 'user' :
{friend: this.presence_user, presence: true} : null,
this.presence_user && this.show_active_event ? 'event' : null,
this.user_notifications ? 'user' : null,
this.friend_notifications ? 'friends' : null,
this.splatnet2_monitors.size ? 'user' : null,
]);
if (this.presence_user && this.presence_user !== this.data.nsoAccount.user.nsaId) {
const friend = friends!.find(f => f.nsaId === this.presence_user);
if (this.presence_user) {
if (this.presence_user !== this.data.nsoAccount.user.nsaId) {
const friend = friends!.find(f => f.nsaId === this.presence_user);
if (!friend) {
throw new Error('User "' + this.presence_user + '" is not friends with this user');
if (!friend) {
throw new Error('User "' + this.presence_user + '" is not friends with this user');
}
await this.updatePresenceForDiscord(friend.presence);
} else {
await this.updatePresenceForDiscord(user!.presence, user!.links.friendCode, activeevent);
}
await this.updatePresenceForDiscord(friend.presence);
} else {
await this.updatePresenceForDiscord(user!.presence, user!.links.friendCode);
}
await this.updatePresenceForNotifications(user, friends);
@ -238,10 +250,15 @@ export class ZncDiscordPresence extends ZncNotifications {
last_presence: Presence | null = null;
friendcode: CurrentUser['links']['friendCode'] | undefined = undefined;
last_event: ActiveEvent | undefined = undefined;
async updatePresenceForDiscord(presence: Presence | null, friendcode?: CurrentUser['links']['friendCode']) {
async updatePresenceForDiscord(
presence: Presence | null, friendcode?: CurrentUser['links']['friendCode'],
activeevent?: ActiveEvent
) {
this.last_presence = presence;
this.friendcode = friendcode;
this.last_event = activeevent;
const online = presence?.state === PresenceState.ONLINE || presence?.state === PresenceState.PLAYING;
@ -262,6 +279,7 @@ export class ZncDiscordPresence extends ZncNotifications {
const presencecontext: DiscordPresenceContext = {
friendcode: this.show_friend_code ? this.force_friend_code ?? friendcode : undefined,
activeevent,
znc_discord_presence: this,
nsaid: this.presence_user!,
};
@ -346,26 +364,29 @@ export class ZncDiscordPresence extends ZncNotifications {
}
async update() {
const {friends, user} = await this.fetch([
const {friends, user, activeevent} = await this.fetch([
this.presence_user ?
this.presence_user === this.data.nsoAccount.user.nsaId ? 'user' :
{friend: this.presence_user, presence: true} : null,
this.presence_user && this.show_active_event ? 'event' : null,
this.user_notifications ? 'user' : null,
this.friend_notifications ? 'friends' : null,
this.splatnet2_monitors.size ? 'user' : null,
]);
if (this.presence_user && this.presence_user !== this.data.nsoAccount.user.nsaId) {
const friend = friends!.find(f => f.nsaId === this.presence_user);
if (this.presence_user) {
if (this.presence_user !== this.data.nsoAccount.user.nsaId) {
const friend = friends!.find(f => f.nsaId === this.presence_user);
if (!friend) {
// Is the authenticated user no longer friends with this user?
await this.updatePresenceForDiscord(null);
if (!friend) {
// Is the authenticated user no longer friends with this user?
await this.updatePresenceForDiscord(null);
} else {
await this.updatePresenceForDiscord(friend.presence);
}
} else {
await this.updatePresenceForDiscord(friend.presence);
await this.updatePresenceForDiscord(user!.presence, user!.links.friendCode, activeevent);
}
} else {
await this.updatePresenceForDiscord(user!.presence, user!.links.friendCode);
}
await this.updatePresenceForNotifications(user, friends);

View File

@ -5,6 +5,7 @@ export const defaultTitle: Title = {
client: '950883021165330493',
titleName: true,
showPlayingOnline: true,
showActiveEvent: true,
};
const titles: Title[] = [
@ -14,6 +15,7 @@ const titles: Title[] = [
client: '950886725398429726',
largeImageKey: '0100f8f0000a2000',
showPlayingOnline: true,
showActiveEvent: true,
},
{
// Splatoon 2 [The Americas]
@ -21,6 +23,7 @@ const titles: Title[] = [
client: '950886725398429726',
largeImageKey: '0100f8f0000a2000',
showPlayingOnline: true,
showActiveEvent: true,
},
{
// Splatoon 2 [Japan]
@ -28,6 +31,7 @@ const titles: Title[] = [
client: '950886725398429726',
largeImageKey: '01003c700009c000',
showPlayingOnline: true,
showActiveEvent: true,
},
{
@ -35,6 +39,7 @@ const titles: Title[] = [
id: '01006a800016e000',
client: '950894516104212490',
largeImageKey: '01006a800016e000',
showActiveEvent: true,
},
{
@ -42,6 +47,7 @@ const titles: Title[] = [
id: '0100152000022000',
client: '950905573149409280',
largeImageKey: '0100152000022000',
showActiveEvent: true,
},
{

View File

@ -1,5 +1,5 @@
import DiscordRPC from 'discord-rpc';
import { CurrentUser, Game, PresenceState } from '../api/znc-types.js';
import { ActiveEvent, CurrentUser, Game, PresenceState } from '../api/znc-types.js';
import titles, { defaultTitle } from './titles.js';
import { getTitleIdFromEcUrl, hrduration } from '../util.js';
import { ZncDiscordPresence } from '../cli/nso/presence.js';
@ -15,9 +15,15 @@ export function getDiscordPresence(
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);
const online = state === PresenceState.PLAYING;
const members = context?.activeevent?.members.filter(m => m.isPlaying);
const event_text = title.showActiveEvent && context?.activeevent ?
' (' + members?.length + ' player' + (members?.length === 1 ? '' : 's') +
')' : '';
if (game.sysDescription) text.push(game.sysDescription + event_text);
else if (online && title.showPlayingOnline === true) text.push('Playing online' + event_text);
else if (online && title.showPlayingOnline) text.push(title.showPlayingOnline as string + event_text);
if (game.totalPlayTime >= 60) {
text.push('Played for ' + hrduration(game.totalPlayTime) +
@ -38,6 +44,18 @@ export function getDiscordPresence(
] : [],
};
if (online && title.showActiveEvent && context?.activeevent?.shareUri) {
activity.buttons?.push({
label: 'Join',
url: context.activeevent.shareUri,
});
} else if (online && title.showActiveEvent) {
activity.buttons?.push({
label: 'Join via Nintendo Switch',
url: 'https://lounge.nintendo.com',
});
}
title.callback?.call(null, activity, game, context);
return {
@ -64,6 +82,7 @@ export function getInactiveDiscordPresence(
export interface DiscordPresenceContext {
friendcode?: CurrentUser['links']['friendCode'];
activeevent?: ActiveEvent;
znc_discord_presence?: ZncDiscordPresence;
nsaid?: string;
}
@ -95,6 +114,7 @@ export interface Title {
showTimestamp?: boolean;
/** Show "Playing online" if playing online and the game doesn't set activity details */
showPlayingOnline?: string | boolean;
showActiveEvent?: boolean;
callback?: (activity: DiscordRPC.Presence, game: Game, context?: DiscordPresenceContext) => void;
}