|
|
import { resolveRedirectingURL } from "../url.js"; |
|
|
import { genericUserAgent, env } from "../../config.js"; |
|
|
import { getCookie, updateCookieValues } from "../cookie/manager.js"; |
|
|
|
|
|
async function getAccessToken() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const cookie = await getCookie('reddit'); |
|
|
if (!cookie) return; |
|
|
|
|
|
const values = cookie.values(), |
|
|
needRefresh = !values.access_token |
|
|
|| !values.expiry |
|
|
|| Number(values.expiry) < new Date().getTime(); |
|
|
if (!needRefresh) return values.access_token; |
|
|
|
|
|
const data = await fetch('https://www.reddit.com/api/v1/access_token', { |
|
|
method: 'POST', |
|
|
headers: { |
|
|
'authorization': `Basic ${Buffer.from( |
|
|
[values.client_id, values.client_secret].join(':') |
|
|
).toString('base64')}`, |
|
|
'content-type': 'application/x-www-form-urlencoded', |
|
|
'user-agent': genericUserAgent, |
|
|
'accept': 'application/json' |
|
|
}, |
|
|
body: `grant_type=refresh_token&refresh_token=${encodeURIComponent(values.refresh_token)}` |
|
|
}).then(r => r.json()).catch(() => {}); |
|
|
if (!data) return; |
|
|
|
|
|
const { access_token, refresh_token, expires_in } = data; |
|
|
if (!access_token) return; |
|
|
|
|
|
updateCookieValues(cookie, { |
|
|
...cookie.values(), |
|
|
access_token, refresh_token, |
|
|
expiry: new Date().getTime() + (expires_in * 1000), |
|
|
}); |
|
|
|
|
|
return access_token; |
|
|
} |
|
|
|
|
|
export default async function(obj) { |
|
|
let params = obj; |
|
|
const accessToken = await getAccessToken(); |
|
|
const headers = { |
|
|
'user-agent': genericUserAgent, |
|
|
authorization: accessToken && `Bearer ${accessToken}`, |
|
|
accept: 'application/json' |
|
|
}; |
|
|
|
|
|
if (params.shortId) { |
|
|
params = await resolveRedirectingURL( |
|
|
`https://www.reddit.com/video/${params.shortId}`, |
|
|
obj.dispatcher, headers |
|
|
); |
|
|
} |
|
|
|
|
|
if (!params.id && params.shareId) { |
|
|
params = await resolveRedirectingURL( |
|
|
`https://www.reddit.com/r/${params.sub}/s/${params.shareId}`, |
|
|
obj.dispatcher, headers |
|
|
); |
|
|
} |
|
|
|
|
|
if (!params?.id) return { error: "fetch.short_link" }; |
|
|
|
|
|
const url = new URL(`https://www.reddit.com/comments/${params.id}.json`); |
|
|
|
|
|
if (accessToken) url.hostname = 'oauth.reddit.com'; |
|
|
|
|
|
let data = await fetch( |
|
|
url, { headers } |
|
|
).then(r => r.json()).catch(() => {}); |
|
|
|
|
|
if (!data || !Array.isArray(data)) { |
|
|
return { error: "fetch.fail" } |
|
|
} |
|
|
|
|
|
data = data[0]?.data?.children[0]?.data; |
|
|
|
|
|
let sourceId; |
|
|
if (params.sub || params.user) { |
|
|
sourceId = `${String(params.sub || params.user).toLowerCase()}_${params.id}`; |
|
|
} else { |
|
|
sourceId = params.id; |
|
|
} |
|
|
|
|
|
if (data?.url?.endsWith('.gif')) return { |
|
|
typeId: "redirect", |
|
|
urls: data.url, |
|
|
filename: `reddit_${sourceId}.gif`, |
|
|
} |
|
|
|
|
|
if (!data.secure_media?.reddit_video) |
|
|
return { error: "fetch.empty" }; |
|
|
|
|
|
if (data.secure_media?.reddit_video?.duration > env.durationLimit) |
|
|
return { error: "content.too_long" }; |
|
|
|
|
|
const video = data.secure_media?.reddit_video?.fallback_url?.split('?')[0]; |
|
|
|
|
|
let audio = false, |
|
|
audioFileLink = `${data.secure_media?.reddit_video?.fallback_url?.split('DASH')[0]}audio`; |
|
|
|
|
|
if (video.match('.mp4')) { |
|
|
audioFileLink = `${video.split('_')[0]}_audio.mp4` |
|
|
} |
|
|
|
|
|
|
|
|
await fetch(audioFileLink, { method: "HEAD" }).then(r => { |
|
|
if (Number(r.status) === 200) { |
|
|
audio = true |
|
|
} |
|
|
}).catch(() => {}) |
|
|
|
|
|
|
|
|
if (!audio) { |
|
|
audioFileLink = `${video.split('_')[0]}_AUDIO_128.mp4` |
|
|
await fetch(audioFileLink, { method: "HEAD" }).then(r => { |
|
|
if (Number(r.status) === 200) { |
|
|
audio = true |
|
|
} |
|
|
}).catch(() => {}) |
|
|
} |
|
|
|
|
|
if (!audio) return { |
|
|
typeId: "redirect", |
|
|
urls: video |
|
|
} |
|
|
|
|
|
return { |
|
|
typeId: "tunnel", |
|
|
type: "merge", |
|
|
urls: [video, audioFileLink], |
|
|
audioFilename: `reddit_${sourceId}_audio`, |
|
|
filename: `reddit_${sourceId}.mp4` |
|
|
} |
|
|
} |
|
|
|