global push notifications toggle, inline status change on post detail
This commit is contained in:
@@ -9,7 +9,7 @@ import { firePluginEvent } from "../services/webhooks.js";
|
||||
import { decrypt } from "../services/encryption.js";
|
||||
import { masterKey } from "../config.js";
|
||||
import { shouldCount } from "../lib/view-tracker.js";
|
||||
import { notifyBoardSubscribers } from "../services/push.js";
|
||||
import { notifyBoardSubscribers, notifyGlobalSubscribers } from "../services/push.js";
|
||||
|
||||
const INVISIBLE_RE = /[\u200B\u200C\u200D\uFEFF\u200E\u200F\u202A-\u202E\u2066-\u2069\u00AD\u2060\u180E]/g;
|
||||
|
||||
@@ -556,6 +556,12 @@ export default async function postRoutes(app: FastifyInstance) {
|
||||
url: `/b/${board.slug}/post/${post.id}`,
|
||||
tag: `board-${board.id}-new`,
|
||||
});
|
||||
notifyGlobalSubscribers({
|
||||
title: `New post in ${board.name}`,
|
||||
body: cleanTitle.slice(0, 100),
|
||||
url: `/b/${board.slug}/post/${post.id}`,
|
||||
tag: `global-new-post`,
|
||||
});
|
||||
|
||||
reply.status(201).send({
|
||||
id: post.id, type: post.type, title: post.title, description: post.description,
|
||||
|
||||
@@ -139,4 +139,60 @@ export default async function pushRoutes(app: FastifyInstance) {
|
||||
reply.send(subs);
|
||||
}
|
||||
);
|
||||
|
||||
// global subscription status
|
||||
app.get(
|
||||
"/push/global-subscription",
|
||||
{ preHandler: [app.requireUser], config: { rateLimit: { max: 30, timeWindow: "1 minute" } } },
|
||||
async (req, reply) => {
|
||||
const sub = await prisma.pushSubscription.findFirst({
|
||||
where: { userId: req.user!.id, boardId: null, postId: null },
|
||||
select: { id: true },
|
||||
});
|
||||
reply.send({ subscribed: !!sub });
|
||||
}
|
||||
);
|
||||
|
||||
// global subscribe
|
||||
app.post(
|
||||
"/push/global-subscribe",
|
||||
{ preHandler: [app.requireUser], config: { rateLimit: { max: 10, timeWindow: "1 minute" } } },
|
||||
async (req, reply) => {
|
||||
const body = subscribeBody.parse(req.body);
|
||||
const endpointIdx = blindIndex(body.endpoint, blindIndexKey);
|
||||
|
||||
const existing = await prisma.pushSubscription.findUnique({ where: { endpointIdx } });
|
||||
if (existing) {
|
||||
await prisma.pushSubscription.update({
|
||||
where: { endpointIdx },
|
||||
data: { userId: req.user!.id, boardId: null, postId: null },
|
||||
});
|
||||
} else {
|
||||
await prisma.pushSubscription.create({
|
||||
data: {
|
||||
endpoint: encrypt(body.endpoint, masterKey),
|
||||
endpointIdx,
|
||||
keysP256dh: encrypt(body.keys.p256dh, masterKey),
|
||||
keysAuth: encrypt(body.keys.auth, masterKey),
|
||||
userId: req.user!.id,
|
||||
boardId: null,
|
||||
postId: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
reply.send({ subscribed: true });
|
||||
}
|
||||
);
|
||||
|
||||
// global unsubscribe
|
||||
app.delete(
|
||||
"/push/global-subscribe",
|
||||
{ preHandler: [app.requireUser], config: { rateLimit: { max: 10, timeWindow: "1 minute" } } },
|
||||
async (req, reply) => {
|
||||
await prisma.pushSubscription.deleteMany({
|
||||
where: { userId: req.user!.id, boardId: null, postId: null },
|
||||
});
|
||||
reply.send({ subscribed: false });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -82,6 +82,11 @@ export async function notifyBoardSubscribers(boardId: string, event: PushPayload
|
||||
await processResults(subs, event);
|
||||
}
|
||||
|
||||
export async function notifyGlobalSubscribers(event: PushPayload) {
|
||||
const subs = await prisma.pushSubscription.findMany({ where: { boardId: null, postId: null } });
|
||||
await processResults(subs, event);
|
||||
}
|
||||
|
||||
export async function notifyUserReply(userId: string, event: PushPayload) {
|
||||
const subs = await prisma.pushSubscription.findMany({ where: { userId } });
|
||||
await processResults(subs, event);
|
||||
|
||||
Reference in New Issue
Block a user