Merge pull request 'Implement full flair functionality' (#72) from StevenNMeza/teddit:flairs into main

Reviewed-on: https://codeberg.org/teddit/teddit/pulls/72
This commit is contained in:
teddit 2020-12-23 11:26:17 +01:00
commit 24b686fe1e
11 changed files with 184 additions and 107 deletions

View File

@ -2,6 +2,7 @@ const config = {
domain: process.env.DOMAIN || '127.0.0.1', // Or for example 'teddit.net'
reddit_app_id: process.env.REDDIT_APP_ID || 'H6-HjZ5pUPjaFQ', // You should obtain your own Reddit app ID. For testing purposes it's okay to use this project's default app ID. Create your Reddit app here: https://old.reddit.com/prefs/apps/. Make sure to create an "installed app" type of app.
cert_dir: process.env.CERT_DIR || '', // For example '/home/teddit/letsencrypt/live/teddit.net', if you are using https. No trailing slash.
flairs_enabled: process.env.FLAIRS_ENABLED !== "true" || true, // Enables the rendering of user and link flairs on teddit
api_enabled: process.env.API_ENABLED !== "true" || true, // Teddit API feature. Might increase loads significantly on your instance.
video_enabled: process.env.VIDEO_ENABLED !== "true" || true,
redis_enabled: process.env.REDIS_ENABLED !== "true" || true, // If disabled, does not cache Reddit API calls
@ -34,7 +35,7 @@ const config = {
shorts: 60 * 60 * 24 * 31
},
post_comments_sort: 'confidence', // "confidence" is the default sorting in Reddit. Must be one of: confidence, top, new, controversial, old, random, qa, live.
valid_media_domains: ['preview.redd.it', 'external-preview.redd.it', 'i.redd.it', 'v.redd.it', 'a.thumbs.redditmedia.com', 'b.thumbs.redditmedia.com', 'thumbs.gfycat.com', 'i.ytimg.com'],
valid_media_domains: ['preview.redd.it', 'external-preview.redd.it', 'i.redd.it', 'v.redd.it', 'a.thumbs.redditmedia.com', 'b.thumbs.redditmedia.com', 'emoji.redditmedia.com', 'thumbs.gfycat.com', 'i.ytimg.com'],
reddit_api_error_text: `Seems like your instance is either blocked (e.g. due to API rate limiting), reddit is currently down, or your API key is expired and not renewd properly. This can also happen for other reasons.`
};

49
dist/css/styles.css vendored
View File

@ -172,11 +172,6 @@ body.dark #search form input[type="text"] {
background: #0f0f0f;
color: white;
}
body.dark #links .link .entry .title span.postflair,
body.dark #post .info .title span.postflair {
color: #eaeaea;
background-color: #404040;
}
a {
color: var(--linkcolor);
text-decoration: none;
@ -402,16 +397,6 @@ input[type="submit"]:hover,
cursor: pointer;
text-decoration: none;
}
#links .link .entry .title span.postflair,
#post .info .title span.postflair {
display: inline-block;
border-radius: 4px;
color: #404040;
background-color: #e8e8e8;
font-size: x-small;
margin-left: 10px;
padding: 0 2px;
}
/* SUBREDDIT LINKS */
#links {
float: left;
@ -994,6 +979,40 @@ input[type="submit"]:hover,
#user .entries .entry a.context {
margin-right: 10px;
}
/* FLAIR */
.flair,
#links .link .entry .title span.flair,
#post .info .title span.flair {
display: inline-block;
border-radius: 4px;
color: #404040;
background-color: #e8e8e8;
font-size: x-small;
margin-left: 10px;
padding: 0 2px;
}
body.dark .flair {
color: #eaeaea !important;
background-color: #404040 !important;
}
#post .comments .flair,
#user .comment .meta .flair {
margin-left: 0 !important;
}
#links .link .entry .meta p.submitted .flair,
#user .comment .meta .flair,
#user .entries p.submitted .flair {
margin-right: 4px;
}
.flair .emoji {
background-position: center;
background-repeat: no-repeat;
background-size: contain;
display: inline-block;
height: 16px;
width: 16px;
vertical-align: middle;
}
/* SIDEBAR */
#sidebar {
float: left;

View File

@ -197,4 +197,61 @@ module.exports = function(request, fs) {
return ''
}
}
this.formatLinkFlair = async (post) => {
if (!config.flairs_enabled) {
return ''
}
const wrap = (inner) => `<span class="flair">${inner}</span>`
if (post.link_flair_text === null)
return ''
if (post.link_flair_type === 'text')
return wrap(post.link_flair_text)
if (post.link_flair_type === 'richtext') {
let flair = ''
for (let fragment of post.link_flair_richtext) {
if (fragment.e === 'text')
flair += fragment.t
else if (fragment.e === 'emoji')
flair += `<span class="emoji" style="background-image: url(${await downloadAndSave(fragment.u, 'flair_')})"></span>`
}
return wrap(flair)
}
return ''
}
this.formatUserFlair = async (post) => {
if (!config.flairs_enabled) {
return ''
}
// Generate the entire HTML here for consistency in both pug and HTML
const wrap = (inner) => `<span class="flair">${inner}</span>`
if (post.author_flair_text === null)
return ''
if (post.author_flair_type === 'text')
return wrap(post.author_flair_text)
if (post.author_flair_type === 'richtext') {
let flair = ''
for (let fragment of post.author_flair_richtext) {
// `e` seems to mean `type`
if (fragment.e === 'text')
flair += fragment.t // `t` is the text
else if (fragment.e === 'emoji')
flair += `<span class="emoji" style="background-image: url(${await downloadAndSave(fragment.u, 'flair_')})"></span>` // `u` is the emoji URL
}
return wrap(flair)
}
return ''
}
}

View File

@ -48,6 +48,7 @@ module.exports = function() {
</summary>
<div class="meta">
<p class="author">${commentAuthor(comments, classlist, submitter && submitter_link, moderator && moderator_badge)}</p>
<p>${comments.user_flair}</p>
<p class="ups">${ups}</p>
<p class="created" title="${toUTCString(comments.created)}">
<a href="${comments.permalink}">${timeDifference(comments.created)}${edited_span}</a>
@ -134,6 +135,7 @@ module.exports = function() {
</summary>
<div class="meta">
<p class="author">${commentAuthor(comment, classlist, submitter && submitter_link, moderator && moderator_badge)}</p>
<p>${comment.user_flair}</p>
<p class="ups">${ups}</p>
<p class="created" title="${toUTCString(comment.created)}">
<a href="${comment.permalink}">${timeDifference(comment.created)}${edited_span}</a>

View File

@ -32,8 +32,10 @@ module.exports = function(tools) {
if(gifmp4) {
file_ext = 'mp4'
} else {
if(!pathname.includes('.')) {
/**
if (file_prefix === 'flair_') {
// Flair emojis end in the name without a file extension
file_ext = 'png'
} else if(!pathname.includes('.')) { /**
* Sometimes reddit API returns video without extension, like
* "DASH_480" and not "DASH_480.mp4".
*/
@ -46,7 +48,7 @@ module.exports = function(tools) {
if(file_prefix === 'thumb_')
dir = 'thumbs/'
if(file_prefix === 'flair')
if(file_prefix === 'flair_')
dir = 'flairs/'
if(valid_video_extensions.includes(file_ext) || gifmp4) {
@ -130,7 +132,14 @@ module.exports = function(tools) {
if(temp_url.searchParams.get('width')) {
width = temp_url.searchParams.get('width')
}
filename = `${file_prefix}w:${temp_url.searchParams.get('width')}_${temp_url.pathname.split('/').slice(-1)}`
if(file_prefix === 'flair_') {
// Flair emojis have a full path of `UUID/name`,
// so we need to incorporate the UUID to avoid duplicates
// since names alone are not unique across all of reddit
filename = `${pathname.slice(1).replace('/', '_')}.png` // Only first replacement is fine
} else {
filename = `${file_prefix}w:${temp_url.searchParams.get('width')}_${temp_url.pathname.split('/').slice(-1)}`
}
}
path = `./dist/pics/${dir}${filename}`
if(!fs.existsSync(path)) {

View File

@ -32,7 +32,9 @@ module.exports = function(fetch) {
media: null,
images: null,
crosspost: false,
selftext: unescape(post.selftext_html)
selftext: unescape(post.selftext_html),
link_flair: await formatLinkFlair(post),
user_flair: await formatUserFlair(post)
}
let validEmbedDomains = ['gfycat.com', 'youtube.com']
@ -84,7 +86,8 @@ module.exports = function(fetch) {
ups: post.crosspost.ups,
selftext: unescape(post.selftext_html),
selftext_crosspost: unescape(post.crosspost.selftext_html),
is_crosspost: true
is_crosspost: true,
user_flair: await formatUserFlair(post)
}
}
@ -143,7 +146,8 @@ module.exports = function(fetch) {
score_hidden: comment.score_hidden,
edited: comment.edited,
replies: [],
depth: 0
depth: 0,
user_flair: await formatUserFlair(comment)
}
} else {
obj = {
@ -159,7 +163,7 @@ module.exports = function(fetch) {
if(comment.replies && kind !== 'more') {
if(comment.replies.data) {
if(comment.replies.data.children.length > 0) {
obj.replies = processReplies(comment.replies.data.children, post_id, 1)
obj.replies = await processReplies(comment.replies.data.children, post_id, 1)
}
}
}
@ -198,7 +202,7 @@ module.exports = function(fetch) {
return { post_data: post_data, comments: comments_html }
}
this.processReplies = (data, post_id, depth) => {
this.processReplies = async (data, post_id, depth) => {
let return_replies = []
for(var i = 0; i < data.length; i++) {
let kind = data[i].kind
@ -220,7 +224,8 @@ module.exports = function(fetch) {
score_hidden: reply.score_hidden,
edited: reply.edited,
replies: [],
depth: depth
depth: depth,
user_flair: await formatUserFlair(reply)
}
} else {
obj = {
@ -255,7 +260,8 @@ module.exports = function(fetch) {
distinguished: comment.distinguished,
distinguished: comment.edited,
replies: [],
depth: depth + 1
depth: depth + 1,
user_flair: await formatUserFlair(comment)
}
} else {
objct = {
@ -277,7 +283,7 @@ module.exports = function(fetch) {
if(comment.replies) {
if(comment.replies.data) {
if(comment.replies.data.children.length > 0) {
objct.replies = processReplies(comment.replies.data.children, post_id, depth )
objct.replies = await processReplies(comment.replies.data.children, post_id, depth )
}
}
}

View File

@ -73,7 +73,9 @@ module.exports = function() {
url: data.url,
stickied: data.stickied,
is_self_link: is_self_link,
subreddit_front: subreddit_front
subreddit_front: subreddit_front,
link_flair: await formatLinkFlair(data),
user_flair: await formatUserFlair(data)
}
ret.links.push(obj)
}

View File

@ -62,7 +62,8 @@ module.exports = function() {
edited: post.edited,
selftext_html: unescape(post.selftext_html),
num_comments: post.num_comments,
permalink: post.permalink
permalink: post.permalink,
user_flair: await formatUserFlair(post)
}
}
if(type === 't1') {
@ -79,7 +80,8 @@ module.exports = function() {
num_comments: post.num_comments,
permalink: post.permalink,
link_author: post.link_author,
link_title: post.link_title
link_title: post.link_title,
user_flair: await formatUserFlair(post)
}
}
posts.push(obj)

View File

@ -23,8 +23,7 @@ html
.title
a(href="" + post.url + "")
h2 #{cleanTitle(post.title)}
if post.link_flair_text
span(class="postflair") #{post.link_flair_text}
!= post.link_flair
span(class="domain") (#{post.domain})
p.submitted
span(title="" + toUTCString(post.created) + "") submitted #{timeDifference(post.created)} by
@ -33,6 +32,7 @@ html
else
a(href="/u/" + post.author + "")
| #{post.author}
!= post.user_flair
if post.crosspost.is_crosspost === true
.crosspost
.title
@ -52,6 +52,7 @@ html
else
a(href="/u/" + post.crosspost.author + "")
| #{post.crosspost.author}
!= post.user_flair
p.to to
a(href="/r/" + post.crosspost.subreddit + "")
| #{post.crosspost.subreddit}

View File

@ -84,14 +84,12 @@ html
if link.is_self_link
a(href="" + link.permalink + "")
h2(class="" + (link.stickied ? 'green' : '') + "") #{cleanTitle(link.title)}
if link.link_flair_text
span(class="postflair") #{link.link_flair_text}
!= link.link_flair
span (#{link.domain})
else
a(href="" + link.url + "")
h2(class="" + (link.stickied ? 'green' : '') + "") #{cleanTitle(link.title)}
if link.link_flair_text
span(class="postflair") #{link.link_flair_text}
!= link.link_flair
span (#{link.domain})
.meta
p.submitted submitted
@ -101,6 +99,7 @@ html
else
a(href="/u/" + link.author + "")
| #{link.author}
!= link.user_flair
p.to to
a(href="/r/" + link.subreddit + "")
| #{link.subreddit}

View File

@ -80,9 +80,11 @@ html
.title
a(href="" + post.permalink + "") #{cleanTitle(post.title)}
.meta
p.submitted(title="" + toUTCString(post.created) + "") submitted #{timeDifference(post.created)} by
p.submitted(title="" + toUTCString(post.created) + "") submitted #{timeDifference(post.created)}
| by
a(href="/u/" + data.username + "") #{data.username}
| to
!= post.user_flair
a(href="/r/" + post.subreddit + "", class="subreddit") #{post.subreddit}
a.comments(href="" + post.permalink + "") #{post.num_comments} comments
if post.type === 't1'
@ -108,6 +110,8 @@ html
.meta
p.author
a(href="/u/" + data.username + "") #{data.username}
p
!= post.user_flair
p.ups #{post.ups} points
p.created(title="" + toUTCString(post.created) + "") #{timeDifference(post.created)}
.body
@ -127,28 +131,3 @@ html
br
p(title="" + toUTCString(data.created) + "") account created: #{toDateString(data.created)}
p verified: #{(data.verified) ? "yes" : "no" }