From baddb1aec29a53504dfcdd690631843ab01a89c0 Mon Sep 17 00:00:00 2001 From: CosmosDev Date: Thu, 15 Dec 2022 20:16:13 +0100 Subject: [PATCH] Add suport for subreddit search API --- inc/processJsonPost.js | 45 ++++++++++- inc/teddit_api/handlePost.js | 2 +- inc/teddit_api/handleSubreddit.js | 71 ++++++++++++++++++ routes/subreddit.js | 119 ++++++++++++++++++++---------- 4 files changed, 194 insertions(+), 43 deletions(-) diff --git a/inc/processJsonPost.js b/inc/processJsonPost.js index f54efa1..7a8ccc8 100644 --- a/inc/processJsonPost.js +++ b/inc/processJsonPost.js @@ -400,8 +400,50 @@ async function finalizeJsonPost( return { post_data: post_data, comments: comments_html }; } -async function getPostItem(post_json, req) { +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; @@ -493,5 +535,6 @@ module.exports = { processReplies, processJsonPost, finalizeJsonPost, + processJsonPostList, getPostItem }; diff --git a/inc/teddit_api/handlePost.js b/inc/teddit_api/handlePost.js index ea74cd5..5fc3444 100644 --- a/inc/teddit_api/handlePost.js +++ b/inc/teddit_api/handlePost.js @@ -29,7 +29,7 @@ module.exports = function () { let post = json[0].data.children[0].data; let comments = json[1].data.children; - items += await getPostItem(post, req); + items += await getPostItem(post, req, protocol); for (var i = 0; i < comments.length; i++) { let comment = comments[i].data; diff --git a/inc/teddit_api/handleSubreddit.js b/inc/teddit_api/handleSubreddit.js index e40d64e..54b6e25 100644 --- a/inc/teddit_api/handleSubreddit.js +++ b/inc/teddit_api/handleSubreddit.js @@ -1,5 +1,7 @@ const processJsonSubreddit = require('../processJsonSubreddit'); const { processJsonSubredditAbout } = require('../processSubredditAbout'); +const processSearchResults = require('../processSearchResults.js'); +const { processJsonPostList, getPostItem } = require('../processJsonPost'); module.exports = function () { const config = require('../../config'); @@ -225,4 +227,73 @@ module.exports = function () { 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'); + let _json = json; // Keep the original json + 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)); + } + } + }; }; diff --git a/routes/subreddit.js b/routes/subreddit.js index 5de6314..046f39e 100644 --- a/routes/subreddit.js +++ b/routes/subreddit.js @@ -19,6 +19,15 @@ 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', { @@ -65,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); @@ -78,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) { @@ -140,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, + }); + } })(); } }