add '/subreddits' feature for searching and exploring subreddits

This commit is contained in:
teddit 2021-01-17 17:29:49 +01:00
parent 9dea345a03
commit 3e01937247
5 changed files with 334 additions and 16 deletions

View File

@ -38,7 +38,11 @@ const config = {
searches: 600, searches: 600,
sidebar: 60 * 60 * 24 * 7, // 7 days sidebar: 60 * 60 * 24 * 7, // 7 days
shorts: 60 * 60 * 24 * 31, shorts: 60 * 60 * 24 * 31,
wikis: 60* 60 * 24 * 7 wikis: 60* 60 * 24 * 7,
subreddits_explore: {
front: 60 * 60 * 24 * 1,
new_page: 60
},
}, },
convert_urls: { convert_urls: {
/** /**

View File

@ -0,0 +1,52 @@
module.exports = function() {
const config = require('../config');
this.processJsonSubredditsExplore = (json, from, subreddit_front, user_preferences) => {
return new Promise(resolve => {
(async () => {
if(from === 'redis') {
json = JSON.parse(json)
}
if(json.error) {
resolve({ error: true, error_data: json })
} else {
let before = json.data.before
let after = json.data.after
let ret = {
info: {
before: before,
after: after
},
links: []
}
let children_len = json.data.children.length
for(var i = 0; i < children_len; i++) {
let data = json.data.children[i].data
if(data.over_18)
if((config.nsfw_enabled === false && user_preferences.nsfw_enabled != 'true') || user_preferences.nsfw_enabled === 'false')
continue
let obj = {
created: data.created_utc,
id: data.id,
over_18: data.over_18,
display_name: data.display_name,
display_name_prefixed: data.display_name_prefixed,
public_description: data.public_description,
url: data.url,
subscribers: data.subscribers,
over_18: data.over18,
title: data.title,
subreddit_front: subreddit_front,
}
ret.links.push(obj)
}
resolve(ret)
}
})()
})
}
}

144
routes.js
View File

@ -10,6 +10,7 @@ module.exports = (app, redis, fetch, RedditAPI) => {
let processAbout = require('./inc/processSubredditAbout.js')(); let processAbout = require('./inc/processSubredditAbout.js')();
let tedditApiSubreddit = require('./inc/teddit_api/handleSubreddit.js')(); let tedditApiSubreddit = require('./inc/teddit_api/handleSubreddit.js')();
let tedditApiUser = require('./inc/teddit_api/handleUser.js')(); let tedditApiUser = require('./inc/teddit_api/handleUser.js')();
let processSubredditsExplore = require('./inc/processSubredditsExplore.js')();
app.get('/about', (req, res, next) => { app.get('/about', (req, res, next) => {
return res.render('about', { user_preferences: req.cookies }) return res.render('about', { user_preferences: req.cookies })
@ -31,6 +32,141 @@ module.exports = (app, redis, fetch, RedditAPI) => {
app.get('/privacy', (req, res, next) => { app.get('/privacy', (req, res, next) => {
return res.render('privacypolicy', { user_preferences: req.cookies }) return res.render('privacypolicy', { user_preferences: req.cookies })
}) })
app.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)
})
}
})
})
app.get('/subscribe/:subreddit', (req, res, next) => { app.get('/subscribe/:subreddit', (req, res, next) => {
let subreddit = req.params.subreddit let subreddit = req.params.subreddit
@ -47,11 +183,11 @@ module.exports = (app, redis, fetch, RedditAPI) => {
subbed.push(subreddit) subbed.push(subreddit)
res.cookie('subbed_subreddits', subbed, { maxAge: 365 * 24 * 60 * 60 * 1000, httpOnly: true }) res.cookie('subbed_subreddits', subbed, { maxAge: 365 * 24 * 60 * 60 * 1000, httpOnly: true })
if(!back) if(!back)
return res.redirect('/r/' + subreddit) return res.redirect('/r/' + subreddit)
else { else {
back = back.replace(/,/g, '+') back = back.replace(/,/g, '+').replace(/§1/g, '&')
return res.redirect(back) return res.redirect(back)
} }
}) })
@ -105,7 +241,7 @@ module.exports = (app, redis, fetch, RedditAPI) => {
if(!back) if(!back)
return res.redirect('/r/' + subreddit) return res.redirect('/r/' + subreddit)
else { else {
back = back.replace(/,/g, '+') back = back.replace(/,/g, '+').replace(/§1/g, '&')
return res.redirect(back) return res.redirect(back)
} }
}) })
@ -577,7 +713,7 @@ module.exports = (app, redis, fetch, RedditAPI) => {
}) })
} }
}).catch(error => { }).catch(error => {
console.error(`Error fetching the JSON file from reddit.com/r/${subreddit}.`, error) console.error(`Error fetching the JSON file from reddit.com/r/random.`, error)
}) })
}) })

View File

@ -555,6 +555,32 @@ footer a {
border-left: 1px solid #dcdcdc; border-left: 1px solid #dcdcdc;
margin-top: 10px; margin-top: 10px;
} }
.infobar {
background-color: #f6e69f;
margin: 5px 305px 5px 11px;
padding: 5px 10px;
float: left;
width: calc(100% - 50px);
}
.infobar.blue {
background: #eff8ff;
border: 1px solid #93abc2;
}
.infobar.explore {
margin-bottom: 15px;
}
.explore#links .link {
padding-left: 10%;
}
.explore#links .link .sub-button {
float: left;
margin: 7px 0px;
width: 90px;
}
.explore#links .link .content {
float: left;
width: calc(100% - 120px);
}
/* POST */ /* POST */
#post { #post {
@ -564,17 +590,6 @@ footer a {
float: left; float: left;
width: 100%; width: 100%;
} }
#post .infobar {
background-color: #f6e69f;
margin: 5px 305px 5px 11px;
padding: 5px 10px;
float: left;
width: calc(100% - 50px);
}
#post .infobar.blue {
background: #eff8ff;
border: 1px solid #93abc2;
}
#post header { #post header {
padding-top: 0px; padding-top: 0px;
} }
@ -1020,6 +1035,11 @@ a.sub-to-subreddit.gray {
margin-left: 20px; margin-left: 20px;
margin-top: 40px; margin-top: 40px;
} }
#search.explore {
width: calc(100% - 60px);
margin-left: 20px;
margin-bottom: 15px;
}
#search form { #search form {
max-width: 600px; max-width: 600px;
} }
@ -1431,5 +1451,15 @@ code {
} }
a.sub-to-subreddit { a.sub-to-subreddit {
padding: 8px 10px 8px 10px; padding: 8px 10px 8px 10px;
}
.explore#links .link {
padding-left: 5px;
}
.explore#links .link .sub-button {
margin: 7px 0px;
width: 90px;
}
.explore#links .link .entry {
width: calc(100% - 20px);
} }
} }

View File

@ -0,0 +1,96 @@
doctype html
html
head
title subreddits - explore
include includes/head.pug
body(class=""+ user_preferences.theme +"")
include includes/topbar.pug
if json === null
h1 Error occured
p Error: #{JSON.stringify(json.error_data)}
else
header
a(href="/", class="main")
h1 teddit
.bottom
a(href="/subreddits", class="subreddit")
h2 subreddits - explore
ul.tabmenu
li(class=!sortby || sortby == 'hot' ? 'active' : '')
a(href="/subreddits") popular
li(class=sortby === 'new' ? 'active' : '')
a(href="/subreddits/new") new
#search.explore
form(action="/subreddits/search", method="GET")
div
label(for="q") search subreddits
input(type="text", name="q", id="q", value="" + (q ? q : '') + "", placeholder="search")
div
label(for="nsfw") include NSFW results
if nsfw === 'on'
input(type="checkbox", name="nsfw", id="nsfw", checked="checked")
else
input(type="checkbox", name="nsfw", id="nsfw")
input(type="submit", value="search")
#links.sr.explore
if json.links.length === 0
p nothing here
else
.infobar.explore
p click the <code>subscribe</code> or unsubscribe buttons to choose which subreddits appear on the home feed.
each link in json.links
.link
.entry
-
let subbed_to_this_subreddit = false
let subbed = []
if(user_preferences.subbed_subreddits && Array.isArray(user_preferences.subbed_subreddits))
subbed = user_preferences.subbed_subreddits
for(let i = 0; i < subbed.length; i++) {
if(subbed[i].toLowerCase() === link.display_name.toLowerCase())
subbed_to_this_subreddit = true
}
.sub-button
if subbed_to_this_subreddit
if !searching
a(href="/unsubscribe/" + link.display_name + "?b=/subreddits/" + sortby + "?after=" + after + "§1before=" + before + "", class="sub-to-subreddit gray", title="subscriptions are saved in your browser's cookies") unsubscribe
else
a(href="/unsubscribe/" + link.display_name + "?b=/subreddits/search?q=" + q + "§1nsfw=" + nsfw + "§1after=" + after + "§1before=" + before + "", class="sub-to-subreddit gray", title="subscriptions are saved in your browser's cookies") unsubscribe
else
if !searching
a(href="/subscribe/" + link.display_name + "?b=/subreddits/" + sortby + "?after=" + after + "§1before=" + before + "", class="sub-to-subreddit", title="subscriptions are saved in your browser's cookies") subscribe
else
a(href="/subscribe/" + link.display_name + "?b=/subreddits/search?q=" + q + "§1nsfw=" + nsfw + "§1after=" + after + "§1before=" + before + "", class="sub-to-subreddit", title="subscriptions are saved in your browser's cookies") subscribe
.content
.title
a(href="" + link.url + "", rel="noopener noreferrer")
h2 #{link.display_name_prefixed}: #{cleanTitle(link.title)}
.description
p #{cleanTitle(link.public_description)}
.meta
p.subscribers #{kFormatter(link.subscribers)} subscribers,
p.submitted &nbsp; created
span(title="" + toUTCString(link.created) + "") #{timeDifference(link.created)}
.links
if link.over_18
span.tag.nsfw NSFW
if json.info.before || json.info.after
.view-more-links
if json.info.before && !subreddits_front
a(href="/subreddits/" + sortby + "?before=" + json.info.before + "&nsfw=" + nsfw + "&q=" + (q ? q : '') + "") prev
if json.info.after
a(href="/subreddits/" + sortby + "?after=" + json.info.after + "&nsfw=" + nsfw + "&q=" + (q ? q : '') + "") next
#sidebar
.content
if user_preferences.subbed_subreddits && Array.isArray(user_preferences.subbed_subreddits)
p your subscribed subreddits
ul.subreddit-listing
each subreddit in user_preferences.subbed_subreddits
li
if !searching
a(href="/unsubscribe/" + subreddit + "?b=/subreddits/" + sortby + "?after=" + after + "§1before=" + before + "", class="sub-to-subreddit gray", title="subscriptions are saved in your browser's cookies") unsubscribe
a(href="/r/" + subreddit) #{subreddit}
else
a(href="/unsubscribe/" + subreddit + "?b=/subreddits/search?q=" + q + "§1nsfw=" + nsfw + "§1after=" + after + "§1before=" + before + "", class="sub-to-subreddit gray", title="subscriptions are saved in your browser's cookies") unsubscribe
a(href="/r/" + subreddit) #{subreddit}
include includes/footer.pug