From b583946c14f5fc5ed2641dd24174d39dcf10f87a Mon Sep 17 00:00:00 2001 From: Brooke Date: Wed, 22 Jul 2026 17:53:59 -0700 Subject: [PATCH] fix scan's broken commit <3 --- server/src/notifier.ts | 39 +++++++++++++++++++++------------------ server/src/pdsClient.ts | 41 ++++++++++++++++++++++------------------- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/server/src/notifier.ts b/server/src/notifier.ts index db1cabb..71970b7 100644 --- a/server/src/notifier.ts +++ b/server/src/notifier.ts @@ -92,26 +92,27 @@ export class BskyDmNotifier { return this.session!; } + /** Any failure falls back to a fresh sign-in — never leave an expired session cached. */ private async refreshSession(session: { pds: string; accessJwt: string; refreshJwt: string; }): Promise { - const res = await fetch(`${session.pds}/xrpc/com.atproto.server.refreshSession`, { - method: "POST", - headers: { Authorization: `Bearer ${session.refreshJwt}` }, - }); - if (res.status === 400 || res.status === 401) return false; - if (!res.ok) { - const body = await res.text().catch(() => ""); - throw new Error(`refreshSession for ${this.cfg.handle} failed: ${res.status} ${body}`); + try { + const res = await fetch(`${session.pds}/xrpc/com.atproto.server.refreshSession`, { + method: "POST", + headers: { Authorization: `Bearer ${session.refreshJwt}` }, + }); + if (!res.ok) return false; + const { accessJwt, refreshJwt } = (await res.json()) as { + accessJwt: string; + refreshJwt: string; + }; + this.session = { pds: session.pds, accessJwt, refreshJwt }; + return true; + } catch { + return false; } - const { accessJwt, refreshJwt } = (await res.json()) as { - accessJwt: string; - refreshJwt: string; - }; - this.session = { pds: session.pds, accessJwt, refreshJwt }; - return true; } private async renewSession(expiredAccessJwt: string): Promise { @@ -136,12 +137,14 @@ export class BskyDmNotifier { "Content-Type": "application/json", }, }); - if (res.status === 401 && retry) { - await this.renewSession(accessJwt); - return this.chatXrpc(path, opts, false); - } if (!res.ok) { const body = await res.text().catch(() => ""); + // expired access tokens are 401 on the reference PDS but 400 ExpiredToken on tranquil-pds + const expired = res.status === 401 || (res.status === 400 && body.includes("ExpiredToken")); + if (expired && retry) { + await this.renewSession(accessJwt); + return this.chatXrpc(path, opts, false); + } throw new Error(`chat ${path} failed: ${res.status} ${body}`); } return res.json(); diff --git a/server/src/pdsClient.ts b/server/src/pdsClient.ts index aea7e14..4d186c2 100644 --- a/server/src/pdsClient.ts +++ b/server/src/pdsClient.ts @@ -88,24 +88,25 @@ export class PdsClient { return this.accessJwt!; } + /** Any failure falls back to a fresh sign-in — never leave an expired session cached. */ private async refreshSession(): Promise { if (!this.refreshJwt) return false; - const res = await fetch(`https://${this.hostname}/xrpc/com.atproto.server.refreshSession`, { - method: "POST", - headers: { Authorization: `Bearer ${this.refreshJwt}` }, - }); - if (res.status === 400 || res.status === 401) return false; - if (!res.ok) { - const body = await res.text().catch(() => ""); - throw new Error(`PDS admin session refresh failed: ${res.status} ${body}`); + try { + const res = await fetch(`https://${this.hostname}/xrpc/com.atproto.server.refreshSession`, { + method: "POST", + headers: { Authorization: `Bearer ${this.refreshJwt}` }, + }); + if (!res.ok) return false; + const { accessJwt, refreshJwt } = (await res.json()) as { + accessJwt: string; + refreshJwt: string; + }; + this.accessJwt = accessJwt; + this.refreshJwt = refreshJwt; + return true; + } catch { + return false; } - const { accessJwt, refreshJwt } = (await res.json()) as { - accessJwt: string; - refreshJwt: string; - }; - this.accessJwt = accessJwt; - this.refreshJwt = refreshJwt; - return true; } private async renewSession(expiredAccessJwt: string): Promise { @@ -132,12 +133,14 @@ export class PdsClient { "Content-Type": "application/json", }, }); - if (res.status === 401 && this.adminIdentifier && retry) { - await this.renewSession(accessJwt!); - return this.xrpc(path, opts, false); - } if (!res.ok) { const body = await res.text().catch(() => ""); + // expired access tokens are 401 on the reference PDS but 400 ExpiredToken on tranquil-pds + const expired = res.status === 401 || (res.status === 400 && body.includes("ExpiredToken")); + if (expired && this.adminIdentifier && retry) { + await this.renewSession(accessJwt!); + return this.xrpc(path, opts, false); + } throw new Error(`PDS ${path} failed: ${res.status} ${body}`); } // some procedures (e.g. disableInviteCodes) return 200 with an empty body -- 2.51.2