feat : comment feature
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import "server-only";
|
||||
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import webPush from "web-push";
|
||||
import { getDb } from "@/db";
|
||||
import { comments, commentPushSubscriptions, commentRevisions, users } from "@/db/schema";
|
||||
import { pushPublicKey, validPushEndpoint } from "@/lib/commission/push";
|
||||
import { authorizeComment } from "./repository";
|
||||
|
||||
export async function sendCommentReplyPush(id: string) {
|
||||
if (!pushPublicKey()) return;
|
||||
const [reply] = await getDb().select().from(comments).where(eq(comments.id, id)).limit(1);
|
||||
if (!reply?.replyToId || reply.hidden || reply.deletedAt) return;
|
||||
const [parent] = await getDb().select().from(comments).where(eq(comments.id, reply.replyToId)).limit(1);
|
||||
if (!parent || parent.authorId === reply.authorId || parent.hidden || parent.deletedAt) return;
|
||||
const [recipient] = await getDb().select().from(users).where(eq(users.id, parent.authorId)).limit(1);
|
||||
if (!recipient || recipient.banned) return;
|
||||
let destination;
|
||||
try {
|
||||
({ destination } = await authorizeComment(id, { id: recipient.id, admin: recipient.role === "admin" && recipient.emailVerified }));
|
||||
} catch { return; }
|
||||
const [author] = await getDb().select({ name: users.name }).from(users).where(eq(users.id, reply.authorId)).limit(1);
|
||||
const [revision] = await getDb().select({ text: commentRevisions.text }).from(commentRevisions)
|
||||
.where(and(eq(commentRevisions.commentId, id), eq(commentRevisions.version, reply.version))).limit(1);
|
||||
const subscriptions = await getDb().select().from(commentPushSubscriptions).where(eq(commentPushSubscriptions.userId, recipient.id));
|
||||
if (!subscriptions.length) return;
|
||||
webPush.setVapidDetails(process.env.WEB_PUSH_SUBJECT!, process.env.WEB_PUSH_PUBLIC_KEY!, process.env.WEB_PUSH_PRIVATE_KEY!);
|
||||
const payload = JSON.stringify({ id: `comment-${id}`, title: `${author?.name ?? "ผู้ใช้"} ตอบกลับความคิดเห็นของคุณ`,
|
||||
body: revision?.text.slice(0, 300) || "ส่งรูปภาพ", icon: "/icon/nav/Comment.webp",
|
||||
url: `${destination.href}${destination.href.includes("?") ? "&" : "?"}reply=${id}#comment-${reply.rootId}` });
|
||||
for (let offset = 0; offset < subscriptions.length; offset += 10) {
|
||||
await Promise.all(subscriptions.slice(offset, offset + 10).map(async (subscription) => {
|
||||
if (!validPushEndpoint(subscription.endpoint)) return;
|
||||
try {
|
||||
await webPush.sendNotification({ endpoint: subscription.endpoint, keys: { p256dh: subscription.p256dh, auth: subscription.auth } }, payload, { TTL: 60 * 60 * 24, timeout: 5000 });
|
||||
} catch (cause) {
|
||||
if (cause && typeof cause === "object" && "statusCode" in cause && (cause.statusCode === 404 || cause.statusCode === 410))
|
||||
await getDb().delete(commentPushSubscriptions).where(eq(commentPushSubscriptions.endpoint, subscription.endpoint));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user