Compare commits

...

14 Commits

Author SHA1 Message Date
teddit 079ea36d24 update _options cookies, add option for opening gated subreddits, fixes #374 2023-01-01 21:55:03 +01:00
teddit d31c418816 update packages 2023-01-01 21:34:41 +01:00
teddit d11ddce9d2 Merge pull request 'Adding port expose to dockerfile' (#377) from bradmurray/teddit:bradmurray-dockerfile-expose into main
Reviewed-on: https://codeberg.org/teddit/teddit/pulls/377
2023-01-01 20:28:14 +00:00
teddit 572068aca4 Merge pull request 'tweak: Add flag to pm2 setup command & improve docs slightly.' (#376) from NunoSempere/teddit:nunosempere-docs-tweak into main
Reviewed-on: https://codeberg.org/teddit/teddit/pulls/376
2023-01-01 20:27:40 +00:00
teddit ea6ad7c8ec Merge pull request 'More API endpoints' (#373) from CosmosDev/teddit:feature/more_api_endpoints into main
Reviewed-on: https://codeberg.org/teddit/teddit/pulls/373
2023-01-01 20:26:36 +00:00
bradmurray d96372b08a Adding port expose to dockerfile
If you want to use a dockerized nginx the dockerfile has to have an expose command or no ports get exposed.
2022-12-27 02:07:31 +00:00
NunoSempere e59e57ca83 tweak: Add name flag to pm2, make docs a bit more explanatory. 2022-12-25 00:37:12 +00:00
NunoSempere 494c7f5417 Merge pull request 'update: update fork before making new pull request.' (#1) from teddit/teddit:main into main
Reviewed-on: https://codeberg.org/NunoSempere/teddit/pulls/1
2022-12-25 00:32:20 +00:00
CosmosDev 2c5c9d7cde Add support for subreddits explore API 2022-12-15 22:03:49 +01:00
CosmosDev 54c658ff9b Clean code 2022-12-15 21:38:21 +01:00
CosmosDev 3a51e9d165 Refactor handleSubreddit.js 2022-12-15 20:25:04 +01:00
CosmosDev baddb1aec2 Add suport for subreddit search API 2022-12-15 20:21:12 +01:00
CosmosDev eec2a24eb3 Add support for subreddit about API 2022-12-15 19:10:32 +01:00
CosmosDev 0852396b6d Add support for post API 2022-12-14 22:08:12 +01:00
10 changed files with 933 additions and 1993 deletions

View File

@ -12,4 +12,6 @@ COPY config.js.template ./config.js
RUN find ./static/ -type d -exec chmod -R 777 {} \; RUN find ./static/ -type d -exec chmod -R 777 {} \;
EXPOSE 8080
CMD npm start CMD npm start

View File

@ -201,11 +201,15 @@ You can also run teddit from a process manager like [pm2](https://www.npmjs.com/
``` ```
## To run: ## To run:
npm install pm2 -g npm install pm2 -g
pm2 start app.js pm2 start app.js --name teddit
## To run on startup: ## To run on startup:
pm2 startup pm2 startup
pm2 save pm2 save ## if using systemd, see below.
## To restart or stop
pm2 restart teddit
pm2 stop teddit
``` ```
See also the [pm2 instructions for running a project on startup](https://pm2.keymetrics.io/docs/usage/startup/), and in particular the section on waiting for your machine to connect to its network. See also the [pm2 instructions for running a project on startup](https://pm2.keymetrics.io/docs/usage/startup/). In particular, if using systemd, see the section on how to modify the systemd init file so that it runs after your system connects to the network.

View File

@ -73,7 +73,7 @@ module.exports = function(fetch) {
}) })
} }
this.redditApiGETHeaders = function() { this.redditApiGETHeaders = function() {
let cookies = '_options=%7B%22pref_quarantine_optin%22%3A%20true%7D' let cookies = `edgebucket=; _options={%22pref_gated_sr_optin%22:true,%22pref_quarantine_optin%22:true}`
if(!config.use_reddit_oauth) if(!config.use_reddit_oauth)
return { headers: { cookie: cookies }, method: 'GET' } return { headers: { cookie: cookies }, method: 'GET' }

View File

@ -1,5 +1,6 @@
const compilePostComments = require('./compilePostComments.js')(); const compilePostComments = require('./compilePostComments.js')();
const procPostMedia = require('./processPostMedia.js')(); const procPostMedia = require('./processPostMedia.js')();
const config = require('../config');
async function processReplies(data, post_id, depth, user_preferences) { async function processReplies(data, post_id, depth, user_preferences) {
let return_replies = []; let return_replies = [];
@ -399,8 +400,141 @@ async function finalizeJsonPost(
return { post_data: post_data, comments: comments_html }; 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 = `<enclosure length="0" type="${mime}" url="${thumbnail}" />`;
}
let append_desc_html = `<br/><a href="${post_json.url}">[link]</a> <a href="${post_json.permalink}">[comments]</a>`;
return `
<item>
<title>${post_json.title}</title>
<author>${post_json.author}</author>
<created>${post_json.created}</created>
<pubDate>${new Date(
post_json.created_utc * 1000
).toGMTString()}</pubDate>
<domain>${post_json.domain}</domain>
<id>${post_json.id}</id>
<thumbnail>${thumbnail}</thumbnail>
${enclosure}
<link>${post_json.permalink}</link>
<url>${post_json.url}</url>
<description><![CDATA[${unescape(
post_json.selftext_html
)}${append_desc_html}]]></description>
<num_comments>${post_json.num_comments}</num_comments>
<ups>${post_json.ups}</ups>
<stickied>${post_json.stickied}</stickied>
<is_self_link>${is_self_link}</is_self_link>
</item>
`;
}
module.exports = { module.exports = {
processReplies, processReplies,
processJsonPost, processJsonPost,
finalizeJsonPost, finalizeJsonPost,
processJsonPostList,
getPostItem
}; };

View File

@ -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
};

View File

@ -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 += `
<item>
<title>${title}</title>
<author>${comment.author}</author>
<created>${comment.created}</created>
<pubDate>${new Date(
comment.created_utc * 1000
).toGMTString()}</pubDate>
<id>${comment.id}</id>
<link>${comment.permalink}</link>
<description><![CDATA[${unescape(
comment.body_html
)}]]></description>
<ups>${comment.ups}</ups>
</item>
`;
}
}
let xml_output = `<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<atom:link href="${post.permalink}?api&amp;type=rss" rel="self" type="application/rss+xml" />
<title>${post.title}</title>
<link>${post.url}</link>
${items}
</channel>
</rss>`;
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));
}
}
};
};

View File

@ -1,4 +1,8 @@
const processJsonSubreddit = require('../processJsonSubreddit'); 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 () { module.exports = function () {
const config = require('../../config'); const config = require('../../config');
@ -27,93 +31,10 @@ module.exports = function () {
if (api_type === 'rss') { if (api_type === 'rss') {
let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http'; let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http';
let items = ''; let items = '';
for (var i = 0; i < json.data.children.length; i++) { for (var i = 0; i < json.data.children.length; i++) {
let link = json.data.children[i].data; let post = json.data.children[i].data;
let thumbnail = ''; items += await getPostItem(post, req, protocol);
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 = `<enclosure length="0" type="${mime}" url="${thumbnail}" />`;
}
let append_desc_html = `<br/><a href="${link.url}">[link]</a> <a href="${link.permalink}">[comments]</a>`;
items += `
<item>
<title>${link.title}</title>
<author>${link.author}</author>
<created>${link.created}</created>
<pubDate>${new Date(
link.created_utc * 1000
).toGMTString()}</pubDate>
<domain>${link.domain}</domain>
<id>${link.id}</id>
<thumbnail>${thumbnail}</thumbnail>
${enclosure}
<link>${link.permalink}</link>
<url>${link.url}</url>
<description><![CDATA[${unescape(
link.selftext_html
)}${append_desc_html}]]></description>
<num_comments>${link.num_comments}</num_comments>
<ups>${link.ups}</ups>
<stickied>${link.stickied}</stickied>
<is_self_link>${is_self_link}</is_self_link>
</item>
`;
} }
let r_subreddit = '/r/' + subreddit; let r_subreddit = '/r/' + subreddit;
@ -149,44 +70,186 @@ module.exports = function () {
req.cookies req.cookies
); );
await processJsonPostList(processed_json.links, mode);
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));
}
console.log('Teddit API request - subreddit about');
if (from === 'redis') json = JSON.parse(json);
res.setHeader('Content-Type', 'application/json');
if (api_target === 'reddit') {
return res.end(JSON.stringify(json));
} else {
let subreddit_about = await processJsonSubredditAbout(
json,
true
);
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 protocol = config.https_enabled || config.api_force_https ? 'https' : 'http';
for (var i = 0; i < processed_json.links.length; i++) { let items = '';
let link = processed_json.links[i];
let valid_reddit_self_domains = ['reddit.com'];
let is_self_link = false;
if (link.domain) { for (var i = 0; i < json.data.children.length; i++) {
let tld = link.domain.split('self.'); let post = json.data.children[i].data;
if (tld.length > 1) { items += await getPostItem(post, req, protocol);
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}`; let r_subreddit = '/r/' + subreddit;
let title = `${query} - ${r_subreddit}`;
let link = `${protocol}://${config.domain}${r_subreddit}/search?q=${query}`;
if (is_self_link) link.url = link.permalink; let xml_output = `<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<atom:link href="${link}&amp;api&amp;type=rss" rel="self" type="application/rss+xml" />
<title>${title}</title>
<link>${link}</link>
<description>Results for: ${query} - ${r_subreddit}</description>
${items}
</channel>
</rss>`;
if (link.images) { res.setHeader('Content-Type', 'application/rss+xml');
if (link.images.thumb !== 'self') {
link.images.thumb = `${protocol}://${config.domain}${link.images.thumb}`; 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));
}
if (mode === 'light') { console.log('Teddit API request - subreddit explore');
link.selftext_html = null; 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 += `
<item>
<title>${data.title}</title>
<created>${data.created}</created>
<pubDate>${new Date(
data.created_utc * 1000
).toGMTString()}</pubDate>
<id>${data.id}</id>
<name>${data.display_name}</name>
<name_prefixed>${data.display_name_prefixed}</name_prefixed>
<url>${replaceDomains(data.url, req.cookies)}</url>
<description><![CDATA[${unescape(
data.public_description_html
)}]]></description>
<subscribers>${data.subscribers}</subscribers>
<over_18>${data.over18}</over_18>
</item>
`;
} }
let title = `${query}`;
let link = `${protocol}://${config.domain}/subreddits/search?q=${query}`;
let xml_output = `<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<atom:link href="${link}&amp;api&amp;type=rss" rel="self" type="application/rss+xml" />
<title>${title}</title>
<link>${link}</link>
<description>Results for: ${query}</description>
${items}
</channel>
</rss>`;
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)); return res.end(JSON.stringify(processed_json));
} }
} }

1818
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@
"dependencies": { "dependencies": {
"compression": "^1.7.4", "compression": "^1.7.4",
"cookie-parser": "^1.4.5", "cookie-parser": "^1.4.5",
"express": "^4.17.1", "express": "^4.18.2",
"helmet": "^4.6.0", "helmet": "^4.6.0",
"https-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0",
"minizlib": "^2.1.2", "minizlib": "^2.1.2",

View File

@ -6,16 +6,28 @@ const {
processJsonPost, processJsonPost,
finalizeJsonPost, finalizeJsonPost,
} = require('../inc/processJsonPost.js'); } = require('../inc/processJsonPost.js');
const processSubredditAbout = require('../inc/processSubredditAbout.js'); const {
processSubredditAbout
} = require('../inc/processSubredditAbout.js');
const processSearchResults = require('../inc/processSearchResults.js'); const processSearchResults = require('../inc/processSearchResults.js');
const processJsonSubreddit = require('../inc/processJsonSubreddit.js'); const processJsonSubreddit = require('../inc/processJsonSubreddit.js');
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')(); const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
const tedditApiPost = require('../inc/teddit_api/handlePost.js')();
const processMoreComments = require('../inc/processMoreComments.js'); const processMoreComments = require('../inc/processMoreComments.js');
const processJsonSubredditsExplore = require('../inc/processSubredditsExplore.js'); const processJsonSubredditsExplore = require('../inc/processSubredditsExplore.js');
subredditRoutes.get('/r/:subreddit/search', (req, res, next) => { subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
let subreddit = req.params.subreddit; let subreddit = req.params.subreddit;
let q = req.query.q; 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') { if (typeof q === 'undefined') {
return res.render('search', { return res.render('search', {
@ -62,7 +74,7 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
count = ''; 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) => { redis.get(key, (error, json) => {
if (error) { if (error) {
console.error('Error getting the search key from redis.', error); console.error('Error getting the search key from redis.', error);
@ -75,6 +87,19 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
if (json) { if (json) {
console.log('Got search key from redis.'); console.log('Got search key from redis.');
(async () => { (async () => {
if (api_req) {
return handleTedditApiSubredditSearch(
json,
req,
res,
'redis',
api_type,
api_target,
subreddit,
q,
api_mode
);
} else {
let processed_json = await processSearchResults( let processed_json = await processSearchResults(
json, json,
false, false,
@ -94,13 +119,14 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
user_preferences: req.cookies, user_preferences: req.cookies,
instance_config: config, instance_config: config,
}); });
}
})(); })();
} else { } else {
let url = ''; let url = '';
if (config.use_reddit_oauth) 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 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()) fetch(encodeURI(url), redditApiGETHeaders())
.then((result) => { .then((result) => {
if (result.status === 200) { if (result.status === 200) {
@ -137,6 +163,19 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
} else { } else {
console.log('Fetched search results from Reddit.'); console.log('Fetched search results from Reddit.');
(async () => { (async () => {
if (api_req) {
return handleTedditApiSubredditSearch(
json,
req,
res,
'from_online',
api_type,
api_target,
subreddit,
q,
api_mode
);
} else {
let processed_json = await processSearchResults( let processed_json = await processSearchResults(
json, json,
true, true,
@ -156,6 +195,7 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
user_preferences: req.cookies, user_preferences: req.cookies,
instance_config: config, 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( subredditRoutes.get(
'/r/:subreddit/wiki/:page?/:sub_page?', '/r/:subreddit/wiki/:page?/:sub_page?',
(req, res, next) => { (req, res, next) => {
@ -605,6 +746,14 @@ subredditRoutes.get(
let viewing_comment = false; let viewing_comment = false;
let comment_ids = req.query.comment_ids; let comment_ids = req.query.comment_ids;
let context = parseInt(req.query.context); 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) { if (req.params.comment_id) {
comment_id = `${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 comments_url = `/r/${subreddit}/comments/${id}/${snippet}/${comment_id}`;
let post_url = `/r/${subreddit}/comments/${id}/${snippet}/`; 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) => { redis.get(comments_key, (error, json) => {
if (error) { if (error) {
@ -654,6 +803,16 @@ subredditRoutes.get(
if (json) { if (json) {
console.log(`Got ${comments_url} key from redis.`); console.log(`Got ${comments_url} key from redis.`);
(async () => { (async () => {
if (api_req) {
return handleTedditApiPost(
json,
req,
res,
'redis',
api_type,
api_target
);
} else {
let parsed = false; let parsed = false;
let more_comments = null; let more_comments = null;
if (comment_ids) { if (comment_ids) {
@ -698,13 +857,14 @@ subredditRoutes.get(
redis_key: comments_key, redis_key: comments_key,
instance_config: config, instance_config: config,
}); });
}
})(); })();
} else { } else {
let url = ''; let url = '';
if (config.use_reddit_oauth) 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 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()) fetch(encodeURI(url), redditApiGETHeaders())
.then((result) => { .then((result) => {
@ -730,6 +890,16 @@ subredditRoutes.get(
`Fetched the JSON from reddit.com${comments_url}.` `Fetched the JSON from reddit.com${comments_url}.`
); );
(async () => { (async () => {
if (api_req) {
return handleTedditApiPost(
json,
req,
res,
'from_online',
api_type,
api_target
);
} else {
let more_comments = null; let more_comments = null;
if (comment_ids) { if (comment_ids) {
let key = `${post_url}:morechildren:comment_ids:${comment_ids}`; let key = `${post_url}:morechildren:comment_ids:${comment_ids}`;
@ -775,6 +945,7 @@ subredditRoutes.get(
redis_key: comments_key, redis_key: comments_key,
instance_config: config, instance_config: config,
}); });
}
})(); })();
} }
} }
@ -839,6 +1010,14 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => {
let before = req.query.before; let before = req.query.before;
let sortby = req.params.sort; let sortby = req.params.sort;
let searching = false; 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) { if (!after) {
after = ''; after = '';
@ -860,12 +1039,12 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => {
sortby = ''; sortby = '';
} }
let key = `subreddits:sort:${sortby}${d}`; let key = `subreddits:sort:${sortby}${d}:raw_json:${raw_json}`;
if (sortby === 'search') { if (sortby === 'search') {
if (typeof q == 'undefined' || q == '') return res.redirect('/subreddits'); 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; searching = true;
} }
@ -881,6 +1060,17 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => {
if (json) { if (json) {
console.log(`Got subreddits key from redis.`); console.log(`Got subreddits key from redis.`);
(async () => { (async () => {
if (api_req) {
return handleTedditApiSubredditsExplore(
json,
req,
res,
'redis',
api_type,
api_target,
q
);
} else {
let processed_json = await processJsonSubredditsExplore( let processed_json = await processJsonSubredditsExplore(
json, json,
'redis', 'redis',
@ -910,19 +1100,20 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => {
instance_config: config, instance_config: config,
}); });
} }
}
})(); })();
} else { } else {
let url = ''; let url = '';
if (config.use_reddit_oauth) { if (config.use_reddit_oauth) {
if (!searching) 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 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 { } else {
if (!searching) 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 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()) fetch(encodeURI(url), redditApiGETHeaders())
@ -946,6 +1137,17 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => {
} else { } else {
console.log(`Fetched the JSON from reddit.com/subreddits.`); console.log(`Fetched the JSON from reddit.com/subreddits.`);
(async () => { (async () => {
if (api_req) {
return handleTedditApiSubredditsExplore(
json,
req,
res,
'from_online',
api_type,
api_target,
q
);
} else {
let processed_json = await processJsonSubredditsExplore( let processed_json = await processJsonSubredditsExplore(
json, json,
'from_online', 'from_online',
@ -965,6 +1167,7 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => {
instance_nsfw_enabled: config.nsfw_enabled, instance_nsfw_enabled: config.nsfw_enabled,
instance_config: config, instance_config: config,
}); });
}
})(); })();
} }
}); });