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};