mirror of
https://github.com/wukko/cobalt.git
synced 2025-01-12 20:25:06 +01:00
reddit: add support for authenticated requests
merge pull request #221 from dumbmoron/reddit-oauth
This commit is contained in:
commit
0361c795f2
2 changed files with 60 additions and 3 deletions
|
@ -56,7 +56,10 @@ export function updateCookie(cookie, headers) {
|
||||||
|
|
||||||
cookie.unset(parsed.filter(c => c.expires < new Date()).map(c => c.name));
|
cookie.unset(parsed.filter(c => c.expires < new Date()).map(c => c.name));
|
||||||
parsed.filter(c => !c.expires || c.expires > new Date()).forEach(c => values[c.name] = c.value);
|
parsed.filter(c => !c.expires || c.expires > new Date()).forEach(c => values[c.name] = c.value);
|
||||||
|
updateCookieValues(cookie, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateCookieValues(cookie, values) {
|
||||||
cookie.set(values);
|
cookie.set(values);
|
||||||
if (Object.keys(values).length) dirty = true
|
if (Object.keys(values).length) dirty = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,61 @@
|
||||||
import { maxVideoDuration } from "../../config.js";
|
import { genericUserAgent, maxVideoDuration } from "../../config.js";
|
||||||
|
import { getCookie, updateCookieValues } from "../cookie/manager.js";
|
||||||
|
|
||||||
|
async function getAccessToken() {
|
||||||
|
/* "cookie" in cookiefile needs to contain:
|
||||||
|
* client_id, client_secret, refresh_token
|
||||||
|
* e.g. client_id=bla; client_secret=bla; refresh_token=bla
|
||||||
|
*
|
||||||
|
* you can get these by making a reddit app and
|
||||||
|
* authenticating an account against reddit's oauth2 api
|
||||||
|
* see: https://github.com/reddit-archive/reddit/wiki/OAuth2
|
||||||
|
*
|
||||||
|
* any additional cookie fields are managed by this code and you
|
||||||
|
* should not touch them unless you know what you're doing. **/
|
||||||
|
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) {
|
export default async function(obj) {
|
||||||
let data = await fetch(`https://www.reddit.com/r/${obj.sub}/comments/${obj.id}/${obj.name}.json`).then((r) => { return r.json() }).catch(() => { return false });
|
const url = new URL(`https://www.reddit.com/r/${obj.sub}/comments/${obj.id}/${obj.title}.json`);
|
||||||
|
|
||||||
|
const accessToken = await getAccessToken();
|
||||||
|
if (accessToken) url.hostname = 'oauth.reddit.com';
|
||||||
|
|
||||||
|
let data = await fetch(
|
||||||
|
url, { headers: accessToken && { authorization: `Bearer ${accessToken}` } }
|
||||||
|
).then((r) => { return r.json() }).catch(() => { return false });
|
||||||
if (!data) return { error: 'ErrorCouldntFetch' };
|
if (!data) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
data = data[0]["data"]["children"][0]["data"];
|
data = data[0]["data"]["children"][0]["data"];
|
||||||
|
@ -17,7 +71,7 @@ export default async function(obj) {
|
||||||
|
|
||||||
await fetch(audioFileLink, { method: "HEAD" }).then((r) => { if (Number(r.status) === 200) audio = true }).catch(() => { audio = false });
|
await fetch(audioFileLink, { method: "HEAD" }).then((r) => { if (Number(r.status) === 200) audio = true }).catch(() => { audio = false });
|
||||||
|
|
||||||
// fallback for videos with differentiating audio quality
|
// fallback for videos with variable audio quality
|
||||||
if (!audio) {
|
if (!audio) {
|
||||||
audioFileLink = `${video.split('_')[0]}_AUDIO_128.mp4`
|
audioFileLink = `${video.split('_')[0]}_AUDIO_128.mp4`
|
||||||
await fetch(audioFileLink, { method: "HEAD" }).then((r) => { if (Number(r.status) === 200) audio = true }).catch(() => { audio = false });
|
await fetch(audioFileLink, { method: "HEAD" }).then((r) => { if (Number(r.status) === 200) audio = true }).catch(() => { audio = false });
|
||||||
|
|
Loading…
Reference in a new issue