fix: #13375, plus additional tests

This commit is contained in:
Julian Lam
2025-05-13 13:59:34 -04:00
parent 30db15836b
commit fe13c75549
3 changed files with 72 additions and 47 deletions

View File

@@ -41,6 +41,7 @@ inbox.create = async (req) => {
return await activitypub.notes.assertPrivate(object); return await activitypub.notes.assertPrivate(object);
} }
// Category sync, remove when cross-posting available
const { cids } = await activitypub.actors.getLocalFollowers(actor); const { cids } = await activitypub.actors.getLocalFollowers(actor);
let cid = null; let cid = null;
if (cids.size > 0) { if (cids.size > 0) {
@@ -262,12 +263,19 @@ inbox.announce = async (req) => {
let tid; let tid;
let pid; let pid;
// Category sync, remove when cross-posting available
const { cids } = await activitypub.actors.getLocalFollowers(actor); const { cids } = await activitypub.actors.getLocalFollowers(actor);
let cid = null; let cid = null;
if (cids.size > 0) { if (cids.size > 0) {
cid = Array.from(cids)[0]; cid = Array.from(cids)[0];
} }
// 1b12 announce
const categoryActor = await categories.exists(actor);
if (categoryActor) {
cid = actor;
}
switch(true) { switch(true) {
case object.type === 'Like': { case object.type === 'Like': {
const id = object.object.id || object.object; const id = object.object.id || object.object;
@@ -318,13 +326,7 @@ inbox.announce = async (req) => {
} }
} }
// Handle case where Announce(Create(Note-ish)) is received pid = object.id;
if (object.type === 'Create' && activitypub._constants.acceptedPostTypes.includes(object.object.type)) {
pid = object.object.id;
} else {
pid = object.id;
}
pid = await activitypub.resolveId(0, pid); // in case wrong id is passed-in; unlikely, but still. pid = await activitypub.resolveId(0, pid); // in case wrong id is passed-in; unlikely, but still.
if (!pid) { if (!pid) {
return; return;

View File

@@ -115,24 +115,18 @@ Notes.assert = async (uid, input, options = { skipChecks: false }) => {
if (hasTid) { if (hasTid) {
mainPid = await topics.getTopicField(tid, 'mainPid'); mainPid = await topics.getTopicField(tid, 'mainPid');
} else { } else {
// Check recipients/audience for category (local or remote) // Check recipients/audience for local category
const set = activitypub.helpers.makeSet(_activitypub, ['to', 'cc', 'audience']); const set = activitypub.helpers.makeSet(_activitypub, ['to', 'cc', 'audience']);
await activitypub.actors.assert(Array.from(set)); await activitypub.actors.assert(Array.from(set));
// Local
const resolved = await Promise.all(Array.from(set).map(async id => await activitypub.helpers.resolveLocalId(id))); const resolved = await Promise.all(Array.from(set).map(async id => await activitypub.helpers.resolveLocalId(id)));
const recipientCids = resolved const recipientCids = resolved
.filter(Boolean) .filter(Boolean)
.filter(({ type }) => type === 'category') .filter(({ type }) => type === 'category')
.map(obj => obj.id); .map(obj => obj.id);
// Remote if (recipientCids.length) {
const assertedGroups = await db.exists(Array.from(set).map(id => `categoryRemote:${id}`));
const remoteCid = Array.from(set).filter((_, idx) => assertedGroups[idx]).shift();
if (remoteCid || recipientCids.length) {
// Overrides passed-in value, respect addressing from main post over booster // Overrides passed-in value, respect addressing from main post over booster
options.cid = remoteCid || recipientCids.shift(); options.cid = recipientCids.shift();
} }
// mainPid ok to leave as-is // mainPid ok to leave as-is

View File

@@ -83,33 +83,6 @@ describe('Notes', () => {
assert.strictEqual(topic.cid, cid); assert.strictEqual(topic.cid, cid);
}); });
it('should slot newly created topic in remote category if addressed', async () => {
const { id: cid, actor } = helpers.mocks.group();
await activitypub.actors.assertGroup([cid]);
const { id } = helpers.mocks.note({
cc: [cid],
});
const assertion = await activitypub.notes.assert(0, id);
assert(assertion);
const { tid, count } = assertion;
assert(tid);
assert.strictEqual(count, 1);
const topic = await topics.getTopicData(tid);
assert.strictEqual(topic.cid, cid);
const tids = await db.getSortedSetMembers(`cid:${cid}:tids`);
assert(tids.includes(tid));
const category = await categories.getCategoryData(cid);
['topic_count', 'post_count', 'totalPostCount', 'totalTopicCount'].forEach((prop) => {
assert.strictEqual(category[prop], 1);
});
});
it('should add a remote category topic to a user\'s inbox if they are following the category', async () => { it('should add a remote category topic to a user\'s inbox if they are following the category', async () => {
const { id: cid, actor } = helpers.mocks.group(); const { id: cid, actor } = helpers.mocks.group();
await activitypub.actors.assertGroup([cid]); await activitypub.actors.assertGroup([cid]);
@@ -120,7 +93,7 @@ describe('Notes', () => {
const { id } = helpers.mocks.note({ const { id } = helpers.mocks.note({
cc: [cid], cc: [cid],
}); });
const { tid } = await activitypub.notes.assert(0, id); const { tid } = await activitypub.notes.assert(0, id, { cid });
const inInbox = await db.isSortedSetMember(`uid:${uid}:inbox`, tid); const inInbox = await db.isSortedSetMember(`uid:${uid}:inbox`, tid);
assert(inInbox); assert(inInbox);
@@ -161,7 +134,7 @@ describe('Notes', () => {
const { id } = helpers.mocks.note({ const { id } = helpers.mocks.note({
cc: [remoteCid], cc: [remoteCid],
}); });
const assertion = await activitypub.notes.assert(0, id); const assertion = await activitypub.notes.assert(0, id, { cid: remoteCid });
assert(assertion); assert(assertion);
const unread = await topics.getTotalUnread(uid); const unread = await topics.getTotalUnread(uid);
@@ -180,7 +153,7 @@ describe('Notes', () => {
const { id, note } = helpers.mocks.note({ const { id, note } = helpers.mocks.note({
cc: [remoteCid], cc: [remoteCid],
}); });
const assertion = await activitypub.notes.assert(0, id); const assertion = await activitypub.notes.assert(0, id, { cid: remoteCid });
assert(assertion); assert(assertion);
const unread = await topics.getTotalUnread(uid); const unread = await topics.getTotalUnread(uid);
@@ -203,7 +176,7 @@ describe('Notes', () => {
const { id, note } = helpers.mocks.note({ const { id, note } = helpers.mocks.note({
cc: [remoteCid], cc: [remoteCid],
}); });
const assertion = await activitypub.notes.assert(0, id); const assertion = await activitypub.notes.assert(0, id, { cid: remoteCid });
assert(assertion); assert(assertion);
const unread = await topics.getTotalUnread(uid); const unread = await topics.getTotalUnread(uid);
@@ -457,6 +430,44 @@ describe('Notes', () => {
}); });
}); });
describe('Create', () => {
let uid;
before(async () => {
uid = await user.create({ username: utils.generateUUID() });
});
describe('(Note)', () => {
it('should create a new topic in cid -1', async () => {
const { note, id } = helpers.mocks.note();
const { activity } = helpers.mocks.create(note);
await db.sortedSetAdd(`followersRemote:${note.attributedTo}`, Date.now(), uid);
await activitypub.inbox.create({ body: activity });
assert(await posts.exists(id));
const cid = await posts.getCidByPid(id);
assert.strictEqual(cid, -1);
});
it('should create a new topic in cid -1 even if a remote category is addressed', async () => {
const { id: remoteCid } = helpers.mocks.group();
const { note, id } = helpers.mocks.note({
audience: [remoteCid],
});
const { activity } = helpers.mocks.create(note);
await activitypub.inbox.create({ body: activity });
assert(await posts.exists(id));
const cid = await posts.getCidByPid(id);
assert.strictEqual(cid, -1);
});
});
});
describe('Announce', () => { describe('Announce', () => {
let cid; let cid;
@@ -464,6 +475,24 @@ describe('Notes', () => {
({ cid } = await categories.create({ name: utils.generateUUID().slice(0, 8) })); ({ cid } = await categories.create({ name: utils.generateUUID().slice(0, 8) }));
}); });
describe('(Create)', () => {
it('should create a new topic in a remote category if addressed', async () => {
const { id: remoteCid } = helpers.mocks.group();
const { id, note } = helpers.mocks.note({
audience: [remoteCid],
});
let { activity } = helpers.mocks.create(note);
({ activity } = helpers.mocks.announce({ actor: remoteCid, object: activity }));
await activitypub.inbox.announce({ body: activity });
assert(await posts.exists(id));
const cid = await posts.getCidByPid(id);
assert.strictEqual(cid, remoteCid);
});
});
describe('(Note)', () => { describe('(Note)', () => {
it('should create a new topic in cid -1 if category not addressed', async () => { it('should create a new topic in cid -1 if category not addressed', async () => {
const { note } = helpers.mocks.note(); const { note } = helpers.mocks.note();