[Video] Authed video upload (#4885)
* add service auth call * update API package --------- Co-authored-by: Samuel Newman <10959775+mozzius@users.noreply.github.com>zio/stable
parent
753a233408
commit
b701e8c68c
|
@ -52,7 +52,7 @@
|
||||||
"open-analyzer": "EXPO_PUBLIC_OPEN_ANALYZER=1 yarn build-web"
|
"open-analyzer": "EXPO_PUBLIC_OPEN_ANALYZER=1 yarn build-web"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@atproto/api": "^0.12.26",
|
"@atproto/api": "0.12.29",
|
||||||
"@bam.tech/react-native-image-resizer": "^3.0.4",
|
"@bam.tech/react-native-image-resizer": "^3.0.4",
|
||||||
"@braintree/sanitize-url": "^6.0.2",
|
"@braintree/sanitize-url": "^6.0.2",
|
||||||
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
|
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
|
||||||
|
|
|
@ -2,10 +2,11 @@ import {createUploadTask, FileSystemUploadType} from 'expo-file-system'
|
||||||
import {useMutation} from '@tanstack/react-query'
|
import {useMutation} from '@tanstack/react-query'
|
||||||
import {nanoid} from 'nanoid/non-secure'
|
import {nanoid} from 'nanoid/non-secure'
|
||||||
|
|
||||||
import {CompressedVideo} from 'lib/media/video/compress'
|
import {CompressedVideo} from '#/lib/media/video/compress'
|
||||||
import {UploadVideoResponse} from 'lib/media/video/types'
|
import {UploadVideoResponse} from '#/lib/media/video/types'
|
||||||
import {createVideoEndpointUrl} from 'state/queries/video/util'
|
import {createVideoEndpointUrl} from '#/state/queries/video/util'
|
||||||
import {useSession} from 'state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
|
|
||||||
const UPLOAD_HEADER = process.env.EXPO_PUBLIC_VIDEO_HEADER ?? ''
|
const UPLOAD_HEADER = process.env.EXPO_PUBLIC_VIDEO_HEADER ?? ''
|
||||||
|
|
||||||
export const useUploadVideoMutation = ({
|
export const useUploadVideoMutation = ({
|
||||||
|
@ -18,6 +19,7 @@ export const useUploadVideoMutation = ({
|
||||||
setProgress: (progress: number) => void
|
setProgress: (progress: number) => void
|
||||||
}) => {
|
}) => {
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
|
const agent = useAgent()
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async (video: CompressedVideo) => {
|
mutationFn: async (video: CompressedVideo) => {
|
||||||
|
@ -26,6 +28,17 @@ export const useUploadVideoMutation = ({
|
||||||
name: `${nanoid(12)}.mp4`, // @TODO what are we limiting this to?
|
name: `${nanoid(12)}.mp4`, // @TODO what are we limiting this to?
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// a logged-in agent should have this set, but we'll check just in case
|
||||||
|
if (!agent.pdsUrl) {
|
||||||
|
throw new Error('Agent does not have a PDS URL')
|
||||||
|
}
|
||||||
|
|
||||||
|
const {data: serviceAuth} =
|
||||||
|
await agent.api.com.atproto.server.getServiceAuth({
|
||||||
|
aud: `did:web:${agent.pdsUrl.hostname}`,
|
||||||
|
lxm: 'com.atproto.repo.uploadBlob',
|
||||||
|
})
|
||||||
|
|
||||||
const uploadTask = createUploadTask(
|
const uploadTask = createUploadTask(
|
||||||
uri,
|
uri,
|
||||||
video.uri,
|
video.uri,
|
||||||
|
@ -33,13 +46,12 @@ export const useUploadVideoMutation = ({
|
||||||
headers: {
|
headers: {
|
||||||
'dev-key': UPLOAD_HEADER,
|
'dev-key': UPLOAD_HEADER,
|
||||||
'content-type': 'video/mp4', // @TODO same question here. does the compression step always output mp4?
|
'content-type': 'video/mp4', // @TODO same question here. does the compression step always output mp4?
|
||||||
|
Authorization: `Bearer ${serviceAuth.token}`,
|
||||||
},
|
},
|
||||||
httpMethod: 'POST',
|
httpMethod: 'POST',
|
||||||
uploadType: FileSystemUploadType.BINARY_CONTENT,
|
uploadType: FileSystemUploadType.BINARY_CONTENT,
|
||||||
},
|
},
|
||||||
p => {
|
p => setProgress(p.totalBytesSent / p.totalBytesExpectedToSend),
|
||||||
setProgress(p.totalBytesSent / p.totalBytesExpectedToSend)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
const res = await uploadTask.uploadAsync()
|
const res = await uploadTask.uploadAsync()
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import {useMutation} from '@tanstack/react-query'
|
import {useMutation} from '@tanstack/react-query'
|
||||||
import {nanoid} from 'nanoid/non-secure'
|
import {nanoid} from 'nanoid/non-secure'
|
||||||
|
|
||||||
import {CompressedVideo} from 'lib/media/video/compress'
|
import {CompressedVideo} from '#/lib/media/video/compress'
|
||||||
import {UploadVideoResponse} from 'lib/media/video/types'
|
import {UploadVideoResponse} from '#/lib/media/video/types'
|
||||||
import {createVideoEndpointUrl} from 'state/queries/video/util'
|
import {createVideoEndpointUrl} from '#/state/queries/video/util'
|
||||||
import {useSession} from 'state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
|
|
||||||
const UPLOAD_HEADER = process.env.EXPO_PUBLIC_VIDEO_HEADER ?? ''
|
const UPLOAD_HEADER = process.env.EXPO_PUBLIC_VIDEO_HEADER ?? ''
|
||||||
|
|
||||||
export const useUploadVideoMutation = ({
|
export const useUploadVideoMutation = ({
|
||||||
|
@ -17,6 +18,7 @@ export const useUploadVideoMutation = ({
|
||||||
setProgress: (progress: number) => void
|
setProgress: (progress: number) => void
|
||||||
}) => {
|
}) => {
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
|
const agent = useAgent()
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async (video: CompressedVideo) => {
|
mutationFn: async (video: CompressedVideo) => {
|
||||||
|
@ -25,6 +27,17 @@ export const useUploadVideoMutation = ({
|
||||||
name: `${nanoid(12)}.mp4`, // @TODO what are we limiting this to?
|
name: `${nanoid(12)}.mp4`, // @TODO what are we limiting this to?
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// a logged-in agent should have this set, but we'll check just in case
|
||||||
|
if (!agent.pdsUrl) {
|
||||||
|
throw new Error('Agent does not have a PDS URL')
|
||||||
|
}
|
||||||
|
|
||||||
|
const {data: serviceAuth} =
|
||||||
|
await agent.api.com.atproto.server.getServiceAuth({
|
||||||
|
aud: `did:web:${agent.pdsUrl.hostname}`,
|
||||||
|
lxm: 'com.atproto.repo.uploadBlob',
|
||||||
|
})
|
||||||
|
|
||||||
const bytes = await fetch(video.uri).then(res => res.arrayBuffer())
|
const bytes = await fetch(video.uri).then(res => res.arrayBuffer())
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest()
|
const xhr = new XMLHttpRequest()
|
||||||
|
@ -53,6 +66,7 @@ export const useUploadVideoMutation = ({
|
||||||
xhr.setRequestHeader('Content-Type', 'video/mp4') // @TODO how we we set the proper content type?
|
xhr.setRequestHeader('Content-Type', 'video/mp4') // @TODO how we we set the proper content type?
|
||||||
// @TODO remove this header for prod
|
// @TODO remove this header for prod
|
||||||
xhr.setRequestHeader('dev-key', UPLOAD_HEADER)
|
xhr.setRequestHeader('dev-key', UPLOAD_HEADER)
|
||||||
|
xhr.setRequestHeader('Authorization', `Bearer ${serviceAuth.token}`)
|
||||||
xhr.send(bytes)
|
xhr.send(bytes)
|
||||||
})) as UploadVideoResponse
|
})) as UploadVideoResponse
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,10 @@
|
||||||
jsonpointer "^5.0.0"
|
jsonpointer "^5.0.0"
|
||||||
leven "^3.1.0"
|
leven "^3.1.0"
|
||||||
|
|
||||||
"@atproto/api@^0.12.26":
|
"@atproto/api@0.12.29":
|
||||||
version "0.12.26"
|
version "0.12.29"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.12.26.tgz#940888466522cc9ff8c03d8164dc39221b29d9ca"
|
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.12.29.tgz#95a19202c2f0eec4c955909685be11009ba9b9a1"
|
||||||
integrity sha512-RH0ymOGbDfT8IL8eNzzY+hwtyTgknHfkzUVqRd0sstNblvTf8WGpDR2FSTveiiMR3OpVO6zG8fRYVzBfmY1+pA==
|
integrity sha512-PyzPLjGWR0qNOMrmj3Nt3N5NuuANSgOk/33Bu3j+rFjjPrHvk9CI6iQPU6zuDaDCoyOTRJRafw8X/aMQw+ilgw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/common-web" "^0.3.0"
|
"@atproto/common-web" "^0.3.0"
|
||||||
"@atproto/lexicon" "^0.4.0"
|
"@atproto/lexicon" "^0.4.0"
|
||||||
|
|
Loading…
Reference in New Issue