2024-12-19 01:32:27 -06:00

162 lines
3.7 KiB
JavaScript
Executable File

const fetch = require("node-fetch")
const path = require("path")
const cacheManager = require("./cache-manager")
const apiInstance = "https://sponsor.ajay.app"
async function internalGetSB(videoID) {
// Check if data already exists
const existingData = cacheManager.read("sb")[videoID]
if (existingData)
return existingData
let data = []
// Otherwise, fetch
let r
try {
r = await fetch(path.join(apiInstance, `/api/skipSegments?videoID=${videoID}&service=youtube`))
if (r.status == 400 || r.status == 404)
throw new Error(r.statusText)
} catch (e) {
if (e instanceof fetch.FetchError)
return new Error(`FetchError (${e.code})`)
return e
}
let sbData = await r.json()
if (!r.ok && !sbData && !sbData.randomTime)
return new Error(`Status: ${r.status}`)
if (sbData)
data = sbData
cacheManager.write("sb", videoID, data)
return data
}
async function internalGetDeArrow(videoID) {
// Check if data already exists
const existingData = cacheManager.read("dearrow")[videoID]
if (existingData && !existingData.loading)
return existingData
let data = {}
// Otherwise, fetch
let r
try {
r = await fetch(path.join(apiInstance, `/api/branding?videoID=${videoID}&service=youtube`))
} catch (e) {
if (e instanceof fetch.FetchError)
return new Error(`FetchError (${e.code})`)
return e
}
let dearrowData = await r.json()
if (!r.ok && !dearrowData && !dearrowData.randomTime)
return new Error(`Status: ${r.status}`)
if (dearrowData) {
for (const title of dearrowData.titles)
if (title.votes > 0 || title.locked) {
// Use original title
if (title.original)
break
data.title = title.title
break
}
for (const thumbnail of dearrowData.thumbnails)
if (thumbnail.votes > 0) {
// Use original thumbnail
if (thumbnail.original)
break
data.thumbnail = `api/v1/getThumbnail?videoID=${videoID}&time=${thumbnail.timestamp}`
break
}
}
cacheManager.write("dearrow", videoID, data)
return data
}
module.exports = {
getSB: async function(id) {
let error = undefined
let outData = undefined
await internalGetSB(id)
.then(data => {
if (data.message)
error = `SponsorBlock for ${id}: ${data}`
else
outData = data
})
return{ error, data: outData }
},
getDeArrow: async function(id) {
let error = undefined
let outData = undefined
await internalGetDeArrow(id)
.then(data => {
if (data.message)
error = `DeArrow for ${id}: ${data}`
else
outData = data
})
return{ error, data: outData }
},
applyToAllDeArrow: async function(videos) {
let errors = {}
let queue = videos.map(v => { return { id: v.videoId, tries: 0 } })
while (queue.length > 0) {
let nextQueue = []
for (let i = 0; i < Math.min(queue.length, 3) && nextQueue.length < 3; i++)
nextQueue.push(queue.shift())
await Promise.all(nextQueue.map(v => internalGetDeArrow(v.id)
.then(data => {
if (data.message)
if (data.message.startsWith("FetchError"))
if (v.tries < 3) {
v.tries++
queue.unshift(v)
} else
errors[data.name] = `DeArrow for ${v.id}: ${data}`
else
errors[data.name] = `DeArrow for ${v.id}: ${data}`
})))
}
return { errors };
},
getAllDeArrowNoBlock: function(videos) {
// Apply a "loading" value to each video before starting the operation
let anyLoading = false
for (const v of videos) {
const oldData = cacheManager.read("dearrow")[v.videoId]
if (!oldData) {
cacheManager.write("dearrow", v.videoId, { loading: true })
v.dearrowData = { loading: true }
anyLoading = true
} else
v.dearrowData = oldData
}
if (anyLoading)
this.applyToAllDeArrow(videos)
}
}