mirror of
https://codeberg.org/tacerus/teddit.git
synced 2024-11-22 06:49:26 +01:00
Merge pull request 'clean up routes.js' (#234) from json/teddit:routes-cleanup into main
Reviewed-on: https://codeberg.org/teddit/teddit/pulls/234
This commit is contained in:
commit
bd010e3b36
205
app.js
205
app.js
@ -1,16 +1,18 @@
|
||||
const config = require('./config')
|
||||
const config = require('./config');
|
||||
|
||||
global.client_id_b64 = Buffer.from(`${config.reddit_app_id}:`).toString('base64')
|
||||
global.reddit_access_token = null
|
||||
global.reddit_refresh_token = null
|
||||
global.ratelimit_counts = {}
|
||||
global.ratelimit_timestamps = {}
|
||||
global.client_id_b64 = Buffer.from(`${config.reddit_app_id}:`).toString(
|
||||
'base64'
|
||||
);
|
||||
global.reddit_access_token = null;
|
||||
global.reddit_refresh_token = null;
|
||||
global.ratelimit_counts = {};
|
||||
global.ratelimit_timestamps = {};
|
||||
|
||||
const pug = require('pug')
|
||||
const compression = require('compression')
|
||||
const express = require('express')
|
||||
const cookieParser = require('cookie-parser')
|
||||
const r = require('redis')
|
||||
const pug = require('pug');
|
||||
const compression = require('compression');
|
||||
const express = require('express');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const r = require('redis');
|
||||
|
||||
const redis = (() => {
|
||||
if (!config.redis_enabled) {
|
||||
@ -18,145 +20,162 @@ const redis = (() => {
|
||||
return {
|
||||
get: (_, callback) => callback(null, null),
|
||||
setex: (_, _1, _2, callback) => callback(null),
|
||||
on: () => {}
|
||||
}
|
||||
on: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
const redisOptions = {
|
||||
host: '127.0.0.1',
|
||||
port: 6379
|
||||
}
|
||||
|
||||
port: 6379,
|
||||
};
|
||||
|
||||
if (config.redis_db) {
|
||||
redisOptions.db = config.redis_db
|
||||
redisOptions.db = config.redis_db;
|
||||
}
|
||||
|
||||
if (config.redis_host) {
|
||||
redisOptions.host = config.redis_host
|
||||
redisOptions.host = config.redis_host;
|
||||
}
|
||||
|
||||
|
||||
if (config.redis_port && config.redis_port > 0) {
|
||||
redisOptions.port = config.redis_port
|
||||
}
|
||||
redisOptions.port = config.redis_port;
|
||||
}
|
||||
|
||||
if (config.redis_password) {
|
||||
redisOptions.password = config.redis_password
|
||||
redisOptions.password = config.redis_password;
|
||||
}
|
||||
|
||||
return r.createClient(redisOptions)
|
||||
})()
|
||||
return r.createClient(redisOptions);
|
||||
})();
|
||||
|
||||
const nodeFetch = require('node-fetch')
|
||||
const nodeFetch = require('node-fetch');
|
||||
const fetch = config.http_proxy
|
||||
? (() => {
|
||||
const agent = require('https-proxy-agent')(config.http_proxy)
|
||||
const agent = require('https-proxy-agent')(config.http_proxy);
|
||||
return (url, options) => {
|
||||
const instanceOptions = {
|
||||
agent,
|
||||
...options
|
||||
...options,
|
||||
};
|
||||
return nodeFetch(url, instanceOptions);
|
||||
}
|
||||
};
|
||||
})()
|
||||
: nodeFetch
|
||||
: nodeFetch;
|
||||
|
||||
const helmet = require('helmet')
|
||||
const bodyParser = require('body-parser')
|
||||
const fs = require('fs')
|
||||
const app = express()
|
||||
const request = require('postman-request')
|
||||
const commons = require('./inc/commons.js')(request, fs)
|
||||
const helmet = require('helmet');
|
||||
const bodyParser = require('body-parser');
|
||||
const fs = require('fs');
|
||||
const app = express();
|
||||
const request = require('postman-request');
|
||||
const commons = require('./inc/commons.js')(request, fs);
|
||||
const dlAndSave = require('./inc/downloadAndSave.js')(commons);
|
||||
|
||||
['pics/thumbs', 'pics/flairs', 'pics/icons', 'vids']
|
||||
.map(d => `./static/${d}`)
|
||||
.filter(d => !fs.existsSync(d))
|
||||
.forEach(d => fs.mkdirSync(d, { recursive: true }))
|
||||
.map((d) => `./static/${d}`)
|
||||
.filter((d) => !fs.existsSync(d))
|
||||
.forEach((d) => fs.mkdirSync(d, { recursive: true }));
|
||||
|
||||
if(!config.https_enabled && config.redirect_http_to_https) {
|
||||
console.error(`Cannot redirect HTTP=>HTTPS while "https_enabled" is false.`)
|
||||
if (!config.https_enabled && config.redirect_http_to_https) {
|
||||
console.error(`Cannot redirect HTTP=>HTTPS while "https_enabled" is false.`);
|
||||
}
|
||||
|
||||
let https = null
|
||||
if(config.https_enabled) {
|
||||
const privateKey = fs.readFileSync(`${config.cert_dir}/privkey.pem`, 'utf8')
|
||||
const certificate = fs.readFileSync(`${config.cert_dir}/cert.pem`, 'utf8')
|
||||
const ca = fs.readFileSync(`${config.cert_dir}/chain.pem`, 'utf8')
|
||||
let https = null;
|
||||
if (config.https_enabled) {
|
||||
const privateKey = fs.readFileSync(`${config.cert_dir}/privkey.pem`, 'utf8');
|
||||
const certificate = fs.readFileSync(`${config.cert_dir}/cert.pem`, 'utf8');
|
||||
const ca = fs.readFileSync(`${config.cert_dir}/chain.pem`, 'utf8');
|
||||
const credentials = {
|
||||
key: privateKey,
|
||||
cert: certificate,
|
||||
ca: ca
|
||||
}
|
||||
https = require('https').Server(credentials, app)
|
||||
global.protocol = 'https://'
|
||||
key: privateKey,
|
||||
cert: certificate,
|
||||
ca: ca,
|
||||
};
|
||||
https = require('https').Server(credentials, app);
|
||||
global.protocol = 'https://';
|
||||
} else {
|
||||
global.protocol = 'http://'
|
||||
global.protocol = 'http://';
|
||||
}
|
||||
|
||||
const http = require('http').Server(app)
|
||||
const http = require('http').Server(app);
|
||||
|
||||
if(config.redirect_www) {
|
||||
if (config.redirect_www) {
|
||||
app.use((req, res, next) => {
|
||||
if(req.headers.host) {
|
||||
if(req.headers.host.slice(0, 4) === 'www.') {
|
||||
let newhost = req.headers.host.slice(4)
|
||||
return res.redirect(301, `${req.protocol}://${newhost}${req.originalUrl}`)
|
||||
if (req.headers.host) {
|
||||
if (req.headers.host.slice(0, 4) === 'www.') {
|
||||
let newhost = req.headers.host.slice(4);
|
||||
return res.redirect(
|
||||
301,
|
||||
`${req.protocol}://${newhost}${req.originalUrl}`
|
||||
);
|
||||
}
|
||||
}
|
||||
next()
|
||||
})
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
if(config.use_helmet && config.https_enabled) {
|
||||
app.use(helmet())
|
||||
if(config.use_helmet_hsts) {
|
||||
app.use(helmet.hsts({ maxAge: 31536000, preload: true }))
|
||||
if (config.use_helmet && config.https_enabled) {
|
||||
app.use(helmet());
|
||||
if (config.use_helmet_hsts) {
|
||||
app.use(helmet.hsts({ maxAge: 31536000, preload: true }));
|
||||
}
|
||||
}
|
||||
|
||||
if(config.use_compression) {
|
||||
app.use(compression())
|
||||
if (config.use_compression) {
|
||||
app.use(compression());
|
||||
}
|
||||
|
||||
app.use(cookieParser())
|
||||
app.use(cookieParser());
|
||||
|
||||
if(config.use_view_cache) {
|
||||
app.set('view cache', true)
|
||||
if (config.use_view_cache) {
|
||||
app.set('view cache', true);
|
||||
}
|
||||
|
||||
if(config.trust_proxy) {
|
||||
app.set('trust proxy', config.trust_proxy_address)
|
||||
if (config.trust_proxy) {
|
||||
app.set('trust proxy', config.trust_proxy_address);
|
||||
}
|
||||
|
||||
app.use(bodyParser.urlencoded({ extended: true, limit: '10mb' }))
|
||||
app.use(bodyParser.json({ limit: '10mb' }))
|
||||
app.use(express.static(`${__dirname}/static`))
|
||||
app.use(bodyParser.urlencoded({ extended: true, limit: '10mb' }));
|
||||
app.use(bodyParser.json({ limit: '10mb' }));
|
||||
app.use(express.static(`${__dirname}/static`));
|
||||
|
||||
app.set('views', './views')
|
||||
app.set('view engine', 'pug')
|
||||
app.set('views', './views');
|
||||
app.set('view engine', 'pug');
|
||||
|
||||
if(config.redirect_http_to_https) {
|
||||
const redditAPI = require('./inc/initRedditApi.js')(fetch);
|
||||
|
||||
/*
|
||||
This is temporary. It's needed for the routes to work.
|
||||
It can be removed once these functions are made more modular.
|
||||
*/
|
||||
module.exports = { redis, fetch, RedditAPI: redditAPI };
|
||||
|
||||
const allRoutes = require('./routes/index');
|
||||
|
||||
app.use('/', allRoutes);
|
||||
|
||||
// The old routes
|
||||
//require('./routes')(app, redis, fetch, redditAPI);
|
||||
|
||||
if (config.redirect_http_to_https) {
|
||||
app.use((req, res, next) => {
|
||||
if(req.secure)
|
||||
next()
|
||||
else
|
||||
res.redirect(`https://${req.headers.host}${req.url}`)
|
||||
})
|
||||
if (req.secure) next();
|
||||
else res.redirect(`https://${req.headers.host}${req.url}`);
|
||||
});
|
||||
}
|
||||
|
||||
const redditAPI = require('./inc/initRedditApi.js')(fetch)
|
||||
require('./routes')(app, redis, fetch, redditAPI)
|
||||
|
||||
redis.on('error', (error) => {
|
||||
if(error) {
|
||||
console.error(`Redis error: ${error}`)
|
||||
if (error) {
|
||||
console.error(`Redis error: ${error}`);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
const cacheControl = require('./cacheControl.js')
|
||||
cacheControl.removeCacheFiles()
|
||||
const cacheControl = require('./cacheControl.js');
|
||||
cacheControl.removeCacheFiles();
|
||||
|
||||
if(config.https_enabled) {
|
||||
https.listen(config.ssl_port, config.listen_address, () => console.log(`Teddit running on https://${config.domain}:${config.ssl_port}`))
|
||||
if (config.https_enabled) {
|
||||
https.listen(config.ssl_port, config.listen_address, () =>
|
||||
console.log(`Teddit running on https://${config.domain}:${config.ssl_port}`)
|
||||
);
|
||||
}
|
||||
http.listen(config.nonssl_port, config.listen_address, () => console.log(`Teddit running on http://${config.domain}:${config.nonssl_port}`))
|
||||
http.listen(config.nonssl_port, config.listen_address, () =>
|
||||
console.log(`Teddit running on http://${config.domain}:${config.nonssl_port}`)
|
||||
);
|
||||
|
7
routes/gallery.js
Normal file
7
routes/gallery.js
Normal file
@ -0,0 +1,7 @@
|
||||
const galleryRoute = require('express').Router();
|
||||
|
||||
galleryRoute.get('/gallery/:id', (req, res, next) => {
|
||||
return res.redirect(`/comments/${req.params.id}`);
|
||||
});
|
||||
|
||||
module.exports = galleryRoute;
|
219
routes/home.js
Normal file
219
routes/home.js
Normal file
@ -0,0 +1,219 @@
|
||||
const config = require('../config');
|
||||
const { redis, fetch } = require('../app');
|
||||
const homeRoute = require('express').Router();
|
||||
|
||||
const processUser = require('../inc/processJsonUser.js')();
|
||||
const processPost = require('../inc/processJsonPost.js')();
|
||||
const processAbout = require('../inc/processSubredditAbout.js')();
|
||||
const tedditApiUser = require('../inc/teddit_api/handleUser.js')();
|
||||
const processSearches = require('../inc/processSearchResults.js')();
|
||||
const processSubreddit = require('../inc/processJsonSubreddit.js')();
|
||||
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
||||
const processMoreComments = require('../inc/processMoreComments.js')();
|
||||
const processSubredditsExplore =
|
||||
require('../inc/processSubredditsExplore.js')();
|
||||
|
||||
homeRoute.get('/:sort?', async (req, res, next) => {
|
||||
let past = req.query.t;
|
||||
let before = req.query.before;
|
||||
let after = req.query.after;
|
||||
let sortby = req.params.sort || '';
|
||||
let api_req = req.query.api;
|
||||
let api_type = req.query.type;
|
||||
let api_target = req.query.target;
|
||||
|
||||
let proxyable =
|
||||
sortby.includes('.jpg') ||
|
||||
sortby.includes('.png') ||
|
||||
sortby.includes('.jpeg')
|
||||
? true
|
||||
: false;
|
||||
if (proxyable) {
|
||||
let params = new URLSearchParams(req.query).toString();
|
||||
let image_url = `https://preview.redd.it/${sortby}?${params}`;
|
||||
let proxied_image = await downloadAndSave(image_url);
|
||||
if (proxied_image) {
|
||||
return res.redirect(proxied_image);
|
||||
} else {
|
||||
return res.redirect('/');
|
||||
}
|
||||
}
|
||||
|
||||
let d = `&after=${after}`;
|
||||
if (before) {
|
||||
d = `&before=${before}`;
|
||||
}
|
||||
|
||||
if (sortby == '') {
|
||||
sortby = 'hot';
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
'apple-touch-icon.png',
|
||||
'apple-touch-icon-precomposed.png',
|
||||
'apple-touch-icon-120x120.png',
|
||||
'apple-touch-icon-120x120-precomposed.png',
|
||||
].includes(sortby)
|
||||
) {
|
||||
return res.sendStatus(404); // return 404 on shitty apple favicon stuff
|
||||
}
|
||||
|
||||
if (
|
||||
!['new', 'rising', 'controversial', 'top', 'gilded', 'hot'].includes(sortby)
|
||||
) {
|
||||
console.log(`Got invalid sort.`, req.originalUrl);
|
||||
return res.redirect('/');
|
||||
}
|
||||
|
||||
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(`/`);
|
||||
}
|
||||
} else {
|
||||
past = undefined;
|
||||
}
|
||||
} else {
|
||||
if (sortby === 'controversial' || sortby === 'top') {
|
||||
past = 'day';
|
||||
}
|
||||
}
|
||||
|
||||
if (req.query.hasOwnProperty('api')) api_req = true;
|
||||
else api_req = false;
|
||||
|
||||
let raw_json = api_req && req.query.raw_json == '1' ? 1 : 0;
|
||||
|
||||
let key = `/after:${after}:before:${before}:sort:${sortby}:past:${past}:raw_json:${raw_json}`;
|
||||
|
||||
let subbed_subreddits = req.cookies.subbed_subreddits;
|
||||
let get_subbed_subreddits = false;
|
||||
if (subbed_subreddits && Array.isArray(subbed_subreddits)) {
|
||||
get_subbed_subreddits = true;
|
||||
subbed_subreddits = subbed_subreddits.join('+');
|
||||
key = `${subbed_subreddits.toLowerCase()}:${after}:${before}:sort:${sortby}:past:${past}:raw_json:${raw_json}`;
|
||||
}
|
||||
|
||||
redis.get(key, (error, json) => {
|
||||
if (error) {
|
||||
console.error('Error getting the frontpage key from redis.', error);
|
||||
return res.render('index', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
if (json) {
|
||||
console.log('Got frontpage key from redis.');
|
||||
(async () => {
|
||||
if (api_req) {
|
||||
return handleTedditApiSubreddit(
|
||||
json,
|
||||
req,
|
||||
res,
|
||||
'redis',
|
||||
api_type,
|
||||
api_target,
|
||||
'/'
|
||||
);
|
||||
} else {
|
||||
let processed_json = await processJsonSubreddit(
|
||||
json,
|
||||
'redis',
|
||||
null,
|
||||
req.cookies
|
||||
);
|
||||
return res.render('index', {
|
||||
json: processed_json,
|
||||
sortby: sortby,
|
||||
past: past,
|
||||
user_preferences: req.cookies,
|
||||
redis_key: key,
|
||||
});
|
||||
}
|
||||
})();
|
||||
} else {
|
||||
let url = '';
|
||||
if (config.use_reddit_oauth) {
|
||||
if (get_subbed_subreddits)
|
||||
url = `https://oauth.reddit.com/r/${subbed_subreddits}/${sortby}?api_type=json&count=25&g=GLOBAL&t=${past}${d}&raw_json=${raw_json}`;
|
||||
else
|
||||
url = `https://oauth.reddit.com/${sortby}?api_type=json&g=GLOBAL&t=${past}${d}&raw_json=${raw_json}`;
|
||||
} else {
|
||||
if (get_subbed_subreddits)
|
||||
url = `https://reddit.com/r/${subbed_subreddits}/${sortby}.json?api_type=json&count=25&g=GLOBAL&t=${past}${d}&raw_json=${raw_json}`;
|
||||
else
|
||||
url = `https://reddit.com/${sortby}.json?g=GLOBAL&t=${past}${d}&raw_json=${raw_json}`;
|
||||
}
|
||||
fetch(encodeURI(url), redditApiGETHeaders())
|
||||
.then((result) => {
|
||||
if (result.status === 200) {
|
||||
result.json().then((json) => {
|
||||
redis.setex(
|
||||
key,
|
||||
config.setexs.frontpage,
|
||||
JSON.stringify(json),
|
||||
(error) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
'Error setting the frontpage key to redis.',
|
||||
error
|
||||
);
|
||||
return res.render('index', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
} else {
|
||||
console.log('Fetched the frontpage from Reddit.');
|
||||
(async () => {
|
||||
if (api_req) {
|
||||
return handleTedditApiSubreddit(
|
||||
json,
|
||||
req,
|
||||
res,
|
||||
'from_online',
|
||||
api_type,
|
||||
api_target,
|
||||
'/'
|
||||
);
|
||||
} else {
|
||||
let processed_json = await processJsonSubreddit(
|
||||
json,
|
||||
'from_online',
|
||||
null,
|
||||
req.cookies
|
||||
);
|
||||
return res.render('index', {
|
||||
json: processed_json,
|
||||
sortby: sortby,
|
||||
past: past,
|
||||
user_preferences: req.cookies,
|
||||
redis_key: key,
|
||||
});
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
} 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 frontpage JSON file.', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = homeRoute;
|
27
routes/index.js
Normal file
27
routes/index.js
Normal file
@ -0,0 +1,27 @@
|
||||
const galleryRoute = require('./gallery');
|
||||
const homeRoute = require('./home');
|
||||
const overridingRoutes = require('./overides');
|
||||
const pollRoute = require('./poll');
|
||||
const preferenceRoutes = require('./preferences');
|
||||
const saveRoutes = require('./save');
|
||||
const searchRoute = require('./search');
|
||||
const staticRoutes = require('./static');
|
||||
const subredditRoutes = require('./subreddit');
|
||||
const subscriptionRoutes = require('./subscription');
|
||||
const userRoutes = require('./user');
|
||||
|
||||
const allRoutes = require('express').Router();
|
||||
|
||||
allRoutes.use(overridingRoutes);
|
||||
allRoutes.use(staticRoutes);
|
||||
allRoutes.use(preferenceRoutes);
|
||||
allRoutes.use(subredditRoutes);
|
||||
allRoutes.use(userRoutes);
|
||||
allRoutes.use(subscriptionRoutes);
|
||||
allRoutes.use(saveRoutes);
|
||||
allRoutes.use(searchRoute);
|
||||
allRoutes.use(homeRoute);
|
||||
allRoutes.use(galleryRoute);
|
||||
allRoutes.use(pollRoute);
|
||||
|
||||
module.exports = allRoutes;
|
184
routes/overides.js
Normal file
184
routes/overides.js
Normal file
@ -0,0 +1,184 @@
|
||||
const config = require('../config');
|
||||
const overridingRoutes = require('express').Router();
|
||||
|
||||
overridingRoutes.all('*', (req, res, next) => {
|
||||
let themeOverride = req.query.theme;
|
||||
if (themeOverride) {
|
||||
// Convert Dark to dark since the stylesheet has it lower case
|
||||
themeOverride = themeOverride.toLowerCase();
|
||||
// This override here will set it for the current request
|
||||
req.cookies.theme = themeOverride;
|
||||
// this will set it for future requests
|
||||
res.cookie('theme', themeOverride, { maxAge: 31536000, httpOnly: true });
|
||||
} else if (!req.cookies.theme && req.cookies.theme !== '') {
|
||||
req.cookies.theme = config.theme;
|
||||
}
|
||||
|
||||
let flairsOverride = req.query.flairs;
|
||||
if (flairsOverride) {
|
||||
req.cookies.flairs = flairsOverride;
|
||||
res.cookie('flairs', flairsOverride, { maxAge: 31536000, httpOnly: true });
|
||||
}
|
||||
|
||||
let nsfwEnabledOverride = req.query.nsfw_enabled;
|
||||
if (nsfwEnabledOverride) {
|
||||
req.cookies.nsfw_enabled = nsfwEnabledOverride;
|
||||
res.cookie('nsfw_enabled', nsfwEnabledOverride, {
|
||||
maxAge: 31536000,
|
||||
httpOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
let highlightControversialOverride = req.query.highlight_controversial;
|
||||
if (highlightControversialOverride) {
|
||||
req.cookies.highlight_controversial = highlightControversialOverride;
|
||||
res.cookie('highlight_controversial', highlightControversialOverride, {
|
||||
maxAge: 31536000,
|
||||
httpOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
let postMediaMaxHeight = req.query.post_media_max_height;
|
||||
if (postMediaMaxHeight) {
|
||||
if (
|
||||
config.post_media_max_heights.hasOwnProperty(postMediaMaxHeight) ||
|
||||
!isNaN(postMediaMaxHeight)
|
||||
) {
|
||||
req.cookies.post_media_max_height = postMediaMaxHeight;
|
||||
res.cookie('post_media_max_height', postMediaMaxHeight, {
|
||||
maxAge: 31536000,
|
||||
httpOnly: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let collapseChildComments = req.query.collapse_child_comments;
|
||||
if (collapseChildComments) {
|
||||
req.cookies.collapse_child_comments = collapseChildComments;
|
||||
res.cookie('collapse_child_comments', collapseChildComments, {
|
||||
maxAge: 31536000,
|
||||
httpOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
let showUpvotedPercentage = req.query.show_upvoted_percentage;
|
||||
if (showUpvotedPercentage) {
|
||||
req.cookies.show_upvoted_percentage = showUpvotedPercentage;
|
||||
res.cookie('show_upvoted_percentage', showUpvotedPercentage, {
|
||||
maxAge: 31536000,
|
||||
httpOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
let domainTwitter = req.query.domain_twitter;
|
||||
if (domainTwitter) {
|
||||
req.cookies.domain_twitter = domainTwitter;
|
||||
res.cookie('domain_twitter', domainTwitter, {
|
||||
maxAge: 31536000,
|
||||
httpOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
let domainYoutube = req.query.domain_youtube;
|
||||
if (domainYoutube) {
|
||||
req.cookies.domain_youtube = domainYoutube;
|
||||
res.cookie('domain_youtube', domainYoutube, {
|
||||
maxAge: 31536000,
|
||||
httpOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
let domainInstagram = req.query.domain_instagram;
|
||||
if (domainInstagram) {
|
||||
req.cookies.domain_instagram = domainInstagram;
|
||||
res.cookie('domain_instagram', domainInstagram, {
|
||||
maxAge: 31536000,
|
||||
httpOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
let videosMuted = req.query.videos_muted;
|
||||
if (videosMuted) {
|
||||
req.cookies.videos_muted = videosMuted;
|
||||
res.cookie('videos_muted', videosMuted, {
|
||||
maxAge: 31536000,
|
||||
httpOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (!config.rate_limiting) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const valid_reddit_starts = [
|
||||
'/https://old.reddit.com',
|
||||
'/https://reddit.com',
|
||||
'/https://www.reddit.com',
|
||||
'/old.reddit.com',
|
||||
'/reddit.com',
|
||||
'/www.reddit.com',
|
||||
];
|
||||
for (var i = 0; i < valid_reddit_starts.length; i++) {
|
||||
if (req.url.startsWith(valid_reddit_starts[i])) {
|
||||
req.url = req.url.substring(1);
|
||||
const redditRegex = /([A-z.]+\.)?(reddit(\.com))/gm;
|
||||
let teddified_url = req.url.replace(redditRegex, '');
|
||||
if (teddified_url.includes('://')) {
|
||||
teddified_url = teddified_url.split('://')[1];
|
||||
}
|
||||
if (teddified_url == '') {
|
||||
teddified_url = '/';
|
||||
}
|
||||
return res.redirect(teddified_url);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.rate_limiting.enabled) {
|
||||
/**
|
||||
* This route enforces request limits based on an IP address if
|
||||
* config.rate_limiting.enabled is true. By default it's false.
|
||||
*/
|
||||
|
||||
let ip = String(
|
||||
req.headers['x-forwarded-for'] ||
|
||||
req.connection.remoteAddress ||
|
||||
'unknown'
|
||||
);
|
||||
|
||||
if (ip === 'unknown') {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (ratelimit_counts[ip] == undefined) {
|
||||
ratelimit_counts[ip] = 0;
|
||||
}
|
||||
|
||||
if (ratelimit_timestamps[ip] == undefined) {
|
||||
ratelimit_timestamps[ip] = Date.now();
|
||||
}
|
||||
|
||||
let diff = Date.now() - ratelimit_timestamps[ip];
|
||||
let credit = (diff / 60000) * config.rate_limiting.limit_after_limited;
|
||||
ratelimit_counts[ip] -= credit;
|
||||
|
||||
if (ratelimit_counts[ip] < 0) {
|
||||
ratelimit_counts[ip] = 0;
|
||||
}
|
||||
|
||||
ratelimit_counts[ip]++;
|
||||
ratelimit_timestamps[ip] = Date.now();
|
||||
|
||||
if (ratelimit_counts[ip] > config.rate_limiting.initial_limit) {
|
||||
console.log(`RATE LIMITED IP ADDRESS: ${ip}`);
|
||||
return res.send(
|
||||
`Hold your horses! You have hit the request limit. You should be able to refresh this page in a couple of seconds. If you think you are wrongfully limited, create an issue at https://codeberg.org/teddit/teddit. Rate limiting is highly experimental feature.`
|
||||
);
|
||||
} else {
|
||||
return next();
|
||||
}
|
||||
} else {
|
||||
return next();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = overridingRoutes;
|
7
routes/poll.js
Normal file
7
routes/poll.js
Normal file
@ -0,0 +1,7 @@
|
||||
const pollRoute = require('express').Router();
|
||||
|
||||
pollRoute.get('/poll/:id', (req, res, next) => {
|
||||
return res.redirect(`/comments/${req.params.id}`);
|
||||
});
|
||||
|
||||
module.exports = pollRoute;
|
229
routes/preferences.js
Normal file
229
routes/preferences.js
Normal file
@ -0,0 +1,229 @@
|
||||
const config = require('../config');
|
||||
const preferenceRoutes = require('express').Router();
|
||||
|
||||
function resetPreferences(res) {
|
||||
res.clearCookie('theme');
|
||||
res.clearCookie('flairs');
|
||||
res.clearCookie('nsfw_enabled');
|
||||
res.clearCookie('highlight_controversial');
|
||||
res.clearCookie('post_media_max_height');
|
||||
res.clearCookie('collapse_child_comments');
|
||||
res.clearCookie('show_upvoted_percentage');
|
||||
res.clearCookie('subbed_subreddits');
|
||||
res.clearCookie('domain_twitter');
|
||||
res.clearCookie('domain_youtube');
|
||||
res.clearCookie('domain_instagram');
|
||||
res.clearCookie('videos_muted');
|
||||
}
|
||||
|
||||
preferenceRoutes.get('/preferences', (req, res, next) => {
|
||||
return res.render('preferences', {
|
||||
user_preferences: req.cookies,
|
||||
instance_config: config,
|
||||
});
|
||||
});
|
||||
|
||||
preferenceRoutes.get('/resetprefs', (req, res, next) => {
|
||||
resetPreferences(res);
|
||||
return res.redirect('/preferences');
|
||||
});
|
||||
|
||||
preferenceRoutes.get('/import_prefs/:key', (req, res, next) => {
|
||||
let key = req.params.key;
|
||||
if (!key) return res.redirect('/');
|
||||
if (key.length !== 10) return res.redirect('/');
|
||||
|
||||
key = `prefs_key:${key}`;
|
||||
redis.get(key, (error, json) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`Error getting the preferences import key ${key} from redis.`,
|
||||
error
|
||||
);
|
||||
return res.render('index', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
if (json) {
|
||||
try {
|
||||
let prefs = JSON.parse(json);
|
||||
let subbed_subreddits_is_set = false;
|
||||
for (var setting in prefs) {
|
||||
if (prefs.hasOwnProperty(setting)) {
|
||||
res.cookie(setting, prefs[setting], {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
if (setting === 'subbed_subreddits')
|
||||
subbed_subreddits_is_set = true;
|
||||
}
|
||||
}
|
||||
if (!subbed_subreddits_is_set) res.clearCookie('subbed_subreddits');
|
||||
return res.redirect('/');
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`Error setting imported preferences to the cookies. Key: ${key}.`,
|
||||
error
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return res.redirect('/preferences');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
preferenceRoutes.post('/saveprefs', (req, res, next) => {
|
||||
let theme = req.body.theme;
|
||||
let flairs = req.body.flairs;
|
||||
let nsfw_enabled = req.body.nsfw_enabled;
|
||||
let highlight_controversial = req.body.highlight_controversial;
|
||||
let post_media_max_height = req.body.post_media_max_height;
|
||||
let collapse_child_comments = req.body.collapse_child_comments;
|
||||
let show_upvoted_percentage = req.body.show_upvoted_percentage;
|
||||
let domain_twitter = req.body.domain_twitter;
|
||||
let domain_youtube = req.body.domain_youtube;
|
||||
let domain_instagram = req.body.domain_instagram;
|
||||
let videos_muted = req.body.videos_muted;
|
||||
|
||||
res.cookie('theme', theme, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
if (flairs === 'on') flairs = 'true';
|
||||
else flairs = 'false';
|
||||
res.cookie('flairs', flairs, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
if (nsfw_enabled === 'on') nsfw_enabled = 'true';
|
||||
else nsfw_enabled = 'false';
|
||||
res.cookie('nsfw_enabled', nsfw_enabled, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
if (highlight_controversial === 'on') highlight_controversial = 'true';
|
||||
else highlight_controversial = 'false';
|
||||
res.cookie('highlight_controversial', highlight_controversial, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
if (
|
||||
config.post_media_max_heights.hasOwnProperty(post_media_max_height) ||
|
||||
!isNaN(post_media_max_height)
|
||||
)
|
||||
res.cookie('post_media_max_height', post_media_max_height, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
if (collapse_child_comments === 'on') collapse_child_comments = 'true';
|
||||
else collapse_child_comments = 'false';
|
||||
res.cookie('collapse_child_comments', collapse_child_comments, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
if (show_upvoted_percentage === 'on') show_upvoted_percentage = 'true';
|
||||
else show_upvoted_percentage = 'false';
|
||||
res.cookie('show_upvoted_percentage', show_upvoted_percentage, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
if (videos_muted === 'on') videos_muted = 'true';
|
||||
else videos_muted = 'false';
|
||||
res.cookie('videos_muted', videos_muted, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
res.cookie('domain_twitter', domain_twitter, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
res.cookie('domain_youtube', domain_youtube, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
res.cookie('domain_instagram', domain_instagram, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
return res.redirect('/preferences');
|
||||
});
|
||||
|
||||
preferenceRoutes.post('/export_prefs', (req, res, next) => {
|
||||
let export_saved = req.body.export_saved;
|
||||
let export_data = req.cookies;
|
||||
let export_to_file = req.body.export_to_file;
|
||||
|
||||
if (export_saved !== 'on') {
|
||||
if (req.cookies.saved) delete export_data.saved;
|
||||
}
|
||||
|
||||
if (export_to_file === 'on') {
|
||||
res.setHeader(
|
||||
'Content-disposition',
|
||||
'attachment; filename=teddit_prefs.json'
|
||||
);
|
||||
res.setHeader('Content-type', 'preferenceRouteslication/json');
|
||||
return res.send(export_data);
|
||||
}
|
||||
|
||||
let r = `${(Math.random().toString(36) + '00000000000000000')
|
||||
.slice(2, 10 + 2)
|
||||
.toUpperCase()}`;
|
||||
let key = `prefs_key:${r}`;
|
||||
redis.set(key, JSON.stringify(export_data), (error) => {
|
||||
if (error) {
|
||||
console.error(`Error saving preferences to redis.`, error);
|
||||
return res.redirect('/preferences');
|
||||
} else {
|
||||
return res.render('preferences', {
|
||||
user_preferences: req.cookies,
|
||||
instance_config: config,
|
||||
preferences_key: r,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
preferenceRoutes.post('/import_prefs', (req, res, next) => {
|
||||
let body = '';
|
||||
req.on('data', (chunk) => {
|
||||
body += chunk.toString();
|
||||
});
|
||||
req.on('end', () => {
|
||||
body = body.toString();
|
||||
try {
|
||||
let json = body
|
||||
.split('Content-Type: preferenceRouteslication/json')[1]
|
||||
.trim()
|
||||
.split('--')[0];
|
||||
let prefs = JSON.parse(json);
|
||||
resetPreferences(res);
|
||||
for (var setting in prefs) {
|
||||
if (prefs.hasOwnProperty(setting)) {
|
||||
res.cookie(setting, prefs[setting], {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
return res.redirect('/preferences');
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`Error importing preferences from a JSON file. Please report this error on https://codeberg.org/teddit/teddit.`,
|
||||
e
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = preferenceRoutes;
|
315
routes/save.js
Normal file
315
routes/save.js
Normal file
@ -0,0 +1,315 @@
|
||||
const config = require('../config');
|
||||
const { redis, fetch } = require('../app');
|
||||
const saveRoutes = require('express').Router();
|
||||
|
||||
const processUser = require('../inc/processJsonUser.js')();
|
||||
const processPost = require('../inc/processJsonPost.js')();
|
||||
const processAbout = require('../inc/processSubredditAbout.js')();
|
||||
const tedditApiUser = require('../inc/teddit_api/handleUser.js')();
|
||||
const processSearches = require('../inc/processSearchResults.js')();
|
||||
const processSubreddit = require('../inc/processJsonSubreddit.js')();
|
||||
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
||||
const processMoreComments = require('../inc/processMoreComments.js')();
|
||||
const processSubredditsExplore =
|
||||
require('../inc/processSubredditsExplore.js')();
|
||||
|
||||
saveRoutes.get('/saved', (req, res, next) => {
|
||||
let saved = req.cookies.saved;
|
||||
|
||||
if (!saved || !Array.isArray(saved)) {
|
||||
return res.render('saved', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
|
||||
let key = `saved_posts:${saved.join(',')}`;
|
||||
redis.get(key, (error, json) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`Error getting saved_post ${saved_post} key from redis.`,
|
||||
error
|
||||
);
|
||||
return res.redirect('/');
|
||||
}
|
||||
if (json) {
|
||||
(async () => {
|
||||
let processed_json = await processJsonSubreddit(
|
||||
json,
|
||||
'redis',
|
||||
null,
|
||||
req.cookies,
|
||||
true
|
||||
);
|
||||
if (!processed_json.error) {
|
||||
return res.render('saved', {
|
||||
json: processed_json,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
} else {
|
||||
return res.render('subreddit', {
|
||||
json: null,
|
||||
error: true,
|
||||
data: processed_json,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
})();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
saveRoutes.get('/save/:id', (req, res, next) => {
|
||||
let post_id = req.params.id;
|
||||
let redis_key = req.query.rk;
|
||||
let back = req.query.b;
|
||||
let saved = req.cookies.saved;
|
||||
let fetched = req.query.f;
|
||||
|
||||
if (!post_id || !redis_key) return res.redirect('/saved');
|
||||
|
||||
if (!saved || !Array.isArray(saved)) saved = [];
|
||||
|
||||
if (saved.length > 100)
|
||||
return res.send('You can not save more than 100 posts.');
|
||||
|
||||
redis.get(redis_key, (error, json) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`Error getting the ${redis_key} key from redis (via /save/).`,
|
||||
error
|
||||
);
|
||||
return res.redirect('/');
|
||||
}
|
||||
if (json) {
|
||||
json = JSON.parse(json);
|
||||
if (fetched === 'true' || redis_key.includes('/comments/'))
|
||||
json = json[0];
|
||||
|
||||
let post_to_save = false;
|
||||
for (var i = 0; i < json.data.children.length; i++) {
|
||||
let post = json.data.children[i];
|
||||
if (post.data.id === post_id) {
|
||||
post_to_save = post;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (post_to_save) {
|
||||
if (!saved || !Array.isArray(saved)) saved = [];
|
||||
|
||||
for (var i = 0; i < saved.length; i++) {
|
||||
if (post_to_save.data.id === saved[i]) return res.redirect('/saved');
|
||||
}
|
||||
|
||||
let key = `saved_posts:${saved.join(',')}`;
|
||||
redis.get(key, (error, json) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`Error getting saved_posts ${key} key from redis.`,
|
||||
error
|
||||
);
|
||||
return res.redirect('/');
|
||||
}
|
||||
links = JSON.parse(json);
|
||||
if (!links) links = [];
|
||||
|
||||
links.unshift(post_to_save);
|
||||
saved.unshift(post_to_save.data.id);
|
||||
res.cookie('saved', saved, {
|
||||
maxAge: 3 * 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
let new_key = `saved_posts:${saved.join(',')}`;
|
||||
redis.set(new_key, JSON.stringify(links), (error) => {
|
||||
if (error)
|
||||
console.error(`Error saving ${new_key} to redis.`, error);
|
||||
|
||||
if (!back) return res.redirect('/saved');
|
||||
else {
|
||||
back = back.replace(/§2/g, '?').replace(/§1/g, '&');
|
||||
return res.redirect(back);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return res.redirect(`/comments/${post_id}/?save=true&b=${back}`);
|
||||
}
|
||||
} else {
|
||||
return res.redirect(`/comments/${post_id}/?save=true&b=${back}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
saveRoutes.get('/unsave/:id', (req, res, next) => {
|
||||
let post_id = req.params.id;
|
||||
let back = req.query.b;
|
||||
let saved = req.cookies.saved;
|
||||
|
||||
if (!post_id) return res.redirect('/saved');
|
||||
|
||||
if (!saved || !Array.isArray(saved)) return res.redirect('/saved');
|
||||
|
||||
let key = `saved_posts:${saved.join(',')}`;
|
||||
redis.get(key, (error, json) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`Error getting the ${key} key from redis (via /save/).`,
|
||||
error
|
||||
);
|
||||
return res.redirect('/');
|
||||
}
|
||||
if (json) {
|
||||
json = JSON.parse(json);
|
||||
let post_found = false;
|
||||
for (var i = 0; i < json.length; i++) {
|
||||
if (json[i].data.id === post_id) {
|
||||
post_found = true;
|
||||
json.splice(i, 1);
|
||||
for (var j = 0; j < saved.length; j++) {
|
||||
if (saved[j] === post_id) saved.splice(j, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (post_found) {
|
||||
res.cookie('saved', saved, {
|
||||
maxAge: 3 * 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
let new_key = `saved_posts:${saved.join(',')}`;
|
||||
redis.set(new_key, JSON.stringify(json), (error) => {
|
||||
if (error) console.error(`Error saving ${new_key} to redis.`, error);
|
||||
|
||||
if (!back) return res.redirect('/saved');
|
||||
else {
|
||||
back = back.replace(/§2/g, '?').replace(/§1/g, '&');
|
||||
return res.redirect(back);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return res.redirect(`/saved`);
|
||||
}
|
||||
} else {
|
||||
return res.redirect(`/saved`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
saveRoutes.get(
|
||||
'/comments/:post_id/:comment?/:comment_id?',
|
||||
(req, res, next) => {
|
||||
let post_id = req.params.post_id;
|
||||
let comment = req.params.comment;
|
||||
let comment_id = req.params.comment_id;
|
||||
let back = req.query.b;
|
||||
let save = req.query.save;
|
||||
let post_url = false;
|
||||
let comment_url = false;
|
||||
|
||||
if (comment)
|
||||
if (comment !== 'comment' || !comment_id) return res.redirect('/');
|
||||
|
||||
if (comment) comment_url = true;
|
||||
else post_url = true;
|
||||
|
||||
let key = `/shorturl:post:${post_id}:comment:${comment_id}`;
|
||||
redis.get(key, (error, json) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
'Error getting the short URL for post key from redis.',
|
||||
error
|
||||
);
|
||||
return res.render('index', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
if (json) {
|
||||
console.log('Got short URL for post key from redis.');
|
||||
json = JSON.parse(json);
|
||||
if (post_url) {
|
||||
if (save === 'true')
|
||||
return res.redirect(`/save/${post_id}/?rk=${key}&b=${back}&f=true`);
|
||||
return res.redirect(json[0].data.children[0].data.permalink);
|
||||
} else {
|
||||
return res.redirect(json[1].data.children[0].data.permalink);
|
||||
}
|
||||
} else {
|
||||
let url = '';
|
||||
if (config.use_reddit_oauth) {
|
||||
if (post_url)
|
||||
url = `https://oauth.reddit.com/comments/${post_id}?api_type=json`;
|
||||
else
|
||||
url = `https://oauth.reddit.com/comments/${post_id}/comment/${comment_id}?api_type=json`;
|
||||
} else {
|
||||
if (post_url)
|
||||
url = `https://reddit.com/comments/${post_id}.json?api_type=json`;
|
||||
else
|
||||
url = `https://reddit.com/comments/${post_id}/comment/${comment_id}.json?api_type=json`;
|
||||
}
|
||||
|
||||
fetch(encodeURI(url), redditApiGETHeaders())
|
||||
.then((result) => {
|
||||
if (result.status === 200) {
|
||||
result.json().then((json) => {
|
||||
redis.setex(
|
||||
key,
|
||||
config.setexs.shorts,
|
||||
JSON.stringify(json),
|
||||
(error) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
'Error setting the short URL for post key to redis.',
|
||||
error
|
||||
);
|
||||
return res.render('index', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
} else {
|
||||
console.log(
|
||||
'Fetched the short URL for post from Reddit.'
|
||||
);
|
||||
if (post_url) {
|
||||
if (save === 'true')
|
||||
return res.redirect(
|
||||
`/save/${post_id}/?rk=${key}&b=${back}&f=true`
|
||||
);
|
||||
return res.redirect(
|
||||
json[0].data.children[0].data.permalink
|
||||
);
|
||||
} else {
|
||||
return res.redirect(
|
||||
json[1].data.children[0].data.permalink
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
} 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 short URL for post with sortby JSON file.',
|
||||
error
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = saveRoutes;
|
48
routes/search.js
Normal file
48
routes/search.js
Normal file
@ -0,0 +1,48 @@
|
||||
const searchRoute = require('express').Router();
|
||||
|
||||
searchRoute.get('/search', (req, res, next) => {
|
||||
let q = req.query.q;
|
||||
|
||||
if (typeof q === 'undefined') {
|
||||
return res.render('search', {
|
||||
json: { posts: [] },
|
||||
no_query: true,
|
||||
q: '',
|
||||
restrict_sr: undefined,
|
||||
nsfw: undefined,
|
||||
subreddit: 'all',
|
||||
sortby: undefined,
|
||||
past: undefined,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
|
||||
let restrict_sr = req.query.restrict_sr;
|
||||
let nsfw = req.query.nsfw;
|
||||
let sortby = req.query.sort;
|
||||
let past = req.query.t;
|
||||
let after = req.query.after;
|
||||
let before = req.query.before;
|
||||
if (!after) {
|
||||
after = '';
|
||||
}
|
||||
if (!before) {
|
||||
before = '';
|
||||
}
|
||||
if (restrict_sr !== 'on') {
|
||||
restrict_sr = 'off';
|
||||
}
|
||||
|
||||
if (nsfw !== 'on') {
|
||||
nsfw = 'off';
|
||||
}
|
||||
let d = `&after=${after}`;
|
||||
if (before) {
|
||||
d = `&before=${before}`;
|
||||
}
|
||||
return res.redirect(
|
||||
`/r/all/search?q=${q}&restrict_sr=${restrict_sr}&nsfw=${nsfw}&sort=${sortby}&t=${past}${d}`
|
||||
);
|
||||
});
|
||||
|
||||
module.exports = searchRoute;
|
11
routes/static.js
Normal file
11
routes/static.js
Normal file
@ -0,0 +1,11 @@
|
||||
const staticRoutes = require('express').Router();
|
||||
|
||||
staticRoutes.get('/privacy', (req, res, next) => {
|
||||
return res.render('privacypolicy', { user_preferences: req.cookies });
|
||||
});
|
||||
|
||||
staticRoutes.get('/about', (req, res, next) => {
|
||||
return res.render('about', { user_preferences: req.cookies });
|
||||
});
|
||||
|
||||
module.exports = staticRoutes;
|
954
routes/subreddit.js
Normal file
954
routes/subreddit.js
Normal file
@ -0,0 +1,954 @@
|
||||
const config = require('../config');
|
||||
const { redis, fetch, RedditAPI } = require('../app');
|
||||
const subredditRoutes = require('express').Router();
|
||||
|
||||
const processUser = require('../inc/processJsonUser.js')();
|
||||
const processPost = require('../inc/processJsonPost.js')();
|
||||
const processAbout = require('../inc/processSubredditAbout.js')();
|
||||
const tedditApiUser = require('../inc/teddit_api/handleUser.js')();
|
||||
const processSearches = require('../inc/processSearchResults.js')();
|
||||
const processSubreddit = require('../inc/processJsonSubreddit.js')();
|
||||
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
||||
const processMoreComments = require('../inc/processMoreComments.js')();
|
||||
const processSubredditsExplore =
|
||||
require('../inc/processSubredditsExplore.js')();
|
||||
|
||||
subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
|
||||
let subreddit = req.params.subreddit;
|
||||
let q = req.query.q;
|
||||
|
||||
if (typeof q === 'undefined') {
|
||||
return res.render('search', {
|
||||
json: { posts: [] },
|
||||
no_query: true,
|
||||
q: '',
|
||||
restrict_sr: undefined,
|
||||
nsfw: undefined,
|
||||
subreddit: subreddit,
|
||||
sortby: undefined,
|
||||
past: undefined,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
|
||||
let restrict_sr = req.query.restrict_sr;
|
||||
let nsfw = req.query.nsfw;
|
||||
let sortby = req.query.sort;
|
||||
let past = req.query.t;
|
||||
let after = req.query.after;
|
||||
let before = req.query.before;
|
||||
if (!after) {
|
||||
after = '';
|
||||
}
|
||||
if (!before) {
|
||||
before = '';
|
||||
}
|
||||
let d = `&after=${after}`;
|
||||
if (before) {
|
||||
d = `&before=${before}`;
|
||||
}
|
||||
|
||||
if (restrict_sr !== 'on') {
|
||||
restrict_sr = 'off';
|
||||
}
|
||||
|
||||
if (nsfw !== 'on') {
|
||||
nsfw = 'off';
|
||||
}
|
||||
|
||||
let key = `search:${subreddit}:${q}:${restrict_sr}:${sortby}:${past}:${after}:${before}:${nsfw}`;
|
||||
redis.get(key, (error, json) => {
|
||||
if (error) {
|
||||
console.error('Error getting the search key from redis.', error);
|
||||
return res.render('index', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
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,
|
||||
});
|
||||
})();
|
||||
} 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}${d}`;
|
||||
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}${d}`;
|
||||
fetch(encodeURI(url), redditApiGETHeaders())
|
||||
.then((result) => {
|
||||
if (result.status === 200) {
|
||||
result.json().then((json) => {
|
||||
(async () => {
|
||||
/**
|
||||
* Fetch suggested subreddits when the restrict_sr option is
|
||||
* turned off ("limit my search to") and we are on the first search
|
||||
* page (just like in Reddit).
|
||||
*/
|
||||
json.suggested_subreddits = {};
|
||||
if (restrict_sr === 'off' && before == '' && after == '') {
|
||||
let url = `https://reddit.com/subreddits/search.json?q=${q}&include_over_18=${nsfw}&limit=3`;
|
||||
const response = await fetch(encodeURI(url));
|
||||
const data = await response.json();
|
||||
json.suggested_subreddits = data;
|
||||
}
|
||||
|
||||
redis.setex(
|
||||
key,
|
||||
config.setexs.searches,
|
||||
JSON.stringify(json),
|
||||
(error) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
'Error setting the searches key to redis.',
|
||||
error
|
||||
);
|
||||
return res.render('index', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
} 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,
|
||||
});
|
||||
})();
|
||||
}
|
||||
}
|
||||
);
|
||||
})();
|
||||
});
|
||||
} 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 frontpage JSON file.', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
subredditRoutes.get(
|
||||
'/r/:subreddit/wiki/:page?/:sub_page?',
|
||||
(req, res, next) => {
|
||||
let subreddit = req.params.subreddit;
|
||||
let page = req.params.page;
|
||||
let sub_page = req.params.sub_page || '';
|
||||
|
||||
if (!page) page = 'index';
|
||||
|
||||
if (sub_page != '') sub_page = `/${sub_page}`;
|
||||
|
||||
function formatWikipagelisting(json, subreddit) {
|
||||
let html = '<ul class="wikipagelisting">';
|
||||
if (json.kind === 'wikipagelisting' && json.data) {
|
||||
for (var i = 0; i < json.data.length; i++) {
|
||||
let d = json.data[i];
|
||||
html += `<li><a href="/r/${subreddit}/wiki/${d}">${d}</a></li>`;
|
||||
}
|
||||
}
|
||||
html += '</ul>';
|
||||
return html;
|
||||
}
|
||||
|
||||
let key = `${subreddit.toLowerCase()}:wiki:page:${page}:sub_page:${sub_page}`;
|
||||
redis.get(key, (error, json) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`Error getting the ${subreddit} wiki key from redis.`,
|
||||
error
|
||||
);
|
||||
return res.render('index', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
if (json) {
|
||||
console.log(`Got /r/${subreddit} wiki key from redis.`);
|
||||
json = JSON.parse(json);
|
||||
return res.render('subreddit_wiki', {
|
||||
content_html:
|
||||
page !== 'pages'
|
||||
? unescape(json.data.content_html)
|
||||
: formatWikipagelisting(json, subreddit),
|
||||
subreddit: subreddit,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
} else {
|
||||
let url = '';
|
||||
if (config.use_reddit_oauth)
|
||||
url = `https://oauth.reddit.com/r/${subreddit}/wiki/${page}${sub_page}?api_type=json`;
|
||||
else
|
||||
url = `https://reddit.com/r/${subreddit}/wiki/${page}${sub_page}.json?api_type=json`;
|
||||
fetch(encodeURI(url), redditApiGETHeaders())
|
||||
.then((result) => {
|
||||
if (result.status === 200) {
|
||||
result.json().then((json) => {
|
||||
redis.setex(
|
||||
key,
|
||||
config.setexs.wikis,
|
||||
JSON.stringify(json),
|
||||
(error) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`Error setting the ${subreddit} wiki 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}/wiki.`
|
||||
);
|
||||
return res.render('subreddit_wiki', {
|
||||
content_html:
|
||||
page !== 'pages'
|
||||
? unescape(json.data.content_html)
|
||||
: formatWikipagelisting(json, subreddit),
|
||||
subreddit: subreddit,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
if (result.status === 404) {
|
||||
console.log('404 – Subreddit wiki 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/r/${subreddit}/wiki.`,
|
||||
error
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
subredditRoutes.get('/r/:subreddit/w/:page?/:sub_page?', (req, res, next) => {
|
||||
/* "w" is a shorturl for wikis for example https://old.reddit.com/r/privacytoolsIO/w/index */
|
||||
let subreddit = req.params.subreddit;
|
||||
let page = req.params.page;
|
||||
let sub_page = req.params.sub_page || '';
|
||||
|
||||
if (!page) page = 'index';
|
||||
|
||||
if (sub_page != '') sub_page = `/${sub_page}`;
|
||||
|
||||
return res.redirect(`/r/${subreddit}/wiki/${page}${sub_page}`);
|
||||
});
|
||||
|
||||
subredditRoutes.get('/r/random', (req, res, next) => {
|
||||
let url = '';
|
||||
if (config.use_reddit_oauth)
|
||||
url = `https://oauth.reddit.com/r/random?api_type=json&count=25&g=GLOBAL`;
|
||||
else url = `https://reddit.com/r/random.json?api_type=json&count=25&g=GLOBAL`;
|
||||
|
||||
fetch(encodeURI(url), redditApiGETHeaders())
|
||||
.then((result) => {
|
||||
if (result.status === 200) {
|
||||
result.json().then((json) => {
|
||||
let subreddit = json.data.children[0].data.subreddit;
|
||||
if (subreddit) {
|
||||
let key = `${subreddit.toLowerCase()}:undefined:undefined:sort:hot:past:undefined`;
|
||||
redis.setex(
|
||||
key,
|
||||
config.setexs.subreddit,
|
||||
JSON.stringify(json),
|
||||
(error) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`Error setting the random 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}.`
|
||||
);
|
||||
return res.redirect(`/r/${subreddit}`);
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
console.error(`Fetching random subreddit failed.`, json);
|
||||
return res.render('index', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
});
|
||||
} 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/r/random.`,
|
||||
error
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
subredditRoutes.get('/r/:subreddit/:sort?', (req, res, next) => {
|
||||
let subreddit = req.params.subreddit;
|
||||
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 raw_json = api_req && req.query.raw_json == '1' ? 1 : 0;
|
||||
|
||||
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(`/r/${subreddit}`);
|
||||
}
|
||||
|
||||
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(`/r/${subreddit}/${sortby}`);
|
||||
}
|
||||
} else {
|
||||
past = undefined;
|
||||
}
|
||||
} else {
|
||||
if (sortby === 'controversial' || sortby === 'top') {
|
||||
past = 'day';
|
||||
}
|
||||
}
|
||||
|
||||
let key = `${subreddit.toLowerCase()}:${after}:${before}:sort:${sortby}:past:${past}:raw_json:${raw_json}`;
|
||||
redis.get(key, (error, json) => {
|
||||
if (error) {
|
||||
console.error(`Error getting the ${subreddit} key from redis.`, error);
|
||||
return res.render('index', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
if (json) {
|
||||
console.log(`Got /r/${subreddit} 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
|
||||
);
|
||||
let subreddit_about = await processSubredditAbout(
|
||||
subreddit,
|
||||
redis,
|
||||
fetch,
|
||||
RedditAPI
|
||||
);
|
||||
if (!processed_json.error) {
|
||||
return res.render('subreddit', {
|
||||
json: processed_json,
|
||||
subreddit: subreddit,
|
||||
subreddit_about: subreddit_about,
|
||||
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/r/${subreddit}/${sortby}?api_type=json&count=25&g=GLOBAL&t=${past}${d}&raw_json=${raw_json}`;
|
||||
else
|
||||
url = `https://reddit.com/r/${subreddit}/${sortby}.json?api_type=json&count=25&g=GLOBAL&t=${past}${d}&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 ${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
|
||||
);
|
||||
let subreddit_about = await processSubredditAbout(
|
||||
subreddit,
|
||||
redis,
|
||||
fetch,
|
||||
RedditAPI
|
||||
);
|
||||
return res.render('subreddit', {
|
||||
json: processed_json,
|
||||
subreddit: subreddit,
|
||||
subreddit_about: subreddit_about,
|
||||
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/r/${subreddit}.`,
|
||||
error
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
subredditRoutes.get(
|
||||
'/r/:subreddit/comments/:id/:snippet?/:comment_id?',
|
||||
(req, res, next) => {
|
||||
let subreddit = req.params.subreddit;
|
||||
let id = req.params.id;
|
||||
let snippet = encodeURIComponent(req.params.snippet);
|
||||
let sortby = req.query.sort;
|
||||
let comment_id = '';
|
||||
let viewing_comment = false;
|
||||
let comment_ids = req.query.comment_ids;
|
||||
let context = parseInt(req.query.context);
|
||||
|
||||
if (req.params.comment_id) {
|
||||
comment_id = `${req.params.comment_id}/`;
|
||||
viewing_comment = true;
|
||||
}
|
||||
|
||||
if (!sortby) {
|
||||
sortby = config.post_comments_sort;
|
||||
}
|
||||
|
||||
if (
|
||||
![
|
||||
'confidence',
|
||||
'top',
|
||||
'new',
|
||||
'controversial',
|
||||
'old',
|
||||
'qa',
|
||||
'random',
|
||||
].includes(sortby)
|
||||
) {
|
||||
console.log(`Got invalid sort.`, req.originalUrl);
|
||||
return res.redirect('/');
|
||||
}
|
||||
|
||||
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}`;
|
||||
|
||||
redis.get(comments_key, (error, json) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`Error getting the ${comments_url} key from redis.`,
|
||||
error
|
||||
);
|
||||
return res.render('index', {
|
||||
post: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
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 moreComments(
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
})();
|
||||
} else {
|
||||
let url = '';
|
||||
if (config.use_reddit_oauth)
|
||||
url = `https://oauth.reddit.com${comments_url}?api_type=json&sort=${sortby}&context=${context}`;
|
||||
else
|
||||
url = `https://reddit.com${comments_url}.json?api_type=json&sort=${sortby}&context=${context}`;
|
||||
|
||||
fetch(encodeURI(url), redditApiGETHeaders())
|
||||
.then((result) => {
|
||||
if (result.status === 200) {
|
||||
result.json().then((json) => {
|
||||
redis.setex(
|
||||
comments_key,
|
||||
config.setexs.posts,
|
||||
JSON.stringify(json),
|
||||
(error) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`Error setting the ${comments_url} key to redis.`,
|
||||
error
|
||||
);
|
||||
return res.render('post', {
|
||||
post: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
} else {
|
||||
console.log(
|
||||
`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 moreComments(
|
||||
fetch,
|
||||
redis,
|
||||
post_url,
|
||||
comment_ids,
|
||||
id
|
||||
);
|
||||
|
||||
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
|
||||
);
|
||||
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,
|
||||
});
|
||||
})();
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
if (result.status === 404) {
|
||||
console.log('404 – Post 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 JSON file from reddit.com${comments_url}.`,
|
||||
error
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
subredditRoutes.post(
|
||||
'/r/:subreddit/comments/:id/:snippet',
|
||||
(req, res, next) => {
|
||||
/**
|
||||
* This is the "morechildren" route. This route is called when the
|
||||
* "load more comments" button at the bottom of some post is clicked.
|
||||
*/
|
||||
if (!config.use_reddit_oauth)
|
||||
return res.send(
|
||||
`This instance is using Reddit's public API (non-OAuth), and therefore this endpoint is not supported. In other words, this feature is only available if the instance is using Reddit OAuth API.`
|
||||
);
|
||||
|
||||
let subreddit = req.params.subreddit;
|
||||
let id = req.params.id;
|
||||
let snippet = encodeURIComponent(req.params.snippet);
|
||||
let post_url = `/r/${subreddit}/comments/${id}/${snippet}/`;
|
||||
let page = req.query.page;
|
||||
let comment_ids = req.body.comment_ids;
|
||||
|
||||
return res.redirect(`${post_url}?comment_ids=${comment_ids}&page=1`);
|
||||
}
|
||||
);
|
||||
|
||||
subredditRoutes.get('/subreddits/:sort?', (req, res, next) => {
|
||||
let q = req.query.q;
|
||||
let nsfw = req.query.nsfw;
|
||||
let after = req.query.after;
|
||||
let before = req.query.before;
|
||||
let sortby = req.params.sort;
|
||||
let searching = false;
|
||||
|
||||
if (!after) {
|
||||
after = '';
|
||||
}
|
||||
if (!before) {
|
||||
before = '';
|
||||
}
|
||||
|
||||
let d = `&after=${after}`;
|
||||
if (before) {
|
||||
d = `&before=${before}`;
|
||||
}
|
||||
|
||||
if (nsfw !== 'on') {
|
||||
nsfw = 'off';
|
||||
}
|
||||
|
||||
if (!sortby) {
|
||||
sortby = '';
|
||||
}
|
||||
|
||||
let key = `subreddits:sort:${sortby}${d}`;
|
||||
|
||||
if (sortby === 'search') {
|
||||
if (typeof q == 'undefined' || q == '') return res.redirect('/subreddits');
|
||||
|
||||
key = `subreddits:search:q:${q}:nsfw:${nsfw}${d}`;
|
||||
searching = true;
|
||||
}
|
||||
|
||||
redis.get(key, (error, json) => {
|
||||
if (error) {
|
||||
console.error(`Error getting the subreddits key from redis.`, error);
|
||||
return res.render('index', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
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,
|
||||
});
|
||||
} else {
|
||||
return res.render('subreddits_explore', {
|
||||
json: null,
|
||||
error: true,
|
||||
data: processed_json,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
}
|
||||
})();
|
||||
} 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}`;
|
||||
else
|
||||
url = `https://oauth.reddit.com/subreddits/search?api_type=json&q=${q}&include_over_18=${nsfw}${d}`;
|
||||
} else {
|
||||
if (!searching)
|
||||
url = `https://reddit.com/subreddits/${sortby}.json?api_type=json&count=25&g=GLOBAL&t=${d}`;
|
||||
else
|
||||
url = `https://reddit.com/subreddits/search.json?api_type=json&q=${q}&include_over_18=${nsfw}${d}`;
|
||||
}
|
||||
|
||||
fetch(encodeURI(url), redditApiGETHeaders())
|
||||
.then((result) => {
|
||||
if (result.status === 200) {
|
||||
result.json().then((json) => {
|
||||
let ex = config.setexs.subreddits_explore.front;
|
||||
if (sortby === 'new')
|
||||
ex = config.setexs.subreddits_explore.new_page;
|
||||
redis.setex(key, ex, JSON.stringify(json), (error) => {
|
||||
if (error) {
|
||||
console.error(
|
||||
`Error setting the subreddits key to redis.`,
|
||||
error
|
||||
);
|
||||
return res.render('subreddits_explore', {
|
||||
json: null,
|
||||
user_preferences: req.cookies,
|
||||
});
|
||||
} 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,
|
||||
});
|
||||
})();
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (result.status === 404) {
|
||||
console.log('404 – Subreddits 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/subreddits.`,
|
||||
error
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = subredditRoutes;
|
82
routes/subscription.js
Normal file
82
routes/subscription.js
Normal file
@ -0,0 +1,82 @@
|
||||
const subscriptionRoutes = require('express').Router();
|
||||
|
||||
subscriptionRoutes.get('/subscribe/:subreddit', (req, res, next) => {
|
||||
let subreddit = req.params.subreddit;
|
||||
let subbed = req.cookies.subbed_subreddits;
|
||||
let back = req.query.b;
|
||||
|
||||
if (!subreddit) return res.redirect('/');
|
||||
|
||||
if (!subbed || !Array.isArray(subbed)) subbed = [];
|
||||
|
||||
if (!subbed.includes(subreddit)) subbed.push(subreddit);
|
||||
|
||||
res.cookie('subbed_subreddits', subbed, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
if (!back) return res.redirect('/r/' + subreddit);
|
||||
else {
|
||||
back = back.replace(/,/g, '+').replace(/§1/g, '&');
|
||||
return res.redirect(back);
|
||||
}
|
||||
});
|
||||
|
||||
subscriptionRoutes.get(
|
||||
'/import_subscriptions/:subreddits',
|
||||
(req, res, next) => {
|
||||
let subreddits = req.params.subreddits;
|
||||
let subbed = req.cookies.subbed_subreddits;
|
||||
let back = req.query.b;
|
||||
|
||||
if (!subreddits) return res.redirect('/');
|
||||
|
||||
if (!subbed || !Array.isArray(subbed)) subbed = [];
|
||||
|
||||
subreddits = subreddits.split('+');
|
||||
for (var i = 0; i < subreddits.length; i++) {
|
||||
if (!subbed.includes(subreddits[i])) subbed.push(subreddits[i]);
|
||||
}
|
||||
|
||||
res.cookie('subbed_subreddits', subbed, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
if (!back) return res.redirect('/r/' + subreddits);
|
||||
else {
|
||||
back = back.replace(/,/g, '+').replace(/ /g, '+');
|
||||
return res.redirect(back);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
subscriptionRoutes.get('/unsubscribe/:subreddit', (req, res, next) => {
|
||||
let subreddit = req.params.subreddit;
|
||||
let subbed = req.cookies.subbed_subreddits;
|
||||
let back = req.query.b;
|
||||
|
||||
if (!subreddit || !subbed || !Array.isArray(subbed)) {
|
||||
res.clearCookie('subbed_subreddits');
|
||||
return res.redirect('/');
|
||||
}
|
||||
|
||||
var index = subbed.indexOf(subreddit);
|
||||
if (index !== -1) subbed.splice(index, 1);
|
||||
|
||||
if (subbed.length <= 0) res.clearCookie('subbed_subreddits');
|
||||
else
|
||||
res.cookie('subbed_subreddits', subbed, {
|
||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||
httpOnly: true,
|
||||
});
|
||||
|
||||
if (!back) return res.redirect('/r/' + subreddit);
|
||||
else {
|
||||
back = back.replace(/,/g, '+').replace(/§1/g, '&');
|
||||
return res.redirect(back);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = subscriptionRoutes;
|
459
routes/user.js
Normal file
459
routes/user.js
Normal file
@ -0,0 +1,459 @@
|
||||
const config = require('../config');
|
||||
const { redis, fetch } = require('../app');
|
||||
const userRoutes = require('express').Router();
|
||||
|
||||
const processUser = require('../inc/processJsonUser.js')();
|
||||
const processPost = require('../inc/processJsonPost.js')();
|
||||
const processAbout = require('../inc/processSubredditAbout.js')();
|
||||
const tedditApiUser = require('../inc/teddit_api/handleUser.js')();
|
||||
const processSearches = require('../inc/processSearchResults.js')();
|
||||
const processSubreddit = require('../inc/processJsonSubreddit.js')();
|
||||
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
||||
const processMoreComments = require('../inc/processMoreComments.js')();
|
||||
const processSubredditsExplore =
|
||||
require('../inc/processSubredditsExplore.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;
|
Loading…
Reference in New Issue
Block a user