diff --git a/_wiki.js b/_wiki.js index cba601e..8676919 100644 --- a/_wiki.js +++ b/_wiki.js @@ -1,54 +1,104 @@ -const fs = require('fs-extra'); -const path = require('path'); -const fetch = require('node-fetch'); -const qs = require('qs'); +const fs = require('fs-extra'); // Reading README.md +const path = require('path'); // Get the correct path for README.md +const fetch = require('node-fetch'); // Make calls to Reddit from Node.js +const qs = require('qs'); // Properly build a query for node-fetch POST +// REDDIT_: For authentication with Reddit API. Oauth MUST be used. ID and Secret come from a "script" app type. const REDDIT_USER = process.env.REDDIT_USER || 'username'; const REDDIT_PASS = process.env.REDDIT_PASS || 'password'; const REDDIT_CLIENT_ID = process.env.REDDIT_CLIENT_ID || 'clientid'; const REDDIT_CLIENT_SECRET = process.env.REDDIT_CLIENT_SECRET || 'clientsecret'; + +// WIKI_: For the Reddit Wiki const WIKI_SUBREDDIT = 'privacy'; const WIKI_PAGE = 'de-go-git'; -const WIKI_REASON = 'Automated edit from [GitHub repo](https://github.com/tycrek/degoogle)'; +const WIKI_REASON = 'Automated edit from GitHub repo: https://github.com/tycrek/degoogle'; + +// Helps POST data be submitted properly const CONTENT_TYPE = 'application/x-www-form-urlencoded'; -updateWiki() +updateWiki(); +/** + * Update the Reddit wiki + */ function updateWiki() { + // Endpoints for each of our fetches to Reddit let endpoints = { revisions: `https://old.reddit.com/r/${WIKI_SUBREDDIT}/wiki/revisions/${WIKI_PAGE}.json`, token: 'https://www.reddit.com/api/v1/access_token', edit: `https://oauth.reddit.com/r/${WIKI_SUBREDDIT}/api/wiki/edit` }; + + // Initial basic authorization for getting the Oauth token let basicAuth = `Basic ${Buffer.from(REDDIT_CLIENT_ID + ':' + REDDIT_CLIENT_SECRET).toString('base64')}`; - let lastId; + let lastId, token; - fetch(endpoints.revisions) - .then((response) => response.json()) - .then((json) => json.data.children[0].id) - .then((mLastId) => { - lastId = mLastId; - return fetch(endpoints.token, { + getLastRevision(endpoints.revisions) + .then((mLastId) => lastId = mLastId) + .then(() => getToken(endpoints.token, basicAuth)) + .then((mToken) => token = mToken) + .then(() => putWiki(endpoints.edit, lastId, token)) + .catch((err) => (console.error(err), process.exit(1))); +} + +/** + * Get the last revision ID on the Wiki. Required otherwise editing the wiki fails + * @param {String} endpoint Endpoint of where to get the ID's + */ +function getLastRevision(endpoint) { + return new Promise((resolve, reject) => { + fetch(endpoint) + .then((response) => response.json()) + .then((json) => json.data.children[0].id) // children[0] is the most recent edit + .then((lastId) => resolve(lastId)) + .catch((err) => reject(err)); + }); +} + +/** + * Gets an Oauth token used to edit the Wiki + * @param {String} endpoint Endpoint of where to get the token + * @param {String} auth Initial authorization data to get the better Oauth data + */ +function getToken(endpoint, auth) { + return new Promise((resolve, reject) => { + fetch(endpoint, { method: 'POST', - headers: { 'Authorization': basicAuth, 'Content-Type': CONTENT_TYPE }, + headers: { 'Authorization': auth, 'Content-Type': CONTENT_TYPE }, body: qs.stringify({ grant_type: 'password', username: REDDIT_USER, password: REDDIT_PASS }) - }); - }) - .then((response) => response.json()) - .then((json) => { - return fetch(endpoints.edit, { + }) + .then((response) => response.json()) + .then((json) => json.access_token) + .then((token) => resolve(token)) + .catch((err) => reject(err)); + }); +} + +/** + * Post the contents from the README into the wiki + * @param {String} endpoint Endpoint for editing the wiki + * @param {String} lastId Revision ID for the Wiki + * @param {String} token Oauth token for authenticating with the Reddit API + */ +function putWiki(endpoint, lastId, token) { + return new Promise((resolve, reject) => { + fetch(endpoint, { method: 'POST', - headers: { 'Authorization': `bearer ${json.access_token}`, 'Content-Type': CONTENT_TYPE }, + headers: { 'Authorization': `bearer ${token}`, 'Content-Type': CONTENT_TYPE }, body: qs.stringify({ content: fs.readFileSync(path.join(__dirname, 'README.md')).toString(), page: WIKI_PAGE, reason: WIKI_REASON, previous: lastId }) - }); - }) - .then((response) => response.json()) - .then((json) => console.log(json)) - .catch((err) => console.error(err)); + }) + .then((response) => response.json()) + .then((json) => { + if (Object.keys(json).length == 0) resolve(); + else throw Error(json); + }) + .catch((err) => reject(err)); + }); }