From 6d73c13495ff3fddde43a9c540cf1834b3ba7c57 Mon Sep 17 00:00:00 2001 From: Misty Release Bot Date: Sun, 9 Feb 2025 01:01:54 +0000 Subject: [PATCH 01/26] chore: incrementing version number - v4.0.3 --- install/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install/package.json b/install/package.json index cd00e60504..af56f2d072 100644 --- a/install/package.json +++ b/install/package.json @@ -2,7 +2,7 @@ "name": "nodebb", "license": "GPL-3.0", "description": "NodeBB Forum", - "version": "4.0.2", + "version": "4.0.3", "homepage": "https://www.nodebb.org", "repository": { "type": "git", @@ -200,4 +200,4 @@ "url": "https://github.com/barisusakli" } ] -} +} \ No newline at end of file From 123e16358d402e466fc785dfc7eeeb69d48f1c4a Mon Sep 17 00:00:00 2001 From: Misty Release Bot Date: Sun, 9 Feb 2025 01:01:55 +0000 Subject: [PATCH 02/26] chore: update changelog for v4.0.3 --- CHANGELOG.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2808bece2b..783b4dd082 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,53 @@ +#### v4.0.3 (2025-02-09) + +##### Chores + +* up harmony (2ee0cda2) +* update persona (b6b76639) +* bump persona to fix theme description issue (cd88cce0) +* up harmony (a01bf73e) +* forgot to remove bad code (865c09a5) +* up harmony (c3f8222f) +* up harmony (f07f3801) +* up harmony (67a789ad) +* up themes (c1c5cc6e) +* up themes (b2b0ed35) +* up peace (55eedcbe) +* up themes (38a21e29) +* up harmony (58e551fe) +* incrementing version number - v4.0.2 (73fe5fcf) +* update changelog for v4.0.2 (75588ffe) +* incrementing version number - v4.0.1 (a461b758) +* incrementing version number - v4.0.0 (c1eaee45) + +##### Bug Fixes + +* delete from payload instead of setting null (1b4e0c87) +* regression :tmi: (f5328aa8) +* #13139, payload.version can be null (bfe6d9d8) +* tidChanged (1f8e2f9a) +* #13135, tids are not numeric for ap topics (d687f081) +* handle cases where url passed to mime does not pass because url contained a query string (5baa46d0) +* isDraft logic, closes #13119 (21156673) +* path on windows, #13119 (36063d1f) +* #13115, prevent messages from getting duplicated (1ff8e1e4) +* #13115, limit bodyLength length (8e9fdb5f) + +##### Other Changes + +* remove log (a8e7bf35) + +##### Refactors + +* events are returned inside post objects (3ab22c2c) +* move dropdown search inputs into dropdown (b993be6f) +* server.destroy (72091ec4) +* remove deprecated methods (265e44f0) + +##### Tests + +* search endpoint with start & end (c1b630d4) + #### v4.0.2 (2025-02-02) ##### Chores From 040584f035547153454cf075e9ae673196ccb492 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 7 Feb 2025 08:20:27 -0500 Subject: [PATCH 03/26] fix: missing actor on some local activities when federating out --- src/api/activitypub.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/api/activitypub.js b/src/api/activitypub.js index 76abcc9c51..3b078a7862 100644 --- a/src/api/activitypub.js +++ b/src/api/activitypub.js @@ -168,6 +168,7 @@ activitypubApi.create.privateNote = enabledCheck(async (caller, { messageObj }) const payload = { id: `${object.id}#activity/create/${Date.now()}`, type: 'Create', + actor: object.attributedTo, to: object.to, object, }; @@ -186,6 +187,7 @@ activitypubApi.update.profile = enabledCheck(async (caller, { uid }) => { await activitypub.send('uid', caller.uid, targets, { id: `${object.id}#activity/update/${Date.now()}`, type: 'Update', + actor: object.id, to: [activitypub._constants.publicAddress], cc: [], object, @@ -201,6 +203,7 @@ activitypubApi.update.category = enabledCheck(async (caller, { cid }) => { await activitypub.send('cid', cid, targets, { id: `${object.id}#activity/update/${Date.now()}`, type: 'Update', + actor: object.id, to: [activitypub._constants.publicAddress], cc: [], object, @@ -227,6 +230,7 @@ activitypubApi.update.note = enabledCheck(async (caller, { post }) => { const payload = { id: `${object.id}#activity/update/${post.edited || Date.now()}`, type: 'Update', + actor: object.attributedTo, to, cc, object, @@ -251,6 +255,7 @@ activitypubApi.update.privateNote = enabledCheck(async (caller, { messageObj }) const payload = { id: `${object.id}#activity/create/${Date.now()}`, type: 'Update', + actor: object.attributedTo, to, object, }; @@ -280,6 +285,7 @@ activitypubApi.delete.note = enabledCheck(async (caller, { pid }) => { const payload = { id: `${id}#activity/delete/${Date.now()}`, type: 'Delete', + actor: object.attributedTo, to, cc, object: id, @@ -334,6 +340,7 @@ activitypubApi.announce.note = enabledCheck(async (caller, { tid }) => { await activitypub.send('uid', caller.uid, Array.from(targets), { id: `${nconf.get('url')}/post/${encodeURIComponent(pid)}#activity/announce/${Date.now()}`, type: 'Announce', + actor: `${nconf.get('url')}/uid/${caller.uid}`, to, cc, object: pid, @@ -380,6 +387,7 @@ activitypubApi.flag = enabledCheck(async (caller, flag) => { await activitypub.send('uid', caller.uid, reportedIds, { id: `${nconf.get('url')}/${flag.type}/${encodeURIComponent(flag.targetId)}#activity/flag/${caller.uid}`, type: 'Flag', + actor: `${nconf.get('url')}/uid/${caller.uid}`, object: reportedIds, content: reason, }); @@ -426,6 +434,7 @@ activitypubApi.undo.flag = enabledCheck(async (caller, flag) => { await activitypub.send('uid', caller.uid, reportedIds, { id: `${nconf.get('url')}/${flag.type}/${encodeURIComponent(flag.targetId)}#activity/undo:flag/${caller.uid}/${Date.now()}`, type: 'Undo', + actor: `${nconf.get('url')}/uid/${caller.uid}`, object: { id: `${nconf.get('url')}/${flag.type}/${encodeURIComponent(flag.targetId)}#activity/flag/${caller.uid}`, actor: `${nconf.get('url')}/uid/${caller.uid}`, From 5cbf3dd7eaaa3b7e703c3a7b9852b4606471ce28 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Sat, 8 Feb 2025 20:28:17 -0500 Subject: [PATCH 04/26] fix: sanity-check the id when mocking a post --- src/activitypub/mocks.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/activitypub/mocks.js b/src/activitypub/mocks.js index 3ea4c03494..493655c272 100644 --- a/src/activitypub/mocks.js +++ b/src/activitypub/mocks.js @@ -155,7 +155,10 @@ Mocks.post = async (objects) => { await activitypub.actors.assert(Array.from(actorIds)); const posts = await Promise.all(objects.map(async (object) => { - if (!activitypub._constants.acceptedPostTypes.includes(object.type)) { + if ( + !activitypub._constants.acceptedPostTypes.includes(object.type) || + !activitypub.helpers.isUri(object.id) // sanity-check the id + ) { return null; } From d1f78295bab9a1baf20e906819aac1a13ee73af9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sat, 8 Feb 2025 20:57:56 -0500 Subject: [PATCH 05/26] chore: up harmony --- install/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index af56f2d072..d5c3521217 100644 --- a/install/package.json +++ b/install/package.json @@ -108,7 +108,7 @@ "nodebb-plugin-spam-be-gone": "2.3.0", "nodebb-plugin-web-push": "0.7.2", "nodebb-rewards-essentials": "1.0.0", - "nodebb-theme-harmony": "2.0.18", + "nodebb-theme-harmony": "2.0.19", "nodebb-theme-lavender": "7.1.17", "nodebb-theme-peace": "2.2.38", "nodebb-theme-persona": "14.0.14", From 893089709cf534052b4e2cb72fa8c14ca38ad654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 11 Feb 2025 10:16:40 -0500 Subject: [PATCH 06/26] add await to notify functions and wrap in try/catch --- src/topics/create.js | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/topics/create.js b/src/topics/create.js index 96113c3e5a..e6d97af77f 100644 --- a/src/topics/create.js +++ b/src/topics/create.js @@ -2,6 +2,7 @@ 'use strict'; const _ = require('lodash'); +const winston = require('winston'); const db = require('../database'); const utils = require('../utils'); @@ -154,12 +155,19 @@ module.exports = function (Topics) { plugins.hooks.fire('action:topic.post', { topic: topicData, post: postData, data: data }); if (!topicData.scheduled) { - if (utils.isNumber(uid)) { - // New topic notifications only sent for local-to-local follows only - user.notifications.sendTopicNotificationToFollowers(uid, topicData, postData); - } - Topics.notifyTagFollowers(postData, uid); - categories.notifyCategoryFollowers(postData, uid); + setImmediate(async () => { + try { + if (utils.isNumber(uid)) { + // New topic notifications only sent for local-to-local follows only + await user.notifications.sendTopicNotificationToFollowers(uid, topicData, postData); + } + + await Topics.notifyTagFollowers(postData, uid); + await categories.notifyCategoryFollowers(postData, uid); + } catch (err) { + winston.error(err.stack); + } + }); } return { @@ -211,13 +219,17 @@ module.exports = function (Topics) { } if (parseInt(uid, 10) || activitypub.helpers.isUri(uid) || meta.config.allowGuestReplyNotifications) { - const { displayname } = postData.user; - - Topics.notifyFollowers(postData, uid, { - type: 'new-reply', - bodyShort: translator.compile('notifications:user-posted-to', displayname, postData.topic.title), - nid: `new_post:tid:${postData.topic.tid}:pid:${postData.pid}:uid:${uid}`, - mergeId: `notifications:user-posted-to|${postData.topic.tid}`, + setImmediate(async () => { + try { + await Topics.notifyFollowers(postData, uid, { + type: 'new-reply', + bodyShort: translator.compile('notifications:user-posted-to', postData.user.displayname, postData.topic.title), + nid: `new_post:tid:${postData.topic.tid}:pid:${postData.pid}:uid:${uid}`, + mergeId: `notifications:user-posted-to|${postData.topic.tid}`, + }); + } catch (err) { + winston.error(err.stack); + } }); } From 224910b133d32c85a09ef5d16e4702f2c72ac532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 11 Feb 2025 10:48:42 -0500 Subject: [PATCH 07/26] fix: isArray check --- src/activitypub/actors.js | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/activitypub/actors.js b/src/activitypub/actors.js index 2208f03de7..b5ecdc8f96 100644 --- a/src/activitypub/actors.js +++ b/src/activitypub/actors.js @@ -230,19 +230,29 @@ Actors.getLocalFollowers = async (id) => { return response; }; -Actors.getLocalFollowCounts = async (actor) => { - let followers = 0; // x local followers - let following = 0; // following x local users - if (!activitypub.helpers.isUri(actor)) { - return { followers, following }; +Actors.getLocalFollowCounts = async (actors) => { + const isArray = Array.isArray(actors); + if (!isArray) { + actors = [actors]; } - [followers, following] = await Promise.all([ - db.sortedSetCard(`followersRemote:${actor}`), - db.sortedSetCard(`followingRemote:${actor}`), + const validActors = actors.filter(actor => activitypub.helpers.isUri(actor)); + const followerKeys = validActors.map(actor => `followersRemote:${actor}`); + const followingKeys = validActors.map(actor => `followingRemote:${actor}`); + + const [followersCounts, followingCounts] = await Promise.all([ + db.sortedSetsCard(followerKeys), + db.sortedSetsCard(followingKeys), ]); - return { followers, following }; + const results = actors.map((actor, index) => { + if (!validActors.includes(actor)) { + return { followers: 0, following: 0 }; + } + return { followers: followersCounts[index], following: followingCounts[index] }; + }); + + return isArray ? results : results[0]; }; Actors.remove = async (id) => { From d590c2afcf9a680323b2387d86378756e9b06d24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 11 Feb 2025 10:39:24 -0500 Subject: [PATCH 08/26] perf: closes #13145, reduce calls in actors.prune instead of deleting 18k users everyday delete max 500 every 30mins like notifications.prune refactor getLocalFollowCounts so it works with an array of actors dont make dbcalls for uids that dont exist --- src/activitypub/actors.js | 25 +++++++++++++------------ src/activitypub/index.js | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/activitypub/actors.js b/src/activitypub/actors.js index b5ecdc8f96..ef4e1497c1 100644 --- a/src/activitypub/actors.js +++ b/src/activitypub/actors.js @@ -298,7 +298,7 @@ Actors.prune = async () => { const days = parseInt(meta.config.activitypubUserPruneDays, 10); const timestamp = Date.now() - (1000 * 60 * 60 * 24 * days); - const uids = await db.getSortedSetRangeByScore('usersRemote:lastCrawled', 0, -1, '-inf', timestamp); + const uids = await db.getSortedSetRangeByScore('usersRemote:lastCrawled', 0, 500, '-inf', timestamp); if (!uids.length) { winston.info('[actors/prune] No remote users to prune, all done.'); return; @@ -309,18 +309,19 @@ Actors.prune = async () => { await batch.processArray(uids, async (uids) => { const exists = await db.exists(uids.map(uid => `userRemote:${uid}`)); - const [postCounts, roomCounts] = await Promise.all([ - db.sortedSetsCard(uids.map(uid => `uid:${uid}:posts`)), - db.sortedSetsCard(uids.map(uid => `uid:${uid}:chat:rooms`)), - ]); - await Promise.all(uids.map(async (uid, idx) => { - if (!exists[idx]) { - // id in zset but not asserted, handle and return early - await db.sortedSetRemove('usersRemote:lastCrawled', uid); - return; - } - const { followers, following } = await Actors.getLocalFollowCounts(uid); + const uidsThatExist = uids.filter((uid, idx) => exists[idx]); + const uidsThatDontExist = uids.filter((uid, idx) => !exists[idx]); + await db.sortedSetRemove('usersRemote:lastCrawled', uidsThatDontExist); + + const [postCounts, roomCounts, followCounts] = await Promise.all([ + db.sortedSetsCard(uidsThatExist.map(uid => `uid:${uid}:posts`)), + db.sortedSetsCard(uidsThatExist.map(uid => `uid:${uid}:chat:rooms`)), + Actors.getLocalFollowCounts(uidsThatExist), + ]); + + await Promise.all(uidsThatExist.map(async (uid, idx) => { + const { followers, following } = followCounts[idx]; const postCount = postCounts[idx]; const roomCount = roomCounts[idx]; if ([postCount, roomCount, followers, following].every(metric => metric < 1)) { diff --git a/src/activitypub/index.js b/src/activitypub/index.js index 4a6d95b48b..3eec80eae1 100644 --- a/src/activitypub/index.js +++ b/src/activitypub/index.js @@ -66,7 +66,7 @@ ActivityPub.startJobs = () => { } }, null, true, null, null, false); // change last argument to true for debugging - new CronJob('0 1 * * *', async () => { + new CronJob('*/30 * * * *', async () => { try { await ActivityPub.actors.prune(); } catch (err) { From e85662a536bf352e023f8c8747ea812b0df59f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 11 Feb 2025 13:28:25 -0500 Subject: [PATCH 09/26] fix: getUserField so that it always returns null if field doesn't exist user.getUserField('foo', 'bar') returned undefined vs user.getUserField('1', 'bar') which returned null --- src/user/data.js | 2 +- test/user.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/user/data.js b/src/user/data.js index ec643f729b..c9d8cb5ae6 100644 --- a/src/user/data.js +++ b/src/user/data.js @@ -161,7 +161,7 @@ module.exports = function (User) { User.getUserField = async function (uid, field) { const user = await User.getUserFields(uid, [field]); - return user ? user[field] : null; + return user && user.hasOwnProperty(field) ? user[field] : null; }; User.getUserFields = async function (uid, fields) { diff --git a/test/user.js b/test/user.js index 84d8711260..579386b166 100644 --- a/test/user.js +++ b/test/user.js @@ -680,6 +680,12 @@ describe('User', () => { done(); }); }); + + it('should return null if field or user doesn not exist', async () => { + assert.strictEqual(await User.getUserField('1', 'doesnotexist'), null); + assert.strictEqual(await User.getUserField('doesnotexistkey', 'doesnotexist'), null); + assert.strictEqual(await User.getUserField('0', 'doesnotexist'), null); + }); }); describe('profile methods', () => { From 70a9f6d3376deeb1faf133baf8d25c7a78905402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 11 Feb 2025 13:37:21 -0500 Subject: [PATCH 10/26] fix: return null if field isn't in hash --- src/categories/data.js | 2 +- src/groups/data.js | 2 +- src/messaging/data.js | 2 +- src/posts/data.js | 2 +- src/topics/data.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/categories/data.js b/src/categories/data.js index 452ccf20b8..2b4e029caf 100644 --- a/src/categories/data.js +++ b/src/categories/data.js @@ -73,7 +73,7 @@ module.exports = function (Categories) { Categories.getCategoryField = async function (cid, field) { const category = await Categories.getCategoryFields(cid, [field]); - return category ? category[field] : null; + return category && category.hasOwnProperty(field) ? category[field] : null; }; Categories.getCategoryFields = async function (cid, fields) { diff --git a/src/groups/data.js b/src/groups/data.js index 5ecb9081e0..1dc52e44ad 100644 --- a/src/groups/data.js +++ b/src/groups/data.js @@ -51,7 +51,7 @@ module.exports = function (Groups) { Groups.getGroupField = async function (groupName, field) { const groupData = await Groups.getGroupFields(groupName, [field]); - return groupData ? groupData[field] : null; + return groupData && groupData.hasOwnProperty(field) ? groupData[field] : null; }; Groups.getGroupFields = async function (groupName, fields) { diff --git a/src/messaging/data.js b/src/messaging/data.js index aa96e11a67..2c3257c74f 100644 --- a/src/messaging/data.js +++ b/src/messaging/data.js @@ -29,7 +29,7 @@ module.exports = function (Messaging) { Messaging.getMessageField = async (mid, field) => { const fields = await Messaging.getMessageFields(mid, [field]); - return fields ? fields[field] : null; + return fields && fields.hasOwnProperty(field) ? fields[field] : null; }; Messaging.getMessageFields = async (mid, fields) => { diff --git a/src/posts/data.js b/src/posts/data.js index 5c44b49254..688c131b8a 100644 --- a/src/posts/data.js +++ b/src/posts/data.js @@ -37,7 +37,7 @@ module.exports = function (Posts) { Posts.getPostField = async function (pid, field) { const post = await Posts.getPostFields(pid, [field]); - return post ? post[field] : null; + return post && post.hasOwnProperty(field) ? post[field] : null; }; Posts.getPostFields = async function (pid, fields) { diff --git a/src/topics/data.js b/src/topics/data.js index 1260c092e1..e9a281ecaa 100644 --- a/src/topics/data.js +++ b/src/topics/data.js @@ -40,7 +40,7 @@ module.exports = function (Topics) { Topics.getTopicField = async function (tid, field) { const topic = await Topics.getTopicFields(tid, [field]); - return topic ? topic[field] : null; + return topic && topic.hasOwnProperty(field) ? topic[field] : null; }; Topics.getTopicFields = async function (tid, fields) { From cfbb8ff8877dae57fe65948e7812f12fce23bf6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 11 Feb 2025 13:45:38 -0500 Subject: [PATCH 11/26] fix: getLocalFollowCounts, show non existing deletes --- src/activitypub/actors.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/activitypub/actors.js b/src/activitypub/actors.js index ef4e1497c1..d134d65721 100644 --- a/src/activitypub/actors.js +++ b/src/activitypub/actors.js @@ -2,6 +2,7 @@ const nconf = require('nconf'); const winston = require('winston'); +const _ = require('lodash'); const db = require('../database'); const meta = require('../meta'); @@ -244,12 +245,17 @@ Actors.getLocalFollowCounts = async (actors) => { db.sortedSetsCard(followerKeys), db.sortedSetsCard(followingKeys), ]); - - const results = actors.map((actor, index) => { - if (!validActors.includes(actor)) { + const actorToCounts = _.zipObject(validActors, validActors.map( + (a, idx) => ({ followers: followersCounts[idx], following: followingCounts[idx] }) + )); + const results = actors.map((actor) => { + if (!actorToCounts.hasOwnProperty(actor)) { return { followers: 0, following: 0 }; } - return { followers: followersCounts[index], following: followingCounts[index] }; + return { + followers: actorToCounts[actor].followers, + following: actorToCounts[actor].following, + }; }); return isArray ? results : results[0]; @@ -306,13 +312,12 @@ Actors.prune = async () => { winston.info(`[actors/prune] Found ${uids.length} remote users last crawled more than ${days} days ago`); let deletionCount = 0; - + let deletionCountNonExisting = 0; await batch.processArray(uids, async (uids) => { const exists = await db.exists(uids.map(uid => `userRemote:${uid}`)); const uidsThatExist = uids.filter((uid, idx) => exists[idx]); const uidsThatDontExist = uids.filter((uid, idx) => !exists[idx]); - await db.sortedSetRemove('usersRemote:lastCrawled', uidsThatDontExist); const [postCounts, roomCounts, followCounts] = await Promise.all([ db.sortedSetsCard(uidsThatExist.map(uid => `uid:${uid}:posts`)), @@ -333,10 +338,13 @@ Actors.prune = async () => { } } })); + + deletionCountNonExisting += uidsThatDontExist.length; + await db.sortedSetRemove('usersRemote:lastCrawled', uidsThatDontExist); }, { batch: 50, interval: 1000, }); - winston.info(`[actors/prune] ${deletionCount} remote users pruned.`); + winston.info(`[actors/prune] ${deletionCount} remote users pruned. ${deletionCountNonExisting} does not exist`); }; From de457210e9417a63eee0f5aadc1a21756e9f0f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 11 Feb 2025 13:48:53 -0500 Subject: [PATCH 12/26] show non deletions --- src/activitypub/actors.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/activitypub/actors.js b/src/activitypub/actors.js index d134d65721..ccd5a9fb41 100644 --- a/src/activitypub/actors.js +++ b/src/activitypub/actors.js @@ -313,6 +313,7 @@ Actors.prune = async () => { winston.info(`[actors/prune] Found ${uids.length} remote users last crawled more than ${days} days ago`); let deletionCount = 0; let deletionCountNonExisting = 0; + let notDeletedDueToLocalContent = 0; await batch.processArray(uids, async (uids) => { const exists = await db.exists(uids.map(uid => `userRemote:${uid}`)); @@ -336,6 +337,8 @@ Actors.prune = async () => { } catch (err) { winston.error(err.stack); } + } else { + notDeletedDueToLocalContent += 1; } })); @@ -346,5 +349,5 @@ Actors.prune = async () => { interval: 1000, }); - winston.info(`[actors/prune] ${deletionCount} remote users pruned. ${deletionCountNonExisting} does not exist`); + winston.info(`[actors/prune] ${deletionCount} remote users pruned. ${deletionCountNonExisting} does not exist. ${notDeletedDueToLocalContent} not deleted due to local content`); }; From c4b013308f981f3ddd227d4c1aaf8b3cc0946515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 11 Feb 2025 13:57:38 -0500 Subject: [PATCH 13/26] refactor: hooks button --- src/views/admin/advanced/hooks.tpl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/views/admin/advanced/hooks.tpl b/src/views/admin/advanced/hooks.tpl index fceffc3655..1f1b4682cc 100644 --- a/src/views/admin/advanced/hooks.tpl +++ b/src/views/admin/advanced/hooks.tpl @@ -2,9 +2,8 @@ {{{ each hooks }}}
-
- {hooks.hookName} - +
+
From ffbe4b7bb727963f6191607e7a984c842b33848a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 11 Feb 2025 14:32:54 -0500 Subject: [PATCH 14/26] fix: actor.prune, dont try deleting same users over and over if they have local content --- src/activitypub/actors.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/activitypub/actors.js b/src/activitypub/actors.js index ccd5a9fb41..bda513661c 100644 --- a/src/activitypub/actors.js +++ b/src/activitypub/actors.js @@ -314,6 +314,7 @@ Actors.prune = async () => { let deletionCount = 0; let deletionCountNonExisting = 0; let notDeletedDueToLocalContent = 0; + const notDeletedUids = []; await batch.processArray(uids, async (uids) => { const exists = await db.exists(uids.map(uid => `userRemote:${uid}`)); @@ -339,11 +340,16 @@ Actors.prune = async () => { } } else { notDeletedDueToLocalContent += 1; + notDeletedUids.push(uid); } })); deletionCountNonExisting += uidsThatDontExist.length; await db.sortedSetRemove('usersRemote:lastCrawled', uidsThatDontExist); + // update timestamp in usersRemote:lastCrawled so we don't try to delete users + // with content over and over + const now = Date.now(); + await db.sortedSetAdd('usersRemote:lastCrawled', notDeletedUids.map(() => now), notDeletedUids); }, { batch: 50, interval: 1000, From 992109189f3695ad3b32e316b055145f88827874 Mon Sep 17 00:00:00 2001 From: Misty Release Bot Date: Thu, 6 Feb 2025 00:55:16 +0000 Subject: [PATCH 15/26] chore(i18n): fallback strings for new resources: nodebb.themes-harmony --- public/language/ar/themes/harmony.json | 2 ++ public/language/bg/themes/harmony.json | 2 ++ public/language/bn/themes/harmony.json | 2 ++ public/language/cs/themes/harmony.json | 2 ++ public/language/da/themes/harmony.json | 2 ++ public/language/de/themes/harmony.json | 2 ++ public/language/el/themes/harmony.json | 2 ++ public/language/en-US/themes/harmony.json | 2 ++ public/language/en-x-pirate/themes/harmony.json | 2 ++ public/language/es/themes/harmony.json | 2 ++ public/language/et/themes/harmony.json | 2 ++ public/language/fa-IR/themes/harmony.json | 2 ++ public/language/fi/themes/harmony.json | 2 ++ public/language/fr/themes/harmony.json | 2 ++ public/language/gl/themes/harmony.json | 2 ++ public/language/he/themes/harmony.json | 2 ++ public/language/hr/themes/harmony.json | 2 ++ public/language/hu/themes/harmony.json | 2 ++ public/language/hy/themes/harmony.json | 2 ++ public/language/id/themes/harmony.json | 2 ++ public/language/it/themes/harmony.json | 2 ++ public/language/ja/themes/harmony.json | 2 ++ public/language/ko/themes/harmony.json | 2 ++ public/language/lt/themes/harmony.json | 2 ++ public/language/lv/themes/harmony.json | 2 ++ public/language/ms/themes/harmony.json | 2 ++ public/language/nb/themes/harmony.json | 2 ++ public/language/nl/themes/harmony.json | 2 ++ public/language/nn-NO/themes/harmony.json | 2 ++ public/language/pl/themes/harmony.json | 2 ++ public/language/pt-BR/themes/harmony.json | 2 ++ public/language/pt-PT/themes/harmony.json | 2 ++ public/language/ro/themes/harmony.json | 2 ++ public/language/ru/themes/harmony.json | 2 ++ public/language/rw/themes/harmony.json | 2 ++ public/language/sc/themes/harmony.json | 2 ++ public/language/sk/themes/harmony.json | 2 ++ public/language/sl/themes/harmony.json | 2 ++ public/language/sq-AL/themes/harmony.json | 2 ++ public/language/sr/themes/harmony.json | 2 ++ public/language/sv/themes/harmony.json | 2 ++ public/language/th/themes/harmony.json | 2 ++ public/language/tr/themes/harmony.json | 2 ++ public/language/uk/themes/harmony.json | 2 ++ public/language/vi/themes/harmony.json | 2 ++ public/language/zh-CN/themes/harmony.json | 2 ++ public/language/zh-TW/themes/harmony.json | 2 ++ 47 files changed, 94 insertions(+) diff --git a/public/language/ar/themes/harmony.json b/public/language/ar/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/ar/themes/harmony.json +++ b/public/language/ar/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/bg/themes/harmony.json b/public/language/bg/themes/harmony.json index 27e0c320e1..0aa61b4924 100644 --- a/public/language/bg/themes/harmony.json +++ b/public/language/bg/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Показване на резюмета на темите на мобилни устройства", "settings.stickyToolbar": "Статична лента с инструменти", "settings.stickyToolbar.help": "Лентата с инструменти в страниците с теми и категории ще стои винаги в горния край на страницата", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Автоматично скриване на долната лента", "settings.autohideBottombar.help": "В изгледа за мобилни устройства долната лента ще се скрива, когато страницата се превърта надолу", "settings.openSidebars": "Отваряне на страничните ленти", diff --git a/public/language/bn/themes/harmony.json b/public/language/bn/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/bn/themes/harmony.json +++ b/public/language/bn/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/cs/themes/harmony.json b/public/language/cs/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/cs/themes/harmony.json +++ b/public/language/cs/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/da/themes/harmony.json b/public/language/da/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/da/themes/harmony.json +++ b/public/language/da/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/de/themes/harmony.json b/public/language/de/themes/harmony.json index 304a3ec023..b6f021d6cb 100644 --- a/public/language/de/themes/harmony.json +++ b/public/language/de/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Themen-Vorschau auf Mobilgeräten anzeigen", "settings.stickyToolbar": "Klebrige Toolbar", "settings.stickyToolbar.help": "Die Toolbar auf Themen- und Kategorieseiten bleibt oben an der Seite kleben", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Fußzeile automatisch verbergen", "settings.autohideBottombar.help": "Die Fußzeile wird auf Mobilgeräten versteckt, sobald nach unten gescrollt wird", "settings.openSidebars": "Seitennavigation öffnen", diff --git a/public/language/el/themes/harmony.json b/public/language/el/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/el/themes/harmony.json +++ b/public/language/el/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/en-US/themes/harmony.json b/public/language/en-US/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/en-US/themes/harmony.json +++ b/public/language/en-US/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/en-x-pirate/themes/harmony.json b/public/language/en-x-pirate/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/en-x-pirate/themes/harmony.json +++ b/public/language/en-x-pirate/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/es/themes/harmony.json b/public/language/es/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/es/themes/harmony.json +++ b/public/language/es/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/et/themes/harmony.json b/public/language/et/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/et/themes/harmony.json +++ b/public/language/et/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/fa-IR/themes/harmony.json b/public/language/fa-IR/themes/harmony.json index 4f0b0e7e95..69dfb3e60f 100644 --- a/public/language/fa-IR/themes/harmony.json +++ b/public/language/fa-IR/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "نمایش تیزرهای تاپیک در گوشی", "settings.stickyToolbar": "نوار ابزار چسبیده ", "settings.stickyToolbar.help": "نوار ابزار در تاپیک و صفحه دسته بدی ها در بالای صفحه ثابت می‌ماند", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "مخفی کردن اتوماتیک منوی پایینی ", "settings.autohideBottombar.help": "وقتی صفحه به پایین اسکرول می شود، منوی پایین در نمایش گوشی مخفی خواهد شد ", "settings.openSidebars": "Open sidebars", diff --git a/public/language/fi/themes/harmony.json b/public/language/fi/themes/harmony.json index ddd27c40fe..9d2db8a733 100644 --- a/public/language/fi/themes/harmony.json +++ b/public/language/fi/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Näytä aihe-ehdotukset mobiilinäkymässä", "settings.stickyToolbar": "Kiinteä työkalupalkki", "settings.stickyToolbar.help": "Aihe- ja kategoriasivujen työkalupalkki näytetään yläreunassa aina.", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Piilota alapalkki automaattisesti", "settings.autohideBottombar.help": "Mobiilinäykymän alapalkki piilotetaan kun sivua vieritetään alaspäin.", "settings.openSidebars": "Avaa sivupalkit", diff --git a/public/language/fr/themes/harmony.json b/public/language/fr/themes/harmony.json index eb122d9d02..d58d85cad7 100644 --- a/public/language/fr/themes/harmony.json +++ b/public/language/fr/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Afficher les teasers de sujet sur mobile", "settings.stickyToolbar": "Barre d'outils", "settings.stickyToolbar.help": "La barre d'outils sur les pages de sujets et de catégories restera en haut de la page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Masquer automatiquement la barre inférieure", "settings.autohideBottombar.help": "La barre inférieure sur mobile sera masquée lorsque la page défilera vers le bas", "settings.openSidebars": "Barres latérales ouvertes", diff --git a/public/language/gl/themes/harmony.json b/public/language/gl/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/gl/themes/harmony.json +++ b/public/language/gl/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/he/themes/harmony.json b/public/language/he/themes/harmony.json index 90675cc6bf..500a923904 100644 --- a/public/language/he/themes/harmony.json +++ b/public/language/he/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "הצגת טיזרים של נושאים בנייד", "settings.stickyToolbar": "הצמד את סרגל הכלים בעת גלילה", "settings.stickyToolbar.help": "סרגל הכלים בדפי נושאים וקטגוריות ייצמד לראש העמוד בעת גלילה", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "הסתרה אוטומטית של סרגל תחתון", "settings.autohideBottombar.help": "הסרגל התחתון בתצוגת הנייד יוסתר כאשר הדף ייגלל מטה", "settings.openSidebars": "פתח סרגלי צד", diff --git a/public/language/hr/themes/harmony.json b/public/language/hr/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/hr/themes/harmony.json +++ b/public/language/hr/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/hu/themes/harmony.json b/public/language/hu/themes/harmony.json index bee0ab5838..c6d48ad76a 100644 --- a/public/language/hu/themes/harmony.json +++ b/public/language/hu/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Oldalsáv nyitása", diff --git a/public/language/hy/themes/harmony.json b/public/language/hy/themes/harmony.json index 72b6b4166a..787a8d7ed5 100644 --- a/public/language/hy/themes/harmony.json +++ b/public/language/hy/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Ցույց տալ թեմայի թիզերները բջջայինով", "settings.stickyToolbar": "Կպչուն գործիքագոտի", "settings.stickyToolbar.help": "Թեմայի և կատեգորիայի էջերի գործիքագոտին կմնա էջի վերևում", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Ավտոմատ թաքցնել ներքևի բարը", "settings.autohideBottombar.help": "Բջջային դիտման ներքևի տողը կթաքցվի, երբ էջը ներքև իջացնեք", "settings.openSidebars": "Բացել կողքի տողերը", diff --git a/public/language/id/themes/harmony.json b/public/language/id/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/id/themes/harmony.json +++ b/public/language/id/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/it/themes/harmony.json b/public/language/it/themes/harmony.json index b63252bdaa..f52afb85ec 100644 --- a/public/language/it/themes/harmony.json +++ b/public/language/it/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Mostra le anteprime delle discussioni su mobile", "settings.stickyToolbar": "Barra degli strumenti adesiva", "settings.stickyToolbar.help": "La barra degli strumenti nelle pagine delle discussioni e delle categorie si attacca alla parte superiore della pagina.", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Nascondi automaticamente la barra inferiore", "settings.autohideBottombar.help": "La barra inferiore nella visualizzazione mobile sarà nascosta quando la pagina viene fatta scorrere verso il basso.", "settings.openSidebars": "Apri le barre laterali", diff --git a/public/language/ja/themes/harmony.json b/public/language/ja/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/ja/themes/harmony.json +++ b/public/language/ja/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/ko/themes/harmony.json b/public/language/ko/themes/harmony.json index e9b4b96845..a8d98525b6 100644 --- a/public/language/ko/themes/harmony.json +++ b/public/language/ko/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "모바일에서 토픽 미리보기 표시", "settings.stickyToolbar": "툴바 고정", "settings.stickyToolbar.help": "토픽 및 카테고리 페이지의 툴바가 페이지 상단에 고정됩니다.", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "하단 바 자동 숨기기", "settings.autohideBottombar.help": "모바일 뷰에서 페이지가 아래로 스크롤될 때 하단 막대가 숨겨집니다.", "settings.openSidebars": "사이드바 열기", diff --git a/public/language/lt/themes/harmony.json b/public/language/lt/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/lt/themes/harmony.json +++ b/public/language/lt/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/lv/themes/harmony.json b/public/language/lv/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/lv/themes/harmony.json +++ b/public/language/lv/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/ms/themes/harmony.json b/public/language/ms/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/ms/themes/harmony.json +++ b/public/language/ms/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/nb/themes/harmony.json b/public/language/nb/themes/harmony.json index 2c78382d54..bd6204cb1a 100644 --- a/public/language/nb/themes/harmony.json +++ b/public/language/nb/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Vis emneforhåndsvisninger på mobil", "settings.stickyToolbar": "Festet verktøylinje", "settings.stickyToolbar.help": "Verktøylinjen på emne- og kategorisider vil feste seg til toppen av siden", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Skjul bunnlinjen automatisk", "settings.autohideBottombar.help": "Bunnlinjen i mobilvisning skjules automatisk når siden rulles ned", "settings.openSidebars": "Åpne sidepaneler", diff --git a/public/language/nl/themes/harmony.json b/public/language/nl/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/nl/themes/harmony.json +++ b/public/language/nl/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/nn-NO/themes/harmony.json b/public/language/nn-NO/themes/harmony.json index ca69583fb2..d7d23b22a7 100644 --- a/public/language/nn-NO/themes/harmony.json +++ b/public/language/nn-NO/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Vis emneteasere på mobil", "settings.stickyToolbar": "Fast verktøylinje", "settings.stickyToolbar.help": "Gjer verktøylinja fast øvst på sida når du rullar.", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Gøym botnlinja automatisk", "settings.autohideBottombar.help": "Botnlinja vert automatisk gøymd når du rullar nedover.", "settings.openSidebars": "Opne sidefelt", diff --git a/public/language/pl/themes/harmony.json b/public/language/pl/themes/harmony.json index 829416ddeb..0a7a315138 100644 --- a/public/language/pl/themes/harmony.json +++ b/public/language/pl/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Pokazuj zwiastuny tematów na telefonie", "settings.stickyToolbar": "Przyklejaj pasek narzędziowy", "settings.stickyToolbar.help": "Pasek z narzędziami na stronach tematów i kategorii będzie przyklejony do góry strony", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Automatycznie chowaj dolny panel", "settings.autohideBottombar.help": "Dolny panel schowa się w widoku mobilnym, jeśli strona zostanie przesunięta w dół", "settings.openSidebars": "Otwórz panele boczne", diff --git a/public/language/pt-BR/themes/harmony.json b/public/language/pt-BR/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/pt-BR/themes/harmony.json +++ b/public/language/pt-BR/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/pt-PT/themes/harmony.json b/public/language/pt-PT/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/pt-PT/themes/harmony.json +++ b/public/language/pt-PT/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/ro/themes/harmony.json b/public/language/ro/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/ro/themes/harmony.json +++ b/public/language/ro/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/ru/themes/harmony.json b/public/language/ru/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/ru/themes/harmony.json +++ b/public/language/ru/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/rw/themes/harmony.json b/public/language/rw/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/rw/themes/harmony.json +++ b/public/language/rw/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/sc/themes/harmony.json b/public/language/sc/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/sc/themes/harmony.json +++ b/public/language/sc/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/sk/themes/harmony.json b/public/language/sk/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/sk/themes/harmony.json +++ b/public/language/sk/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/sl/themes/harmony.json b/public/language/sl/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/sl/themes/harmony.json +++ b/public/language/sl/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/sq-AL/themes/harmony.json b/public/language/sq-AL/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/sq-AL/themes/harmony.json +++ b/public/language/sq-AL/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/sr/themes/harmony.json b/public/language/sr/themes/harmony.json index 06eb4ec656..03c5638a6d 100644 --- a/public/language/sr/themes/harmony.json +++ b/public/language/sr/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Прикажи најавне теме на мобилном телефону", "settings.stickyToolbar": "Лепљива трака алата", "settings.stickyToolbar.help": "Трака алата на страницама са темама и категоријама ће бити на врху странице", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Аутоматско сакривање доње траке", "settings.autohideBottombar.help": "Доња трака у приказу за мобилне уређаје биће скривена када се страница помера надоле", "settings.openSidebars": "Open sidebars", diff --git a/public/language/sv/themes/harmony.json b/public/language/sv/themes/harmony.json index 14a2604e1c..797298e428 100644 --- a/public/language/sv/themes/harmony.json +++ b/public/language/sv/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/th/themes/harmony.json b/public/language/th/themes/harmony.json index 94bb567d0a..bd67eabcce 100644 --- a/public/language/th/themes/harmony.json +++ b/public/language/th/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "แสดงตัวอย่างเนื้อหากระทู้บนมือถือ", "settings.stickyToolbar": "แถบเครื่องมือแบบ sticky", "settings.stickyToolbar.help": "แถบเครื่องมือในหน้ากระทู้และหมวดหมู่จะอยู่ด้านบนสุดของหน้าเสมอ", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "ซ่อนแถบล่าง", "settings.autohideBottombar.help": "แถบล่างบนมือถือจะถูกซ่อนเมื่อเลื่อนหน้าลง", "settings.openSidebars": "เปิดแถบข้าง", diff --git a/public/language/tr/themes/harmony.json b/public/language/tr/themes/harmony.json index 524af6091f..b8f56c369a 100644 --- a/public/language/tr/themes/harmony.json +++ b/public/language/tr/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Başlık Önizlemelerini mobilde göster", "settings.stickyToolbar": "Yapışkan Araç Çubuğu", "settings.stickyToolbar.help": "Kategori ve konu sayfalarındaki araç çubuğu sayfanın üstünde sabitlenmiş şekilde kalacak", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Alttaki şeridi otomatik olarak gizle", "settings.autohideBottombar.help": "Sayfanın altındaki şerit sayfayı aşağıya doğru kaydırırken mobilde gizlenecek", "settings.openSidebars": "Yan menüleri aç", diff --git a/public/language/uk/themes/harmony.json b/public/language/uk/themes/harmony.json index 01038d7641..e3ba514912 100644 --- a/public/language/uk/themes/harmony.json +++ b/public/language/uk/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "Open sidebars", diff --git a/public/language/vi/themes/harmony.json b/public/language/vi/themes/harmony.json index 4f7b19c44e..a4740df89e 100644 --- a/public/language/vi/themes/harmony.json +++ b/public/language/vi/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Hiển thị đoạn giới thiệu chủ đề trên di động", "settings.stickyToolbar": "Thanh công cụ cố định", "settings.stickyToolbar.help": "Thanh công cụ trên các trang chủ đề và danh mục sẽ nằm ở đầu trang", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Tự động ẩn thanh dưới cùng", "settings.autohideBottombar.help": "Thanh dưới cùng trên chế độ xem di động sẽ ẩn khi trang được cuộn xuống", "settings.openSidebars": "Mở thanh bên", diff --git a/public/language/zh-CN/themes/harmony.json b/public/language/zh-CN/themes/harmony.json index 64cc85a607..dfba3d89d5 100644 --- a/public/language/zh-CN/themes/harmony.json +++ b/public/language/zh-CN/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "在移动设备显示话题预告", "settings.stickyToolbar": "附着工具条", "settings.stickyToolbar.help": "主题和类别页面上的工具条将附着在页面顶部", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "自动隐藏底栏", "settings.autohideBottombar.help": "当页面向下滚动时,移动设备视图的底栏将被隐藏", "settings.openSidebars": "打开侧栏", diff --git a/public/language/zh-TW/themes/harmony.json b/public/language/zh-TW/themes/harmony.json index bf12d4f6f0..2a04ca3420 100644 --- a/public/language/zh-TW/themes/harmony.json +++ b/public/language/zh-TW/themes/harmony.json @@ -13,6 +13,8 @@ "settings.mobileTopicTeasers": "Show topic teasers on mobile", "settings.stickyToolbar": "Sticky toolbar", "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", + "settings.topicSidebarTools": "Topic sidebar tools", + "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", "settings.autohideBottombar": "Auto hide bottom bar", "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", "settings.openSidebars": "打開側欄", From de5caf8f70722c6a00082d17b438dcb5dcc125a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Wed, 12 Feb 2025 19:32:40 -0500 Subject: [PATCH 16/26] chore: up harmony --- install/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index d5c3521217..aef5dc2ba7 100644 --- a/install/package.json +++ b/install/package.json @@ -108,7 +108,7 @@ "nodebb-plugin-spam-be-gone": "2.3.0", "nodebb-plugin-web-push": "0.7.2", "nodebb-rewards-essentials": "1.0.0", - "nodebb-theme-harmony": "2.0.19", + "nodebb-theme-harmony": "2.0.21", "nodebb-theme-lavender": "7.1.17", "nodebb-theme-peace": "2.2.38", "nodebb-theme-persona": "14.0.14", From df07fcfa5481a18abdf19c6817b82553724f1a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Wed, 12 Feb 2025 19:38:43 -0500 Subject: [PATCH 17/26] chore: up harmony --- install/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index aef5dc2ba7..5de8e827b4 100644 --- a/install/package.json +++ b/install/package.json @@ -108,7 +108,7 @@ "nodebb-plugin-spam-be-gone": "2.3.0", "nodebb-plugin-web-push": "0.7.2", "nodebb-rewards-essentials": "1.0.0", - "nodebb-theme-harmony": "2.0.21", + "nodebb-theme-harmony": "2.0.22", "nodebb-theme-lavender": "7.1.17", "nodebb-theme-peace": "2.2.38", "nodebb-theme-persona": "14.0.14", From d87247084364694d3d826859902284b59691c7d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Fri, 14 Feb 2025 10:25:59 -0500 Subject: [PATCH 18/26] refactor: cleanup ip:recent --- .../en-GB/admin/settings/advanced.json | 3 -- public/openapi/read/admin/dashboard.yaml | 2 + src/analytics.js | 47 +++++++------------ src/controllers/admin/dashboard.js | 4 +- src/views/admin/partials/dashboard/stats.tpl | 29 +++++++----- src/views/admin/settings/advanced.tpl | 14 ------ 6 files changed, 37 insertions(+), 62 deletions(-) diff --git a/public/language/en-GB/admin/settings/advanced.json b/public/language/en-GB/admin/settings/advanced.json index 982eaa2f64..fa1abbad0f 100644 --- a/public/language/en-GB/admin/settings/advanced.json +++ b/public/language/en-GB/admin/settings/advanced.json @@ -41,9 +41,6 @@ "sockets.default-placeholder": "Default: %1", "sockets.delay": "Reconnection Delay", - "analytics.settings": "Analytics Settings", - "analytics.max-cache": "Analytics Cache Max Value", - "analytics.max-cache-help": "On high-traffic installs, the cache could be exhausted continuously if there are more concurrent active users than the Max Cache value. (Restart required)", "compression.settings": "Compression Settings", "compression.enable": "Enable Compression", "compression.help": "This setting enables gzip compression. For a high-traffic website in production, the best way to put compression in place is to implement it at a reverse proxy level. You can enable it here for testing purposes." diff --git a/public/openapi/read/admin/dashboard.yaml b/public/openapi/read/admin/dashboard.yaml index a416d51b56..72f989b2b2 100644 --- a/public/openapi/read/admin/dashboard.yaml +++ b/public/openapi/read/admin/dashboard.yaml @@ -18,6 +18,8 @@ get: latestVersion: type: string nullable: true + hideAllTime: + type: boolean upgradeAvailable: type: boolean nullable: true diff --git a/src/analytics.js b/src/analytics.js index 49c987d52d..16ae85cea9 100644 --- a/src/analytics.js +++ b/src/analytics.js @@ -3,7 +3,6 @@ const cronJob = require('cron').CronJob; const winston = require('winston'); const nconf = require('nconf'); -const crypto = require('crypto'); const util = require('util'); const _ = require('lodash'); @@ -12,36 +11,24 @@ const sleep = util.promisify(setTimeout); const db = require('./database'); const utils = require('./utils'); const plugins = require('./plugins'); -const meta = require('./meta'); const pubsub = require('./pubsub'); -const cacheCreate = require('./cache/lru'); const Analytics = module.exports; -const secret = nconf.get('secret'); - let local = { counters: {}, pageViews: 0, pageViewsRegistered: 0, pageViewsGuest: 0, pageViewsBot: 0, - uniqueIPCount: 0, uniquevisitors: 0, }; const empty = _.cloneDeep(local); const total = _.cloneDeep(local); -let ipCache; - const runJobs = nconf.get('runJobs'); Analytics.init = async function () { - ipCache = cacheCreate({ - max: parseInt(meta.config['analytics:maxCache'], 10) || 500, - ttl: 0, - }); - new cronJob('*/10 * * * * *', (async () => { publishLocalAnalytics(); if (runJobs) { @@ -50,6 +37,14 @@ Analytics.init = async function () { } }), null, true); + if (runJobs) { + new cronJob('*/30 * * * *', (async () => { + const cutoff = Date.now() - 172800000; + const ips = await db.getSortedSetRangeByScore('ip:recent', 0, 500, '-inf', cutoff); + await db.sortedSetRemove('ip:recent', ips); + }), null, true); + } + if (runJobs) { pubsub.on('analytics:publish', (data) => { incrementProperties(total, data.local); @@ -106,22 +101,17 @@ Analytics.pageView = async function (payload) { } if (payload.ip) { - // Retrieve hash or calculate if not present - let hash = ipCache.get(payload.ip + secret); - if (!hash) { - hash = crypto.createHash('sha1').update(payload.ip + secret).digest('hex'); - ipCache.set(payload.ip + secret, hash); + const score = await db.sortedSetScore('ip:recent', payload.ip); + let record = !score; + if (score) { + const today = new Date(); + today.setHours(today.getHours(), 0, 0, 0); + record = score < today.getTime(); } - const score = await db.sortedSetScore('ip:recent', hash); - if (!score) { - local.uniqueIPCount += 1; - } - const today = new Date(); - today.setHours(today.getHours(), 0, 0, 0); - if (!score || score < today.getTime()) { + if (record) { local.uniquevisitors += 1; - await db.sortedSetAdd('ip:recent', Date.now(), hash); + await db.sortedSetAdd('ip:recent', Date.now(), payload.ip); } } }; @@ -176,11 +166,6 @@ Analytics.writeData = async function () { total.uniquevisitors = 0; } - if (total.uniqueIPCount > 0) { - dbQueue.push(db.incrObjectFieldBy('global', 'uniqueIPCount', total.uniqueIPCount)); - total.uniqueIPCount = 0; - } - for (const [key, value] of Object.entries(total.counters)) { incrByBulk.push([`analytics:${key}`, value, today.getTime()]); metrics.push(key); diff --git a/src/controllers/admin/dashboard.js b/src/controllers/admin/dashboard.js index 405a239aaf..d3bf019443 100644 --- a/src/controllers/admin/dashboard.js +++ b/src/controllers/admin/dashboard.js @@ -41,6 +41,7 @@ dashboardController.get = async function (req, res) { lastrestart: lastrestart, showSystemControls: isAdmin, popularSearches: popularSearches, + hideAllTime: true, }); }; @@ -128,7 +129,7 @@ async function getStats() { } let results = await Promise.all([ - getStatsFromAnalytics('uniquevisitors', 'uniqueIPCount'), + getStatsFromAnalytics('uniquevisitors', ''), getStatsFromAnalytics('logins', 'loginCount'), getStatsForSet('users:joindate', 'userCount'), getStatsForSet('posts:pid', 'postCount'), @@ -227,6 +228,7 @@ function calculateDeltas(results) { } async function getGlobalField(field) { + if (!field) return 0; const count = await db.getObjectField('global', field); return parseInt(count, 10) || 0; } diff --git a/src/views/admin/partials/dashboard/stats.tpl b/src/views/admin/partials/dashboard/stats.tpl index abd4f9cd31..e0b9910ea7 100644 --- a/src/views/admin/partials/dashboard/stats.tpl +++ b/src/views/admin/partials/dashboard/stats.tpl @@ -1,31 +1,33 @@
- - +
+ - - + + - - + + - - + + + {{{ if !hideAllTime}}} + {{{ end }}} - + {{{ each stats }}} - @@ -38,8 +40,9 @@ - + {{{ if !hideAllTime}}} + {{{ end }}} {{{ end }}} diff --git a/src/views/admin/settings/advanced.tpl b/src/views/admin/settings/advanced.tpl index 049942b2ee..2da5eddc4e 100644 --- a/src/views/admin/settings/advanced.tpl +++ b/src/views/admin/settings/advanced.tpl @@ -146,20 +146,6 @@
-
-
[[admin/settings/advanced:analytics.settings]]
- -
- - -

- [[admin/settings/advanced:analytics.max-cache-help]] -

-
-
- -
-
[[admin/settings/advanced:compression.settings]]
From 77dd6dd0e7e361eee376637d7b768cf62233f1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Fri, 14 Feb 2025 10:41:52 -0500 Subject: [PATCH 19/26] refactor: single remove --- src/analytics.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/analytics.js b/src/analytics.js index 16ae85cea9..45e8f698d9 100644 --- a/src/analytics.js +++ b/src/analytics.js @@ -39,9 +39,7 @@ Analytics.init = async function () { if (runJobs) { new cronJob('*/30 * * * *', (async () => { - const cutoff = Date.now() - 172800000; - const ips = await db.getSortedSetRangeByScore('ip:recent', 0, 500, '-inf', cutoff); - await db.sortedSetRemove('ip:recent', ips); + await db.sortedSetsRemoveRangeByScore(['ip:recent'], '-inf', Date.now() - 172800000); }), null, true); } From 04f51cc63a187f7bd2582f4c56d1cc118836ae0e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 14 Feb 2025 20:25:05 -0500 Subject: [PATCH 20/26] fix: change the passed-in notificatiom id for `notifyTagFollowers` to contain the list of matched tags fixes: #13087 --- src/topics/tags.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/topics/tags.js b/src/topics/tags.js index 4f2bc6dc97..9d4865122d 100644 --- a/src/topics/tags.js +++ b/src/topics/tags.js @@ -621,7 +621,7 @@ module.exports = function (Topics) { const notification = await notifications.create({ type: 'new-topic-with-tag', - nid: `new_topic:tid:${postData.topic.tid}:uid:${exceptUid}`, + nid: `new_topic:tags:${tags.join('.')}:tid:${postData.topic.tid}:uid:${exceptUid}`, bodyShort: bodyShort, bodyLong: postData.content, pid: postData.pid, From fa36609537180e47193c3155a7d75f5ed0ba73ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sat, 15 Feb 2025 12:15:54 -0500 Subject: [PATCH 21/26] chore: up deps --- install/package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/install/package.json b/install/package.json index 5de8e827b4..43e4ca648a 100644 --- a/install/package.json +++ b/install/package.json @@ -98,16 +98,16 @@ "mousetrap": "1.6.5", "multiparty": "4.2.3", "nconf": "0.12.1", - "nodebb-plugin-2factor": "7.5.8", - "nodebb-plugin-composer-default": "10.2.44", - "nodebb-plugin-dbsearch": "6.2.8", + "nodebb-plugin-2factor": "7.5.9", + "nodebb-plugin-composer-default": "10.2.45", + "nodebb-plugin-dbsearch": "6.2.9", "nodebb-plugin-emoji": "6.0.2", "nodebb-plugin-emoji-android": "4.1.1", - "nodebb-plugin-markdown": "13.0.0", + "nodebb-plugin-markdown": "13.1.0", "nodebb-plugin-mentions": "4.6.10", - "nodebb-plugin-spam-be-gone": "2.3.0", + "nodebb-plugin-spam-be-gone": "2.3.1", "nodebb-plugin-web-push": "0.7.2", - "nodebb-rewards-essentials": "1.0.0", + "nodebb-rewards-essentials": "1.0.1", "nodebb-theme-harmony": "2.0.22", "nodebb-theme-lavender": "7.1.17", "nodebb-theme-peace": "2.2.38", From f1da510f04f66db689d19396f1d485887ebf9147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sat, 15 Feb 2025 20:36:07 -0500 Subject: [PATCH 22/26] chore: up harmony --- install/package.json | 2 +- public/language/en-GB/themes/harmony.json | 5 +++-- src/socket.io/posts.js | 2 -- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/install/package.json b/install/package.json index 43e4ca648a..b8577ddb8a 100644 --- a/install/package.json +++ b/install/package.json @@ -108,7 +108,7 @@ "nodebb-plugin-spam-be-gone": "2.3.1", "nodebb-plugin-web-push": "0.7.2", "nodebb-rewards-essentials": "1.0.1", - "nodebb-theme-harmony": "2.0.22", + "nodebb-theme-harmony": "2.0.23", "nodebb-theme-lavender": "7.1.17", "nodebb-theme-peace": "2.2.38", "nodebb-theme-persona": "14.0.14", diff --git a/public/language/en-GB/themes/harmony.json b/public/language/en-GB/themes/harmony.json index e3ba514912..727a1b0553 100644 --- a/public/language/en-GB/themes/harmony.json +++ b/public/language/en-GB/themes/harmony.json @@ -15,8 +15,9 @@ "settings.stickyToolbar.help": "The toolbar on topic and category pages will stick to the top of the page", "settings.topicSidebarTools": "Topic sidebar tools", "settings.topicSidebarTools.help": "This option will move the topic tools to the sidebar on desktop", - "settings.autohideBottombar": "Auto hide bottom bar", - "settings.autohideBottombar.help": "The bottom bar on mobile view will be hidden when the page is scrolled down", + "settings.autohideBottombar": "Auto hide mobile navigation bar", + "settings.autohideBottombar.help": "The mobile bar will be hidden when the page is scrolled down", + "settings.topMobilebar": "Move the mobile navigation bar to the top", "settings.openSidebars": "Open sidebars", "settings.chatModals": "Enable chat modals" } \ No newline at end of file diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index a684d95783..d6833e363a 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -28,8 +28,6 @@ SocketPosts.getRawPost = async function (socket, pid) { }; SocketPosts.getPostSummaryByIndex = async function (socket, data) { - sockets.warnDeprecated(socket, 'GET /api/v3/posts/byIndex/:index/summary?tid=:tid'); - if (data.index < 0) { data.index = 0; } From ef2c606dcb8b12c91a36f710b2519aa556d76f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sat, 15 Feb 2025 21:02:25 -0500 Subject: [PATCH 23/26] chore: up harmony --- install/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index b8577ddb8a..4149e23861 100644 --- a/install/package.json +++ b/install/package.json @@ -108,7 +108,7 @@ "nodebb-plugin-spam-be-gone": "2.3.1", "nodebb-plugin-web-push": "0.7.2", "nodebb-rewards-essentials": "1.0.1", - "nodebb-theme-harmony": "2.0.23", + "nodebb-theme-harmony": "2.0.24", "nodebb-theme-lavender": "7.1.17", "nodebb-theme-peace": "2.2.38", "nodebb-theme-persona": "14.0.14", From 0fed9a76c0fd6c0870b34af64093c2845b90cefa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sat, 15 Feb 2025 21:15:28 -0500 Subject: [PATCH 24/26] chore: up harmony --- install/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index 4149e23861..ee8ba84e8a 100644 --- a/install/package.json +++ b/install/package.json @@ -108,7 +108,7 @@ "nodebb-plugin-spam-be-gone": "2.3.1", "nodebb-plugin-web-push": "0.7.2", "nodebb-rewards-essentials": "1.0.1", - "nodebb-theme-harmony": "2.0.24", + "nodebb-theme-harmony": "2.0.25", "nodebb-theme-lavender": "7.1.17", "nodebb-theme-peace": "2.2.38", "nodebb-theme-persona": "14.0.14", From d936d5c073c1f06781e3c3bf4d503ee6512e72bf Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Sun, 16 Feb 2025 14:27:57 -0500 Subject: [PATCH 25/26] fix: logic failure causing remote posts with image to not parse properly, #13164 --- src/activitypub/mocks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/activitypub/mocks.js b/src/activitypub/mocks.js index 493655c272..003d392333 100644 --- a/src/activitypub/mocks.js +++ b/src/activitypub/mocks.js @@ -190,7 +190,7 @@ Mocks.post = async (objects) => { } switch (true) { - case image && image.hasOwnProperty('url') && image.url: { + case image && image.hasOwnProperty('url') && !!image.url: { image = image.url; break; } From 33d7b9b3ab58382d979b93b3155a87485170fa58 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Sun, 16 Feb 2025 14:48:44 -0500 Subject: [PATCH 26/26] fix: clear parsed post cache when updating a post's attachments, #13164 --- src/posts/attachments.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/posts/attachments.js b/src/posts/attachments.js index 3683aa0de4..99aece3010 100644 --- a/src/posts/attachments.js +++ b/src/posts/attachments.js @@ -63,6 +63,7 @@ Attachments.update = async (pid, attachments) => { await Promise.all([ db.setObjectBulk(bulkOps.hash), db.setObjectField(`post:${pid}`, 'attachments', hashes.join(',')), + posts.clearCachedPost(pid), ]); };
[[admin/dashboard:stats.yesterday]][[admin/dashboard:stats.today]][[admin/dashboard:stats.yesterday]][[admin/dashboard:stats.today]] [[admin/dashboard:stats.last-week]][[admin/dashboard:stats.this-week]][[admin/dashboard:stats.last-week]][[admin/dashboard:stats.this-week]] [[admin/dashboard:stats.last-month]][[admin/dashboard:stats.this-month]][[admin/dashboard:stats.last-month]][[admin/dashboard:stats.this-month]] [[admin/dashboard:stats.all]]
- + + {{{ if ./href }}} {./name} {{{ else }}} {./name} {{{ end }}} - + {formattedNumber(./yesterday)} {formattedNumber(./today)}{formattedNumber(./lastmonth)} {formattedNumber(./thismonth)} {./monthIncrease}%{formattedNumber(./alltime)}