~ knotless Search/
↑↓ move↵ open⇧↵ all results

grain.social/grain

photography-focused photo sharing platform

grain.social
1 collaborator
0
2
90 lines · 3.4 KB Raw History
import { defineHook } from "$hatk";
import { shouldPush } from "../helpers/notifPrefs.ts";
import { isBlockedOrMuted } from "../helpers/isModerated.ts";
import { isRecent } from "../helpers/isRecent.ts";
import { getUnseenCount } from "../helpers/unseenCount.ts";

export default defineHook(
  "on-commit",
  { collections: ["social.grain.favorite"] },
  async ({ action, record, repo, db, lookup, push }) => {
    if (action !== "create" || !record) return;

    // Backfill re-creates a repo's whole history; only notify on fresh records.
    if (!isRecent(record)) return;
    const subject = record.subject as string;
    if (!subject) return;

    // A taken-down account should not announce itself on someone's content.
    const [repos] = (await db.query(
      `SELECT 1 FROM _repos WHERE did = $1 AND status = 'takendown' LIMIT 1`,
      [repo],
    )) as unknown[];
    if (repos) return;

    // Check if the subject is a gallery
    const [gallery] = (await db.query(
      `SELECT did AS author FROM "social.grain.gallery" WHERE uri = $1`,
      [subject],
    )) as { author: string }[];

    if (gallery && gallery.author !== repo) {
      if (await isBlockedOrMuted(db, gallery.author, repo)) return;
      if (!(await shouldPush(db, gallery.author, repo, "favorites"))) return;
      const profiles = await lookup("social.grain.actor.profile", "did", [repo]);
      const actor = profiles.get(repo);
      const badge = (await getUnseenCount(db, gallery.author)) + 1;
      await push.send({
        did: gallery.author,
        title: "New favorite",
        body: `${(actor?.value as any)?.displayName ?? "Someone"} favorited your gallery`,
        data: { type: "gallery-favorite", uri: subject },
        badge,
      });
      return;
    }

    // Check if the subject is a story
    const [story] = (await db.query(
      `SELECT did AS author FROM "social.grain.story" WHERE uri = $1`,
      [subject],
    )) as { author: string }[];

    if (story && story.author !== repo) {
      if (await isBlockedOrMuted(db, story.author, repo)) return;
      if (!(await shouldPush(db, story.author, repo, "favorites"))) return;
      const profiles = await lookup("social.grain.actor.profile", "did", [repo]);
      const actor = profiles.get(repo);
      const badge = (await getUnseenCount(db, story.author)) + 1;
      await push.send({
        did: story.author,
        title: "New favorite",
        body: `${(actor?.value as any)?.displayName ?? "Someone"} favorited your story`,
        data: { type: "story-favorite", uri: subject },
        badge,
      });
      return;
    }

    // Check if the subject is a comment
    const [comment] = (await db.query(
      `SELECT did AS author, subject AS comment_subject FROM "social.grain.comment" WHERE uri = $1`,
      [subject],
    )) as { author: string; comment_subject: string }[];

    if (comment && comment.author !== repo) {
      if (await isBlockedOrMuted(db, comment.author, repo)) return;
      if (!(await shouldPush(db, comment.author, repo, "favorites"))) return;
      const profiles = await lookup("social.grain.actor.profile", "did", [repo]);
      const actor = profiles.get(repo);
      const badge = (await getUnseenCount(db, comment.author)) + 1;
      await push.send({
        did: comment.author,
        title: "New favorite",
        body: `${(actor?.value as any)?.displayName ?? "Someone"} favorited your comment`,
        data: { type: "comment-favorite", uri: subject },
        badge,
      });
    }
  },
);