atmosphere explorer pds.ls
tool typescript atproto
427
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 95 lines 3.3 kB view raw
1import { Client, simpleFetchHandler } from "@atcute/client"; 2import { Did } from "@atcute/lexicons"; 3import { 4 finalizeAuthorization, 5 getSession, 6 OAuthUserAgent, 7 type Session, 8} from "@atcute/oauth-browser-client"; 9import { resolveDidDoc } from "../lib/api"; 10import { Sessions, setAgent, setSessions } from "./state"; 11 12export const saveSessionToStorage = (sessions: Sessions) => { 13 localStorage.setItem("sessions", JSON.stringify(sessions)); 14}; 15 16export const loadSessionsFromStorage = (): Sessions | null => { 17 const localSessions = localStorage.getItem("sessions"); 18 return localSessions ? JSON.parse(localSessions) : null; 19}; 20 21export const getAvatar = async (did: Did): Promise<string | undefined> => { 22 const rpc = new Client({ 23 handler: simpleFetchHandler({ service: "https://public.api.bsky.app" }), 24 }); 25 const res = await rpc.get("app.bsky.actor.getProfile", { params: { actor: did } }); 26 if (res.ok) { 27 return res.data.avatar; 28 } 29 return undefined; 30}; 31 32export const loadHandleForSession = async (did: Did, storedSessions: Sessions) => { 33 const doc = await resolveDidDoc(did); 34 const alias = doc.alsoKnownAs?.find((alias) => alias.startsWith("at://")); 35 if (alias) { 36 setSessions(did, { 37 signedIn: storedSessions[did].signedIn, 38 handle: alias.replace("at://", ""), 39 grantedScopes: storedSessions[did].grantedScopes, 40 }); 41 } 42}; 43 44export const retrieveSession = async (): Promise<void> => { 45 const init = async (): Promise<Session | undefined> => { 46 const params = new URLSearchParams(decodeURIComponent(location.hash.slice(1))); 47 48 if (params.has("state") && (params.has("code") || params.has("error"))) { 49 history.replaceState(null, "", location.pathname + location.search); 50 51 const auth = await finalizeAuthorization(params); 52 const did = auth.session.info.sub; 53 54 localStorage.setItem("lastSignedIn", did); 55 56 const grantedScopes = localStorage.getItem("pendingScopes") || "atproto"; 57 localStorage.removeItem("pendingScopes"); 58 59 const sessions = loadSessionsFromStorage(); 60 const newSessions: Sessions = sessions || {}; 61 newSessions[did] = { signedIn: true, grantedScopes }; 62 saveSessionToStorage(newSessions); 63 return auth.session; 64 } else { 65 const lastSignedIn = localStorage.getItem("lastSignedIn"); 66 67 if (lastSignedIn) { 68 const sessions = loadSessionsFromStorage(); 69 const newSessions: Sessions = sessions || {}; 70 try { 71 const session = await getSession(lastSignedIn as Did); 72 const rpc = new Client({ handler: new OAuthUserAgent(session) }); 73 const res = await rpc.get("com.atproto.server.getSession"); 74 newSessions[lastSignedIn].signedIn = true; 75 saveSessionToStorage(newSessions); 76 if (!res.ok) throw res.data.error; 77 return session; 78 } catch (err) { 79 newSessions[lastSignedIn].signedIn = false; 80 saveSessionToStorage(newSessions); 81 throw err; 82 } 83 } 84 } 85 }; 86 87 const session = await init(); 88 89 if (session) setAgent(new OAuthUserAgent(session)); 90}; 91 92export const resumeSession = async (did: Did): Promise<void> => { 93 localStorage.setItem("lastSignedIn", did); 94 await retrieveSession(); 95};