Bluesky app fork with some witchin' additions 馃挮
at main 166 lines 4.2 kB view raw
1import { 2 type $Typed, 3 type AppBskyActorDefs, 4 type AppBskyGraphGetStarterPack, 5 type BskyAgent, 6 type ComAtprotoRepoApplyWrites, 7 type Facet, 8} from '@atproto/api' 9import {msg} from '@lingui/macro' 10import {useLingui} from '@lingui/react' 11import {useMutation} from '@tanstack/react-query' 12 13import {until} from '#/lib/async/until' 14import {sanitizeDisplayName} from '#/lib/strings/display-names' 15import {sanitizeHandle} from '#/lib/strings/handles' 16import {enforceLen} from '#/lib/strings/helpers' 17import {useAgent} from '#/state/session' 18import {pdsAgent} from '#/state/session/agent' 19import type * as bsky from '#/types/bsky' 20 21export const createStarterPackList = async ({ 22 name, 23 description, 24 descriptionFacets, 25 profiles, 26 agent, 27}: { 28 name: string 29 description?: string 30 descriptionFacets?: Facet[] 31 profiles: bsky.profile.AnyProfileView[] 32 agent: BskyAgent 33}): Promise<{uri: string; cid: string}> => { 34 if (profiles.length === 0) throw new Error('No profiles given') 35 36 const list = await agent.app.bsky.graph.list.create( 37 {repo: agent.session!.did}, 38 { 39 name, 40 description, 41 descriptionFacets, 42 avatar: undefined, 43 createdAt: new Date().toISOString(), 44 purpose: 'app.bsky.graph.defs#referencelist', 45 }, 46 ) 47 if (!list) throw new Error('List creation failed') 48 await pdsAgent(agent).com.atproto.repo.applyWrites({ 49 repo: agent.session!.did, 50 writes: profiles.map(p => createListItem({did: p.did, listUri: list.uri})), 51 }) 52 53 return list 54} 55 56export function useGenerateStarterPackMutation({ 57 onSuccess, 58 onError, 59}: { 60 onSuccess: ({uri, cid}: {uri: string; cid: string}) => void 61 onError: (e: Error) => void 62}) { 63 const {_} = useLingui() 64 const agent = useAgent() 65 66 return useMutation<{uri: string; cid: string}, Error, void>({ 67 mutationFn: async () => { 68 let profile: AppBskyActorDefs.ProfileViewDetailed | undefined 69 let profiles: AppBskyActorDefs.ProfileView[] | undefined 70 71 await Promise.all([ 72 (async () => { 73 profile = ( 74 await agent.app.bsky.actor.getProfile({ 75 actor: agent.session!.did, 76 }) 77 ).data 78 })(), 79 (async () => { 80 profiles = ( 81 await agent.app.bsky.actor.searchActors({ 82 q: encodeURIComponent('*'), 83 limit: 49, 84 }) 85 ).data.actors.filter(p => p.viewer?.following) 86 })(), 87 ]) 88 89 if (!profile || !profiles) { 90 throw new Error('ERROR_DATA') 91 } 92 93 // We include ourselves when we make the list 94 if (profiles.length < 7) { 95 throw new Error('NOT_ENOUGH_FOLLOWERS') 96 } 97 98 const displayName = enforceLen( 99 profile.displayName 100 ? sanitizeDisplayName(profile.displayName) 101 : `@${sanitizeHandle(profile.handle)}`, 102 25, 103 true, 104 ) 105 const starterPackName = _(msg`${displayName}'s Starter Pack`) 106 107 const list = await createStarterPackList({ 108 name: starterPackName, 109 profiles, 110 agent, 111 }) 112 113 return await agent.app.bsky.graph.starterpack.create( 114 { 115 repo: agent.session!.did, 116 }, 117 { 118 name: starterPackName, 119 list: list.uri, 120 createdAt: new Date().toISOString(), 121 }, 122 ) 123 }, 124 onSuccess: async data => { 125 await whenAppViewReady(agent, data.uri, v => { 126 return typeof v?.data.starterPack.uri === 'string' 127 }) 128 onSuccess(data) 129 }, 130 onError: error => { 131 onError(error) 132 }, 133 }) 134} 135 136function createListItem({ 137 did, 138 listUri, 139}: { 140 did: string 141 listUri: string 142}): $Typed<ComAtprotoRepoApplyWrites.Create> { 143 return { 144 $type: 'com.atproto.repo.applyWrites#create', 145 collection: 'app.bsky.graph.listitem', 146 value: { 147 $type: 'app.bsky.graph.listitem', 148 subject: did, 149 list: listUri, 150 createdAt: new Date().toISOString(), 151 }, 152 } 153} 154 155async function whenAppViewReady( 156 agent: BskyAgent, 157 uri: string, 158 fn: (res?: AppBskyGraphGetStarterPack.Response) => boolean, 159) { 160 await until( 161 5, // 5 tries 162 1e3, // 1s delay between tries 163 fn, 164 () => agent.app.bsky.graph.getStarterPack({starterPack: uri}), 165 ) 166}