import "./ingest/tap.ts"; import { Hono } from "hono"; import { cors } from "hono/cors"; import { serve } from "@hono/node-server"; import { db } from "./db/index.ts"; import { tangledFollow, tangledProfile } from "./db/tables/tangled.ts"; import { and, desc, eq, isNotNull } from "drizzle-orm"; import { alias } from "drizzle-orm/pg-core"; import { channel } from "./ingest/tap.ts"; import { bskyProfile } from "./db/tables/bsky.ts"; import { type AtprotoData, DidResolver, MemoryCache } from "@atproto/identity"; const didCache = new MemoryCache(); const didres = new DidResolver({ didCache }); const app = new Hono(); app.use("*", cors()); app.get("/", async (c) => { console.log("TING"); const tangledFollowed = alias(tangledProfile, "tangledFollowed"); const bskyFollowed = alias(bskyProfile, "bskyFollowed"); const follows = await db .select({ followerDid: tangledFollow.did, followedDid: tangledFollow.subject, followerTangledProfile: tangledProfile, followedTangledProfile: tangledFollowed, followerBskyProfile: bskyProfile, followedBskyProfileProfile: bskyFollowed, followedAt: tangledFollow.createdAt, }) .from(tangledFollow) .leftJoin(tangledProfile, eq(tangledProfile.did, tangledFollow.did)) .leftJoin(tangledFollowed, eq(tangledFollowed.did, tangledFollow.subject)) .leftJoin(bskyProfile, eq(bskyProfile.did, tangledFollow.did)) .leftJoin(bskyFollowed, eq(bskyFollowed.did, tangledFollow.subject)) .where(and(eq(tangledFollow.deleted, false), isNotNull(tangledFollow.subject))) .orderBy(desc(tangledFollow.createdAt)) .limit(500); const didSet = new Set( follows .flatMap(({ followerDid, followedDid }) => [followerDid, followedDid]) .filter((d): d is string => !!d), ); const resolvedDids = await Promise.all( [...didSet].map(async (did) => { try { return await didres.resolveAtprotoData(did); } catch { return null; } }), ); const didMap = new Map(); for (const resolved of resolvedDids) { if (resolved) didMap.set(resolved.did, resolved); } return c.json( follows.map((follow) => ({ ...follow, followerHandle: didMap.get(follow.followerDid)?.handle, followedHandle: didMap.get(follow.followedDid!)?.handle, })), ); }); const server = serve(app, (d) => console.log("Listening on", d)); // graceful shutdown process.on("SIGINT", () => { server.close(); channel.destroy(); process.exit(0); }); process.on("SIGTERM", () => { server.close((err) => { channel.destroy(); if (err) { console.error(err); process.exit(1); } process.exit(0); }); });