Merge branch 'hot-threads' into develop

indiachan-spamvector
Thomas Lynch 2 years ago
commit 850d82f969
  1. 1
      CHANGELOG.md
  2. 5
      configs/template.js.example
  3. 4
      controllers/forms/globalsettings.js
  4. 26
      db/posts.js
  5. 7
      gulp/res/css/style.css
  6. 4
      lib/build/tasks.js
  7. 11
      migrations/0.6.0.js
  8. 2
      models/forms/changeglobalsettings.js
  9. 6
      views/pages/globalmanagesettings.pug
  10. 24
      views/pages/home.pug

@ -2,6 +2,7 @@
- Bans+Appeal form will now appear in the modal popup when js enabled, instead of a dodgy workaround which often caused posting bugs and broke over Tor.
- Bans can now be "upgraded" retroactively to expand single IP bans to qrange/hrange bans.
- Ban table now shows columns for "Type" (IP/Bypass/Pruned) and "Range" (Single/Narrow/Wide).
- Global setting to show some popular threads from listed boards on the homepage, with adjustible limit (0=disabled) and threshold. (courtesy ptchan.org)
- Big refactor of backend, the awfully named and disorganised "helpers" is now the more appropriately named and better organised "lib".
- Some form and input handling code made more robust based on test feedback.
- More tests.

@ -94,6 +94,11 @@ module.exports = {
//allow custom overboard (user pick what boards to show)
allowCustomOverboard: true,
//how many hot threads show on homepage. 0 disabled
hotThreadsLimit: 5,
//how many replies the thread needs to be "hot"
hotThreadsThreshold: 10,
//default url format/links for archive and reverse image search links, %s will be replaced by the url
archiveLinksURL: 'https://archive.today/?run=1&url=%s',
reverseImageLinksURL: 'https://tineye.com/search?url=%s',

@ -17,7 +17,7 @@ module.exports = {
'captcha_options_generate_limit', 'captcha_options_grid_size', 'captcha_options_grid_image_size', 'captcha_options_num_distorts_min', 'captcha_options_num_distorts_max',
'captcha_options_distortion', 'captcha_options_grid_icon_y_offset', 'flood_timers_same_content_same_ip', 'flood_timers_same_content_any_ip', 'flood_timers_any_content_same_ip',
'block_bypass_expire_after_uses', 'rate_limit_cost_captcha', 'rate_limit_cost_board_settings', 'rate_limit_cost_edit_post',
'overboard_limit', 'overboard_catalog_limit', 'lock_wait', 'prune_modlogs', 'prune_ips', 'thumb_size', 'video_thumb_percentage', 'quote_limit', 'preview_replies',
'overboard_limit', 'hot_threads_limit', 'hot_threads_threshold', 'overboard_catalog_limit', 'lock_wait', 'prune_modlogs', 'prune_ips', 'thumb_size', 'video_thumb_percentage', 'quote_limit', 'preview_replies',
'sticky_preview_replies', 'early_404_fraction', 'early_404_replies', 'max_recent_news', 'highlight_options_threshold', 'global_limits_thread_limit_min',
'global_limits_thread_limit_max', 'global_limits_reply_limit_min', 'global_limits_reply_limit_max', 'global_limits_bump_limit_min', 'global_limits_bump_limit_max',
'global_limits_post_files_max', 'global_limits_post_files_size_max', 'global_limits_asset_files_total', 'global_limits_asset_files_max', 'global_limits_asset_files_size_max',
@ -95,6 +95,8 @@ module.exports = {
{ result: numberBody(req.body.rate_limit_cost_captcha, 1, 100), expected: true, error: 'Rate limit cost captcha must be a number from 1-100' },
{ result: numberBody(req.body.rate_limit_cost_board_settings, 1, 100), expected: true, error: 'Rate limit cost board settings must be a number from 1-100' },
{ result: numberBody(req.body.rate_limit_cost_edit_post, 1, 100), expected: true, error: 'Rate limit cost edit post must be a number from 1-100' },
{ result: numberBody(req.body.hot_threads_limit), expected: true, error: 'Invalid hot threads limit' },
{ result: numberBody(req.body.hot_threads_threshold), expected: true, error: 'Invalid hot threads threshold' },
{ result: numberBody(req.body.overboard_limit), expected: true, error: 'Invalid overboard limit' },
{ result: numberBody(req.body.overboard_catalog_limit), expected: true, error: 'Invalid overboard catalog limit' },
{ result: numberBody(req.body.lock_wait), expected: true, error: 'Invalid lock wait' },

@ -2,6 +2,7 @@
const Mongo = require(__dirname+'/db.js')
, { isIP } = require('net')
, { DAY } = require(__dirname+'/../lib/converter/timeutils.js')
, Boards = require(__dirname+'/boards.js')
, Stats = require(__dirname+'/stats.js')
, Permissions = require(__dirname+'/../lib/permission/permissions.js')
@ -708,6 +709,31 @@ module.exports = {
]).toArray();
},
hotThreads: async () => {
const { hotThreadsLimit, hotThreadsThreshold } = config.get;
if (hotThreadsLimit === 0){ //0 limit = no limit in mongodb
return [];
}
const listedBoards = await Boards.getLocalListed();
return db.find({
'board': {
'$in': listedBoards
},
'thread': null,
'date': {
//created in last 7 days
'$gte': new Date(Date.now() - (7 * DAY))
},
'replyposts': {
'$gte': hotThreadsThreshold,
}
}).sort({
'replyposts': -1
})
.limit(hotThreadsLimit)
.toArray();
},
deleteMany: (ids) => {
return db.deleteMany({
'_id': {

@ -1446,6 +1446,10 @@ row.wrap.sb .col {
flex-basis: calc(50% - 5px);
}
#hotposts td:nth-child(1) {
white-space: nowrap;
}
@media only screen and (max-height: 400px) {
.modal {
top: 5px;
@ -1484,6 +1488,9 @@ row.wrap.sb .col {
margin-left: 3px;
width: 1em;
}
#hotposts td:nth-child(3) {
display: none;
}
#settings::after {
content: "\2699"!important;
}

@ -246,11 +246,12 @@ module.exports = {
const { maxRecentNews } = config.get;
const label = '/index.html';
const start = process.hrtime();
let [ totalStats, boards, fileStats, recentNews ] = await Promise.all([
let [ totalStats, boards, fileStats, recentNews, hotThreads ] = await Promise.all([
Boards.totalStats(), //overall total posts ever made
Boards.boardSort(0, 20), //top 20 boards sorted by users, pph, total posts
Files.activeContent(), //size and number of files
News.find(maxRecentNews), //some recent newsposts
Posts.hotThreads(), //top 5 threads last 7 days
]);
const [ localStats, webringStats ] = totalStats;
const { html } = await render('index.html', 'home.pug', {
@ -259,6 +260,7 @@ module.exports = {
boards,
fileStats,
recentNews,
hotThreads,
});
const end = process.hrtime(start);
debugLogs && console.log(timeDiffString(label, end));

@ -53,4 +53,15 @@ module.exports = async(db, redis) => {
'type': 2,
},
});
console.log('Add options for adjusting hot threads to globalsettings');
await db.collection('globalsettings').updateOne({ _id: 'globalsettings' }, {
'$set': {
'hotThreadsLimit': 5,
'hotThreadsThreshold': 10,
},
});
console.log('Clearing globalsettings cache');
await redis.deletePattern('globalsettings');
};

@ -109,6 +109,8 @@ module.exports = async (req, res, next) => {
},
overboardLimit: numberSetting(req.body.overboard_limit, oldSettings.overboardLimit),
overboardCatalogLimit: numberSetting(req.body.overboard_catalog_limit, oldSettings.overboardCatalogLimit),
hotThreadsLimit: numberSetting(req.body.hot_threads_limit, oldSettings.hotThreadsLimit),
hotThreadsThreshold: numberSetting(req.body.hot_threads_threshold, oldSettings.hotThreadsThreshold),
allowCustomOverboard: booleanSetting(req.body.allow_custom_overboard, oldSettings.allowCustomOverboard),
archiveLinksURL: trimSetting(req.body.archive_links, oldSettings.archiveLinksURL),
reverseImageLinksURL: trimSetting(req.body.reverse_links, oldSettings.reverseImageLinksURL),

@ -92,6 +92,12 @@ block content
.row
.label Template Generation Lock Time
input(type='number' name='lock_wait' value=settings.lockWait)
.row
.label Hot Threads Limit
input(type='number' name='hot_threads_limit' value=settings.hotThreadsLimit)
.row
.label Hot Threads Threshold
input(type='number' name='hot_threads_threshold' value=settings.hotThreadsThreshold)
.row
.label Overboard Index Thread Limit
input(type='number' name='overboard_limit' value=settings.overboardLimit)

@ -28,7 +28,29 @@ block content
td
- const newsDate = new Date(post.date);
time.right.reltime(datetime=newsDate.toISOString()) #{newsDate.toLocaleString(undefined, {hourCycle:'h23'})}
if hotThreads && hotThreads.length > 0
.table-container.flex-center.mv-5
table#hotposts
tr(colspan=3)
each post, i in hotThreads
tr
td.text-center
span.help(title='Hot Thread') 🔥
| #{post.replyposts + post.replyfiles}
td
- const threadLink = `/${post.board}/thread/${post.postId}.html#${post.postId}`;
a.quote(href=threadLink)
if post.subject
| #{post.subject.substring(0,30)}#{post.subject.length > 30 ? '...' : ''}
if post.nomarkup
| -
if post.nomarkup
| #{post.nomarkup.substring(0,40)}#{post.nomarkup.length > 40 ? '...' : ''}
if !post.nomarkup && !post.subject
| >>>/#{post.board}/#{post.postId}
td
- const bumpDate = new Date(post.bumped);
time.right.reltime(datetime=bumpDate.toISOString()) #{bumpDate.toLocaleString(undefined, {hourCycle:'h23'})}
if boards && boards.length > 0
+boardtable(true, false)
each board in boards

Loading…
Cancel
Save