grain.social is a photo sharing platform built on atproto.
grain.social
atproto
photography
appview
1import { defineHook } from "$hatk";
2
3export default defineHook("on-commit", { collections: ["social.grain.comment"] },
4 async ({ action, record, repo, db, lookup, push }) => {
5 if (action !== "create" || !record) return
6 const subject = record.subject as string
7 if (!subject) return
8
9 // Find the gallery author (comment.subject is the gallery URI)
10 const [gallery] = await db.query(
11 `SELECT did AS author FROM "social.grain.gallery" WHERE uri = $1`,
12 [subject],
13 ) as { author: string }[]
14
15 if (!gallery) return
16
17 // Look up commenter's profile
18 const profiles = await lookup("social.grain.actor.profile", "did", [repo])
19 const actor = profiles.get(repo)
20 const displayName = (actor?.value as any)?.displayName ?? "Someone"
21
22 // If this is a reply, notify the parent comment author instead
23 if (record.replyTo) {
24 const [parent] = await db.query(
25 `SELECT did AS author FROM "social.grain.comment" WHERE uri = $1`,
26 [record.replyTo],
27 ) as { author: string }[]
28
29 if (parent && parent.author !== repo) {
30 await push.send({
31 did: parent.author,
32 title: "New reply",
33 body: `${displayName} replied to your comment`,
34 data: { type: "comment-reply", uri: subject },
35 })
36 }
37 }
38
39 // Notify the gallery author (unless they're the commenter)
40 if (gallery.author !== repo) {
41 await push.send({
42 did: gallery.author,
43 title: "New comment",
44 body: `${displayName} commented on your gallery`,
45 data: { type: "gallery-comment", uri: subject },
46 })
47 }
48 }
49)