Live video on the AT Protocol
1import { PlaceStreamMetadataConfiguration } from "streamplace";
2import {
3 ContentMetadataResult,
4 useDID,
5 useSetContentMetadata,
6 useStreamplaceStore,
7} from "./streamplace-store";
8import { usePDSAgent } from "./xrpc";
9
10export const useGetBroadcasterDID = () => {
11 const pdsAgent = usePDSAgent();
12 const did = useDID();
13 const setBroadcasterDID = useStreamplaceStore(
14 (state) => state.setBroadcasterDID,
15 );
16 const setServerDID = useStreamplaceStore((state) => state.setServerDID);
17 return async () => {
18 if (!pdsAgent || !did) {
19 throw new Error("No PDS agent or DID available");
20 }
21
22 const result = await pdsAgent.place.stream.broadcast.getBroadcaster();
23 if (!result.success) {
24 throw new Error("Failed to get broadcaster DID");
25 }
26 setBroadcasterDID(result.data.broadcaster);
27 if (result.data.server) {
28 setServerDID(result.data.server);
29 } else {
30 setServerDID(null);
31 }
32 };
33};
34
35export const useSaveContentMetadata = () => {
36 const pdsAgent = usePDSAgent();
37 const did = useDID();
38 const setContentMetadata = useSetContentMetadata();
39
40 return async (metadataRecord: PlaceStreamMetadataConfiguration.Record) => {
41 if (!pdsAgent || !did) {
42 throw new Error("No PDS agent or DID available");
43 }
44
45 try {
46 // Try to update existing record first
47 const result = await (pdsAgent as any).com.atproto.repo.putRecord({
48 repo: did,
49 collection: "place.stream.metadata.configuration",
50 rkey: "self",
51 record: metadataRecord,
52 });
53
54 const contentMetadata: ContentMetadataResult = {
55 record: metadataRecord as any,
56 uri: result.data.uri,
57 cid: result.data.cid || "",
58 rkey: "self",
59 };
60
61 setContentMetadata(contentMetadata);
62 return contentMetadata;
63 } catch (error) {
64 // If record doesn't exist, create it
65 if (
66 error instanceof Error &&
67 (error.message?.includes("not found") ||
68 error.message?.includes("RecordNotFound") ||
69 error.message?.includes("mst: not found") ||
70 (error as any)?.status === 404)
71 ) {
72 const createResult = await (
73 pdsAgent as any
74 ).com.atproto.repo.createRecord({
75 repo: did,
76 collection: "place.stream.metadata.configuration",
77 rkey: "self",
78 record: metadataRecord,
79 });
80
81 const contentMetadata: ContentMetadataResult = {
82 record: metadataRecord as any,
83 uri: createResult.data.uri,
84 cid: createResult.data.cid || "",
85 rkey: "self",
86 };
87
88 setContentMetadata(contentMetadata);
89 return contentMetadata;
90 }
91 throw error;
92 }
93 };
94};
95
96// Simple get function
97export const useGetContentMetadata = () => {
98 const pdsAgent = usePDSAgent();
99 const did = useDID();
100 const setContentMetadata = useSetContentMetadata();
101
102 return async (params?: { userDid?: string; rkey?: string }) => {
103 if (!pdsAgent) {
104 throw new Error("No PDS agent available");
105 }
106
107 const targetDid = params?.userDid || did;
108 if (!targetDid) {
109 throw new Error("No DID provided or user not authenticated");
110 }
111
112 try {
113 const result = await (pdsAgent as any).com.atproto.repo.getRecord({
114 repo: targetDid,
115 collection: "place.stream.metadata.configuration",
116 rkey: params?.rkey || "self",
117 });
118
119 if (!result.success) {
120 throw new Error("Failed to get content metadata record");
121 }
122
123 const contentMetadata: ContentMetadataResult = {
124 record: result.data.value,
125 uri: result.data.uri,
126 cid: result.data.cid || "",
127 };
128
129 setContentMetadata(contentMetadata);
130 return contentMetadata;
131 } catch (error) {
132 // Handle record not found - this is normal for new users
133 if (
134 error instanceof Error &&
135 (error.message?.includes("not found") ||
136 error.message?.includes("RecordNotFound") ||
137 error.message?.includes("mst: not found") ||
138 (error as any)?.status === 404)
139 ) {
140 return null;
141 }
142 throw error;
143 }
144 };
145};