view who was fronting when a record was made

feat: show fronters on reposts and likes stats

ptr.pet 39a13a6f ae26612b

verified
Changed files
+154
src
+111
src/entrypoints/background.ts
···
});
// console.log("sent thread fronters", results);
};
+
const handleInteractions = async (
+
data: any,
+
sender: globalThis.Browser.runtime.MessageSender,
+
collection: string,
+
actors: { did: AtprotoDid; displayName: string }[],
+
) => {
+
const postUri = data.uri as ResourceUri;
+
const fetchInteractions = async (cursor?: string) => {
+
const resp = await fetch(
+
`https://constellation.microcosm.blue/links?target=${postUri}&collection=${collection}&path=.subject.uri&limit=100${cursor ? `&cursor=${cursor}` : ""}`,
+
);
+
if (!resp.ok) return;
+
const data = await resp.json();
+
return {
+
total: data.total as number,
+
records: data.linking_records.map(
+
(record: any) =>
+
`at://${record.did}/${record.collection}/${record.rkey}` as ResourceUri,
+
) as ResourceUri[],
+
cursor: data.cursor as string,
+
};
+
};
+
let interactions = await fetchInteractions();
+
if (!interactions) return;
+
let allRecords: (typeof interactions)["records"] = [];
+
while (allRecords.length < interactions.total) {
+
allRecords.push(...interactions.records);
+
if (!interactions.cursor) break;
+
interactions = await fetchInteractions(interactions.cursor);
+
if (!interactions) break;
+
}
+
+
const actorMap = new Map(
+
actors.map((actor) => [actor.did, actor.displayName]),
+
);
+
const allPromises = allRecords.map(
+
async (recordUri): Promise<FronterView | undefined> => {
+
const cachedFronter = await frontersCache.get(recordUri);
+
let fronter =
+
(cachedFronter ?? null) ||
+
(await getFronter(recordUri).then((fronter) => {
+
if (!fronter.ok) {
+
frontersCache.set(recordUri, null);
+
return null;
+
}
+
return fronter.value;
+
}));
+
if (!fronter) return;
+
const parsedUri = await cacheFronter(recordUri, fronter);
+
const displayName =
+
actorMap.get(fronter.did) ??
+
(await displayNameCache.get(fronter.did));
+
if (!displayName) return;
+
return {
+
type:
+
collection === "app.bsky.feed.repost"
+
? "post_repost_entry"
+
: "post_like_entry",
+
rkey: parsedUri.rkey!,
+
displayName,
+
...fronter,
+
};
+
},
+
);
+
+
const results = new Map(
+
(await Promise.allSettled(allPromises))
+
.filter((result) => result.status === "fulfilled")
+
.flatMap((result) => result.value ?? [])
+
.flatMap((fronter) =>
+
fronterGetSocialAppHrefs(fronter).map((href) => [href, fronter]),
+
),
+
);
+
if (results.size === 0) return;
+
browser.tabs.sendMessage(sender.tab?.id!, {
+
type: "APPLY_FRONTERS",
+
results: Object.fromEntries(results),
+
});
+
};
+
const handleReposts = async (
+
data: any,
+
sender: globalThis.Browser.runtime.MessageSender,
+
) =>
+
handleInteractions(
+
data,
+
sender,
+
"app.bsky.feed.repost",
+
data.repostedBy.map((by: any) => ({
+
did: by.did,
+
displayName: by.displayName,
+
})),
+
);
+
const handleLikes = async (
+
data: any,
+
sender: globalThis.Browser.runtime.MessageSender,
+
) =>
+
handleInteractions(
+
data,
+
sender,
+
"app.bsky.feed.like",
+
data.likes.map((by: any) => ({
+
did: by.actor.did,
+
displayName: by.actor.displayName,
+
})),
+
);
browser.runtime.onMessage.addListener(async (message, sender) => {
if (message.type !== "RESPONSE_CAPTURED") return;
···
break;
case "notifications":
await handleNotifications(JSON.parse(message.data.body), sender);
+
break;
+
case "reposts":
+
await handleReposts(JSON.parse(message.data.body), sender);
+
break;
+
case "likes":
+
await handleLikes(JSON.parse(message.data.body), sender);
break;
}
});
+27
src/entrypoints/content.ts
···
type: "notifications",
body,
};
+
} else if (response.url.includes("/xrpc/app.bsky.feed.getLikes")) {
+
detail = {
+
type: "likes",
+
body,
+
};
+
} else if (response.url.includes("/xrpc/app.bsky.feed.getRepostedBy")) {
+
detail = {
+
type: "reposts",
+
body,
+
};
}
if (detail) {
sendEvent(detail);
···
fronter.did !== actorIdentifier;
if (isUser) displayNameElement = null;
} else displayNameElement = null;
+
} else if (
+
fronter.type === "post_repost_entry" ||
+
fronter.type === "post_like_entry"
+
) {
+
// HACK: evil ass way to do this
+
if (el.ariaLabel !== `View ${fronter.displayName}'s profile`) return;
+
displayNameElement =
+
el.firstElementChild?.firstElementChild?.firstElementChild
+
?.nextElementSibling?.firstElementChild?.firstElementChild ??
+
null;
+
if (displayNameElement?.tagName !== "DIV") {
+
console.log(
+
`invalid display element tag ${displayNameElement?.tagName}, expected div:`,
+
displayNameElement,
+
);
+
return;
+
}
}
if (!displayNameElement) return;
return applyFronterName(displayNameElement, fronter.members);
+16
src/lib/utils.ts
···
type: "notification";
reason: InferOutput<AppBskyNotificationListNotifications.notificationSchema>["reason"];
}
+
| {
+
type: "post_repost_entry";
+
displayName: string;
+
}
+
| {
+
type: "post_like_entry";
+
displayName: string;
+
}
);
export type FronterType = FronterView["type"];
···
return [
handle ? [`${fronterGetSocialAppHref(handle, subject.rkey)}`] : [],
`${fronterGetSocialAppHref(subject.did, subject.rkey)}`,
+
].flat();
+
} else if (
+
view.type === "post_repost_entry" ||
+
view.type === "post_like_entry"
+
) {
+
return [
+
view.handle ? [`/profile/${view.handle}`] : [],
+
`/profile/${view.did}`,
].flat();
}
const depth = view.type === "thread_post" ? view.depth : undefined;