mirror of
https://github.com/LBRYFoundation/Watch-on-LBRY.git
synced 2025-08-23 17:47:26 +00:00
84 lines
3.3 KiB
TypeScript
84 lines
3.3 KiB
TypeScript
import { chunk } from "lodash"
|
|
import { sign } from "../crypto"
|
|
import { getExtensionSettingsAsync, ytUrlResolversSettings } from "../settings"
|
|
import { LbryPathnameCache } from "./urlCache"
|
|
|
|
const QUERY_CHUNK_SIZE = 100
|
|
|
|
export type YtUrlResolveItem = { type: 'video' | 'channel', id: string }
|
|
type Results = Record<string, YtUrlResolveItem>
|
|
type Paramaters = YtUrlResolveItem[]
|
|
|
|
interface ApiResponse {
|
|
channels?: Record<string, string>
|
|
videos?: Record<string, string>
|
|
}
|
|
|
|
export async function resolveById(params: Paramaters, progressCallback?: (progress: number) => void): Promise<Results> {
|
|
const { urlResolver: urlResolverSettingName, privateKey, publicKey } = await getExtensionSettingsAsync()
|
|
const urlResolverSetting = ytUrlResolversSettings[urlResolverSettingName]
|
|
|
|
async function requestChunk(params: Paramaters) {
|
|
const results: Results = {}
|
|
|
|
// Check for cache first, add them to the results if there are any cache
|
|
// And remove them from the params, so we dont request for them
|
|
params = (await Promise.all(params.map(async (item) => {
|
|
const cachedLbryUrl = await LbryPathnameCache.get(item.id)
|
|
|
|
// Cache can be null, if there is no lbry url yet
|
|
if (cachedLbryUrl !== undefined) {
|
|
// Null values shouldn't be in the results
|
|
if (cachedLbryUrl !== null) results[item.id] = { id: cachedLbryUrl, type: item.type }
|
|
return null
|
|
}
|
|
|
|
// No cache found
|
|
return item
|
|
}))).filter((o) => o) as Paramaters
|
|
|
|
if (params.length === 0) return results
|
|
|
|
const url = new URL(`${urlResolverSetting.href}`)
|
|
url.searchParams.set('video_ids', params.filter((item) => item.type === 'video').map((item) => item.id).join(','))
|
|
url.searchParams.set('channel_ids', params.filter((item) => item.type === 'channel').map((item) => item.id).join(','))
|
|
if (urlResolverSetting.signRequest && publicKey && privateKey)
|
|
url.searchParams.set('keys', JSON.stringify({
|
|
signature: await sign(url.searchParams.toString(), privateKey),
|
|
publicKey
|
|
}))
|
|
|
|
const apiResponse = await fetch(url.toString(), { cache: 'no-store' })
|
|
if (apiResponse.ok) {
|
|
const response: ApiResponse = await apiResponse.json()
|
|
for (const [id, lbryUrl] of Object.entries(response.channels ?? {})) {
|
|
// we cache it no matter if its null or not
|
|
await LbryPathnameCache.put(lbryUrl, id)
|
|
|
|
if (lbryUrl) results[id] = { id: lbryUrl, type: 'channel' }
|
|
}
|
|
for (const [id, lbryUrl] of Object.entries(response.videos ?? {})) {
|
|
// we cache it no matter if its null or not
|
|
await LbryPathnameCache.put(lbryUrl, id)
|
|
|
|
if (lbryUrl) results[id] = { id: lbryUrl, type: 'video' }
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
const results: Results = {}
|
|
const chunks = chunk(params, QUERY_CHUNK_SIZE)
|
|
|
|
let i = 0
|
|
if (progressCallback) progressCallback(0)
|
|
for (const chunk of chunks) {
|
|
if (progressCallback) progressCallback(++i / (chunks.length + 1))
|
|
Object.assign(results, await requestChunk(chunk))
|
|
}
|
|
console.log(results)
|
|
|
|
if (progressCallback) progressCallback(1)
|
|
return results
|
|
}
|