88 lines · 3.8 KB
import { all, first, run } from "./db";
import { badRequest, notFoundError } from "./errors";
import { recordAdminAction } from "./admin-audit";
import { publicUrl } from "./events/emit";
import { invalidateUnread } from "./user-inbox";
import { HIDEABLE_KINDS } from "~/lib/abuse";
import type { AbuseTargetKind } from "~/lib/abuse";

type Hideable = "pages" | "repo" | "issue" | "comment" | "review_comment" | "discussion_comment";

type Target = { table: string; key: string; column: string; counter?: string };

/** `counter` keeps the parent's comment count in step, so hidden comments don't show up as a number either. */
const TARGETS: Record<Hideable, Target> = {
  repo: { table: "repos", key: "id", column: "hidden_at" },
  issue: { table: "issues", key: "id", column: "hidden_at" },
  comment: {
    table: "comments",
    key: "id",
    column: "hidden_at",
    counter: `UPDATE issues SET comments_count = MAX(comments_count + ?, 0)
              WHERE id = (SELECT issue_id FROM comments WHERE id = ?)`,
  },
  review_comment: { table: "review_comments", key: "id", column: "hidden_at" },
  discussion_comment: {
    table: "discussion_comments",
    key: "id",
    column: "hidden_at",
    counter: `UPDATE discussions SET comments_count = MAX(comments_count + ?, 0)
              WHERE id = (SELECT discussion_id FROM discussion_comments WHERE id = ?)`,
  },
  pages: { table: "pages_sites", key: "repo_id", column: "taken_down_at" },
};

export function isHideable(kind: string): kind is Hideable {
  return HIDEABLE_KINDS.has(kind as AbuseTargetKind);
}

/** Drops inbox rows that point at a hidden issue or pull request, so its title stops showing in notifications. */
async function purgeIssueNotifications(issueId: string): Promise<void> {