123 lines · 4.6 KB
import { env } from "cloudflare:workers";
import { first } from "./db";
import { sitesDomain } from "./sites/config";
import { hostLabel } from "./sites/naming";
import { pagesRepoIdForUrl } from "./pages/serve";
import type { AbuseTargetKind } from "~/lib/abuse";

export type AbuseTarget = { kind: AbuseTargetKind; id: string };

const COMMENT_ANCHOR = /^#(?:issue|review-|discussion-)?comment-([A-Za-z0-9_-]{1,64})$/;
const ISSUE_PATH = /^(issues|pull)$/;

function parseUrl(targetUrl: string): URL | null {
  try {
    return new URL(targetUrl);
  } catch {
    return null;
  }
}

/** Maps a reported URL to the hosted site behind it: site labels, preview labels, then verified custom domains. */
export async function siteIdForUrl(targetUrl: string): Promise<string | null> {
  const host = parseUrl(targetUrl)?.hostname.toLowerCase();
  if (!host) return null;
  const domain = sitesDomain();
  const label = domain ? hostLabel(host, domain) : null;
  if (label) {
    const site = await first<{ id: string }>("SELECT id FROM sites WHERE label = ?", label);
    if (site) return site.id;
    const preview = await first<{ site_id: string }>(
      "SELECT site_id FROM site_deployments WHERE label = ? ORDER BY created_at DESC LIMIT 1",
      label,
    );
    return preview?.site_id ?? null;
  }
  const custom = await first<{ id: string }>("SELECT id FROM sites WHERE custom_domain = ? COLLATE NOCASE", host);
  return custom?.id ?? null;
}

function isForgeUrl(url: URL): boolean {