From 44a0f56b93818a83d9ee2fc2f85e3c9e72332db9 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Tue, 22 Apr 2025 11:00:53 -0700 Subject: [PATCH 1/5] add shuttleId as custom key in notification alert argument --- src/notifications/schedulers/ETANotificationScheduler.ts | 3 +++ src/notifications/senders/AppleNotificationSender.ts | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/notifications/schedulers/ETANotificationScheduler.ts b/src/notifications/schedulers/ETANotificationScheduler.ts index 97a2d4d..3eb57cb 100644 --- a/src/notifications/schedulers/ETANotificationScheduler.ts +++ b/src/notifications/schedulers/ETANotificationScheduler.ts @@ -45,6 +45,9 @@ export class ETANotificationScheduler { const notificationAlertArguments: NotificationAlertArguments = { title: "Shuttle is arriving", body: `Shuttle is approaching ${stop.name} in ${Math.ceil(eta.secondsRemaining / 60)} minutes.`, + customKeys: { + shuttleId, + }, } return this.appleNotificationSender.sendNotificationImmediately(deviceId, notificationAlertArguments); } diff --git a/src/notifications/senders/AppleNotificationSender.ts b/src/notifications/senders/AppleNotificationSender.ts index 8e5904a..012846f 100644 --- a/src/notifications/senders/AppleNotificationSender.ts +++ b/src/notifications/senders/AppleNotificationSender.ts @@ -10,6 +10,7 @@ interface APNsUrl { export interface NotificationAlertArguments { title: string; body: string; + customKeys?: any, } export class AppleNotificationSender { @@ -110,7 +111,8 @@ export class AppleNotificationSender { aps: { alert: notificationAlertArguments, sound: "default" - } + }, + ...notificationAlertArguments.customKeys, })); req.end(); }); From ba0375f58292200dcc1d1121a31e75d3e99ff77a Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Tue, 22 Apr 2025 11:01:31 -0700 Subject: [PATCH 2/5] add link to APNs documentation --- src/notifications/senders/AppleNotificationSender.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/notifications/senders/AppleNotificationSender.ts b/src/notifications/senders/AppleNotificationSender.ts index 012846f..898bf05 100644 --- a/src/notifications/senders/AppleNotificationSender.ts +++ b/src/notifications/senders/AppleNotificationSender.ts @@ -107,6 +107,8 @@ export class AppleNotificationSender { resolve(); }); + // See https://developer.apple.com/documentation/usernotifications/generating-a-remote-notification + // for notification payload examples req.write(JSON.stringify({ aps: { alert: notificationAlertArguments, From 1cb498b1500599ef8dd1a1ec0a6df2243a06656c Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Tue, 22 Apr 2025 11:10:00 -0700 Subject: [PATCH 3/5] update custom keys to not be included in alert property --- src/notifications/senders/AppleNotificationSender.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/notifications/senders/AppleNotificationSender.ts b/src/notifications/senders/AppleNotificationSender.ts index 898bf05..2f458af 100644 --- a/src/notifications/senders/AppleNotificationSender.ts +++ b/src/notifications/senders/AppleNotificationSender.ts @@ -107,15 +107,21 @@ export class AppleNotificationSender { resolve(); }); + const customKeys = { + ...notificationAlertArguments.customKeys, + } + delete notificationAlertArguments.customKeys; + // See https://developer.apple.com/documentation/usernotifications/generating-a-remote-notification // for notification payload examples - req.write(JSON.stringify({ + const payload = JSON.stringify({ aps: { alert: notificationAlertArguments, sound: "default" }, - ...notificationAlertArguments.customKeys, - })); + customKeys, + }); + req.write(payload); req.end(); }); return true; From 95f2e6ec298de861caec1944dbb60e56d8b3ae76 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Tue, 22 Apr 2025 11:15:35 -0700 Subject: [PATCH 4/5] add system id to the notification payload for good measure --- src/entities/InterchangeSystem.ts | 2 ++ src/notifications/schedulers/ETANotificationScheduler.ts | 4 +++- .../schedulers/ETANotificationSchedulerTests.test.ts | 6 ++++-- .../senders/AppleNotificationSenderTests.test.ts | 3 +-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/entities/InterchangeSystem.ts b/src/entities/InterchangeSystem.ts index 2cb9072..37aed58 100644 --- a/src/entities/InterchangeSystem.ts +++ b/src/entities/InterchangeSystem.ts @@ -71,6 +71,7 @@ export class InterchangeSystem { shuttleRepository, notificationRepository, new AppleNotificationSender(), + args.id, ); notificationScheduler.startListeningForUpdates(); @@ -115,6 +116,7 @@ export class InterchangeSystem { shuttleRepository, notificationRepository, new AppleNotificationSender(false), + args.id, ); notificationScheduler.startListeningForUpdates(); diff --git a/src/notifications/schedulers/ETANotificationScheduler.ts b/src/notifications/schedulers/ETANotificationScheduler.ts index 3eb57cb..7d61c11 100644 --- a/src/notifications/schedulers/ETANotificationScheduler.ts +++ b/src/notifications/schedulers/ETANotificationScheduler.ts @@ -13,7 +13,8 @@ export class ETANotificationScheduler { constructor( private shuttleRepository: ShuttleGetterRepository, private notificationRepository: NotificationRepository = new InMemoryNotificationRepository(), - private appleNotificationSender = new AppleNotificationSender() + private appleNotificationSender = new AppleNotificationSender(), + private interchangeSystemId: string, ) { this.etaSubscriberCallback = this.etaSubscriberCallback.bind(this); this.sendEtaNotificationImmediately = this.sendEtaNotificationImmediately.bind(this); @@ -47,6 +48,7 @@ export class ETANotificationScheduler { body: `Shuttle is approaching ${stop.name} in ${Math.ceil(eta.secondsRemaining / 60)} minutes.`, customKeys: { shuttleId, + systemId: this.interchangeSystemId, }, } return this.appleNotificationSender.sendNotificationImmediately(deviceId, notificationAlertArguments); diff --git a/test/notifications/schedulers/ETANotificationSchedulerTests.test.ts b/test/notifications/schedulers/ETANotificationSchedulerTests.test.ts index b9f1790..db6a94b 100644 --- a/test/notifications/schedulers/ETANotificationSchedulerTests.test.ts +++ b/test/notifications/schedulers/ETANotificationSchedulerTests.test.ts @@ -40,7 +40,8 @@ describe("ETANotificationScheduler", () => { notificationService = new ETANotificationScheduler( shuttleRepository, notificationRepository, - appleNotificationSender + appleNotificationSender, + "1", ); notificationService.startListeningForUpdates(); }); @@ -127,7 +128,8 @@ describe("ETANotificationScheduler", () => { notificationService = new ETANotificationScheduler( shuttleRepository, notificationRepository, - updatedNotificationSender + updatedNotificationSender, + "1", ); notificationService.startListeningForUpdates(); diff --git a/test/notifications/senders/AppleNotificationSenderTests.test.ts b/test/notifications/senders/AppleNotificationSenderTests.test.ts index 9cbc0cb..948be7d 100644 --- a/test/notifications/senders/AppleNotificationSenderTests.test.ts +++ b/test/notifications/senders/AppleNotificationSenderTests.test.ts @@ -5,7 +5,6 @@ import { AppleNotificationSender, NotificationAlertArguments } from "../../../src/notifications/senders/AppleNotificationSender"; -import { ETANotificationScheduler } from "../../../src/notifications/schedulers/ETANotificationScheduler"; jest.mock("http2"); @@ -13,7 +12,7 @@ const sampleKeyBase64 = "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR1RBZ0VBTUJNR0J function mockHttp2Connect(status: number) { class MockClient extends EventEmitter { - request = jest.fn((headers: any) => { + request = jest.fn((_) => { const mockRequest: any = new EventEmitter(); mockRequest.setEncoding = jest.fn(); mockRequest.write = jest.fn(); From 12bdd4c631f1984d2accebdf5305e86253a1c16c Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Tue, 22 Apr 2025 11:17:10 -0700 Subject: [PATCH 5/5] add stop id, in case app wants to switch stops on notification tap --- src/notifications/schedulers/ETANotificationScheduler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/notifications/schedulers/ETANotificationScheduler.ts b/src/notifications/schedulers/ETANotificationScheduler.ts index 7d61c11..b269982 100644 --- a/src/notifications/schedulers/ETANotificationScheduler.ts +++ b/src/notifications/schedulers/ETANotificationScheduler.ts @@ -48,6 +48,7 @@ export class ETANotificationScheduler { body: `Shuttle is approaching ${stop.name} in ${Math.ceil(eta.secondsRemaining / 60)} minutes.`, customKeys: { shuttleId, + stopId, systemId: this.interchangeSystemId, }, }