mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-05-07 04:06:17 +02:00
fix: #14147, dont create wrong backlinks
syncBacklinks expects raw post content, html was passed to it from onNewPost since it was switched to use getPostSummary
backlinkRegex was matching ${nconf.get('url')}/topic/1aef954c-d0dc-45cf-acf2-e3a59f6cc134/foo and return tid=1 instead of the uuid
remove useless if check in syncBacklinks
fixed parseInts on tids
current - remove are both arrays use .length
This commit is contained in:
@@ -259,14 +259,14 @@ module.exports = function (Topics) {
|
||||
return postData;
|
||||
};
|
||||
|
||||
async function onNewPost({ pid, tid, uid: postOwner }, { uid, handle }) {
|
||||
async function onNewPost({ pid, tid, content, uid: postOwner }, { uid, handle }) {
|
||||
const [[postData], [userInfo]] = await Promise.all([
|
||||
posts.getPostSummaryByPids([pid], uid, { extraFields: ['attachments'] }),
|
||||
posts.getUserInfoForPosts([postOwner], uid),
|
||||
]);
|
||||
await Promise.all([
|
||||
Topics.addParentPosts([postData], uid),
|
||||
Topics.syncBacklinks(postData),
|
||||
Topics.syncBacklinks({ ...postData, content }),
|
||||
Topics.markAsRead([tid], uid),
|
||||
]);
|
||||
if (utils.isNumber(postOwner) && postData.category.cid === -1) {
|
||||
|
||||
@@ -14,7 +14,7 @@ const plugins = require('../plugins');
|
||||
const utils = require('../utils');
|
||||
const privileges = require('../privileges');
|
||||
|
||||
const backlinkRegex = new RegExp(`(?:${nconf.get('url').replace('/', '\\/')}|\b|\\s)\\/topic\\/(\\d+)(?:\\/\\w+)?`, 'g');
|
||||
const backlinkRegex = new RegExp(`(?:${nconf.get('url').replace('/', '\\/')}|\b|\\s)\\/topic\\/([a-fA-F0-9-]+)(?=\\/|$|\\s)?`, 'g');
|
||||
|
||||
module.exports = function (Topics) {
|
||||
Topics.onNewPostMade = async function (postData) {
|
||||
@@ -447,29 +447,27 @@ module.exports = function (Topics) {
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
}
|
||||
|
||||
|
||||
let { content } = postData;
|
||||
let { pid, uid, content } = postData;
|
||||
// ignore lines that start with `>`
|
||||
content = (content || '').split('\n').filter(line => !line.trim().startsWith('>')).join('\n');
|
||||
// Scan post content for topic links
|
||||
const matches = [...content.matchAll(backlinkRegex)];
|
||||
if (!matches) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const { pid, uid, tid } = postData;
|
||||
let add = _.uniq(matches.map(match => match[1]).map(tid => parseInt(tid, 10)));
|
||||
let add = _.uniq(matches.map(match => match[1]));
|
||||
|
||||
const now = Date.now();
|
||||
const topicsExist = await Topics.exists(add);
|
||||
const current = (await db.getSortedSetMembers(`pid:${pid}:backlinks`)).map(tid => parseInt(tid, 10));
|
||||
const [topicsExist, current] = await Promise.all([
|
||||
Topics.exists(add),
|
||||
db.getSortedSetMembers(`pid:${pid}:backlinks`),
|
||||
]);
|
||||
const remove = current.filter(tid => !add.includes(tid));
|
||||
add = add.filter((_tid, idx) => topicsExist[idx] && !current.includes(_tid) && tid !== _tid);
|
||||
const postTid = String(postData.tid);
|
||||
add = add.filter((_tid, idx) => topicsExist[idx] && !current.includes(_tid) && postTid !== _tid);
|
||||
|
||||
// Remove old backlinks
|
||||
await db.sortedSetRemove(`pid:${pid}:backlinks`, remove);
|
||||
|
||||
// Add new backlinks
|
||||
const now = Date.now();
|
||||
await db.sortedSetAdd(`pid:${pid}:backlinks`, add.map(() => now), add);
|
||||
await Promise.all(add.map(async (tid) => {
|
||||
await Topics.events.log(tid, {
|
||||
@@ -479,6 +477,6 @@ module.exports = function (Topics) {
|
||||
});
|
||||
}));
|
||||
|
||||
return add.length + (current - remove);
|
||||
return add.length + (current.length - remove.length);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1152,12 +1152,10 @@ describe('Post\'s', () => {
|
||||
|
||||
describe('.syncBacklinks()', () => {
|
||||
it('should error on invalid data', async () => {
|
||||
try {
|
||||
await topics.syncBacklinks();
|
||||
} catch (e) {
|
||||
assert(e);
|
||||
assert.strictEqual(e.message, '[[error:invalid-data]]');
|
||||
}
|
||||
await assert.rejects(
|
||||
topics.syncBacklinks(),
|
||||
{ message: '[[error:invalid-data]]' },
|
||||
);
|
||||
});
|
||||
|
||||
it('should do nothing if the post does not contain a link to a topic', async () => {
|
||||
@@ -1192,9 +1190,7 @@ describe('Post\'s', () => {
|
||||
const backlinks = await db.getSortedSetMembers('pid:2:backlinks');
|
||||
|
||||
assert.strictEqual(count, 0);
|
||||
assert(events);
|
||||
assert.strictEqual(events.length, 1);
|
||||
assert(backlinks);
|
||||
assert.strictEqual(backlinks.length, 0);
|
||||
});
|
||||
|
||||
@@ -1219,6 +1215,17 @@ describe('Post\'s', () => {
|
||||
assert(backlinks);
|
||||
assert.strictEqual(backlinks.length, 0);
|
||||
});
|
||||
|
||||
it('should not create a wrong backlink to topic/1 with AP topic url', async () => {
|
||||
const { postData } = await topics.post({
|
||||
uid: 1,
|
||||
cid,
|
||||
title: 'Topic backlink testing - topic 2',
|
||||
content: `testing ${nconf.get('url')}/topic/1aef954c-d0dc-45cf-acf2-e3a59f6cc134/foo`,
|
||||
});
|
||||
const backlinks = await db.getSortedSetMembers(`pid:${postData.pid}:backlinks`);
|
||||
assert.strictEqual(backlinks.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('integration tests', () => {
|
||||
|
||||
Reference in New Issue
Block a user