Bluesky app fork with some witchin' additions 馃挮
at main 79 lines 2.0 kB view raw
1import {createUploadTask, FileSystemUploadType} from 'expo-file-system/legacy' 2import {type AppBskyVideoDefs, type BskyAgent} from '@atproto/api' 3import {type I18n} from '@lingui/core' 4import {msg} from '@lingui/core/macro' 5import {nanoid} from 'nanoid/non-secure' 6 7import {AbortError} from '#/lib/async/cancelable' 8import {ServerError} from '#/lib/media/video/errors' 9import {type CompressedVideo} from '#/lib/media/video/types' 10import {getServiceAuthToken, getVideoUploadLimits} from './upload.shared' 11import {createVideoEndpointUrl, mimeToExt} from './util' 12 13export async function uploadVideo({ 14 video, 15 agent, 16 did, 17 setProgress, 18 signal, 19 _, 20}: { 21 video: CompressedVideo 22 agent: BskyAgent 23 did: string 24 setProgress: (progress: number) => void 25 signal: AbortSignal 26 _: I18n['_'] 27}) { 28 if (signal.aborted) { 29 throw new AbortError() 30 } 31 await getVideoUploadLimits(agent, _) 32 33 const uri = createVideoEndpointUrl('/xrpc/app.bsky.video.uploadVideo', { 34 did, 35 name: `${nanoid(12)}.${mimeToExt(video.mimeType)}`, 36 }) 37 38 if (signal.aborted) { 39 throw new AbortError() 40 } 41 const token = await getServiceAuthToken({ 42 agent, 43 lxm: 'com.atproto.repo.uploadBlob', 44 exp: Date.now() / 1000 + 60 * 30, // 30 minutes 45 }) 46 const uploadTask = createUploadTask( 47 uri, 48 video.uri, 49 { 50 headers: { 51 'content-type': video.mimeType, 52 Authorization: `Bearer ${token}`, 53 }, 54 httpMethod: 'POST', 55 uploadType: FileSystemUploadType.BINARY_CONTENT, 56 }, 57 p => setProgress(p.totalBytesSent / p.totalBytesExpectedToSend), 58 ) 59 60 if (signal.aborted) { 61 throw new AbortError() 62 } 63 const res = await uploadTask.uploadAsync() 64 65 if (!res?.body) { 66 throw new Error('No response') 67 } 68 69 const responseBody = JSON.parse(res.body) as AppBskyVideoDefs.JobStatus 70 71 if (!responseBody.jobId) { 72 throw new ServerError(responseBody.error || _(msg`Failed to upload video`)) 73 } 74 75 if (signal.aborted) { 76 throw new AbortError() 77 } 78 return responseBody 79}