diff --git a/routes/index.js b/routes/index.js index c9ab462..5bb72ef 100644 --- a/routes/index.js +++ b/routes/index.js @@ -2,6 +2,7 @@ const overridingRoutes = require('./overides'); const preferenceRoutes = require('./preferences'); const staticRoutes = require('./static'); const subredditRoutes = require('./subreddit'); +const userRoutes = require('./user'); const allRoutes = require('express').Router(); @@ -9,5 +10,6 @@ allRoutes.use(overridingRoutes); allRoutes.use(staticRoutes); allRoutes.use(preferenceRoutes); allRoutes.use(subredditRoutes); +allRoutes.use(userRoutes); module.exports = allRoutes; diff --git a/routes/user.js b/routes/user.js new file mode 100644 index 0000000..26d83f7 --- /dev/null +++ b/routes/user.js @@ -0,0 +1,450 @@ +const config = require('../config'); +const { redis, fetch } = require('../app'); +const userRoutes = require('express').Router(); + +const processUser = require('../inc/processJsonUser.js')(); + +userRoutes.get('/user/:user/:kind?', (req, res, next) => { + let kind = ''; + if (req.params.kind) kind = `/${req.params.kind}`; + let q = ''; + if (req.query.sort) q += `?sort=${req.query.sort}&`; + if (req.query.t) q += `t=${req.query.t}`; + + res.redirect(`/u/${req.params.user}${kind}${q}`); +}); + +userRoutes.get('/u/:user/:kind?', (req, res, next) => { + let user = req.params.user; + let after = req.query.after; + let before = req.query.before; + let post_type = req.params.kind; + let kind = post_type; + let user_data = {}; + let api_req = req.query.api; + let api_type = req.query.type; + let api_target = req.query.target; + + if (req.query.hasOwnProperty('api')) api_req = true; + else api_req = false; + + let raw_json = api_req && req.query.raw_json == '1' ? 1 : 0; + + if (!after) { + after = ''; + } + if (!before) { + before = ''; + } + let d = `&after=${after}`; + if (before) { + d = `&before=${before}`; + } + + post_type = `/${post_type}`; + switch (post_type) { + case '/comments': + kind = 't1'; + break; + case '/submitted': + kind = 't3'; + break; + default: + post_type = ''; + kind = ''; + } + + let sortby = req.query.sort; + let past = req.query.t; + + if (!sortby) { + sortby = 'new'; + } + + if (!['hot', 'new', 'controversial', 'top'].includes(sortby)) { + console.log(`Got invalid sort.`, req.originalUrl); + return res.redirect(`/u/${user}`); + } + + if (past) { + if (sortby === 'controversial' || sortby === 'top') { + if (!['hour', 'day', 'week', 'month', 'year', 'all'].includes(past)) { + console.error(`Got invalid past.`, req.originalUrl); + return res.redirect(`/u/${user}/${sortby}`); + } + } else { + past = ''; + } + } else { + if (sortby === 'controversial' || sortby === 'top') { + past = 'all'; + } else { + past = ''; + } + } + + let key = `${user}:${after}:${before}:sort:${sortby}:past:${past}:post_type:${post_type}:raw_json:${raw_json}`; + redis.get(key, (error, json) => { + if (error) { + console.error(`Error getting the user ${key} key from redis.`, error); + return res.render('index', { + json: null, + user_preferences: req.cookies, + }); + } + if (json) { + console.log(`Got user ${user} key from redis.`); + (async () => { + if (api_req) { + return handleTedditApiUser( + json, + req, + res, + 'redis', + api_type, + api_target, + user, + after, + before + ); + } else { + let processed_json = await processJsonUser( + json, + false, + after, + before, + req.cookies, + kind, + post_type + ); + return res.render('user', { + data: processed_json, + sortby: sortby, + past: past, + user_preferences: req.cookies, + }); + } + })(); + } else { + let url = ''; + if (config.use_reddit_oauth) + url = `https://oauth.reddit.com/user/${user}/about?raw_json=${raw_json}`; + else + url = `https://reddit.com/user/${user}/about.json?raw_json=${raw_json}`; + fetch(encodeURI(url), redditApiGETHeaders()) + .then((result) => { + if (result.status === 200) { + result.json().then((json) => { + user_data.about = json; + let url = ''; + if (config.use_reddit_oauth) { + let endpoint = '/overview'; + if (post_type !== '') endpoint = post_type; + url = `https://oauth.reddit.com/user/${user}${post_type}?limit=26${d}&sort=${sortby}&t=${past}&raw_json=${raw_json}`; + } else { + url = `https://reddit.com/user/${user}${post_type}.json?limit=26${d}&sort=${sortby}&t=${past}&raw_json=${raw_json}`; + } + fetch(encodeURI(url), redditApiGETHeaders()) + .then((result) => { + if (result.status === 200) { + result.json().then((json) => { + user_data.overview = json; + redis.setex( + key, + config.setexs.user, + JSON.stringify(user_data), + (error) => { + if (error) { + console.error( + `Error setting the user ${key} key to redis.`, + error + ); + return res.render('index', { + post: null, + user_preferences: req.cookies, + }); + } else { + (async () => { + if (api_req) { + return handleTedditApiUser( + user_data, + req, + res, + 'online', + api_type, + api_target, + user, + after, + before + ); + } else { + let processed_json = await processJsonUser( + user_data, + true, + after, + before, + req.cookies, + kind, + post_type + ); + return res.render('user', { + data: processed_json, + sortby: sortby, + past: past, + user_preferences: req.cookies, + }); + } + })(); + } + } + ); + }); + } else { + console.error( + `Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}` + ); + console.error(config.reddit_api_error_text); + return res.render('index', { + json: null, + http_status_code: result.status, + user_preferences: req.cookies, + }); + } + }) + .catch((error) => { + console.error( + `Error fetching the overview JSON file from reddit.com/u/${user}`, + error + ); + return res.render('index', { + json: null, + http_status_code: result.status, + user_preferences: req.cookies, + }); + }); + }); + } else { + if (result.status === 404) { + console.log('404 – User not found'); + } else { + console.error( + `Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}` + ); + console.error(config.reddit_api_error_text); + } + return res.render('index', { + json: null, + http_status_code: result.status, + http_statustext: result.statusText, + user_preferences: req.cookies, + }); + } + }) + .catch((error) => { + console.error( + `Error fetching the about JSON file from reddit.com/u/${user}`, + error + ); + }); + } + }); +}); + +userRoutes.get('/user/:user/m/:custom_feed', (req, res, next) => { + res.redirect(`/u/${req.params.user}/m/${req.params.custom_feed}`); +}); + +userRoutes.get('/u/:user/m/:custom_feed/:sort?', (req, res, next) => { + let user = req.params.user; + let custom_feed = req.params.custom_feed; + let subreddit = `u/${user}/m/${custom_feed}`; + let sortby = req.params.sort; + let past = req.query.t; + let before = req.query.before; + let after = req.query.after; + let api_req = req.query.api; + let api_type = req.query.type; + let api_target = req.query.target; + + if (req.query.hasOwnProperty('api')) api_req = true; + else api_req = false; + + let d = `&after=${after}`; + if (before) { + d = `&before=${before}`; + } + + if (!sortby) { + sortby = 'hot'; + } + + if ( + !['new', 'rising', 'controversial', 'top', 'gilded', 'hot'].includes(sortby) + ) { + console.log(`Got invalid sort.`, req.originalUrl); + return res.redirect(`/u/${user}`); + } + + if (past) { + if (sortby === 'controversial' || sortby === 'top') { + if (!['hour', 'day', 'week', 'month', 'year', 'all'].includes(past)) { + console.error(`Got invalid past.`, req.originalUrl); + return res.redirect(`/u/${user}/${sortby}`); + } + } else { + past = undefined; + } + } else { + if (sortby === 'controversial' || sortby === 'top') { + past = 'day'; + } + } + + let key = `${user.toLowerCase()}:m:${custom_feed}:${after}:${before}:sort:${sortby}:past:${past}`; + redis.get(key, (error, json) => { + if (error) { + console.error( + `Error getting the ${user} custom_feed key from redis.`, + error + ); + return res.render('index', { + json: null, + user_preferences: req.cookies, + }); + } + if (json) { + console.log(`Got /u/${user} custom_feed key from redis.`); + (async () => { + if (api_req) { + return handleTedditApiSubreddit( + json, + req, + res, + 'redis', + api_type, + api_target, + subreddit + ); + } else { + let processed_json = await processJsonSubreddit( + json, + 'redis', + null, + req.cookies + ); + if (!processed_json.error) { + return res.render('subreddit', { + json: processed_json, + subreddit: '../' + subreddit, + subreddit_about: null, + subreddit_front: !before && !after ? true : false, + sortby: sortby, + past: past, + user_preferences: req.cookies, + instance_nsfw_enabled: config.nsfw_enabled, + redis_key: key, + after: req.query.after, + before: req.query.before, + }); + } else { + return res.render('subreddit', { + json: null, + error: true, + data: processed_json, + user_preferences: req.cookies, + }); + } + } + })(); + } else { + let url = ''; + if (config.use_reddit_oauth) + url = `https://oauth.reddit.com/${subreddit}/${sortby}?api_type=json&count=25&g=GLOBAL&t=${past}${d}`; + else + url = `https://reddit.com/${subreddit}/${sortby}.json?api_type=json&count=25&g=GLOBAL&t=${past}${d}`; + fetch(encodeURI(url), redditApiGETHeaders()) + .then((result) => { + if (result.status === 200) { + result.json().then((json) => { + redis.setex( + key, + config.setexs.subreddit, + JSON.stringify(json), + (error) => { + if (error) { + console.error( + `Error setting the ${subreddit} key to redis.`, + error + ); + return res.render('subreddit', { + json: null, + user_preferences: req.cookies, + }); + } else { + console.log( + `Fetched the JSON from reddit.com/r/${subreddit}.` + ); + (async () => { + if (api_req) { + return handleTedditApiSubreddit( + json, + req, + res, + 'from_online', + api_type, + api_target, + subreddit + ); + } else { + let processed_json = await processJsonSubreddit( + json, + 'from_online', + null, + req.cookies + ); + return res.render('subreddit', { + json: processed_json, + subreddit: '../' + subreddit, + subreddit_about: null, + subreddit_front: !before && !after ? true : false, + sortby: sortby, + past: past, + user_preferences: req.cookies, + instance_nsfw_enabled: config.nsfw_enabled, + redis_key: key, + after: req.query.after, + before: req.query.before, + }); + } + })(); + } + } + ); + }); + } else { + if (result.status === 404) { + console.log('404 – Subreddit not found'); + } else { + console.error( + `Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}` + ); + console.error(config.reddit_api_error_text); + } + return res.render('index', { + json: null, + http_status_code: result.status, + user_preferences: req.cookies, + }); + } + }) + .catch((error) => { + console.error( + `Error fetching the JSON file from reddit.com/${subreddit}.`, + error + ); + }); + } + }); +}); + +module.exports = userRoutes;