Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send mark-read-generic notification on updateSeen #2567

Merged
merged 9 commits into from
Oct 4, 2024
1 change: 1 addition & 0 deletions packages/bsky/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"key-encoder": "^2.0.3",
"kysely": "^0.22.0",
"multiformats": "^9.9.0",
"murmurhash": "^2.0.1",
"p-queue": "^6.6.2",
"pg": "^8.10.0",
"pino": "^8.21.0",
Expand Down
1 change: 1 addition & 0 deletions packages/bsky/proto/courier.proto
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ message Notification {
bool always_deliver = 6;
google.protobuf.Timestamp timestamp = 7;
google.protobuf.Struct additional = 8;
bool client_controlled = 9;
}

message PushNotificationsRequest {
Expand Down
10 changes: 9 additions & 1 deletion packages/bsky/src/api/app/bsky/notification/registerPush.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { InvalidRequestError } from '@atproto/xrpc-server'
import {
InvalidRequestError,
MethodNotImplementedError,
} from '@atproto/xrpc-server'
import { Server } from '../../../../lexicon'
import AppContext from '../../../../context'
import { AppPlatform } from '../../../../proto/courier_pb'
Expand All @@ -7,6 +10,11 @@ export default function (server: Server, ctx: AppContext) {
server.app.bsky.notification.registerPush({
auth: ctx.authVerifier.standard,
handler: async ({ auth, input }) => {
if (!ctx.courierClient) {
throw new MethodNotImplementedError(
'This service is not configured to support push token registration.',
)
}
const { token, platform, serviceDid, appId } = input.body
const did = auth.credentials.iss
if (serviceDid !== auth.credentials.aud) {
Expand Down
25 changes: 24 additions & 1 deletion packages/bsky/src/api/app/bsky/notification/updateSeen.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Timestamp } from '@bufbuild/protobuf'
import murmur from 'murmurhash'
import { Struct, Timestamp } from '@bufbuild/protobuf'
import { Server } from '../../../../lexicon'
import AppContext from '../../../../context'

Expand All @@ -20,7 +21,29 @@ export default function (server: Server, ctx: AppContext) {
timestamp: Timestamp.fromDate(seenAt),
priority: true,
}),
ctx.courierClient?.pushNotifications({
notifications: [
{
id: getNotifId(viewer, seenAt),
clientControlled: true,
recipientDid: viewer,
alwaysDeliver: false,
collapseKey: 'mark-read-generic',
timestamp: Timestamp.fromDate(new Date()),
additional: Struct.fromJson({
reason: 'mark-read-generic',
}),
},
],
}),
])
},
})
}

function getNotifId(viewer: string, seenAt: Date) {
const key = ['mark-read-generic', viewer, seenAt.getTime().toString()].join(
'::',
)
return murmur.v3(key).toString(16)
}
3 changes: 1 addition & 2 deletions packages/bsky/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface ServerConfigValues {
bsyncApiKey?: string
bsyncHttpVersion?: '1.1' | '2'
bsyncIgnoreBadTls?: boolean
courierUrl: string
courierUrl?: string
courierApiKey?: string
courierHttpVersion?: '1.1' | '2'
courierIgnoreBadTls?: boolean
Expand Down Expand Up @@ -92,7 +92,6 @@ export class ServerConfig {
const bsyncIgnoreBadTls = process.env.BSKY_BSYNC_IGNORE_BAD_TLS === 'true'
assert(bsyncHttpVersion === '1.1' || bsyncHttpVersion === '2')
const courierUrl = process.env.BSKY_COURIER_URL || undefined
assert(courierUrl)
const courierApiKey = process.env.BSKY_COURIER_API_KEY || undefined
const courierHttpVersion = process.env.BSKY_COURIER_HTTP_VERSION || '2'
const courierIgnoreBadTls =
Expand Down
4 changes: 2 additions & 2 deletions packages/bsky/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class AppContext {
signingKey: Keypair
idResolver: IdResolver
bsyncClient: BsyncClient
courierClient: CourierClient
courierClient: CourierClient | undefined
authVerifier: AuthVerifier
featureGates: FeatureGates
},
Expand Down Expand Up @@ -76,7 +76,7 @@ export class AppContext {
return this.opts.bsyncClient
}

get courierClient(): CourierClient {
get courierClient(): CourierClient | undefined {
return this.opts.courierClient
}

Expand Down
2 changes: 1 addition & 1 deletion packages/bsky/src/data-plane/server/routes/notifs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export default (db: Database): Partial<ServiceImpl<typeof Service>> => ({
.selectFrom('follow')
.select(sql<boolean>`${true}`.as('val'))
.where('creator', '=', actorDid)
.whereRef('subjectDid', '=', ref('notif.author')),
.whereRef('subjectDid', '=', ref('notification.author')),
),
)
.executeTakeFirst()
Expand Down
18 changes: 10 additions & 8 deletions packages/bsky/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,16 @@ export class BskyAppView {
interceptors: config.bsyncApiKey ? [bsyncAuth(config.bsyncApiKey)] : [],
})

const courierClient = createCourierClient({
baseUrl: config.courierUrl,
httpVersion: config.courierHttpVersion ?? '2',
nodeOptions: { rejectUnauthorized: !config.courierIgnoreBadTls },
interceptors: config.courierApiKey
? [courierAuth(config.courierApiKey)]
: [],
})
const courierClient = config.courierUrl
? createCourierClient({
baseUrl: config.courierUrl,
httpVersion: config.courierHttpVersion ?? '2',
nodeOptions: { rejectUnauthorized: !config.courierIgnoreBadTls },
interceptors: config.courierApiKey
? [courierAuth(config.courierApiKey)]
: [],
})
: undefined

const entrywayJwtPublicKey = config.entrywayJwtPublicKeyHex
? createPublicKeyObject(config.entrywayJwtPublicKeyHex)
Expand Down
11 changes: 11 additions & 0 deletions packages/bsky/src/proto/courier_pb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ export class Notification extends Message<Notification> {
*/
additional?: Struct

/**
* @generated from field: bool client_controlled = 9;
*/
clientControlled = false

constructor(data?: PartialMessage<Notification>) {
super()
proto3.util.initPartial(data, this)
Expand Down Expand Up @@ -206,6 +211,12 @@ export class Notification extends Message<Notification> {
},
{ no: 7, name: 'timestamp', kind: 'message', T: Timestamp },
{ no: 8, name: 'additional', kind: 'message', T: Struct },
{
no: 9,
name: 'client_controlled',
kind: 'scalar',
T: 8 /* ScalarType.BOOL */,
},
])

static fromBinary(
Expand Down
1 change: 0 additions & 1 deletion packages/dev-env/src/bsky.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ export class TestBsky {
dataplaneHttpVersion: '1.1',
bsyncUrl: `http://localhost:${bsyncPort}`,
bsyncHttpVersion: '1.1',
courierUrl: 'https://fake.example',
modServiceDid: cfg.modServiceDid ?? 'did:example:invalidMod',
labelsFromIssuerDids: [EXAMPLE_LABELER],
...cfg,
Expand Down
7 changes: 7 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.