creates video voice memos from audio clips; with bluesky integration. trill.ptr.pet
1import { XrpcHandleResolver } from "@atcute/identity-resolver"; 2import { OAuthUserAgent } from "@atcute/oauth-browser-client"; 3import { Client as AtcuteClient, simpleFetchHandler } from "@atcute/client"; 4import { getSessionClient } from "./oauth"; 5import { AppBskyFeedPost } from "@atcute/bluesky"; 6import { AtprotoDid } from "@atcute/lexicons/syntax"; 7 8export const slingshotUrl = "https://slingshot.microcosm.blue"; 9 10export const handleResolver = new XrpcHandleResolver({ 11 serviceUrl: slingshotUrl, 12}); 13export const slingshot = new AtcuteClient({ 14 handler: simpleFetchHandler({ service: slingshotUrl }), 15}); 16 17export const login = async (agent: OAuthUserAgent) => { 18 const rpc = new AtcuteClient({ handler: agent }); 19 const res = await rpc.get("com.atproto.server.getSession", { params: {} }); 20 if (!res.ok) throw res.data.error; 21 const didDoc = await slingshot.get( 22 "com.bad-example.identity.resolveMiniDoc", 23 { params: { identifier: res.data.did } }, 24 ); 25 if (!didDoc.ok) throw didDoc.data.error; 26 return { 27 client: rpc, 28 did: res.data.did, 29 handle: res.data.handle, 30 pds: didDoc.data.pds, 31 }; 32}; 33 34export const sendPost = async ( 35 did: AtprotoDid, 36 blob: Blob, 37 postContent: string, 38) => { 39 const login = await getSessionClient(did); 40 const upload = await login.client.post("com.atproto.repo.uploadBlob", { 41 input: blob, 42 }); 43 if (!upload.ok) throw `failed to upload blob: ${upload.data.error}`; 44 const record: AppBskyFeedPost.Main = { 45 $type: "app.bsky.feed.post", 46 text: postContent, 47 embed: { 48 $type: "app.bsky.embed.video", 49 video: upload.data.blob, 50 }, 51 createdAt: new Date().toISOString(), 52 }; 53 const result = await login.client.post("com.atproto.repo.createRecord", { 54 input: { 55 collection: "app.bsky.feed.post", 56 record, 57 repo: did, 58 }, 59 }); 60 if (!result.ok) throw `failed to upload post: ${result.data.error}`; 61 return result.data; 62};