From 2a383c10a1315d9432fac1fd8e79dfba3d6323c3 Mon Sep 17 00:00:00 2001 From: Rory& Date: Tue, 16 Dec 2025 08:19:56 +0100 Subject: [PATCH] Expire old sessions, update last seen on gateway heartbeat --- src/api/util/handlers/Instance.ts | 20 +++++++++++++++----- src/gateway/opcodes/Identify.ts | 6 ++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/api/util/handlers/Instance.ts b/src/api/util/handlers/Instance.ts index 72b2e79b5..e018f8760 100644 --- a/src/api/util/handlers/Instance.ts +++ b/src/api/util/handlers/Instance.ts @@ -16,8 +16,9 @@ along with this program. If not, see . */ -import { Session } from "@spacebar/util"; +import { Session, TimeSpan } from "@spacebar/util"; import { Like } from "typeorm"; +import { setInterval } from "timers"; export async function initInstance() { // TODO: clean up database and delete tombstone data @@ -37,8 +38,17 @@ export async function initInstance() { // TODO: do no clear sessions for instance cluster // await Session.clear(); // This is now used as part of authentication... // ... but we can still expire temporary sessions for legacy tokens - for await (const session of await Session.createQueryBuilder("session").where("last_seen = '1970/01/01'").select().stream()) { - console.log("Instance[sessions]:",session); - } - await Session.delete({ session_id: Like("TEMP_%") }); + setInterval( + async () => { + for await (const session of await Session.createQueryBuilder("session").where("last_seen = '1970/01/01'").select().stream()) { + // session object has all fields prefixed with `session_`... thanks typeorm + if (TimeSpan.fromDates((session.session_created_at as Date).getTime(), new Date().getTime()).totalHours > 1) { + console.log(`[API/Instance.ts] Deleting temporary session ${session.session_session_id} created at ${session.session_created_at}`); + await Session.delete({ session_id: session.session_session_id }); + } + } + }, + 1000 * 60 * 30, + ); + // await Session.delete({ session_id: Like("TEMP_%") }); } diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts index bd6653d80..56dd88df5 100644 --- a/src/gateway/opcodes/Identify.ts +++ b/src/gateway/opcodes/Identify.ts @@ -51,6 +51,7 @@ import { Sticker, VoiceState, UserSettingsProtos, + IpDataClient, } from "@spacebar/util"; import { check } from "./instanceOf"; import { In } from "typeorm"; @@ -147,6 +148,11 @@ export async function onIdentify(this: WebSocket, data: Payload) { this.session.client_info.os = (identify.properties?.os || identify.properties?.$os) ?? this.session.client_info.os; this.session.client_status = {}; this.session.activities = identify.presence?.activities ?? []; // TODO: validation + if (this.ipAddress && this.ipAddress !== this.session.last_seen_ip) { + this.session.last_seen_ip = this.ipAddress; + const ipInfo = await IpDataClient.getIpInfo(this.ipAddress); + if (ipInfo?.ip) this.session.last_seen_location = `${ipInfo.emoji_flag} ${ipInfo.postal} ${ipInfo.city}, ${ipInfo.region}, ${ipInfo.country_name}`; + } const createSessionTime = taskSw.getElapsedAndReset();