Discord: scope presence cache by account

This commit is contained in:
Shadow 2026-01-26 10:29:17 -06:00
parent 5933593659
commit 8a8d1024b4
No known key found for this signature in database
4 changed files with 47 additions and 13 deletions

View File

@ -55,7 +55,7 @@ export async function handleDiscordGuildAction(
const member = accountId
? await fetchMemberInfoDiscord(guildId, userId, { accountId })
: await fetchMemberInfoDiscord(guildId, userId);
const presence = getPresence(userId);
const presence = getPresence(accountId, userId);
const activities = presence?.activities ?? undefined;
const status = presence?.status ?? undefined;
return jsonResult({ ok: true, member, ...(presence ? { status, activities } : {}) });

View File

@ -276,10 +276,12 @@ type PresenceUpdateEvent = Parameters<PresenceUpdateListener["handle"]>[0];
export class DiscordPresenceListener extends PresenceUpdateListener {
private logger?: Logger;
private accountId?: string;
constructor(logger?: Logger) {
constructor(params: { logger?: Logger; accountId?: string }) {
super();
this.logger = logger;
this.logger = params.logger;
this.accountId = params.accountId;
}
async handle(data: PresenceUpdateEvent) {
@ -289,7 +291,11 @@ export class DiscordPresenceListener extends PresenceUpdateListener {
? String(data.user.id)
: undefined;
if (!userId) return;
setPresence(userId, data as import("discord-api-types/v10").GatewayPresenceUpdate);
setPresence(
this.accountId,
userId,
data as import("discord-api-types/v10").GatewayPresenceUpdate,
);
} catch (err) {
const logger = this.logger ?? discordEventQueueLog;
logger.error(danger(`discord presence handler failed: ${String(err)}`));

View File

@ -4,24 +4,49 @@ import type { GatewayPresenceUpdate } from "discord-api-types/v10";
* In-memory cache of Discord user presence data.
* Populated by PRESENCE_UPDATE gateway events when the GuildPresences intent is enabled.
*/
const presenceCache = new Map<string, GatewayPresenceUpdate>();
const presenceCache = new Map<string, Map<string, GatewayPresenceUpdate>>();
function resolveAccountKey(accountId?: string): string {
return accountId ?? "default";
}
/** Update cached presence for a user. */
export function setPresence(userId: string, data: GatewayPresenceUpdate): void {
presenceCache.set(userId, data);
export function setPresence(
accountId: string | undefined,
userId: string,
data: GatewayPresenceUpdate,
): void {
const accountKey = resolveAccountKey(accountId);
let accountCache = presenceCache.get(accountKey);
if (!accountCache) {
accountCache = new Map();
presenceCache.set(accountKey, accountCache);
}
accountCache.set(userId, data);
}
/** Get cached presence for a user. Returns undefined if not cached. */
export function getPresence(userId: string): GatewayPresenceUpdate | undefined {
return presenceCache.get(userId);
export function getPresence(
accountId: string | undefined,
userId: string,
): GatewayPresenceUpdate | undefined {
return presenceCache.get(resolveAccountKey(accountId))?.get(userId);
}
/** Clear all cached presence data. */
export function clearPresences(): void {
/** Clear cached presence data. */
export function clearPresences(accountId?: string): void {
if (accountId) {
presenceCache.delete(resolveAccountKey(accountId));
return;
}
presenceCache.clear();
}
/** Get the number of cached presence entries. */
export function presenceCacheSize(): number {
return presenceCache.size;
let total = 0;
for (const accountCache of presenceCache.values()) {
total += accountCache.size;
}
return total;
}

View File

@ -542,7 +542,10 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
);
if (discordCfg.intents?.presence) {
registerDiscordListener(client.listeners, new DiscordPresenceListener(logger));
registerDiscordListener(
client.listeners,
new DiscordPresenceListener({ logger, accountId: account.accountId }),
);
runtime.log?.("discord: GuildPresences intent enabled — presence listener registered");
}