a tool for shared writing and social publishing
1"use server";
2
3import { getCurrentDeploymentDomain } from "src/utils/getCurrentDeploymentDomain";
4import { createServerClient } from "@supabase/ssr";
5import { and, eq } from "drizzle-orm";
6import { drizzle } from "drizzle-orm/node-postgres";
7import { email_subscriptions_to_entity, entities } from "drizzle/schema";
8import postgres from "postgres";
9import type { PermissionToken } from "src/replicache";
10import { Database } from "supabase/database.types";
11import { pool } from "supabase/pool";
12
13let supabase = createServerClient<Database>(
14 process.env.NEXT_PUBLIC_SUPABASE_API_URL as string,
15 process.env.SUPABASE_SERVICE_ROLE_KEY as string,
16 { cookies: {} },
17);
18export async function sendPostToSubscribers({
19 title,
20 permission_token,
21 mailboxEntity,
22 messageEntity,
23 contents,
24}: {
25 title: string;
26 permission_token: PermissionToken;
27 mailboxEntity: string;
28 messageEntity: string;
29 contents: {
30 html: string;
31 markdown: string;
32 };
33}) {
34 let token_rights = await supabase
35 .from("permission_tokens")
36 .select("*, permission_token_rights(*)")
37 .eq("id", permission_token.id)
38 .single();
39 let rootEntity = token_rights.data?.root_entity;
40 if (!rootEntity || !token_rights.data) return { title: "Leaflet not found" };
41 let { data } = await supabase.rpc("get_facts", {
42 root: rootEntity,
43 });
44
45 const client = await pool.connect();
46 const db = drizzle(client);
47 let subscribers = await db
48 .select()
49 .from(email_subscriptions_to_entity)
50 .innerJoin(entities, eq(email_subscriptions_to_entity.entity, entities.id))
51 .where(eq(email_subscriptions_to_entity.entity, mailboxEntity));
52 let entity_set = subscribers[0]?.entities.set;
53 if (
54 !token_rights.data.permission_token_rights.find(
55 (r) => r.entity_set === entity_set,
56 )
57 ) {
58 return;
59 }
60 let domain = getCurrentDeploymentDomain();
61 let res = await fetch("https://api.postmarkapp.com/email/batch", {
62 method: "POST",
63 headers: {
64 "Content-Type": "application/json",
65 "X-Postmark-Server-Token": process.env.POSTMARK_API_KEY!,
66 },
67 body: JSON.stringify(
68 subscribers.map((sub) => ({
69 Headers: [
70 {
71 Name: "List-Unsubscribe-Post",
72 Value: "List-Unsubscribe=One-Click",
73 },
74 {
75 Name: "List-Unsubscribe",
76 Value: `<${domain}/mail/unsubscribe?sub_id=${sub.email_subscriptions_to_entity.id}>`,
77 },
78 ],
79 MessageStream: "broadcast",
80 From: "Leaflet Mailbox <mailbox@leaflet.pub>",
81 Subject: `New Mail in: ${title}`,
82 To: sub.email_subscriptions_to_entity.email,
83 HtmlBody: `
84 You've got new mail from <a href="${domain}/${sub.email_subscriptions_to_entity.token}?sub_id=${sub.email_subscriptions_to_entity.id}&email=${sub.email_subscriptions_to_entity.email}&entity=${sub.email_subscriptions_to_entity.entity}&openPage=${messageEntity}">
85 ${title}!
86 </a>
87 <hr style="margin-top: 1em; margin-bottom: 1em;">
88 ${contents.html}
89 <hr style="margin-top: 1em; margin-bottom: 1em;">
90 <em>Manage your subscription at
91 <a href="${domain}/${sub.email_subscriptions_to_entity.token}?sub_id=${sub.email_subscriptions_to_entity.id}&email=${sub.email_subscriptions_to_entity.email}&entity=${sub.email_subscriptions_to_entity.entity}&openPage=${messageEntity}">
92 ${title}
93 </a></em>
94 `,
95 TextBody: contents.markdown,
96 })),
97 ),
98 });
99 client.release();
100 return;
101}