Gateway: review fixes for stale summaries, history cursors that survive a moving window, timeouts on T3 calls, push size, T3's snooze rules, and input checks
This commit is contained in:
1 parent
edc4b88990
commit
99b300855e
13 files changed
+208
-58
No files matched your search
+28
-9
@@ -6,6 +6,7 @@ import type { Apns } from "./apns.ts";
|
||||
import type { NotificationPrefs, PushResult } from "./contract.ts";
|
||||
import type { Db, DeviceRow } from "./db.ts";
|
||||
import type { Push } from "./notify.ts";
|
||||
import { trimText } from "./views.ts";
|
||||
|
||||
const ALL_ON: NotificationPrefs = { needsMe: true, finished: true, failed: true, subagents: true };
|
||||
|
||||
@@ -30,6 +31,32 @@ export function wants(prefs: NotificationPrefs, push: Push): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
/** APNs refuses a payload over 4096 bytes. This leaves room for the JSON APNs adds. */
|
||||
const PAYLOAD_LIMIT = 3900;
|
||||
|
||||
/**
|
||||
* The APNs payload for a push, kept under APNs' size limit. Long titles and bodies in multi-byte
|
||||
* scripts can overflow it, so the question's buttons go first, then the body is cut.
|
||||
*/
|
||||
export function apnsPayload(push: Push) {
|
||||
const build = (data: Push["data"], body: string) => ({
|
||||
aps: {
|
||||
alert: { title: push.title, ...(push.subtitle ? { subtitle: push.subtitle } : {}), body },
|
||||
sound: "default",
|
||||
category: push.category,
|
||||
"thread-id": data.threadId ?? data.hostId ?? push.category,
|
||||
},
|
||||
...data,
|
||||
});
|
||||
const fits = (payload: object) => Buffer.byteLength(JSON.stringify(payload)) <= PAYLOAD_LIMIT;
|
||||
let payload = build(push.data, push.body);
|
||||
if (fits(payload)) return payload;
|
||||
const { question: _, ...plain } = push.data;
|
||||
payload = build(plain, push.body);
|
||||
for (let chars = 120; !fits(payload) && chars >= 20; chars -= 50) payload = build(plain, trimText(push.body, chars));
|
||||
return payload;
|
||||
}
|
||||
|
||||
export class Pusher {
|
||||
/** Apple's answer to the most recent push sent to any watch. */
|
||||
last: PushResult | null = null;
|
||||
@@ -63,15 +90,7 @@ export class Pusher {
|
||||
if (!device.apns_token || !device.apns_env) {
|
||||
return { ok: false, at, status: 0, reason: "This watch has not registered for notifications." };
|
||||
}
|
||||
const payload = {
|
||||
aps: {
|
||||
alert: { title: push.title, ...(push.subtitle ? { subtitle: push.subtitle } : {}), body: push.body },
|
||||
sound: "default",
|
||||
category: push.category,
|
||||
"thread-id": push.data.threadId ?? push.data.hostId ?? push.category,
|
||||
},
|
||||
...push.data,
|
||||
};
|
||||
const payload = apnsPayload(push);
|
||||
const answer = await this.apns.send({
|
||||
deviceToken: device.apns_token,
|
||||
environment: device.apns_env,
|
||||
|
||||
Reference in new issue
Block a user