view who was fronting when a record was made

feat: handle record deletion

ptr.pet 92e6e478 b172643d

verified
Changed files
+71
src
+24
src/entrypoints/background.ts
··· 11 11 frontersCache, 12 12 parseSocialAppPostUrl, 13 13 displayNameCache, 14 + deleteFronter, 14 15 } from "@/lib/utils"; 15 16 import { 16 17 parseCanonicalResourceUri, ··· 57 58 browser.tabs.onUpdated.addListener(deleteOld); 58 59 }; 59 60 61 + const handleDelete = async ( 62 + data: any, 63 + authToken: string | null, 64 + sender: globalThis.Browser.runtime.MessageSender, 65 + ) => { 66 + if (!authToken) return; 67 + const deleted = await deleteFronter( 68 + data.repo, 69 + data.collection, 70 + data.rkey, 71 + authToken, 72 + ); 73 + if (!deleted.ok) { 74 + console.error("failed to delete fronter:", deleted.error); 75 + } 76 + }; 60 77 const handleWrite = async ( 61 78 items: any[], 62 79 authToken: string | null, ··· 238 255 if (message.type !== "RESPONSE_CAPTURED") return; 239 256 console.log("handling response", message.data); 240 257 switch (message.data.type as string) { 258 + case "delete": 259 + await handleDelete( 260 + JSON.parse(message.data.body), 261 + message.data.authToken, 262 + sender, 263 + ); 264 + break; 241 265 case "write": 242 266 await handleWrite( 243 267 JSON.parse(message.data.body).results,
+22
src/entrypoints/content.ts
··· 28 28 const overriddenFetch = async ( 29 29 ...args: [input: RequestInfo | URL, init?: RequestInit] 30 30 ) => { 31 + const getRequestBody = async () => { 32 + if (args[0] instanceof Request) { 33 + if (args[0].bodyUsed) return null; 34 + try { 35 + const clone = args[0].clone(); 36 + return await clone.text(); 37 + } catch { 38 + return null; 39 + } 40 + } else if (args[1]?.body) { 41 + return typeof args[1].body === "string" 42 + ? args[1].body 43 + : JSON.stringify(args[1].body); 44 + } 45 + return null; 46 + }; 47 + const requestBody = await getRequestBody(); 31 48 const response = await originalFetch.apply(this, args); 32 49 33 50 if (respEventName === null) return response; ··· 73 90 authToken: getAuthToken(), 74 91 }; 75 92 } else if (response.url.includes("/xrpc/com.atproto.repo.deleteRecord")) { 93 + detail = { 94 + type: "delete", 95 + body: requestBody, 96 + authToken: getAuthToken(), 97 + }; 76 98 } else if (response.url.includes("/xrpc/com.atproto.repo.createRecord")) { 77 99 detail = { 78 100 type: "writeOne",
+25
src/lib/utils.ts
··· 10 10 GenericUri, 11 11 Handle, 12 12 isHandle, 13 + Nsid, 13 14 RecordKey, 14 15 type AtprotoDid, 15 16 type ResourceUri, ··· 288 289 handle, 289 290 members: filteredMembers, 290 291 }); 292 + }; 293 + 294 + export const deleteFronter = async ( 295 + did: AtprotoDid, 296 + collection: Nsid, 297 + rkey: RecordKey, 298 + authToken: string, 299 + ): Promise<Result<boolean, string>> => { 300 + // make client 301 + const atpClient = await getAtpClient(did); 302 + 303 + // delete 304 + let maybeRecord = await atpClient.post("com.atproto.repo.deleteRecord", { 305 + input: { 306 + repo: did, 307 + collection: fronterSchema.object.shape.$type.expected, 308 + rkey: `${collection}_${rkey}`, 309 + }, 310 + headers: { authorization: `Bearer ${authToken}` }, 311 + }); 312 + if (!maybeRecord.ok) 313 + return err(maybeRecord.data.message ?? maybeRecord.data.error); 314 + 315 + return ok(true); 291 316 }; 292 317 293 318 export const getSpFronters = async (): Promise<MemberUri[]> => {