forked from bluesky-social/atproto
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Appview v1 maintaining device tokens and pushing notifications w/ cou…
…rier (bluesky-social#2073) * add courier proto to bsky, build * update registerPush on appview to support registering device tokens with courier * setup bsky notifications to send to either gorush or courier * wire courier push into indexer, test * courier push retries * tidy and build
- Loading branch information
Showing
19 changed files
with
1,059 additions
and
196 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
syntax = "proto3"; | ||
|
||
package courier; | ||
option go_package = "./;courier"; | ||
|
||
import "google/protobuf/struct.proto"; | ||
import "google/protobuf/timestamp.proto"; | ||
|
||
// | ||
// Messages | ||
// | ||
|
||
// Ping | ||
message PingRequest {} | ||
message PingResponse {} | ||
|
||
// Notifications | ||
|
||
enum AppPlatform { | ||
APP_PLATFORM_UNSPECIFIED = 0; | ||
APP_PLATFORM_IOS = 1; | ||
APP_PLATFORM_ANDROID = 2; | ||
APP_PLATFORM_WEB = 3; | ||
} | ||
|
||
message Notification { | ||
string id = 1; | ||
string recipient_did = 2; | ||
string title = 3; | ||
string message = 4; | ||
string collapse_key = 5; | ||
bool always_deliver = 6; | ||
google.protobuf.Timestamp timestamp = 7; | ||
google.protobuf.Struct additional = 8; | ||
} | ||
|
||
message PushNotificationsRequest { | ||
repeated Notification notifications = 1; | ||
} | ||
|
||
message PushNotificationsResponse {} | ||
|
||
message RegisterDeviceTokenRequest { | ||
string did = 1; | ||
string token = 2; | ||
string app_id = 3; | ||
AppPlatform platform = 4; | ||
} | ||
|
||
message RegisterDeviceTokenResponse {} | ||
|
||
service Service { | ||
rpc Ping(PingRequest) returns (PingResponse); | ||
rpc PushNotifications(PushNotificationsRequest) returns (PushNotificationsResponse); | ||
rpc RegisterDeviceToken(RegisterDeviceTokenRequest) returns (RegisterDeviceTokenResponse); | ||
} |
50 changes: 42 additions & 8 deletions
50
packages/bsky/src/api/app/bsky/notification/registerPush.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,63 @@ | ||
import assert from 'node:assert' | ||
import { InvalidRequestError } from '@atproto/xrpc-server' | ||
import { Server } from '../../../../lexicon' | ||
import AppContext from '../../../../context' | ||
import { Platform } from '../../../../notifications' | ||
import { CourierClient } from '../../../../courier' | ||
import { AppPlatform } from '../../../../proto/courier_pb' | ||
|
||
export default function (server: Server, ctx: AppContext) { | ||
server.app.bsky.notification.registerPush({ | ||
auth: ctx.authVerifier.standard, | ||
handler: async ({ auth, input }) => { | ||
handler: async ({ req, auth, input }) => { | ||
const { token, platform, serviceDid, appId } = input.body | ||
const did = auth.credentials.iss | ||
if (serviceDid !== auth.credentials.aud) { | ||
throw new InvalidRequestError('Invalid serviceDid.') | ||
} | ||
const { notifServer } = ctx | ||
if (platform !== 'ios' && platform !== 'android' && platform !== 'web') { | ||
throw new InvalidRequestError( | ||
'Unsupported platform: must be "ios", "android", or "web".', | ||
) | ||
} | ||
await notifServer.registerDeviceForPushNotifications( | ||
did, | ||
token, | ||
platform as Platform, | ||
appId, | ||
) | ||
|
||
const db = ctx.db.getPrimary() | ||
|
||
const registerDeviceWithAppview = async () => { | ||
await ctx.services | ||
.actor(db) | ||
.registerPushDeviceToken(did, token, platform as Platform, appId) | ||
} | ||
|
||
const registerDeviceWithCourier = async ( | ||
courierClient: CourierClient, | ||
) => { | ||
await courierClient.registerDeviceToken({ | ||
did, | ||
token, | ||
platform: | ||
platform === 'ios' | ||
? AppPlatform.IOS | ||
: platform === 'android' | ||
? AppPlatform.ANDROID | ||
: AppPlatform.WEB, | ||
appId, | ||
}) | ||
} | ||
|
||
if (ctx.cfg.courierOnlyRegistration) { | ||
assert(ctx.courierClient) | ||
await registerDeviceWithCourier(ctx.courierClient) | ||
} else { | ||
await registerDeviceWithAppview() | ||
if (ctx.courierClient) { | ||
try { | ||
await registerDeviceWithCourier(ctx.courierClient) | ||
} catch (err) { | ||
req.log.warn(err, 'failed to register device token with courier') | ||
} | ||
} | ||
} | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { Service } from './proto/courier_connect' | ||
import { | ||
Code, | ||
ConnectError, | ||
PromiseClient, | ||
createPromiseClient, | ||
Interceptor, | ||
} from '@connectrpc/connect' | ||
import { | ||
createConnectTransport, | ||
ConnectTransportOptions, | ||
} from '@connectrpc/connect-node' | ||
|
||
export type CourierClient = PromiseClient<typeof Service> | ||
|
||
export const createCourierClient = ( | ||
opts: ConnectTransportOptions, | ||
): CourierClient => { | ||
const transport = createConnectTransport(opts) | ||
return createPromiseClient(Service, transport) | ||
} | ||
|
||
export { Code } | ||
|
||
export const isCourierError = ( | ||
err: unknown, | ||
code?: Code, | ||
): err is ConnectError => { | ||
if (err instanceof ConnectError) { | ||
return !code || err.code === code | ||
} | ||
return false | ||
} | ||
|
||
export const authWithApiKey = | ||
(apiKey: string): Interceptor => | ||
(next) => | ||
(req) => { | ||
req.header.set('authorization', `Bearer ${apiKey}`) | ||
return next(req) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.