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}