Live video on the AT Protocol
79
fork

Configure Feed

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

at eli/handle-changes 98 lines 3.2 kB view raw
1import { bytesToMultibase, Secp256k1Keypair } from "@atproto/crypto"; 2import { useEffect, useState } from "react"; 3import { Platform } from "react-native"; 4import { PlaceStreamKey } from "streamplace"; 5import { privateKeyToAccount } from "viem/accounts"; 6import { getBrowserName } from "../lib/browser"; 7import { usePDSAgent } from "../streamplace-store/xrpc"; 8import { useLivestreamStore } from "./livestream-store"; 9 10export const useStreamKey = (): { 11 streamKey: { 12 privateKey: string; 13 did: string; 14 address: string; 15 } | null; 16 error: string | null; 17} => { 18 const pdsAgent = usePDSAgent(); 19 const streamKey = useLivestreamStore((state) => state.streamKey); 20 const setStreamKey = useLivestreamStore((state) => state.setStreamKey); 21 const [key, setKey] = useState<any>(streamKey ? JSON.parse(streamKey) : null); 22 const [error, setError] = useState<string | null>(null); 23 24 useEffect(() => { 25 if (key) return; // already have key 26 27 const generateKey = async () => { 28 if (!pdsAgent) { 29 setError("PDS Agent is not available"); 30 return; 31 } 32 let did = pdsAgent.did; 33 if (!did) { 34 setError("PDS Agent did is not available (not logged in?)"); 35 return; 36 } 37 38 const keypair = await Secp256k1Keypair.create({ exportable: true }); 39 const exportedKey = await keypair.export(); 40 const didBytes = new TextEncoder().encode(did); 41 const combinedKey = new Uint8Array([...exportedKey, ...didBytes]); 42 const multibaseKey = bytesToMultibase(combinedKey, "base58btc"); 43 const hexKey = Array.from(exportedKey) 44 .map((b) => b.toString(16).padStart(2, "0")) 45 .join(""); 46 const account = privateKeyToAccount(`0x${hexKey}`); 47 const newKey = { 48 privateKey: multibaseKey, 49 did: keypair.did(), 50 address: account.address.toLowerCase(), 51 }; 52 53 let platform: string = Platform.OS; 54 if ( 55 Platform.OS === "web" && 56 typeof window !== "undefined" && 57 window.navigator 58 ) { 59 if (window.navigator.userAgent.includes("streamplace-desktop")) { 60 platform = "Desktop"; 61 } else { 62 platform = getBrowserName(window.navigator.userAgent); 63 if (platform !== "unknown") { 64 platform = platform; 65 } 66 } 67 } else if (platform === "android") { 68 platform = "Android"; 69 } else if (platform === "ios") { 70 platform = "iOS"; 71 } else if (platform === "macos") { 72 platform = "macOS"; 73 } else if (platform === "windows") { 74 platform = "Windows"; 75 } 76 77 const record: PlaceStreamKey.Record = { 78 $type: "place.stream.key", 79 signingKey: keypair.did(), 80 createdAt: new Date().toISOString(), 81 createdBy: "Streamplace on " + platform, 82 }; 83 await pdsAgent.com.atproto.repo.createRecord({ 84 repo: did, 85 collection: "place.stream.key", 86 record, 87 }); 88 89 setStreamKey(JSON.stringify(newKey)); 90 setKey(newKey); 91 }; 92 93 generateKey(); 94 // eslint-disable-next-line react-hooks/exhaustive-deps 95 }, [key, setStreamKey]); 96 97 return { streamKey: key, error }; 98};