mirror of
https://codeberg.org/teddit/teddit.git
synced 2026-04-18 21:45:06 -04:00
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:
+62
-5
@@ -1,4 +1,4 @@
|
||||
module.exports = function(request, fs) {
|
||||
module.exports = function(request, fs) {
|
||||
const config = require('../config')
|
||||
this.downloadFile = (url) => {
|
||||
return new Promise(resolve => {
|
||||
@@ -51,7 +51,7 @@ module.exports = function(request, fs) {
|
||||
if(video_exts.includes(file_ext) || !image_exts.includes(file_ext))
|
||||
url = url.replace(u.host, `${config.domain}/vids`) + '.mp4'
|
||||
}
|
||||
|
||||
|
||||
} catch(e) { }
|
||||
return url
|
||||
}
|
||||
@@ -59,7 +59,7 @@ module.exports = function(request, fs) {
|
||||
this.kFormatter = (num) => {
|
||||
return Math.abs(num) > 999 ? Math.sign(num)*((Math.abs(num)/1000).toFixed(1)) + 'k' : Math.sign(num)*Math.abs(num)
|
||||
}
|
||||
|
||||
|
||||
this.timeDifference = (time) => {
|
||||
time = parseInt(time) * 1000
|
||||
let ms_per_minute = 60 * 1000
|
||||
@@ -121,7 +121,7 @@ module.exports = function(request, fs) {
|
||||
return r
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.toUTCString = (time) => {
|
||||
let d = new Date();
|
||||
d.setTime(time*1000);
|
||||
@@ -165,7 +165,7 @@ module.exports = function(request, fs) {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
this.isGif = (url) => {
|
||||
try {
|
||||
url = new URL(url)
|
||||
@@ -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 ''
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ module.exports = function() {
|
||||
let moderator = false
|
||||
let submitter = false
|
||||
let edited_span = ''
|
||||
|
||||
|
||||
if(post_author === comments.author) {
|
||||
classlist.push('submitter')
|
||||
submitter_link = `<a href="${post_url}" title="submitter">[S]</a>`
|
||||
@@ -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>
|
||||
@@ -104,7 +105,7 @@ module.exports = function() {
|
||||
let submitter = false
|
||||
let ups = ''
|
||||
let edited_span = ''
|
||||
|
||||
|
||||
if(post_author === comment.author) {
|
||||
classlist.push('submitter')
|
||||
submitter_link = `<a href="${post_url}" title="submitter">[S]</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>
|
||||
@@ -185,7 +187,7 @@ module.exports = function() {
|
||||
comments_html += `</details></div>`
|
||||
}
|
||||
next_comment_parent_id = null
|
||||
|
||||
|
||||
resolve(comments_html)
|
||||
})()
|
||||
})
|
||||
|
||||
+18
-9
@@ -1,12 +1,12 @@
|
||||
module.exports = function(tools) {
|
||||
module.exports = function(tools) {
|
||||
const config = require('../config')
|
||||
const {spawn} = require('child_process')
|
||||
const fs = require('fs')
|
||||
this.downloadAndSave = (url, file_prefix = '', gifmp4, isYouTubeThumbnail) => {
|
||||
/**
|
||||
/**
|
||||
* This function downloads media (video or image) to disk.
|
||||
* Returns a localized URL
|
||||
*
|
||||
*
|
||||
* For example for images:
|
||||
* https://external-preview.redd.it/DiaeK_j5fqpBqbatvo7GZzbHNJY2oxEym93B_3.jpg
|
||||
* =>
|
||||
@@ -32,21 +32,23 @@ 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".
|
||||
*/
|
||||
file_ext = 'mp4'
|
||||
has_extension = false
|
||||
} else {
|
||||
} else {
|
||||
file_ext = pathname.substring(pathname.lastIndexOf('.') + 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)) {
|
||||
|
||||
+31
-25
@@ -7,7 +7,7 @@ module.exports = function(fetch) {
|
||||
if(!parsed) {
|
||||
json = JSON.parse(json)
|
||||
}
|
||||
|
||||
|
||||
let post = json[0].data.children[0].data
|
||||
let post_id = post.name
|
||||
let comments = json[1].data.children
|
||||
@@ -32,14 +32,16 @@ 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']
|
||||
let has_gif = false
|
||||
let gif_to_mp4 = null
|
||||
let reddit_video = null
|
||||
|
||||
|
||||
if(post.preview) {
|
||||
if(post.preview.reddit_video_preview) {
|
||||
if(post.preview.reddit_video_preview.is_gif) {
|
||||
@@ -66,7 +68,7 @@ module.exports = function(fetch) {
|
||||
}
|
||||
|
||||
obj = await processPostMedia(obj, post, post.media, has_gif, reddit_video, gif_to_mp4)
|
||||
|
||||
|
||||
if(post.crosspost_parent_list) {
|
||||
post.crosspost = post.crosspost_parent_list[0]
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +96,7 @@ module.exports = function(fetch) {
|
||||
source: await downloadAndSave(post.preview.images[0].source.url)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(obj.media) {
|
||||
if(obj.media.source === 'external') {
|
||||
if(post.preview) {
|
||||
@@ -103,7 +106,7 @@ module.exports = function(fetch) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(post.gallery_data) {
|
||||
obj.gallery = true
|
||||
obj.gallery_items = []
|
||||
@@ -120,13 +123,13 @@ module.exports = function(fetch) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let comms = []
|
||||
for(var i = 0; i < comments.length; i++) {
|
||||
let comment = comments[i].data
|
||||
let kind = comments[i].kind
|
||||
let obj = {}
|
||||
|
||||
|
||||
if(kind !== 'more') {
|
||||
obj = {
|
||||
author: comment.author,
|
||||
@@ -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 = {
|
||||
@@ -155,26 +159,26 @@ module.exports = function(fetch) {
|
||||
children: []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(comment.children) {
|
||||
for(var j = 0; j < comment.children.length; j++) {
|
||||
obj.children.push(comment.children[j])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
comms.push(obj)
|
||||
}
|
||||
|
||||
|
||||
obj.comments = comms
|
||||
|
||||
|
||||
resolve(obj)
|
||||
})()
|
||||
})
|
||||
@@ -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 = {
|
||||
@@ -233,13 +238,13 @@ module.exports = function(fetch) {
|
||||
depth: depth
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(reply.replies && kind !== 'more') {
|
||||
if(reply.replies.data.children.length) {
|
||||
for(var j = 0; j < reply.replies.data.children.length; j++) {
|
||||
let comment = reply.replies.data.children[j].data
|
||||
let objct = {}
|
||||
|
||||
|
||||
if(comment.author && comment.body_html) {
|
||||
objct = {
|
||||
author: comment.author,
|
||||
@@ -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 = {
|
||||
@@ -273,11 +279,11 @@ 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 )
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,13 +292,13 @@ module.exports = function(fetch) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(reply.children) {
|
||||
for(var j = 0; j < reply.children.length; j++) {
|
||||
obj.children.push(reply.children[j])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return_replies.push(obj)
|
||||
}
|
||||
return return_replies
|
||||
|
||||
@@ -11,7 +11,7 @@ module.exports = function() {
|
||||
} else {
|
||||
let before = json.data.before
|
||||
let after = json.data.after
|
||||
|
||||
|
||||
let ret = {
|
||||
info: {
|
||||
before: before,
|
||||
@@ -19,9 +19,9 @@ module.exports = function() {
|
||||
},
|
||||
links: []
|
||||
}
|
||||
|
||||
|
||||
let children_len = json.data.children.length
|
||||
|
||||
|
||||
for(var i = 0; i < children_len; i++) {
|
||||
let data = json.data.children[i].data
|
||||
let images = null
|
||||
@@ -39,7 +39,7 @@ module.exports = function() {
|
||||
is_self_link = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(data.preview && data.thumbnail !== 'self') {
|
||||
if(!data.url.startsWith('/r/') && isGif(data.url)) {
|
||||
images = {
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ module.exports = function() {
|
||||
if(!after && !before) {
|
||||
user_front = true
|
||||
}
|
||||
|
||||
|
||||
if(json.overview.data.children) {
|
||||
if(json.overview.data.children[posts_limit - 1]) {
|
||||
after = json.overview.data.children[posts_limit - 1].data.name
|
||||
@@ -30,16 +30,16 @@ module.exports = function() {
|
||||
before = json.overview.data.children[0].data.name
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(var i = 0; i < posts_limit; i++) {
|
||||
let post = json.overview.data.children[i].data
|
||||
let thumbnail = 'self'
|
||||
let type = json.overview.data.children[i].kind
|
||||
let obj
|
||||
|
||||
|
||||
let post_id = post.permalink.split('/').slice(-2)[0] + '/'
|
||||
let url = post.permalink.replace(post_id, '')
|
||||
|
||||
|
||||
if(type === 't3') {
|
||||
let duration = null
|
||||
if(post.media) {
|
||||
@@ -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)
|
||||
@@ -98,7 +100,7 @@ module.exports = function() {
|
||||
after: after,
|
||||
posts: posts
|
||||
}
|
||||
|
||||
|
||||
resolve(obj)
|
||||
})()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user