diff --git a/routes/index.js b/routes/index.js index a28d127..dda6488 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,9 +1,11 @@ const overridingRoutes = require('./overides'); +const preferenceRoutes = require('./preferences'); const staticRoutes = require('./static'); const allRoutes = require('express').Router(); allRoutes.use(overridingRoutes); allRoutes.use(staticRoutes); +allRoutes.use(preferenceRoutes); module.exports = allRoutes; diff --git a/routes/preferences.js b/routes/preferences.js new file mode 100644 index 0000000..bcb18fd --- /dev/null +++ b/routes/preferences.js @@ -0,0 +1,229 @@ +const config = '../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;