Update CurrentUser type

This commit is contained in:
Ellie 2025-12-10 00:25:07 +00:00
parent 8cae29d035
commit 10dbc366eb
No known key found for this signature in database
GPG Key ID: 9DBD8FA906936CFF
18 changed files with 90 additions and 85 deletions

View File

@ -67,7 +67,7 @@ export interface AccountLoginParameter {
/** /v3/Account/Login */
export interface AccountLogin {
user: CurrentUser;
user: CurrentUser<true>;
webApiServerCredential: {
accessToken: string;
expiresIn: number;
@ -83,9 +83,7 @@ export type AccountToken = AccountLogin;
/** /v4/Account/Login */
export interface AccountLogin_4 {
user: Exclude<CurrentUser, 'links'> & {
links: Exclude<CurrentUser['links'], 'nintendoAccount'>;
};
user: CurrentUser<false>;
webApiServerCredential: {
accessToken: string;
expiresIn: number;
@ -377,7 +375,7 @@ export interface User {
}
/** /v4/User/ShowSelf */
export interface CurrentUser {
export interface CurrentUser<WithNintendoAccount extends boolean = true> {
id: number;
nsaId: string;
imageUri: string;
@ -386,17 +384,12 @@ export interface CurrentUser {
supportId: string;
isChildRestricted: boolean;
etag: string;
links: {
nintendoAccount: {
membership: {
active: boolean;
};
};
friendCode: {
regenerable: boolean;
regenerableAt: number;
id: string;
};
links: (boolean extends WithNintendoAccount ? {
nintendoAccount?: CurrentUserNintendoAccountLink;
} : true extends WithNintendoAccount ? {
nintendoAccount: CurrentUserNintendoAccountLink;
} : {}) & {
friendCode: CurrentUserFriendCodeLink;
};
permissions: {
playLog: PlayLogPermissions;
@ -406,6 +399,17 @@ export interface CurrentUser {
presence: PresenceOnline_4 | PresenceOffline;
}
export interface CurrentUserNintendoAccountLink {
membership: {
active: boolean;
};
}
export interface CurrentUserFriendCodeLink {
regenerable: boolean;
regenerableAt: number;
id: string;
}
export enum PlayLogPermissions {
EVERYONE = 'EVERYONE',
FRIENDS = 'FRIENDS',

View File

@ -63,7 +63,7 @@ export interface CoralApiInterface {
getEvent(id: number): Promise<Result<Event>>;
getUser(id: number): Promise<Result<User>>;
getUserByFriendCode(friend_code: string, hash?: string): Promise<Result<FriendCodeUser>>;
getCurrentUser(): Promise<Result<CurrentUser>>;
getCurrentUser(): Promise<Result<CurrentUser<true> | CurrentUser<false>>>;
getReceivedFriendRequests(): Promise<Result<ReceivedFriendRequests>>;
getSentFriendRequests(): Promise<Result<SentFriendRequests>>;
getFriendCodeUrl(): Promise<Result<FriendCodeUrl>>;
@ -260,7 +260,7 @@ export abstract class AbstractCoralApi {
});
}
abstract getCurrentUser(): Promise<Result<CurrentUser>>;
abstract getCurrentUser(): Promise<Result<CurrentUser<true> | CurrentUser<false>>>;
async getFriendCodeUrl() {
return this.call<FriendCodeUrl>('/v3/Friend/CreateFriendCodeUrl', {
@ -502,7 +502,7 @@ export default class CoralApi extends AbstractCoralApi implements CoralApiInterf
}
async getCurrentUser() {
return this.call<CurrentUser, {id: number}>('/v4/User/ShowSelf', {
return this.call<CurrentUser<true>, {id: number}>('/v4/User/ShowSelf', {
id: this[CoralUserIdSymbol],
});
}

View File

@ -175,7 +175,7 @@ export default class ZncProxyApi extends AbstractCoralApi implements CoralApiInt
// }
async getCurrentUser() {
const result = await this.fetchProxyApi<{user: CurrentUser}>('user');
const result = await this.fetchProxyApi<{user: CurrentUser<true> | CurrentUser<false>}>('user');
return createResult(result, result.user);
}
@ -338,7 +338,7 @@ export async function getPresenceFromUrl(presence_url: string, useragent?: strin
const data = await response.json() as PresenceUrlResponse;
const user: CurrentUser | Friend | Friend_4 | undefined =
const user: CurrentUser<true> | CurrentUser<false> | Friend | Friend_4 | undefined =
'user' in data ? data.user :
'friend' in data ? data.friend :
'nsaId' in data ? data :

View File

@ -1,10 +1,10 @@
import React, { useCallback, useMemo } from 'react';
import { StyleSheet, Text } from 'react-native';
import { CurrentUser } from '../../../api/coral-types.js';
import { CurrentUserFriendCodeLink } from '../../../api/coral-types.js';
import ipc from '../ipc.js';
export default function FriendCode(props: {
friendcode: CurrentUser['links']['friendCode'];
friendcode: CurrentUserFriendCodeLink;
} | {
id: string;
}) {

View File

@ -6,7 +6,7 @@ export default function NintendoSwitchUser(props: {
friend: Friend;
nickname?: string;
} | {
user: CurrentUser;
user: CurrentUser<true> | CurrentUser<false>;
nickname?: string;
}) {
const user = 'friend' in props ? props.friend : props.user;

View File

@ -9,7 +9,7 @@ import { askAddNsoAccount, askAddPctlAccount } from './na-auth.js';
import { App } from './index.js';
import { EmbeddedPresenceMonitor } from './monitor.js';
import { DiscordPresenceConfiguration, DiscordPresenceSource, DiscordStatus, LoginItemOptions, WindowType } from '../common/types.js';
import { CurrentUser, Friend, Game, PresencePlatform, PresenceState, WebService } from '../../api/coral-types.js';
import { CurrentUser, CurrentUserFriendCodeLink, Friend, Game, PresencePlatform, PresenceState, WebService } from '../../api/coral-types.js';
import { NintendoAccountSessionTokenJwtPayload, NintendoAccountUser } from '../../api/na.js';
import { DiscordPresence } from '../../discord/types.js';
import { getDiscordRpcClients } from '../../discord/rpc.js';
@ -201,7 +201,7 @@ export function setupIpc(appinstance: App, ipcMain: IpcMain) {
handle('misc:share', (e, item: SharingItem) =>
new ShareMenu(item).popup({window: BrowserWindow.fromWebContents(e.sender)!}));
handle('menu:user', (e, user: NintendoAccountUser, nso?: CurrentUser, moon?: boolean) =>
handle('menu:user', (e, user: NintendoAccountUser, nso?: CurrentUser<true> | CurrentUser<false>, moon?: boolean) =>
(buildUserMenu(appinstance, user, nso, moon, BrowserWindow.fromWebContents(e.sender) ?? undefined)
.popup({window: BrowserWindow.fromWebContents(e.sender)!}), undefined));
handle('menu:add-user', e => (Menu.buildFromTemplate([
@ -212,7 +212,7 @@ export function setupIpc(appinstance: App, ipcMain: IpcMain) {
(item: MenuItem, window: BrowserWindow | undefined, event: KeyboardEvent) =>
askAddPctlAccount(appinstance, !event.shiftKey)}),
]).popup({window: BrowserWindow.fromWebContents(e.sender)!}), undefined));
handle('menu:friend-code', (e, fc: CurrentUser['links']['friendCode']) => (Menu.buildFromTemplate([
handle('menu:friend-code', (e, fc: CurrentUserFriendCodeLink) => (Menu.buildFromTemplate([
new MenuItem({label: 'SW-' + fc.id, enabled: false}),
new MenuItem({label: t('friend_code.share')!, role: 'shareMenu', sharingItem: {texts: ['SW-' + fc.id]}}),
new MenuItem({label: t('friend_code.copy')!, click: () => clipboard.writeText('SW-' + fc.id)}),
@ -223,7 +223,7 @@ export function setupIpc(appinstance: App, ipcMain: IpcMain) {
formatParams: { date: { dateStyle: 'short', timeStyle: 'medium' } },
})!, enabled: false}),
]).popup({window: BrowserWindow.fromWebContents(e.sender)!}), undefined));
handle('menu:friend', (e, user: NintendoAccountUser, nso: CurrentUser, friend: Friend) =>
handle('menu:friend', (e, user: NintendoAccountUser, nso: CurrentUser<true> | CurrentUser<false>, friend: Friend) =>
(buildFriendMenu(appinstance, user, nso, friend)
.popup({window: BrowserWindow.fromWebContents(e.sender)!}), undefined));
@ -255,7 +255,7 @@ export function sendToAllWindows(channel: string, ...args: any[]) {
}
}
function buildUserMenu(app: App, user: NintendoAccountUser, nso?: CurrentUser, moon?: boolean, window?: BrowserWindow) {
function buildUserMenu(app: App, user: NintendoAccountUser, nso?: CurrentUser<true> | CurrentUser<false>, moon?: boolean, window?: BrowserWindow) {
const t = app.i18n.getFixedT(null, 'menus', 'user');
const dm = app.monitors.getActiveDiscordPresenceMonitor();
const monitor = app.monitors.monitors.find(m => m instanceof EmbeddedPresenceMonitor &&
@ -307,7 +307,7 @@ function buildUserMenu(app: App, user: NintendoAccountUser, nso?: CurrentUser, m
]);
}
function buildFriendMenu(app: App, user: NintendoAccountUser, nso: CurrentUser, friend: Friend) {
function buildFriendMenu(app: App, user: NintendoAccountUser, nso: CurrentUser<true> | CurrentUser<false>, friend: Friend) {
const t = app.i18n.getFixedT(null, 'menus', 'friend');
const discord_presence_source = app.monitors.getDiscordPresenceSource();
const discord_presence_active = !!discord_presence_source && 'na_id' in discord_presence_source &&

View File

@ -574,7 +574,7 @@ export class ElectronNotificationManager extends NotificationManager {
this.t = i18n.getFixedT(null, 'notifications');
}
async onFriendOnline(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
async onFriendOnline(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
const currenttitle = friend.presence.game as PresenceGame;
new Notification({
@ -585,7 +585,7 @@ export class ElectronNotificationManager extends NotificationManager {
}).show();
}
async onFriendOffline(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
async onFriendOffline(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
new Notification({
title: friend.name,
body: this.t('offline')!,
@ -593,7 +593,7 @@ export class ElectronNotificationManager extends NotificationManager {
}).show();
}
async onFriendPlayingChangeTitle(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
async onFriendPlayingChangeTitle(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
const currenttitle = friend.presence.game as PresenceGame;
new Notification({
@ -604,7 +604,7 @@ export class ElectronNotificationManager extends NotificationManager {
}).show();
}
async onFriendTitleStateChange(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
async onFriendTitleStateChange(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
const currenttitle = friend.presence.game as PresenceGame;
new Notification({

View File

@ -7,7 +7,7 @@ import type { SavedToken } from '../../common/auth/coral.js';
import type { SavedMoonToken } from '../../common/auth/moon.js';
import type { UpdateCacheData } from '../../common/update.js';
import type { StatusUpdate } from '../../common/status.js';
import type { Announcements_4, CoralSuccessResponse, CurrentUser, Friend, Friend_4, FriendCodeUrl, FriendCodeUser, GetActiveEventResult, ReceivedFriendRequests, SentFriendRequests, WebService, WebServices_4 } from '../../api/coral-types.js';
import type { Announcements_4, CoralSuccessResponse, CurrentUser, CurrentUserFriendCodeLink, Friend, Friend_4, FriendCodeUrl, FriendCodeUser, GetActiveEventResult, ReceivedFriendRequests, SentFriendRequests, WebService, WebServices_4 } from '../../api/coral-types.js';
import type { DiscordPresence } from '../../discord/types.js';
import type { CachedErrorKey } from '../main/ipc.js';
import type { DiscordSetupProps } from '../browser/discord/index.js';
@ -102,10 +102,10 @@ const ipc = {
openExternalUrl: (url: string) => inv('misc:open-url', url),
share: (item: SharingItem) => inv('misc:share', item),
showUserMenu: (user: NintendoAccountUserCoral | NintendoAccountUserMoon, nso?: CurrentUser, moon?: boolean) => inv('menu:user', user, nso, moon),
showUserMenu: (user: NintendoAccountUserCoral | NintendoAccountUserMoon, nso?: CurrentUser<true> | CurrentUser<false>, moon?: boolean) => inv('menu:user', user, nso, moon),
showAddUserMenu: () => inv('menu:add-user'),
showFriendCodeMenu: (fc: CurrentUser['links']['friendCode']) => inv('menu:friend-code', fc),
showFriendMenu: (user: NintendoAccountUserCoral, nso: CurrentUser, friend: Friend_4) => inv('menu:friend', user, nso, friend),
showFriendCodeMenu: (fc: CurrentUserFriendCodeLink) => inv('menu:friend-code', fc),
showFriendMenu: (user: NintendoAccountUserCoral, nso: CurrentUser<true> | CurrentUser<false>, friend: Friend_4) => inv('menu:friend', user, nso, friend),
registerEventListener: (event: string, listener: (args: any[]) => void) => events.on(event, listener),
removeEventListener: (event: string, listener: (args: any[]) => void) => events.removeListener(event, listener),

View File

@ -962,7 +962,7 @@ class EventStreamNotificationManager extends NotificationManager {
}
onPresenceUpdated(
friend: CurrentUser | Friend, prev?: CurrentUser | Friend, type?: PresenceEvent,
friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, type?: PresenceEvent,
naid?: string, ir?: boolean
) {
this.stream.sendEvent(ZncPresenceEventStreamEvent.PRESENCE_UPDATED, {
@ -970,25 +970,25 @@ class EventStreamNotificationManager extends NotificationManager {
});
}
onFriendOnline(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
onFriendOnline(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
this.stream.sendEvent(ZncPresenceEventStreamEvent.FRIEND_ONLINE, {
id: friend.nsaId, presence: friend.presence, prev: prev?.presence,
});
}
onFriendOffline(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
onFriendOffline(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
this.stream.sendEvent(ZncPresenceEventStreamEvent.FRIEND_OFFLINE, {
id: friend.nsaId, presence: friend.presence, prev: prev?.presence,
});
}
onFriendPlayingChangeTitle(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
onFriendPlayingChangeTitle(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
this.stream.sendEvent(ZncPresenceEventStreamEvent.FRIEND_TITLE_CHANGE, {
id: friend.nsaId, presence: friend.presence, prev: prev?.presence,
});
}
onFriendTitleStateChange(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
onFriendTitleStateChange(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
this.stream.sendEvent(ZncPresenceEventStreamEvent.FRIEND_TITLE_STATECHANGE, {
id: friend.nsaId, presence: friend.presence, prev: prev?.presence,
});

View File

@ -136,7 +136,7 @@ export class TerminalNotificationManager extends NotificationManager {
super();
}
onFriendOnline(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
onFriendOnline(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
const currenttitle = friend.presence.game as PresenceGame;
this.notifier.notify({
@ -148,7 +148,7 @@ export class TerminalNotificationManager extends NotificationManager {
});
}
onFriendOffline(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
onFriendOffline(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
this.notifier.notify({
title: friend.name,
message: 'Offline',
@ -156,7 +156,7 @@ export class TerminalNotificationManager extends NotificationManager {
});
}
onFriendPlayingChangeTitle(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
onFriendPlayingChangeTitle(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
const currenttitle = friend.presence.game as PresenceGame;
this.notifier.notify({
@ -168,7 +168,7 @@ export class TerminalNotificationManager extends NotificationManager {
});
}
onFriendTitleStateChange(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean) {
onFriendTitleStateChange(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean) {
const currenttitle = friend.presence.game as PresenceGame;
this.notifier.notify({

View File

@ -58,10 +58,10 @@ export async function handler(argv: ArgumentsCamelCase<Arguments>) {
const friendcodeurl = await user.nso.getFriendCodeUrl();
const webservice = webservices.find(webservice => {
// Since coral 3.2.0 we can't check if the user has an active NSO
// membership, so just choose one that definitely won't fail
const verifymembership = webservice.customAttributes.find(a => a.attrKey === 'verifyMembership');
if (verifymembership?.attrValue === 'true' &&
!user.data.nsoAccount.user.links.nintendoAccount.membership.active
) return false;
if (verifymembership?.attrValue === 'true') return false;
return true;
});

View File

@ -1,7 +1,7 @@
import process from 'node:process';
import { fetch } from 'undici';
import { getPresenceFromUrl } from '../../api/znc-proxy.js';
import { ActiveEvent, CurrentUser, Friend, PresenceGame, PresenceOffline, PresenceOnline, PresenceOnline_4, PresencePlatform, PresenceState } from '../../api/coral-types.js';
import { ActiveEvent, CurrentUser, CurrentUserFriendCodeLink, Friend, PresenceGame, PresenceOffline, PresenceOnline, PresenceOnline_4, PresencePlatform, PresenceState } from '../../api/coral-types.js';
import type { Arguments as ParentArguments } from './index.js';
import { getDiscordPresence, getInactiveDiscordPresence } from '../../discord/util.js';
import { DiscordPresenceContext, DiscordPresencePlayTime } from '../../discord/types.js';
@ -184,8 +184,8 @@ async function getPresenceFromCoral(argv: ArgumentsCamelCase<Arguments>) {
function getActivityFromPresence(
argv: ArgumentsCamelCase<Arguments>,
presence: Presence | null,
user?: CurrentUser | Friend,
friendcode?: CurrentUser['links']['friendCode'],
user?: CurrentUser<true> | CurrentUser<false> | Friend,
friendcode?: CurrentUserFriendCodeLink,
activeevent?: ActiveEvent,
proxy_response?: unknown,
) {

View File

@ -56,7 +56,7 @@ export default class Coral {
public chats: Result<ListChat> | null = null,
public media: Result<ListMedia> | null = null,
public active_event: Result<GetActiveEventResult> | null = null,
public current_user: Result<CurrentUser> | null = null,
public current_user: Result<CurrentUser<true> | CurrentUser<false>> | null = null,
) {
if (announcements) this.updated.announcements = Date.now();
if (friends) this.updated.friends = Date.now();

View File

@ -118,6 +118,9 @@ export class RateLimitError extends Error implements HasErrorDescription {
}
export function checkMembershipActive(data: SavedToken) {
// Since 3.2.0 we can't check if the user has an active NSO membership
if (!('nintendoAccount' in data.nsoAccount.user.links)) return;
const membership = data.nsoAccount.user.links.nintendoAccount.membership;
const active = typeof membership.active === 'object' ? (membership.active as typeof membership).active : membership.active;

View File

@ -1,8 +1,6 @@
import persist from 'node-persist';
import { CoralApiInterface } from '../api/coral.js';
import { CurrentUser, Friend, Presence, PresenceState, CoralError, PresenceGame } from '../api/coral-types.js';
import { ErrorResponse } from '../api/util.js';
import { SavedToken } from './auth/coral.js';
import { SplatNet2RecordsMonitor } from './splatnet2/monitor.js';
import createDebug from '../util/debug.js';
import Loop, { LoopResult } from '../util/loop.js';
@ -35,7 +33,7 @@ export class ZncNotifications extends Loop {
}
async updateFriendsStatusForNotifications(
friends: (CurrentUser | Friend)[],
friends: (CurrentUser<false> | Friend)[],
naid = this.user.data.user.id,
initialRun?: boolean
) {
@ -43,15 +41,15 @@ export class ZncNotifications extends Loop {
}
async updatePresenceForNotifications(
user: CurrentUser | null, friends: Friend[] | null,
user: CurrentUser<false> | null, friends: Friend[] | null,
naid = this.user.data.user.id, initialRun?: boolean
) {
await this.updateFriendsStatusForNotifications(([] as (CurrentUser | Friend)[])
await this.updateFriendsStatusForNotifications(([] as (CurrentUser<false> | Friend)[])
.concat(this.user_notifications && user ? [user] : [])
.concat(this.friend_notifications && friends ? friends : []), naid, initialRun);
}
async updatePresenceForSplatNet2Monitors(friends: (CurrentUser | Friend)[]) {
async updatePresenceForSplatNet2Monitors(friends: (CurrentUser<false> | Friend)[]) {
for (const friend of friends) {
await this.updatePresenceForSplatNet2Monitor(friend.presence, friend.nsaId, friend.name);
}
@ -91,8 +89,8 @@ export class ZncNotifications extends Loop {
this.friend_notifications ? this.user.getFriends() : null,
]);
await this.updatePresenceForNotifications(user, friends, this.user.data.user.id, false);
if (user) await this.updatePresenceForSplatNet2Monitors([user]);
await this.updatePresenceForNotifications(user as CurrentUser<false>, friends, this.user.data.user.id, false);
if (user) await this.updatePresenceForSplatNet2Monitors([user as CurrentUser<false>]);
}
async handleError(err: ErrorResponse<CoralError> | NodeJS.ErrnoException): Promise<LoopResult> {
@ -101,18 +99,18 @@ export class ZncNotifications extends Loop {
}
export class NotificationManager {
onPresenceUpdated?(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, type?: PresenceEvent, naid?: string, ir?: boolean): void;
onPresenceUpdated?(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, type?: PresenceEvent, naid?: string, ir?: boolean): void;
onFriendOnline?(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean): void;
onFriendOffline?(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean): void;
onFriendPlayingChangeTitle?(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean): void;
onFriendTitleStateChange?(friend: CurrentUser | Friend, prev?: CurrentUser | Friend, naid?: string, ir?: boolean): void;
onFriendOnline?(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean): void;
onFriendOffline?(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean): void;
onFriendPlayingChangeTitle?(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean): void;
onFriendTitleStateChange?(friend: CurrentUser<false> | Friend, prev?: CurrentUser<false> | Friend, naid?: string, ir?: boolean): void;
onlinefriends = new Map</** NA ID */ string, (CurrentUser | Friend)[]>();
onlinefriends = new Map</** NA ID */ string, (CurrentUser<false> | Friend)[]>();
accounts = new Map</** NSA ID */ string, /** NA ID */ string>();
updateFriendsStatusForNotifications(friends: (CurrentUser | Friend)[], naid: string, initialRun?: boolean) {
const newonlinefriends: (CurrentUser | Friend)[] = [];
updateFriendsStatusForNotifications(friends: (CurrentUser<false> | Friend)[], naid: string, initialRun?: boolean) {
const newonlinefriends: (CurrentUser<false> | Friend)[] = [];
for (const friend of friends) {
const prev = this.onlinefriends.get(naid)?.find(f => f.nsaId === friend.nsaId);

View File

@ -12,7 +12,7 @@ import { DiscordRpcClient, findDiscordRpcClient } from '../discord/rpc.js';
import { getDiscordPresence, getInactiveDiscordPresence } from '../discord/util.js';
import { DiscordPresencePlayTime, DiscordPresenceContext, DiscordPresence, ExternalMonitorConstructor, ExternalMonitor, ErrorResult } from '../discord/types.js';
import { CoralApiInterface } from '../api/coral.js';
import { ActiveEvent, CurrentUser, Friend, Game, PresenceState, CoralError, PresenceOnline_4, PresenceOffline, PresenceOnline } from '../api/coral-types.js';
import { ActiveEvent, CurrentUser, Friend, Game, PresenceState, CoralError, PresenceOnline_4, PresenceOffline, PresenceOnline, CurrentUserFriendCodeLink } from '../api/coral-types.js';
import { getPresenceFromUrl } from '../api/znc-proxy.js';
import { ErrorResponse, ResponseSymbol } from '../api/util.js';
import { CoralUser } from './users.js';
@ -44,8 +44,8 @@ class ZncDiscordPresenceClient {
protected i = 0;
last_presence: Presence | null = null;
last_user: CurrentUser | Friend | null = null;
last_friendcode: CurrentUser['links']['friendCode'] | null = null;
last_user: CurrentUser<false> | Friend | null = null;
last_friendcode: CurrentUserFriendCodeLink | null = null;
last_event: ActiveEvent | null = null;
last_activity: DiscordPresence | string | null = null;
@ -68,8 +68,8 @@ class ZncDiscordPresenceClient {
async updatePresenceForDiscord(
presence: Presence | null,
user?: CurrentUser | Friend | null,
friendcode?: CurrentUser['links']['friendCode'] | null,
user?: CurrentUser<false> | Friend | null,
friendcode?: CurrentUserFriendCodeLink | null,
activeevent?: ActiveEvent | null,
) {
this.last_presence = presence;
@ -449,13 +449,13 @@ export class ZncDiscordPresence extends ZncNotifications {
await this.savePresenceForTitleUpdateAt(friend.nsaId, friend.presence, this.discord.title?.since);
}
} else {
await this.discord.updatePresenceForDiscord(user!.presence, user, user!.links.friendCode, activeevent);
await this.discord.updatePresenceForDiscord(user!.presence, user as CurrentUser<false>, user!.links.friendCode, activeevent);
await this.savePresenceForTitleUpdateAt(user!.nsaId, user!.presence, this.discord.title?.since);
}
}
await this.updatePresenceForNotifications(user, friends, this.user.data.user.id, false);
if (user) await this.updatePresenceForSplatNet2Monitors([user]);
await this.updatePresenceForNotifications(user as CurrentUser<false>, friends, this.user.data.user.id, false);
if (user) await this.updatePresenceForSplatNet2Monitors([user as CurrentUser<false>]);
}
async onStop() {
@ -555,7 +555,7 @@ export class ZncProxyDiscordPresence extends Loop {
this.last_data = data;
this.proxy_temporary_errors = 0;
await this.discord.updatePresenceForDiscord(presence, user);
await this.discord.updatePresenceForDiscord(presence, user as Friend | CurrentUser<false>);
await this.updatePresenceForSplatNet2Monitor(presence, this.presence_url);
const link_header = result[ResponseSymbol].headers.get('Link');
@ -665,7 +665,7 @@ export class ZncProxyDiscordPresence extends Loop {
this.updateStatusUpdateSource(links);
};
let user: CurrentUser | Friend | undefined = undefined;
let user: CurrentUser<false> | Friend | undefined = undefined;
let presence: Presence | null = null;
this.last_data = {};

View File

@ -109,7 +109,7 @@ export interface CoralUserData<T extends CoralApiInterface = CoralApi> extends U
chats: CoralSuccessResponse<ListChat>;
media: CoralSuccessResponse<ListMedia>;
active_event: CoralSuccessResponse<GetActiveEventResult>;
user: CoralSuccessResponse<CurrentUser>;
user: CoralSuccessResponse<CurrentUser<true> | CurrentUser<false>>;
}
export class CoralUser<T extends CoralApiInterface = CoralApi> implements CoralUserData<T> {
@ -149,7 +149,7 @@ export class CoralUser<T extends CoralApiInterface = CoralApi> implements CoralU
public chats: CoralSuccessResponse<ListChat>,
public media: CoralSuccessResponse<ListMedia>,
public active_event: CoralSuccessResponse<GetActiveEventResult>,
public user: CoralSuccessResponse<CurrentUser>,
public user: CoralSuccessResponse<CurrentUser<true> | CurrentUser<false>>,
) {}
private async update(key: keyof CoralUser['updated'], callback: () => Promise<void>, ttl: number) {

View File

@ -1,18 +1,18 @@
import DiscordRPC from 'discord-rpc';
import { ActiveEvent, CurrentUser, Friend, Game, PresencePlatform } from '../api/coral-types.js';
import { ActiveEvent, CurrentUser, CurrentUserFriendCodeLink, 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'];
friendcode?: CurrentUserFriendCodeLink;
activeevent?: ActiveEvent;
show_play_time?: DiscordPresencePlayTime;
znc_discord_presence?: ZncDiscordPresence | ZncProxyDiscordPresence;
proxy_response?: unknown;
monitors?: ExternalMonitor[];
nsaid?: string;
user?: CurrentUser | Friend;
user?: CurrentUser<true> | CurrentUser<false> | Friend;
platform?: PresencePlatform;
}