mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
Move push notification rendering to its own view
This commit is contained in:
parent
8bf0a443db
commit
7fbda4a56b
3 changed files with 65 additions and 23 deletions
|
|
@ -2,7 +2,6 @@ import { NKinds, NostrEvent, NSchema as n } from '@nostrify/nostrify';
|
|||
import { Stickynotes } from '@soapbox/stickynotes';
|
||||
import { Kysely, sql } from 'kysely';
|
||||
import { LRUCache } from 'lru-cache';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Conf } from '@/config.ts';
|
||||
|
|
@ -14,7 +13,6 @@ import { RelayError } from '@/RelayError.ts';
|
|||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||
import { Storages } from '@/storages.ts';
|
||||
import { MastodonPush } from '@/types/MastodonPush.ts';
|
||||
import { eventAge, parseNip05, Time } from '@/utils.ts';
|
||||
import { getAmount } from '@/utils/bolt11.ts';
|
||||
import { detectLanguage } from '@/utils/language.ts';
|
||||
|
|
@ -22,7 +20,7 @@ import { nip05Cache } from '@/utils/nip05.ts';
|
|||
import { purifyEvent } from '@/utils/purify.ts';
|
||||
import { updateStats } from '@/utils/stats.ts';
|
||||
import { getTagSet } from '@/utils/tags.ts';
|
||||
import { renderNotification } from '@/views/mastodon/notifications.ts';
|
||||
import { renderWebPushNotification } from '@/views/mastodon/push.ts';
|
||||
import { policyWorker } from '@/workers/policy.ts';
|
||||
import { verifyEventWorker } from '@/workers/verify.ts';
|
||||
|
||||
|
|
@ -257,12 +255,14 @@ async function webPush(event: NostrEvent): Promise<void> {
|
|||
.execute();
|
||||
|
||||
for (const row of rows) {
|
||||
if (row.pubkey === event.pubkey) {
|
||||
const viewerPubkey = row.pubkey;
|
||||
|
||||
if (viewerPubkey === event.pubkey) {
|
||||
continue; // Don't notify authors about their own events.
|
||||
}
|
||||
|
||||
const notification = await renderNotification(event, { viewerPubkey: row.pubkey });
|
||||
if (!notification) {
|
||||
const message = await renderWebPushNotification(event, viewerPubkey);
|
||||
if (!message) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -274,18 +274,8 @@ async function webPush(event: NostrEvent): Promise<void> {
|
|||
},
|
||||
};
|
||||
|
||||
const message: MastodonPush = {
|
||||
notification_id: notification.id,
|
||||
notification_type: notification.type,
|
||||
access_token: nip19.npubEncode(row.pubkey),
|
||||
preferred_locale: 'en',
|
||||
title: notification.account.display_name || notification.account.username,
|
||||
icon: notification.account.avatar_static,
|
||||
body: event.content,
|
||||
};
|
||||
|
||||
await DittoPush.push(subscription, message);
|
||||
webPushNotificationsCounter.inc({ type: notification.type });
|
||||
webPushNotificationsCounter.inc({ type: message.notification_type });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ async function renderMention(event: DittoEvent, opts: RenderNotificationOpts) {
|
|||
|
||||
return {
|
||||
id: notificationId(event),
|
||||
type: 'mention',
|
||||
type: 'mention' as const,
|
||||
created_at: nostrDate(event.created_at).toISOString(),
|
||||
account: status.account,
|
||||
status: status,
|
||||
|
|
@ -59,7 +59,7 @@ async function renderReblog(event: DittoEvent, opts: RenderNotificationOpts) {
|
|||
|
||||
return {
|
||||
id: notificationId(event),
|
||||
type: 'reblog',
|
||||
type: 'reblog' as const,
|
||||
created_at: nostrDate(event.created_at).toISOString(),
|
||||
account,
|
||||
status,
|
||||
|
|
@ -74,7 +74,7 @@ async function renderFavourite(event: DittoEvent, opts: RenderNotificationOpts)
|
|||
|
||||
return {
|
||||
id: notificationId(event),
|
||||
type: 'favourite',
|
||||
type: 'favourite' as const,
|
||||
created_at: nostrDate(event.created_at).toISOString(),
|
||||
account,
|
||||
status,
|
||||
|
|
@ -89,7 +89,7 @@ async function renderReaction(event: DittoEvent, opts: RenderNotificationOpts) {
|
|||
|
||||
return {
|
||||
id: notificationId(event),
|
||||
type: 'pleroma:emoji_reaction',
|
||||
type: 'pleroma:emoji_reaction' as const,
|
||||
emoji: event.content,
|
||||
emoji_url: event.tags.find(([name, value]) => name === 'emoji' && `:${value}:` === event.content)?.[2],
|
||||
created_at: nostrDate(event.created_at).toISOString(),
|
||||
|
|
@ -106,7 +106,7 @@ async function renderNameGrant(event: DittoEvent) {
|
|||
|
||||
return {
|
||||
id: notificationId(event),
|
||||
type: 'ditto:name_grant',
|
||||
type: 'ditto:name_grant' as const,
|
||||
name: d,
|
||||
created_at: nostrDate(event.created_at).toISOString(),
|
||||
account,
|
||||
|
|
@ -125,7 +125,7 @@ async function renderZap(event: DittoEvent, opts: RenderNotificationOpts) {
|
|||
|
||||
return {
|
||||
id: notificationId(event),
|
||||
type: 'ditto:zap',
|
||||
type: 'ditto:zap' as const,
|
||||
amount: zap_amount,
|
||||
message: zap_message,
|
||||
created_at: nostrDate(event.created_at).toISOString(),
|
||||
|
|
|
|||
52
src/views/mastodon/push.ts
Normal file
52
src/views/mastodon/push.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import type { NostrEvent } from '@nostrify/nostrify';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
|
||||
import { MastodonPush } from '@/types/MastodonPush.ts';
|
||||
import { renderNotification } from '@/views/mastodon/notifications.ts';
|
||||
|
||||
/**
|
||||
* Render a web push notification for the viewer.
|
||||
* Unlike other views, only one will be rendered at a time, so making use of async calls is okay.
|
||||
*/
|
||||
export async function renderWebPushNotification(
|
||||
event: NostrEvent,
|
||||
viewerPubkey: string,
|
||||
): Promise<MastodonPush | undefined> {
|
||||
const notification = await renderNotification(event, { viewerPubkey });
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
notification_id: notification.id,
|
||||
notification_type: notification.type,
|
||||
access_token: nip19.npubEncode(viewerPubkey),
|
||||
preferred_locale: 'en',
|
||||
title: renderTitle(notification),
|
||||
icon: notification.account.avatar_static,
|
||||
body: event.content,
|
||||
};
|
||||
}
|
||||
|
||||
type MastodonNotification = NonNullable<Awaited<ReturnType<typeof renderNotification>>>;
|
||||
|
||||
function renderTitle(notification: MastodonNotification): string {
|
||||
const { account } = notification;
|
||||
|
||||
switch (notification.type) {
|
||||
case 'ditto:name_grant':
|
||||
return `You were granted the name ${notification.name}`;
|
||||
case 'ditto:zap':
|
||||
return `${account.display_name} zapped you ${notification.amount} sats`;
|
||||
case 'pleroma:emoji_reaction':
|
||||
return `${account.display_name} reacted to your post`;
|
||||
case 'favourite':
|
||||
return `${account.display_name} liked your post`;
|
||||
case 'mention':
|
||||
return `${account.display_name} mentioned you`;
|
||||
case 'reblog':
|
||||
return `${account.display_name} reposted your post`;
|
||||
default:
|
||||
return account.display_name || account.username;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue