From a46324d0793265ef755f79b4b5e1b422003f9759 Mon Sep 17 00:00:00 2001 From: Dachi Date: Thu, 5 Sep 2024 08:47:02 -0700 Subject: [PATCH 1/3] fixed my issue --- dump.rdb | Bin 0 -> 31580 bytes src/topics/tags.js | 122 ++++++++++++++++++++++----------------------- test/topics.js | 30 +++++++++++ 3 files changed, 90 insertions(+), 62 deletions(-) create mode 100644 dump.rdb diff --git a/dump.rdb b/dump.rdb new file mode 100644 index 0000000000000000000000000000000000000000..d4182c2704a257be95a6fa6e6d7a0d54d2ba94b2 GIT binary patch literal 31580 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

rlXZ3Gs~^&|`CM?~9s=q>uM+(vB35 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 literal 0 HcmV?d00001 diff --git a/src/topics/tags.js b/src/topics/tags.js index daab4e5f77..5f3068a04d 100644 --- a/src/topics/tags.js +++ b/src/topics/tags.js @@ -18,20 +18,25 @@ const batch = require('../batch'); const cache = require('../cache'); module.exports = function (Topics) { + console.log('dcharkvi') Topics.createTags = async function (tags, tid, timestamp) { if (!Array.isArray(tags) || !tags.length) { return; } - const cid = await Topics.getTopicField(tid, 'cid'); - const topicSets = tags.map(tag => `tag:${tag}:topics`).concat( - tags.map(tag => `cid:${cid}:tag:${tag}:topics`) - ); + const topicSets = generateTopicSets(tags, cid); await db.sortedSetsAdd(topicSets, timestamp, tid); await Topics.updateCategoryTagsCount([cid], tags); - await Promise.all(tags.map(updateTagCount)); + await updateTagCountsForAll(tags); }; - + function generateTopicSets(tags, cid) { + return tags.map(tag => `tag:${tag}:topics`).concat( + tags.map(tag => `cid:${cid}:tag:${tag}:topics`) + ); + } + async function updateTagCountsForAll(tags) { + await Promise.all(tags.map(updateTagCount)); + } Topics.filterTags = async function (tags, cid) { const result = await plugins.hooks.fire('filter:tags.filter', { tags: tags, cid: cid }); tags = _.uniq(result.tags) @@ -65,36 +70,42 @@ module.exports = function (Topics) { cids.map(cid => `cid:${cid}:tags`), '-inf', 0 ); }; - + console.log("dcharkvi") Topics.validateTags = async function (tags, cid, uid, tid = null) { if (!Array.isArray(tags)) { throw new Error('[[error:invalid-data]]'); } tags = _.uniq(tags); - const [categoryData, isPrivileged, currentTags] = await Promise.all([ + const [categoryData, isPrivileged, currentTags] = await getValidationData(tags, cid, uid, tid); + validateTagCount(tags, categoryData); + await validateSystemTags(tags, currentTags, isPrivileged); + }; + async function getValidationData(tags, cid, uid, tid) { + return await Promise.all([ categories.getCategoryFields(cid, ['minTags', 'maxTags']), user.isPrivileged(uid), tid ? Topics.getTopicTags(tid) : [], ]); + } + function validateTagCount(tags, categoryData) { if (tags.length < parseInt(categoryData.minTags, 10)) { throw new Error(`[[error:not-enough-tags, ${categoryData.minTags}]]`); } else if (tags.length > parseInt(categoryData.maxTags, 10)) { throw new Error(`[[error:too-many-tags, ${categoryData.maxTags}]]`); } - + } + async function validateSystemTags(tags, currentTags, isPrivileged) { const addedTags = tags.filter(tag => !currentTags.includes(tag)); const removedTags = currentTags.filter(tag => !tags.includes(tag)); - const systemTags = (meta.config.systemTags || '').split(','); - - if (!isPrivileged && systemTags.length && addedTags.length && addedTags.some(tag => systemTags.includes(tag))) { + const systemTags = (meta.config.systemTags || '').split(',').map(tag => tag.trim()).filter(Boolean); + if (!isPrivileged && systemTags.length && addedTags.some(tag => systemTags.includes(tag))) { throw new Error('[[error:cant-use-system-tag]]'); } - - if (!isPrivileged && systemTags.length && removedTags.length && removedTags.some(tag => systemTags.includes(tag))) { + if (!isPrivileged && systemTags.length && removedTags.some(tag => systemTags.includes(tag))) { throw new Error('[[error:cant-remove-system-tag]]'); } - }; - + } + console.log('dcharkvi') async function filterCategoryTags(tags, cid) { const tagWhitelist = await categories.getTagWhitelist([cid]); if (!Array.isArray(tagWhitelist[0]) || !tagWhitelist[0].length) { @@ -103,7 +114,6 @@ module.exports = function (Topics) { const whitelistSet = new Set(tagWhitelist[0]); return tags.filter(tag => whitelistSet.has(tag)); } - Topics.createEmptyTag = async function (tag) { if (!tag) { throw new Error('[[error:invalid-tag]]'); @@ -124,67 +134,55 @@ module.exports = function (Topics) { .map(cid => ([`cid:${cid}:tags`, 0, tag])); await db.sortedSetAddBulk(bulkAdd); }; - + console.log('dcharkvi') Topics.renameTags = async function (data) { - for (const tagData of data) { - // eslint-disable-next-line no-await-in-loop - await renameTag(tagData.value, tagData.newName); - } + await Promise.all(data.map(tagData => renameTag(tagData.value, tagData.newName))); }; - async function renameTag(tag, newTagName) { if (!newTagName || tag === newTagName) { return; } newTagName = utils.cleanUpTag(newTagName, meta.config.maximumTagLength); - await Topics.createEmptyTag(newTagName); + const allCids = await processTagForAllTids(tag, newTagName); + await Topics.updateCategoryTagsCount(Object.keys(allCids), [newTagName]); + await updateTagCount(newTagName); + } + console.log('dcharkvi') + async function processTagForAllTids(tag, newTagName) { const allCids = {}; - await batch.processSortedSet(`tag:${tag}:topics`, async (tids) => { const topicData = await Topics.getTopicsFields(tids, ['tid', 'cid', 'tags']); const cids = topicData.map(t => t.cid); topicData.forEach((t) => { allCids[t.cid] = true; }); const scores = await db.sortedSetScores(`tag:${tag}:topics`, tids); - // update tag::topics - await db.sortedSetAdd(`tag:${newTagName}:topics`, scores, tids); - await db.sortedSetRemove(`tag:${tag}:topics`, tids); - - // update cid::tag::topics - await db.sortedSetAddBulk(topicData.map( - (t, index) => [`cid:${t.cid}:tag:${newTagName}:topics`, scores[index], t.tid] - )); - await db.sortedSetRemove(cids.map(cid => `cid:${cid}:tag:${tag}:topics`), tids); - - // update 'tags' field in topic hash - topicData.forEach((topic) => { - topic.tags = topic.tags.map(tagItem => tagItem.value); - const index = topic.tags.indexOf(tag); - if (index !== -1) { - topic.tags.splice(index, 1, newTagName); - } - }); - await db.setObjectBulk( - topicData.map(t => [`topic:${t.tid}`, { tags: t.tags.join(',') }]), - ); + await updateTagTopics(newTagName, tag, scores, tids, topicData, cids); }, {}); - const followers = await db.getSortedSetRangeWithScores(`tag:${tag}:followers`, 0, -1); - if (followers.length) { - const userKeys = followers.map(item => `uid:${item.value}:followed_tags`); - const scores = await db.sortedSetsScore(userKeys, tag); - await db.sortedSetsRemove(userKeys, tag); - await db.sortedSetsAdd(userKeys, scores, newTagName); - await db.sortedSetAdd( - `tag:${newTagName}:followers`, - followers.map(item => item.score), - followers.map(item => item.value), - ); - } - await Topics.deleteTag(tag); - await updateTagCount(newTagName); - await Topics.updateCategoryTagsCount(Object.keys(allCids), [newTagName]); + return allCids; + } + async function updateTagTopics(newTagName, tag, scores, tids, topicData, cids) { + await db.sortedSetAdd(`tag:${newTagName}:topics`, scores, tids); + await db.sortedSetRemove(`tag:${tag}:topics`, tids); + // Update cid::tag::topics + await db.sortedSetAddBulk(topicData.map( + (t, index) => [`cid:${t.cid}:tag:${newTagName}:topics`, scores[index], t.tid] + )); + await db.sortedSetRemove(cids.map(cid => `cid:${cid}:tag:${tag}:topics`), tids); + // Update 'tags' field in topic hash + await updateTopicHashTags(tids, topicData, tag, newTagName); + } + async function updateTopicHashTags(tids, topicData, oldTag, newTag) { + topicData.forEach((topic) => { + topic.tags = topic.tags.map(tagItem => tagItem.value); + const index = topic.tags.indexOf(oldTag); + if (index !== -1) { + topic.tags.splice(index, 1, newTag); + } + }); + await db.setObjectBulk( + topicData.map(t => [`topic:${t.tid}`, { tags: t.tags.join(',') }]), + ); } - async function updateTagCount(tag) { const count = await Topics.getTagTopicCount(tag); await db.sortedSetAdd('tags:topic:count', count || 0, tag); diff --git a/test/topics.js b/test/topics.js index 8a32e445f5..f2da7033d3 100644 --- a/test/topics.js +++ b/test/topics.js @@ -2503,6 +2503,36 @@ describe('Topic\'s', () => { const score = await db.sortedSetScore('topics:scheduled', topicData.tid); assert(!score); }); + + it('should throw an error when tags is not an array', (done) => { + const invalidTags = 'notAnArray'; + const cid = 1; + const uid = 1; + topics.validateTags(invalidTags, cid, uid) + .then(() => { + done(new Error('Test failed: Expected an error to be thrown')); + }) + .catch((err) => { + try { + assert.equal(err.message, '[[error:invalid-data]]'); + done(); + } catch (assertionErr) { + done(assertionErr); + } + }); + }); + + it('should do nothing if newTagName is null or the same as tag', (done) => { + const tag = 'existingTag'; + const newTagName = tag; + topics.renameTags([{ value: tag, newName: newTagName }]) + .then(() => { + done(); + }) + .catch((err) => { + done(new Error(`Test failed: Unexpected error was thrown - ${err.message}`)); + }); + }); }); }); From 9e34d336e7790abb78a542eadee8fee6443102d6 Mon Sep 17 00:00:00 2001 From: Dachi Date: Thu, 5 Sep 2024 08:59:55 -0700 Subject: [PATCH 2/3] fixed lint issues --- src/topics/tags.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/topics/tags.js b/src/topics/tags.js index 5f3068a04d..854f8019e9 100644 --- a/src/topics/tags.js +++ b/src/topics/tags.js @@ -18,7 +18,7 @@ const batch = require('../batch'); const cache = require('../cache'); module.exports = function (Topics) { - console.log('dcharkvi') + console.log('dcharkvi'); Topics.createTags = async function (tags, tid, timestamp) { if (!Array.isArray(tags) || !tags.length) { return; @@ -70,7 +70,7 @@ module.exports = function (Topics) { cids.map(cid => `cid:${cid}:tags`), '-inf', 0 ); }; - console.log("dcharkvi") + console.log('dcharkvi'); Topics.validateTags = async function (tags, cid, uid, tid = null) { if (!Array.isArray(tags)) { throw new Error('[[error:invalid-data]]'); @@ -105,7 +105,7 @@ module.exports = function (Topics) { throw new Error('[[error:cant-remove-system-tag]]'); } } - console.log('dcharkvi') + console.log('dcharkvi'); async function filterCategoryTags(tags, cid) { const tagWhitelist = await categories.getTagWhitelist([cid]); if (!Array.isArray(tagWhitelist[0]) || !tagWhitelist[0].length) { @@ -134,7 +134,7 @@ module.exports = function (Topics) { .map(cid => ([`cid:${cid}:tags`, 0, tag])); await db.sortedSetAddBulk(bulkAdd); }; - console.log('dcharkvi') + console.log('dcharkvi'); Topics.renameTags = async function (data) { await Promise.all(data.map(tagData => renameTag(tagData.value, tagData.newName))); }; @@ -148,7 +148,7 @@ module.exports = function (Topics) { await Topics.updateCategoryTagsCount(Object.keys(allCids), [newTagName]); await updateTagCount(newTagName); } - console.log('dcharkvi') + console.log('dcharkvi'); async function processTagForAllTids(tag, newTagName) { const allCids = {}; await batch.processSortedSet(`tag:${tag}:topics`, async (tids) => { From 0fd0cd0718ec4abe7983161be20ddb6d8f82ad80 Mon Sep 17 00:00:00 2001 From: Dachi Date: Thu, 5 Sep 2024 09:16:10 -0700 Subject: [PATCH 3/3] corrected log locations --- src/topics/tags.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/topics/tags.js b/src/topics/tags.js index 854f8019e9..db4ba219fb 100644 --- a/src/topics/tags.js +++ b/src/topics/tags.js @@ -18,8 +18,8 @@ const batch = require('../batch'); const cache = require('../cache'); module.exports = function (Topics) { - console.log('dcharkvi'); Topics.createTags = async function (tags, tid, timestamp) { + console.log('dcharkvi'); if (!Array.isArray(tags) || !tags.length) { return; } @@ -30,11 +30,13 @@ module.exports = function (Topics) { await updateTagCountsForAll(tags); }; function generateTopicSets(tags, cid) { + console.log('dcharkvi'); return tags.map(tag => `tag:${tag}:topics`).concat( tags.map(tag => `cid:${cid}:tag:${tag}:topics`) ); } async function updateTagCountsForAll(tags) { + console.log('dcharkvi'); await Promise.all(tags.map(updateTagCount)); } Topics.filterTags = async function (tags, cid) { @@ -70,8 +72,8 @@ module.exports = function (Topics) { cids.map(cid => `cid:${cid}:tags`), '-inf', 0 ); }; - console.log('dcharkvi'); Topics.validateTags = async function (tags, cid, uid, tid = null) { + console.log('dcharkvi'); if (!Array.isArray(tags)) { throw new Error('[[error:invalid-data]]'); } @@ -105,7 +107,6 @@ module.exports = function (Topics) { throw new Error('[[error:cant-remove-system-tag]]'); } } - console.log('dcharkvi'); async function filterCategoryTags(tags, cid) { const tagWhitelist = await categories.getTagWhitelist([cid]); if (!Array.isArray(tagWhitelist[0]) || !tagWhitelist[0].length) { @@ -134,11 +135,12 @@ module.exports = function (Topics) { .map(cid => ([`cid:${cid}:tags`, 0, tag])); await db.sortedSetAddBulk(bulkAdd); }; - console.log('dcharkvi'); Topics.renameTags = async function (data) { + console.log('dcharkvi'); await Promise.all(data.map(tagData => renameTag(tagData.value, tagData.newName))); }; async function renameTag(tag, newTagName) { + console.log('dcharkvi'); if (!newTagName || tag === newTagName) { return; } @@ -148,7 +150,6 @@ module.exports = function (Topics) { await Topics.updateCategoryTagsCount(Object.keys(allCids), [newTagName]); await updateTagCount(newTagName); } - console.log('dcharkvi'); async function processTagForAllTids(tag, newTagName) { const allCids = {}; await batch.processSortedSet(`tag:${tag}:topics`, async (tids) => {