get deleted posts from Jetstream
@roland.cros.by · 9h ago · typescript · 155 loc · raw · 0 comments
1#!/usr/bin/env -S deno --allow-net --allow-env23import * as path from "jsr:@std/path";4import { simpleFetchHandler, XRPC } from "npm:@atcute/client";5import { JetstreamSubscription } from "npm:@atcute/jetstream";6import * as TID from "npm:@atcute/tid";78function usage() {9 const scriptName = path.basename(Deno.mainModule);10 console.log(11 `Usage:12 ${scriptName} at://handle-or-did/collection/rkey13 ${scriptName} https://bsky.app/profile/handle-or-did/post/rkey14 ${scriptName} handle-or-did rkey`,15 );16 Deno.exit(1);17}1819if (Deno.args.length < 1 || Deno.args.length > 2) {20 usage();21}2223const atRegex = /at:\/\/([^/]+)\/([^/]+)\/([^/"]+)/;2425let didOrHandle;26let did;27let collection;28let rkey;29if (Deno.args.length == 1) {30 if (Deno.args[0].startsWith("at://")) {31 const match = Deno.args[0].match(atRegex);32 if (match) {33 didOrHandle = match[1];34 collection = match[2];35 rkey = match[3];36 } else usage();37 } else {38 const match = Deno.args[0].match(/\/profile\/([^/]+)\/post\/([2-7a-z]+)/);39 if (match) {40 didOrHandle = match[1];41 collection = "app.bsky.feed.post";42 rkey = match[2];43 } else usage();44 }45} else {46 didOrHandle = Deno.args[0];47 rkey = Deno.args[1];48 collection = "app.bsky.feed.post";49}5051if (didOrHandle.startsWith("did:")) {52 did = didOrHandle;53} else {54 const handler = simpleFetchHandler({55 service: "https://public.api.bsky.app",56 });57 const rpc = new XRPC({ handler });58 try {59 const { data } = await rpc.get("com.atproto.identity.resolveHandle", {60 params: { handle: didOrHandle },61 });62 did = data.did;63 } catch (e) {64 console.error(e);65 Deno.exit(1);66 }67}6869console.log(did, rkey);7071function dateFromTID(tid: String): Date {72 return new Date(TID.parse(tid).timestamp / 1000.0);73}7475function dateFromCursor(cursor: Number): Date {76 return new Date(cursor / 1000.0);77}7879function formatDate(date: Date): string {80 return date.toISOString().replace("T", " ").replace("Z", "");81}8283function atURILink(did: string, collection: string, rkey: string): string {84 const atURI = `at://${did}/${collection}/${rkey}`;85 return `\x1b]8;;https://pdsls.dev/${atURI}\x1b\\${atURI}\x1b]8;;\x1b\\`;86}8788function linkify(text: string): string {89 return text.replace(90 /at:\/\/([^/]+)\/([^/]+)\/([^/"]+)/g,91 (match, did, collection, rkey) => {92 return atURILink(did, collection, rkey);93 },94 );95}9697async function getSingleEvent() {98 const subscription = new JetstreamSubscription({99 url: "wss://jetstream1.us-east.bsky.network",100 });101 for await (const event of subscription) {102 if (event.kind === "commit") return event;103 }104 throw new Error("No commit events received");105}106107// const event = await getSingleEvent();108// console.log(109// `Latest:110// Cursor: ${formatDate(dateFromCursor(event.time_us))} (${event.time_us})111// Rev: ${formatDate(dateFromTID(event.commit.rev))} (${event.commit.rev})`,112// );113114const postTime = dateFromTID(rkey);115const offset = 5 * 60 * 1000;116const startCursor = (postTime.getTime() - offset) * 1000;117118console.log(119 `Target:120Rkey time: ${formatDate(postTime)} (${rkey})121Start cursor: ${formatDate(dateFromCursor(startCursor))} (${startCursor})122`,123);124125const subscription = new JetstreamSubscription({126 url: "wss://jetstream2.us-east.bsky.network",127 wantedCollections: [collection],128 wantedDids: [did],129 cursor: startCursor,130});131132for await (const event of subscription) {133 if (event.kind === "commit") {134 const atURI = atURILink(135 event.did,136 event.commit.collection,137 event.commit.rkey,138 );139 console.log(140 `Stream event ${atURI}141Rev time: ${formatDate(dateFromTID(event.commit.rev))} (${event.commit.rev})142Cursor: ${formatDate(dateFromCursor(event.time_us))} (${event.time_us})143`,144 );145 if (event.commit.rkey === rkey) {146 console.log(`Found post ${atURI}`);147 console.log(linkify(JSON.stringify(event, null, 2)));148 break;149 } else if (event.commit.rkey > rkey) {150 console.log("Saw event with rkey after expected rkey");151 break;152 }153 }154}155
login to post a comment