a tool for shared writing and social publishing

handle quotes of standalone documents

Changed files
+50 -20
app
api
inngest
+50 -20
app/api/inngest/functions/index_post_mention.ts
··· 5 5 import { ids } from "lexicons/api/lexicons"; 6 6 import { Notification, pingIdentityToUpdateNotification } from "src/notifications"; 7 7 import { v7 } from "uuid"; 8 + import { idResolver } from "app/(home-pages)/reader/idResolver"; 8 9 9 10 export const index_post_mention = inngest.createFunction( 10 11 { id: "index_post_mention" }, ··· 13 14 let url = new URL(event.data.document_link); 14 15 let path = url.pathname.split("/").filter(Boolean); 15 16 16 - let { data: pub, error } = await supabaseServerClient 17 - .from("publications") 18 - .select("*") 19 - .eq("record->>base_path", url.host) 20 - .single(); 17 + // Check if this is a standalone document URL (/p/didOrHandle/rkey/...) 18 + const isStandaloneDoc = path[0] === "p" && path.length >= 3; 19 + 20 + let documentUri: string; 21 + let authorDid: string; 22 + 23 + if (isStandaloneDoc) { 24 + // Standalone doc: /p/didOrHandle/rkey/l-quote/... 25 + const didOrHandle = decodeURIComponent(path[1]); 26 + const rkey = path[2]; 27 + 28 + // Resolve handle to DID if necessary 29 + let did = didOrHandle; 30 + if (!didOrHandle.startsWith("did:")) { 31 + const resolved = await step.run("resolve-handle", async () => { 32 + return idResolver.handle.resolve(didOrHandle); 33 + }); 34 + if (!resolved) { 35 + return { message: `Could not resolve handle: ${didOrHandle}` }; 36 + } 37 + did = resolved; 38 + } 21 39 22 - if (!pub) { 23 - return { 24 - message: `No publication found for ${url.host}/${path[0]}`, 25 - error, 26 - }; 40 + documentUri = AtUri.make(did, ids.PubLeafletDocument, rkey).toString(); 41 + authorDid = did; 42 + } else { 43 + // Publication post: look up by custom domain 44 + let { data: pub, error } = await supabaseServerClient 45 + .from("publications") 46 + .select("*") 47 + .eq("record->>base_path", url.host) 48 + .single(); 49 + 50 + if (!pub) { 51 + return { 52 + message: `No publication found for ${url.host}/${path[0]}`, 53 + error, 54 + }; 55 + } 56 + 57 + documentUri = AtUri.make( 58 + pub.identity_did, 59 + ids.PubLeafletDocument, 60 + path[0], 61 + ).toString(); 62 + authorDid = pub.identity_did; 27 63 } 28 64 29 65 let bsky_post = await step.run("get-bsky-post-data", async () => { ··· 38 74 if (!bsky_post) { 39 75 return { message: `No post found for ${event.data.post_uri}` }; 40 76 } 41 - 42 - const documentUri = AtUri.make( 43 - pub.identity_did, 44 - ids.PubLeafletDocument, 45 - path[0], 46 - ).toString(); 47 77 48 78 await step.run("index-bsky-post", async () => { 49 79 await supabaseServerClient.from("bsky_posts").upsert({ ··· 60 90 61 91 await step.run("create-notification", async () => { 62 92 // Only create notification if the quote is from someone other than the author 63 - if (bsky_post.author.did !== pub.identity_did) { 93 + if (bsky_post.author.did !== authorDid) { 64 94 // Check if a notification already exists for this post and recipient 65 95 const { data: existingNotification } = await supabaseServerClient 66 96 .from("notifications") 67 97 .select("id") 68 - .eq("recipient", pub.identity_did) 98 + .eq("recipient", authorDid) 69 99 .eq("data->>type", "quote") 70 100 .eq("data->>bsky_post_uri", bsky_post.uri) 71 101 .eq("data->>document_uri", documentUri) ··· 74 104 if (!existingNotification) { 75 105 const notification: Notification = { 76 106 id: v7(), 77 - recipient: pub.identity_did, 107 + recipient: authorDid, 78 108 data: { 79 109 type: "quote", 80 110 bsky_post_uri: bsky_post.uri, ··· 82 112 }, 83 113 }; 84 114 await supabaseServerClient.from("notifications").insert(notification); 85 - await pingIdentityToUpdateNotification(pub.identity_did); 115 + await pingIdentityToUpdateNotification(authorDid); 86 116 } 87 117 } 88 118 });