a tool for shared writing and social publishing
1import { getIdentityData } from "actions/getIdentityData";
2import { BlueskyLogin } from "app/login/LoginForm";
3import { codeToHtml } from "shiki";
4import { FixFeedsButton } from "./fixFeedsButton";
5
6export default async function Page() {
7 let identity = await getIdentityData();
8 if (!identity) {
9 return (
10 <Layout>
11 <BlueskyLogin redirectRoute="/lish/sorry-boris" />
12 </Layout>
13 );
14 }
15 let code = await codeToHtml(source, {
16 lang: "typescript",
17 theme: "catppuccin-latte",
18 });
19 return (
20 <Layout>
21 <FixFeedsButton />
22 <pre dangerouslySetInnerHTML={{ __html: code }} />
23 </Layout>
24 );
25}
26
27function Layout(props: { children: React.ReactNode }) {
28 return (
29 <div className="flex flex-col items-center justify-center h-screen gap-4">
30 {props.children}
31 </div>
32 );
33}
34
35let source = `
36 import { AppBskyActorDefs, Agent as BskyAgent } from "@atproto/api";
37 import { getIdentityData } from "actions/getIdentityData";
38 import { createOauthClient } from "src/atproto-oauth";
39 const leafletFeedURI =
40 "at://did:plc:btxrwcaeyodrap5mnjw2fvmz/app.bsky.feed.generator/subscribedPublications";
41
42 export async function fixFeeds() {
43 const oauthClient = await createOauthClient();
44 let identity = await getIdentityData();
45 if (!identity || !identity.atp_did) {
46 throw new Error("Invalid identity data");
47 }
48
49 let credentialSession = await oauthClient.restore(identity.atp_did);
50 let bsky = new BskyAgent(credentialSession);
51 let prefs = await bsky.app.bsky.actor.getPreferences();
52 let savedFeeds = prefs.data.preferences.find(
53 (pref) => pref.$type === "app.bsky.actor.defs#savedFeedsPrefV2",
54 ) as AppBskyActorDefs.SavedFeedsPrefV2;
55
56 let pubFeeds = savedFeeds.items.filter(
57 (feed) => feed.value === leafletFeedURI,
58 );
59 await bsky.removeSavedFeeds(pubFeeds.map((f) => f.id));
60
61 await bsky.addSavedFeeds([
62 {
63 value: leafletFeedURI,
64 pinned: true,
65 type: "feed",
66 },
67 ]);
68 }
69 `;