diff --git a/inc/processJsonPost.js b/inc/processJsonPost.js index d57711d..7a8ccc8 100644 --- a/inc/processJsonPost.js +++ b/inc/processJsonPost.js @@ -1,5 +1,6 @@ const compilePostComments = require('./compilePostComments.js')(); const procPostMedia = require('./processPostMedia.js')(); +const config = require('../config'); async function processReplies(data, post_id, depth, user_preferences) { let return_replies = []; @@ -399,8 +400,141 @@ async function finalizeJsonPost( return { post_data: post_data, comments: comments_html }; } +async function processJsonPostList(posts, mode) { + let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http'; + + for (var i = 0; i < posts.length; i++) { + let link = posts[i]; + let valid_reddit_self_domains = ['reddit.com']; + let is_self_link = false; + + if (link.domain) { + let tld = link.domain.split('self.'); + if (tld.length > 1) { + if (!tld[1].includes('.')) { + is_self_link = true; + link.url = teddifyUrl(link.url); + } + } + if ( + config.valid_media_domains.includes(link.domain) || + valid_reddit_self_domains.includes(link.domain) + ) { + is_self_link = true; + link.url = teddifyUrl(link.url); + } + } + + link.permalink = `${protocol}://${config.domain}${link.permalink}`; + + if (is_self_link) link.url = link.permalink; + + if (link.images) { + if (link.images.thumb !== 'self') { + link.images.thumb = `${protocol}://${config.domain}${link.images.thumb}`; + } + } + + if (mode === 'light') { + link.selftext_html = null; + } + } + + return posts; +} + +async function getPostItem(post_json, req, protocol) { + let thumbnail = ''; + let post_image = ''; + let is_self_link = false; + let valid_reddit_self_domains = ['reddit.com']; + + if (post_json.domain) { + let tld = post_json.domain.split('self.'); + if (tld.length > 1) { + if (!tld[1].includes('.')) { + is_self_link = true; + post_json.url = teddifyUrl(post_json.url); + } + } + if ( + config.valid_media_domains.includes(post_json.domain) || + valid_reddit_self_domains.includes(post_json.domain) + ) { + is_self_link = true; + post_json.url = teddifyUrl(post_json.url); + } + } + + if (post_json.preview && post_json.thumbnail !== 'self') { + if (!post_json.url.startsWith('/r/') && isGif(post_json.url)) { + let s = await downloadAndSave(post_json.thumbnail, 'thumb_'); + thumbnail = `${protocol}://${config.domain}${s}`; + } else { + if (post_json.preview.images[0].resolutions[0]) { + let s = await downloadAndSave( + post_json.preview.images[0].resolutions[0].url, + 'thumb_' + ); + thumbnail = `${protocol}://${config.domain}${s}`; + if (!isGif(post_json.url) && !post_json.post_hint.includes(':video')) { + s = await downloadAndSave(post_json.preview.images[0].source.url); + post_image = `${protocol}://${config.domain}${s}`; + } + } + } + } + + post_json.permalink = `${protocol}://${config.domain}${post_json.permalink}`; + + if (is_self_link) post_json.url = post_json.permalink; + + if (req.query.hasOwnProperty('full_thumbs')) { + if (!post_image) post_image = thumbnail; + + thumbnail = post_image; + } + + let enclosure = ''; + if (thumbnail != '') { + let mime = ''; + let ext = thumbnail.split('.').pop(); + if (ext === 'png') mime = 'image/png'; + else mime = 'image/jpeg'; + enclosure = ``; + } + + let append_desc_html = `
[link] [comments]`; + + return ` + + ${post_json.title} + ${post_json.author} + ${post_json.created} + ${new Date( + post_json.created_utc * 1000 + ).toGMTString()} + ${post_json.domain} + ${post_json.id} + ${thumbnail} + ${enclosure} + ${post_json.permalink} + ${post_json.url} + + ${post_json.num_comments} + ${post_json.ups} + ${post_json.stickied} + ${is_self_link} + + `; +} + module.exports = { processReplies, processJsonPost, finalizeJsonPost, + processJsonPostList, + getPostItem }; diff --git a/inc/processSubredditAbout.js b/inc/processSubredditAbout.js index 0800f14..2d7ad05 100644 --- a/inc/processSubredditAbout.js +++ b/inc/processSubredditAbout.js @@ -64,4 +64,15 @@ async function processSubredditAbout(subreddit, redis, fetch, RedditAPI) { } } -module.exports = processSubredditAbout; +async function processJsonSubredditAbout(json, parsed) { + if (!parsed) { + json = JSON.parse(json); + } + + return returnRelevantKeys(json); +} + +module.exports = { + processSubredditAbout, + processJsonSubredditAbout +}; diff --git a/inc/teddit_api/handlePost.js b/inc/teddit_api/handlePost.js new file mode 100644 index 0000000..b5877e4 --- /dev/null +++ b/inc/teddit_api/handlePost.js @@ -0,0 +1,87 @@ +const { processJsonPost, getPostItem } = require('../processJsonPost'); + +module.exports = function () { + const config = require('../../config'); + this.handleTedditApiPost = async ( + json, + req, + res, + from, + api_type, + api_target + ) => { + if (!config.api_enabled) { + res.setHeader('Content-Type', 'application/json'); + let msg = { + info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.', + }; + return res.end(JSON.stringify(msg)); + } + + console.log('Teddit API request - post'); + if (from === 'redis') json = JSON.parse(json); + + if (api_type === 'rss') { + let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http'; + let items = ''; + + let post = json[0].data.children[0].data; + let comments = json[1].data.children; + + items += await getPostItem(post, req, protocol); + + for (var i = 0; i < comments.length; i++) { + let comment = comments[i].data; + let kind = comments[i].kind; + + let title = `/u/${comment.author} on ${post.title}`; + + comment.permalink = `${protocol}://${config.domain}${comment.permalink}`; + + if (kind !== 'more') { + items += ` + + ${title} + ${comment.author} + ${comment.created} + ${new Date( + comment.created_utc * 1000 + ).toGMTString()} + ${comment.id} + ${comment.permalink} + + ${comment.ups} + + `; + } + } + + let xml_output = ` + + + + ${post.title} + ${post.url} + ${items} + + `; + res.setHeader('Content-Type', 'application/rss+xml'); + return res.end(xml_output); + } else { + res.setHeader('Content-Type', 'application/json'); + if (api_target === 'reddit') { + return res.end(JSON.stringify(json)); + } else { + let processed_json = await processJsonPost( + json, + true, + req.cookies + ); + + return res.end(JSON.stringify(processed_json)); + } + } + }; +}; diff --git a/inc/teddit_api/handleSubreddit.js b/inc/teddit_api/handleSubreddit.js index 3925be6..9b063c3 100644 --- a/inc/teddit_api/handleSubreddit.js +++ b/inc/teddit_api/handleSubreddit.js @@ -1,4 +1,8 @@ const processJsonSubreddit = require('../processJsonSubreddit'); +const { processJsonSubredditAbout } = require('../processSubredditAbout'); +const processSearchResults = require('../processSearchResults.js'); +const { processJsonPostList, getPostItem } = require('../processJsonPost'); +const processJsonSubredditsExplore = require('../processSubredditsExplore.js'); module.exports = function () { const config = require('../../config'); @@ -27,93 +31,10 @@ module.exports = function () { if (api_type === 'rss') { let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http'; let items = ''; + for (var i = 0; i < json.data.children.length; i++) { - let link = json.data.children[i].data; - let thumbnail = ''; - let post_image = ''; - let is_self_link = false; - let valid_reddit_self_domains = ['reddit.com']; - - if (link.domain) { - let tld = link.domain.split('self.'); - if (tld.length > 1) { - if (!tld[1].includes('.')) { - is_self_link = true; - link.url = teddifyUrl(link.url); - } - } - if ( - config.valid_media_domains.includes(link.domain) || - valid_reddit_self_domains.includes(link.domain) - ) { - is_self_link = true; - link.url = teddifyUrl(link.url); - } - } - - if (link.preview && link.thumbnail !== 'self') { - if (!link.url.startsWith('/r/') && isGif(link.url)) { - let s = await downloadAndSave(link.thumbnail, 'thumb_'); - thumbnail = `${protocol}://${config.domain}${s}`; - } else { - if (link.preview.images[0].resolutions[0]) { - let s = await downloadAndSave( - link.preview.images[0].resolutions[0].url, - 'thumb_' - ); - thumbnail = `${protocol}://${config.domain}${s}`; - if (!isGif(link.url) && !link.post_hint.includes(':video')) { - s = await downloadAndSave(link.preview.images[0].source.url); - post_image = `${protocol}://${config.domain}${s}`; - } - } - } - } - - link.permalink = `${protocol}://${config.domain}${link.permalink}`; - - if (is_self_link) link.url = link.permalink; - - if (req.query.hasOwnProperty('full_thumbs')) { - if (!post_image) post_image = thumbnail; - - thumbnail = post_image; - } - - let enclosure = ''; - if (thumbnail != '') { - let mime = ''; - let ext = thumbnail.split('.').pop(); - if (ext === 'png') mime = 'image/png'; - else mime = 'image/jpeg'; - enclosure = ``; - } - - let append_desc_html = `
[link] [comments]`; - - items += ` - - ${link.title} - ${link.author} - ${link.created} - ${new Date( - link.created_utc * 1000 - ).toGMTString()} - ${link.domain} - ${link.id} - ${thumbnail} - ${enclosure} - ${link.permalink} - ${link.url} - - ${link.num_comments} - ${link.ups} - ${link.stickied} - ${is_self_link} - - `; + let post = json.data.children[i].data; + items += await getPostItem(post, req, protocol); } let r_subreddit = '/r/' + subreddit; @@ -149,43 +70,185 @@ module.exports = function () { req.cookies ); - let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http'; - for (var i = 0; i < processed_json.links.length; i++) { - let link = processed_json.links[i]; - let valid_reddit_self_domains = ['reddit.com']; - let is_self_link = false; + await processJsonPostList(processed_json.links, mode); - if (link.domain) { - let tld = link.domain.split('self.'); - if (tld.length > 1) { - if (!tld[1].includes('.')) { - is_self_link = true; - link.url = teddifyUrl(link.url); - } - } - if ( - config.valid_media_domains.includes(link.domain) || - valid_reddit_self_domains.includes(link.domain) - ) { - is_self_link = true; - link.url = teddifyUrl(link.url); - } - } + return res.end(JSON.stringify(processed_json)); + } + } + }; + this.handleTedditApiSubredditAbout = async ( + json, + res, + from, + api_target + ) => { + if (!config.api_enabled) { + res.setHeader('Content-Type', 'application/json'); + let msg = { + info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.', + }; + return res.end(JSON.stringify(msg)); + } - link.permalink = `${protocol}://${config.domain}${link.permalink}`; + console.log('Teddit API request - subreddit about'); + if (from === 'redis') json = JSON.parse(json); - if (is_self_link) link.url = link.permalink; + res.setHeader('Content-Type', 'application/json'); - if (link.images) { - if (link.images.thumb !== 'self') { - link.images.thumb = `${protocol}://${config.domain}${link.images.thumb}`; - } - } + if (api_target === 'reddit') { + return res.end(JSON.stringify(json)); + } else { + let subreddit_about = await processJsonSubredditAbout( + json, + true + ); - if (mode === 'light') { - link.selftext_html = null; - } - } + return res.end(JSON.stringify(subreddit_about)); + } + }; + this.handleTedditApiSubredditSearch = async ( + json, + req, + res, + from, + api_type, + api_target, + subreddit, + query, + mode + ) => { + if (!config.api_enabled) { + res.setHeader('Content-Type', 'application/json'); + let msg = { + info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.', + }; + return res.end(JSON.stringify(msg)); + } + + console.log('Teddit API request - subreddit search'); + if (from === 'redis') json = JSON.parse(json); + + if (api_type === 'rss') { + let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http'; + let items = ''; + + for (var i = 0; i < json.data.children.length; i++) { + let post = json.data.children[i].data; + items += await getPostItem(post, req, protocol); + } + + let r_subreddit = '/r/' + subreddit; + let title = `${query} - ${r_subreddit}`; + let link = `${protocol}://${config.domain}${r_subreddit}/search?q=${query}`; + + let xml_output = ` + + + + ${title} + ${link} + Results for: ${query} - ${r_subreddit} + ${items} + + `; + + res.setHeader('Content-Type', 'application/rss+xml'); + + return res.end(xml_output); + } else { + res.setHeader('Content-Type', 'application/json'); + if (api_target === 'reddit') { + return res.end(JSON.stringify(json)); + } else { + let processed_json = await processSearchResults( + json, + true, + null, + null, + req.cookies + ); + + await processJsonPostList(processed_json.posts, mode); + + return res.end(JSON.stringify(processed_json)); + } + } + }; + this.handleTedditApiSubredditsExplore = async ( + json, + req, + res, + from, + api_type, + api_target, + query + ) => { + if (!config.api_enabled) { + res.setHeader('Content-Type', 'application/json'); + let msg = { + info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.', + }; + return res.end(JSON.stringify(msg)); + } + + console.log('Teddit API request - subreddit explore'); + if (from === 'redis') json = JSON.parse(json); + + if (api_type === 'rss') { + let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http'; + let items = ''; + + let children_len = json.data.children.length; + + for (var i = 0; i < children_len; i++) { + let data = json.data.children[i].data; + + items += ` + + ${data.title} + ${data.created} + ${new Date( + data.created_utc * 1000 + ).toGMTString()} + ${data.id} + ${data.display_name} + ${data.display_name_prefixed} + ${replaceDomains(data.url, req.cookies)} + + ${data.subscribers} + ${data.over18} + + `; + } + + let title = `${query}`; + let link = `${protocol}://${config.domain}/subreddits/search?q=${query}`; + + let xml_output = ` + + + + ${title} + ${link} + Results for: ${query} + ${items} + + `; + res.setHeader('Content-Type', 'application/rss+xml'); + return res.end(xml_output); + } else { + res.setHeader('Content-Type', 'application/json'); + if (api_target === 'reddit') { + return res.end(JSON.stringify(json)); + } else { + let processed_json = await processJsonSubredditsExplore( + json, + true, + null, + req.cookies + ); return res.end(JSON.stringify(processed_json)); } diff --git a/routes/subreddit.js b/routes/subreddit.js index 5891d35..82139fc 100644 --- a/routes/subreddit.js +++ b/routes/subreddit.js @@ -6,16 +6,28 @@ const { processJsonPost, finalizeJsonPost, } = require('../inc/processJsonPost.js'); -const processSubredditAbout = require('../inc/processSubredditAbout.js'); +const { + processSubredditAbout +} = require('../inc/processSubredditAbout.js'); const processSearchResults = require('../inc/processSearchResults.js'); const processJsonSubreddit = require('../inc/processJsonSubreddit.js'); const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')(); +const tedditApiPost = require('../inc/teddit_api/handlePost.js')(); const processMoreComments = require('../inc/processMoreComments.js'); const processJsonSubredditsExplore = require('../inc/processSubredditsExplore.js'); subredditRoutes.get('/r/:subreddit/search', (req, res, next) => { let subreddit = req.params.subreddit; let q = req.query.q; + let api_req = req.query.api; + let api_type = req.query.type; + let api_target = req.query.target; + let api_mode = req.query.mode; + + 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 (typeof q === 'undefined') { return res.render('search', { @@ -62,7 +74,7 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => { count = ''; } - let key = `search:${subreddit}:${q}:${restrict_sr}:${sortby}:${past}:${after}:${before}:${nsfw}`; + let key = `search:${subreddit}:${q}:${restrict_sr}:${sortby}:${past}:${after}:${before}:${nsfw}:raw_json:${raw_json}`; redis.get(key, (error, json) => { if (error) { console.error('Error getting the search key from redis.', error); @@ -75,32 +87,46 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => { if (json) { console.log('Got search key from redis.'); (async () => { - let processed_json = await processSearchResults( - json, - false, - after, - before, - req.cookies - ); - return res.render('search', { - json: processed_json, - no_query: false, - q: q, - restrict_sr: restrict_sr, - nsfw: nsfw, - subreddit: subreddit, - sortby: sortby, - past: past, - user_preferences: req.cookies, - instance_config: config, - }); + if (api_req) { + return handleTedditApiSubredditSearch( + json, + req, + res, + 'redis', + api_type, + api_target, + subreddit, + q, + api_mode + ); + } else { + let processed_json = await processSearchResults( + json, + false, + after, + before, + req.cookies + ); + return res.render('search', { + json: processed_json, + no_query: false, + q: q, + restrict_sr: restrict_sr, + nsfw: nsfw, + subreddit: subreddit, + sortby: sortby, + past: past, + user_preferences: req.cookies, + instance_config: config, + }); + } })(); } else { let url = ''; if (config.use_reddit_oauth) - url = `https://oauth.reddit.com/r/${subreddit}/search?api_type=json&q=${q}&restrict_sr=${restrict_sr}&include_over_18=${nsfw}&sort=${sortby}&t=${past}${count}${d}`; + url = `https://oauth.reddit.com/r/${subreddit}/search?api_type=json&q=${q}&restrict_sr=${restrict_sr}&include_over_18=${nsfw}&sort=${sortby}&t=${past}${count}${d}&raw_json=${raw_json}`; else - url = `https://reddit.com/r/${subreddit}/search.json?api_type=json&q=${q}&restrict_sr=${restrict_sr}&include_over_18=${nsfw}&sort=${sortby}&t=${past}${count}${d}`; + url = `https://reddit.com/r/${subreddit}/search.json?api_type=json&q=${q}&restrict_sr=${restrict_sr}&include_over_18=${nsfw}&sort=${sortby}&t=${past}${count}${d}&raw_json=${raw_json}`; fetch(encodeURI(url), redditApiGETHeaders()) .then((result) => { if (result.status === 200) { @@ -137,25 +163,39 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => { } else { console.log('Fetched search results from Reddit.'); (async () => { - let processed_json = await processSearchResults( - json, - true, - after, - before, - req.cookies - ); - return res.render('search', { - no_query: false, - json: processed_json, - q: q, - restrict_sr: restrict_sr, - nsfw: nsfw, - subreddit: subreddit, - sortby: sortby, - past: past, - user_preferences: req.cookies, - instance_config: config, - }); + if (api_req) { + return handleTedditApiSubredditSearch( + json, + req, + res, + 'from_online', + api_type, + api_target, + subreddit, + q, + api_mode + ); + } else { + let processed_json = await processSearchResults( + json, + true, + after, + before, + req.cookies + ); + return res.render('search', { + no_query: false, + json: processed_json, + q: q, + restrict_sr: restrict_sr, + nsfw: nsfw, + subreddit: subreddit, + sortby: sortby, + past: past, + user_preferences: req.cookies, + instance_config: config, + }); + } })(); } } @@ -182,6 +222,107 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => { }); }); +subredditRoutes.get('/r/:subreddit/about', (req, res, next) => { + let subreddit = req.params.subreddit; + let api_type = req.query.type; + let api_target = req.query.target; + let api_mode = req.query.mode; + + if (!req.query.hasOwnProperty('api')) { + console.log(`This route is only available via the API.`, req.originalUrl); + return res.redirect(`/r/${subreddit}`); + } + + let raw_json = req.query.raw_json == '1' ? 1 : 0; + + let key = `about:${subreddit.toLowerCase()}:raw_json:${raw_json}`; + redis.get(key, (error, json) => { + if (error) { + console.error(`Error getting the about key from redis.`, error); + return res.render('frontpage', { + json: null, + user_preferences: req.cookies, + instance_config: config, + }); + } + if (json) { + console.log(`Got about key from redis.`); + (async () => { + return handleTedditApiSubredditAbout( + json, + res, + 'redis', + api_target + ); + })(); + } else { + let url = ''; + if (config.use_reddit_oauth) + url = `https://oauth.reddit.com/r/${subreddit}/about.json?api_type=json&raw_json=${raw_json}`; + else + url = `https://reddit.com/r/${subreddit}/about.json?api_type=json&raw_json=${raw_json}`; + 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 about key to redis.`, + error + ); + return res.render('subreddit', { + json: null, + user_preferences: req.cookies, + instance_config: config, + }); + } else { + console.log( + `Fetched the JSON from reddit.com/r/${subreddit}/about.` + ); + (async () => { + return handleTedditApiSubredditAbout( + json, + res, + 'from_online', + api_target + ); + })(); + } + } + ); + }); + } 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('frontpage', { + json: null, + http_status_code: result.status, + user_preferences: req.cookies, + instance_config: config, + }); + } + }) + .catch((error) => { + console.error( + `Error fetching the JSON file from reddit.com/r/${subreddit}/about.`, + error + ); + }); + } + }); +}); + subredditRoutes.get( '/r/:subreddit/wiki/:page?/:sub_page?', (req, res, next) => { @@ -605,6 +746,14 @@ subredditRoutes.get( let viewing_comment = false; let comment_ids = req.query.comment_ids; let context = parseInt(req.query.context); + 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 (req.params.comment_id) { comment_id = `${req.params.comment_id}/`; @@ -637,7 +786,7 @@ subredditRoutes.get( let comments_url = `/r/${subreddit}/comments/${id}/${snippet}/${comment_id}`; let post_url = `/r/${subreddit}/comments/${id}/${snippet}/`; - let comments_key = `${comments_url}:sort:${sortby}`; + let comments_key = `${comments_url}:sort:${sortby}:raw_json:${raw_json}`; redis.get(comments_key, (error, json) => { if (error) { @@ -654,57 +803,68 @@ subredditRoutes.get( if (json) { console.log(`Got ${comments_url} key from redis.`); (async () => { - let parsed = false; - let more_comments = null; - if (comment_ids) { - let key = `${post_url}:morechildren:comment_ids:${comment_ids}`; - more_comments = await processMoreComments( - fetch, - redis, - post_url, - comment_ids, - id + if (api_req) { + return handleTedditApiPost( + json, + req, + res, + 'redis', + api_type, + api_target ); + } else { + let parsed = false; + let more_comments = null; + if (comment_ids) { + let key = `${post_url}:morechildren:comment_ids:${comment_ids}`; + more_comments = await processMoreComments( + fetch, + redis, + post_url, + comment_ids, + id + ); - if (more_comments === false) { - return res.redirect(post_url); - } else { - json = JSON.parse(json); - json[1].data.children = more_comments; - parsed = true; + if (more_comments === false) { + return res.redirect(post_url); + } else { + json = JSON.parse(json); + json[1].data.children = more_comments; + parsed = true; + } } - } - let processed_json = await processJsonPost(json, parsed, req.cookies); - let finalized_json = await finalizeJsonPost( - processed_json, - id, - post_url, - more_comments, - viewing_comment, - req.cookies - ); - return res.render('post', { - post: finalized_json.post_data, - comments: finalized_json.comments, - viewing_comment: viewing_comment, - post_url: post_url, - subreddit: subreddit, - sortby: sortby, - user_preferences: req.cookies, - instance_nsfw_enabled: config.nsfw_enabled, - instance_videos_muted: config.videos_muted, - post_media_max_heights: config.post_media_max_heights, - redis_key: comments_key, - instance_config: config, - }); + let processed_json = await processJsonPost(json, parsed, req.cookies); + let finalized_json = await finalizeJsonPost( + processed_json, + id, + post_url, + more_comments, + viewing_comment, + req.cookies + ); + return res.render('post', { + post: finalized_json.post_data, + comments: finalized_json.comments, + viewing_comment: viewing_comment, + post_url: post_url, + subreddit: subreddit, + sortby: sortby, + user_preferences: req.cookies, + instance_nsfw_enabled: config.nsfw_enabled, + instance_videos_muted: config.videos_muted, + post_media_max_heights: config.post_media_max_heights, + redis_key: comments_key, + instance_config: config, + }); + } })(); } else { let url = ''; if (config.use_reddit_oauth) - url = `https://oauth.reddit.com${comments_url}?api_type=json&sort=${sortby}&context=${context}`; + url = `https://oauth.reddit.com${comments_url}?api_type=json&sort=${sortby}&context=${context}&raw_json=${raw_json}`; else - url = `https://reddit.com${comments_url}.json?api_type=json&sort=${sortby}&context=${context}`; + url = `https://reddit.com${comments_url}.json?api_type=json&sort=${sortby}&context=${context}&raw_json=${raw_json}`; fetch(encodeURI(url), redditApiGETHeaders()) .then((result) => { @@ -730,51 +890,62 @@ subredditRoutes.get( `Fetched the JSON from reddit.com${comments_url}.` ); (async () => { - let more_comments = null; - if (comment_ids) { - let key = `${post_url}:morechildren:comment_ids:${comment_ids}`; - more_comments = await processMoreComments( - fetch, - redis, - post_url, - comment_ids, - id + if (api_req) { + return handleTedditApiPost( + json, + req, + res, + 'from_online', + api_type, + api_target ); + } else { + let more_comments = null; + if (comment_ids) { + let key = `${post_url}:morechildren:comment_ids:${comment_ids}`; + more_comments = await processMoreComments( + fetch, + redis, + post_url, + comment_ids, + id + ); - if (more_comments === false) { - return res.redirect(post_url); - } else { - json[1].data.children = more_comments; + if (more_comments === false) { + return res.redirect(post_url); + } else { + json[1].data.children = more_comments; + } } - } - let processed_json = await processJsonPost( - json, - true, - req.cookies - ); - let finalized_json = await finalizeJsonPost( - processed_json, - id, - post_url, - more_comments, - viewing_comment, - req.cookies - ); - return res.render('post', { - post: finalized_json.post_data, - comments: finalized_json.comments, - viewing_comment: viewing_comment, - post_url: post_url, - subreddit: subreddit, - sortby: sortby, - user_preferences: req.cookies, - instance_nsfw_enabled: config.nsfw_enabled, - instance_videos_muted: config.videos_muted, - post_media_max_heights: config.post_media_max_heights, - redis_key: comments_key, - instance_config: config, - }); + let processed_json = await processJsonPost( + json, + true, + req.cookies + ); + let finalized_json = await finalizeJsonPost( + processed_json, + id, + post_url, + more_comments, + viewing_comment, + req.cookies + ); + return res.render('post', { + post: finalized_json.post_data, + comments: finalized_json.comments, + viewing_comment: viewing_comment, + post_url: post_url, + subreddit: subreddit, + sortby: sortby, + user_preferences: req.cookies, + instance_nsfw_enabled: config.nsfw_enabled, + instance_videos_muted: config.videos_muted, + post_media_max_heights: config.post_media_max_heights, + redis_key: comments_key, + instance_config: config, + }); + } })(); } } @@ -839,6 +1010,14 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => { let before = req.query.before; let sortby = req.params.sort; let searching = false; + 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 = ''; @@ -860,12 +1039,12 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => { sortby = ''; } - let key = `subreddits:sort:${sortby}${d}`; + let key = `subreddits:sort:${sortby}${d}:raw_json:${raw_json}`; if (sortby === 'search') { if (typeof q == 'undefined' || q == '') return res.redirect('/subreddits'); - key = `subreddits:search:q:${q}:nsfw:${nsfw}${d}`; + key = `subreddits:search:q:${q}:nsfw:${nsfw}${d}:raw_json:${raw_json}`; searching = true; } @@ -881,48 +1060,60 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => { if (json) { console.log(`Got subreddits key from redis.`); (async () => { - let processed_json = await processJsonSubredditsExplore( - json, - 'redis', - null, - req.cookies - ); - if (!processed_json.error) { - return res.render('subreddits_explore', { - json: processed_json, - sortby: sortby, - after: after, - before: before, - q: q, - nsfw: nsfw, - searching: searching, - subreddits_front: !before && !after ? true : false, - user_preferences: req.cookies, - instance_nsfw_enabled: config.nsfw_enabled, - instance_config: config, - }); + if (api_req) { + return handleTedditApiSubredditsExplore( + json, + req, + res, + 'redis', + api_type, + api_target, + q + ); } else { - return res.render('subreddits_explore', { - json: null, - error: true, - data: processed_json, - user_preferences: req.cookies, - instance_config: config, - }); + let processed_json = await processJsonSubredditsExplore( + json, + 'redis', + null, + req.cookies + ); + if (!processed_json.error) { + return res.render('subreddits_explore', { + json: processed_json, + sortby: sortby, + after: after, + before: before, + q: q, + nsfw: nsfw, + searching: searching, + subreddits_front: !before && !after ? true : false, + user_preferences: req.cookies, + instance_nsfw_enabled: config.nsfw_enabled, + instance_config: config, + }); + } else { + return res.render('subreddits_explore', { + json: null, + error: true, + data: processed_json, + user_preferences: req.cookies, + instance_config: config, + }); + } } })(); } else { let url = ''; if (config.use_reddit_oauth) { if (!searching) - url = `https://oauth.reddit.com/subreddits/${sortby}?api_type=json&count=25&g=GLOBAL&t=${d}`; + url = `https://oauth.reddit.com/subreddits/${sortby}?api_type=json&count=25&g=GLOBAL&t=${d}&raw_json=${raw_json}`; else - url = `https://oauth.reddit.com/subreddits/search?api_type=json&q=${q}&include_over_18=${nsfw}${d}`; + url = `https://oauth.reddit.com/subreddits/search?api_type=json&q=${q}&include_over_18=${nsfw}${d}&raw_json=${raw_json}`; } else { if (!searching) - url = `https://reddit.com/subreddits/${sortby}.json?api_type=json&count=25&g=GLOBAL&t=${d}`; + url = `https://reddit.com/subreddits/${sortby}.json?api_type=json&count=25&g=GLOBAL&t=${d}&raw_json=${raw_json}`; else - url = `https://reddit.com/subreddits/search.json?api_type=json&q=${q}&include_over_18=${nsfw}${d}`; + url = `https://reddit.com/subreddits/search.json?api_type=json&q=${q}&include_over_18=${nsfw}${d}&raw_json=${raw_json}`; } fetch(encodeURI(url), redditApiGETHeaders()) @@ -946,25 +1137,37 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => { } else { console.log(`Fetched the JSON from reddit.com/subreddits.`); (async () => { - let processed_json = await processJsonSubredditsExplore( - json, - 'from_online', - null, - req.cookies - ); - return res.render('subreddits_explore', { - json: processed_json, - sortby: sortby, - after: after, - before: before, - q: q, - nsfw: nsfw, - searching: searching, - subreddits_front: !before && !after ? true : false, - user_preferences: req.cookies, - instance_nsfw_enabled: config.nsfw_enabled, - instance_config: config, - }); + if (api_req) { + return handleTedditApiSubredditsExplore( + json, + req, + res, + 'from_online', + api_type, + api_target, + q + ); + } else { + let processed_json = await processJsonSubredditsExplore( + json, + 'from_online', + null, + req.cookies + ); + return res.render('subreddits_explore', { + json: processed_json, + sortby: sortby, + after: after, + before: before, + q: q, + nsfw: nsfw, + searching: searching, + subreddits_front: !before && !after ? true : false, + user_preferences: req.cookies, + instance_nsfw_enabled: config.nsfw_enabled, + instance_config: config, + }); + } })(); } });