a tool for shared writing and social publishing

add page for boris

+135
+35
app/lish/sorry-boris/fixFeeds.ts
··· 1 + "use server"; 2 + 3 + import { AppBskyActorDefs, Agent as BskyAgent } from "@atproto/api"; 4 + import { getIdentityData } from "actions/getIdentityData"; 5 + import { createOauthClient } from "src/atproto-oauth"; 6 + const leafletFeedURI = 7 + "at://did:plc:btxrwcaeyodrap5mnjw2fvmz/app.bsky.feed.generator/subscribedPublications"; 8 + 9 + export async function fixFeeds() { 10 + const oauthClient = await createOauthClient(); 11 + let identity = await getIdentityData(); 12 + if (!identity || !identity.atp_did) { 13 + throw new Error("Invalid identity data"); 14 + } 15 + 16 + let credentialSession = await oauthClient.restore(identity.atp_did); 17 + let bsky = new BskyAgent(credentialSession); 18 + let prefs = await bsky.app.bsky.actor.getPreferences(); 19 + let savedFeeds = prefs.data.preferences.find( 20 + (pref) => pref.$type === "app.bsky.actor.defs#savedFeedsPrefV2", 21 + ) as AppBskyActorDefs.SavedFeedsPrefV2; 22 + 23 + let pubFeeds = savedFeeds.items.filter( 24 + (feed) => feed.value === leafletFeedURI, 25 + ); 26 + await bsky.removeSavedFeeds(pubFeeds.map((f) => f.id)); 27 + 28 + await bsky.addSavedFeeds([ 29 + { 30 + value: leafletFeedURI, 31 + pinned: true, 32 + type: "feed", 33 + }, 34 + ]); 35 + }
+31
app/lish/sorry-boris/fixFeedsButton.tsx
··· 1 + "use client"; 2 + 3 + import { useSmoker } from "components/Toast"; 4 + import { fixFeeds } from "./fixFeeds"; 5 + import { ButtonPrimary } from "components/Buttons"; 6 + import { DotLoader } from "components/utils/DotLoader"; 7 + import { useState } from "react"; 8 + 9 + export function FixFeedsButton() { 10 + let smoker = useSmoker(); 11 + let [loading, setLoading] = useState(false); 12 + return ( 13 + <ButtonPrimary 14 + onClick={async (e) => { 15 + let rect = e.currentTarget?.getBoundingClientRect(); 16 + setLoading(true); 17 + await fixFeeds(); 18 + setLoading(false); 19 + smoker({ 20 + position: { 21 + x: rect.left + (rect.right - rect.left) / 2, 22 + y: rect.top - 16, 23 + }, 24 + text: "Fixed your feeds!", 25 + }); 26 + }} 27 + > 28 + {loading ? <DotLoader /> : "Fix My Feeds"} 29 + </ButtonPrimary> 30 + ); 31 + }
+69
app/lish/sorry-boris/page.tsx
··· 1 + import { getIdentityData } from "actions/getIdentityData"; 2 + import { BlueskyLogin } from "app/login/LoginForm"; 3 + import { codeToHtml } from "shiki"; 4 + import { FixFeedsButton } from "./fixFeedsButton"; 5 + 6 + export 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 + 27 + function 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 + 35 + let 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 + `;