diff --git a/src/modules/processing/services/reddit.js b/src/modules/processing/services/reddit.js index 8fae3f0..bf5ef91 100644 --- a/src/modules/processing/services/reddit.js +++ b/src/modules/processing/services/reddit.js @@ -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) { - 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' }; data = data[0]["data"]["children"][0]["data"];