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

grain.social/grain

photography-focused photo sharing platform

grain.social
1 collaborator
0
2
58 lines · 2.3 KB Raw History
/**
 * Accounts bridged in by Bridgy Fed, from the fediverse or from a website. It
 * writes their image posts as grain galleries: news feeds, blogs and toots
 * that carry a picture, mirrored here without anyone choosing to post on
 * grain. Every post from one is labelled `spam`, by the label rule in
 * `labels/spam.ts` as a post is indexed live and by the `bridged` classifier
 * for posts a backfill wrote.
 */

/** The collections whose records are hidden when a bridged account writes them. */
export const BRIDGED_HIDDEN_COLLECTIONS = [
  "social.grain.gallery",
  "social.grain.story",
  "social.grain.comment",
];

/** A handle Bridgy Fed issued: `*.ap.brid.gy` for the fediverse, `*.web.brid.gy` for a website. */
export function isBridgedHandle(handle: string | null | undefined): boolean {
  return !!handle?.toLowerCase().endsWith(".brid.gy");
}

/**
 * The footer Bridgy Fed appends to every bridged profile's description, which
 * is the signal for a bridged account that has set a domain handle of its own:
 * `🌉 bridged from ⁂ https://…, follow @ap.brid.gy to interact` for the
 * fediverse, `🌉 bridged from 🌐 https://…: https://fed.brid.gy/web/…` for a
 * website. A person who mentions their bridged account in their own words
 * writes neither.
 */
export function isBridgedDescription(description: string | null | undefined): boolean {
  if (!description?.includes("🌉 bridged from")) return false;
  return (
    description.includes("follow @ap.brid.gy to interact") ||
    description.includes("https://fed.brid.gy/")
  );
}

type Db = { query: (sql: string, params?: unknown[]) => Promise<unknown[]> };

/** Whether `did` is a bridged account, by its handle or else its grain profile. */
export async function isBridgedAccount(
  db: Db,
  did: string,
  handle?: string | null,
): Promise<boolean> {
  if (handle === undefined) {
    const [repo] = (await db.query(`SELECT handle FROM _repos WHERE did = $1`, [did])) as {
      handle: string | null;
    }[];
    handle = repo?.handle;
  }
  if (isBridgedHandle(handle)) return true;
  const [profile] = (await db.query(
    `SELECT description FROM "social.grain.actor.profile" WHERE did = $1 LIMIT 1`,
    [did],
  )) as { description: string | null }[];
  return isBridgedDescription(profile?.description);
}