From 6ebea82dbabaf705d882c7ce97fd9f523c084eee Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 4 Oct 2023 16:12:44 +0900 Subject: [PATCH 1/7] add more test --- packages/backend/test/e2e/timelines.ts | 162 ++++++++++++++++--------- 1 file changed, 107 insertions(+), 55 deletions(-) diff --git a/packages/backend/test/e2e/timelines.ts b/packages/backend/test/e2e/timelines.ts index 6efdbd63b..08af5bf97 100644 --- a/packages/backend/test/e2e/timelines.ts +++ b/packages/backend/test/e2e/timelines.ts @@ -15,6 +15,10 @@ function genHost() { return randomString() + '.example.com'; } +function waitForPushToTl() { + return sleep(100); +} + let app: INestApplicationContext; beforeAll(async () => { @@ -32,7 +36,7 @@ describe('Timelines', () => { const aliceNote = await post(alice, { text: 'hi', visibility: 'followers' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -44,10 +48,11 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi' }); const carolNote = await post(carol, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -59,10 +64,11 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); const carolNote = await post(carol, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -75,10 +81,11 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -91,10 +98,11 @@ describe('Timelines', () => { await api('/following/create', { userId: bob.id }, alice); await api('/following/update', { userId: bob.id, withReplies: true }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -107,10 +115,11 @@ describe('Timelines', () => { await api('/following/create', { userId: bob.id }, alice); await api('/following/update', { userId: bob.id, withReplies: true }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id, visibility: 'specified', visibleUserIds: [carolNote.id] }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -123,10 +132,11 @@ describe('Timelines', () => { await api('/following/create', { userId: bob.id }, alice); await api('/following/update', { userId: bob.id, withReplies: true }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi', visibility: 'followers' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -140,10 +150,11 @@ describe('Timelines', () => { await api('/following/create', { userId: bob.id }, alice); await api('/following/create', { userId: carol.id }, alice); await api('/following/update', { userId: bob.id, withReplies: true }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi', visibility: 'followers' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -158,10 +169,11 @@ describe('Timelines', () => { await api('/following/create', { userId: bob.id }, alice); await api('/following/create', { userId: carol.id }, alice); await api('/following/update', { userId: bob.id, withReplies: true }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id, visibility: 'specified', visibleUserIds: [carolNote.id] }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -173,10 +185,11 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -190,7 +203,7 @@ describe('Timelines', () => { const bobNote = await post(bob, { text: 'hi' }); const aliceNote = await post(alice, { text: 'hi', replyId: bobNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -202,10 +215,11 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { renoteId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -217,10 +231,11 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { renoteId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', { withRenotes: false, @@ -234,10 +249,11 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', { withRenotes: false, @@ -251,9 +267,10 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -265,10 +282,11 @@ describe('Timelines', () => { await api('/following/create', { userId: bob.id }, alice); await api('/mute/create', { userId: carol.id }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -282,10 +300,11 @@ describe('Timelines', () => { await api('/following/create', { userId: bob.id }, alice); await api('/following/update', { userId: bob.id, withReplies: true }, alice); await api('/mute/create', { userId: carol.id }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -297,9 +316,10 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -310,9 +330,10 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', {}, alice); @@ -323,6 +344,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const [bobFile, carolFile] = await Promise.all([ uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/assets/main/icon.png'), uploadUrl(carol, 'https://raw.githubusercontent.com/misskey-dev/assets/main/icon.png'), @@ -332,7 +354,7 @@ describe('Timelines', () => { const carolNote1 = await post(carol, { text: 'hi' }); const carolNote2 = await post(carol, { fileIds: [carolFile.id] }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/timeline', { withFiles: true }, alice); @@ -350,7 +372,7 @@ describe('Timelines', () => { const carolNote = await post(carol, { text: 'hi', visibility: 'home' }); const bobNote = await post(bob, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/local-timeline', {}, alice); @@ -363,7 +385,7 @@ describe('Timelines', () => { const bobNote = await post(bob, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/local-timeline', {}, alice); @@ -374,13 +396,12 @@ describe('Timelines', () => { test.concurrent('フォローしているユーザーの visibility: home なノートが含まれない', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); - await api('/following/create', { - userId: carol.id, - }, alice); + await api('/following/create', { userId: carol.id }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi', visibility: 'home' }); const bobNote = await post(bob, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/local-timeline', {}, alice); @@ -392,10 +413,11 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('/mute/create', { userId: carol.id }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/local-timeline', {}, alice); @@ -408,10 +430,11 @@ describe('Timelines', () => { await api('/following/create', { userId: bob.id }, alice); await api('/mute/create', { userId: carol.id }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/local-timeline', {}, alice); @@ -425,10 +448,11 @@ describe('Timelines', () => { await api('/following/create', { userId: bob.id }, alice); await api('/following/update', { userId: bob.id, withReplies: true }, alice); await api('/mute/create', { userId: carol.id }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/local-timeline', {}, alice); @@ -443,7 +467,7 @@ describe('Timelines', () => { const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { fileIds: [file.id] }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/local-timeline', { withFiles: true }, alice); @@ -458,7 +482,7 @@ describe('Timelines', () => { const bobNote = await post(bob, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/hybrid-timeline', {}, alice); @@ -470,7 +494,7 @@ describe('Timelines', () => { const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/hybrid-timeline', {}, alice); @@ -481,9 +505,10 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/hybrid-timeline', {}, alice); @@ -495,7 +520,7 @@ describe('Timelines', () => { const bobNote = await post(bob, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/local-timeline', {}, alice); @@ -506,9 +531,10 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/hybrid-timeline', {}, alice); @@ -519,9 +545,10 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]); await api('/following/create', { userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/hybrid-timeline', {}, alice); @@ -535,7 +562,7 @@ describe('Timelines', () => { const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { fileIds: [file.id] }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/hybrid-timeline', { withFiles: true }, alice); @@ -550,9 +577,10 @@ describe('Timelines', () => { const list = await api('/users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('/users/lists/push', { listId: list.id, userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/user-list-timeline', { listId: list.id }, alice); @@ -564,9 +592,10 @@ describe('Timelines', () => { const list = await api('/users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('/users/lists/push', { listId: list.id, userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/user-list-timeline', { listId: list.id }, alice); @@ -579,9 +608,10 @@ describe('Timelines', () => { const list = await api('/users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('/users/lists/push', { listId: list.id, userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/user-list-timeline', { listId: list.id }, alice); @@ -594,9 +624,10 @@ describe('Timelines', () => { const list = await api('/users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('/users/lists/push', { listId: list.id, userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/user-list-timeline', { listId: list.id }, alice); @@ -609,10 +640,11 @@ describe('Timelines', () => { const list = await api('/users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('/users/lists/push', { listId: list.id, userId: bob.id }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/user-list-timeline', { listId: list.id }, alice); @@ -624,10 +656,11 @@ describe('Timelines', () => { const list = await api('/users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('/users/lists/push', { listId: list.id, userId: bob.id }, alice); + await sleep(1000); const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/user-list-timeline', { listId: list.id }, alice); @@ -641,10 +674,11 @@ describe('Timelines', () => { const list = await api('/users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('/users/lists/push', { listId: list.id, userId: bob.id }, alice); await api('/users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: true }, alice); + await sleep(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/user-list-timeline', { listId: list.id }, alice); @@ -657,9 +691,10 @@ describe('Timelines', () => { await api('/following/create', { userId: bob.id }, alice); const list = await api('/users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('/users/lists/push', { listId: list.id, userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/user-list-timeline', { listId: list.id }, alice); @@ -672,9 +707,10 @@ describe('Timelines', () => { await api('/following/create', { userId: bob.id }, alice); const list = await api('/users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('/users/lists/push', { listId: list.id, userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/user-list-timeline', { listId: list.id }, alice); @@ -691,7 +727,7 @@ describe('Timelines', () => { const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { fileIds: [file.id] }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/notes/user-list-timeline', { listId: list.id, withFiles: true }, alice); @@ -706,7 +742,7 @@ describe('Timelines', () => { const bobNote = await post(bob, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/users/notes', { userId: bob.id }, alice); @@ -718,7 +754,7 @@ describe('Timelines', () => { const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/users/notes', { userId: bob.id }, alice); @@ -732,7 +768,7 @@ describe('Timelines', () => { await sleep(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/users/notes', { userId: bob.id }, alice); @@ -747,7 +783,7 @@ describe('Timelines', () => { const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { text: 'hi', replyId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/users/notes', { userId: bob.id }, alice); @@ -762,7 +798,7 @@ describe('Timelines', () => { const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { text: 'hi', replyId: carolNote.id }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/users/notes', { userId: bob.id, withReplies: true }, alice); @@ -777,7 +813,7 @@ describe('Timelines', () => { const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { text: 'hi', replyId: carolNote.id, visibility: 'specified' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/users/notes', { userId: bob.id, withReplies: true }, alice); @@ -792,7 +828,7 @@ describe('Timelines', () => { const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { fileIds: [file.id] }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/users/notes', { userId: bob.id, withFiles: true }, alice); @@ -800,13 +836,29 @@ describe('Timelines', () => { assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); }, 1000 * 10); + test.concurrent('ミュートしているユーザーに関連する投稿が含まれない', async () => { + const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); + + await api('/mute/create', { userId: carol.id }, alice); + await sleep(1000); + const carolNote = await post(carol, { text: 'hi' }); + const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); + + await waitForPushToTl(); + + const res = await api('/users/notes', { userId: bob.id }, alice); + + assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); + }); + test.concurrent('ミュートしていても userId に指定したユーザーの投稿が含まれる', async () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('/mute/create', { userId: bob.id }, alice); + await sleep(1000); const bobNote = await post(bob, { text: 'hi' }); - await sleep(100); // redisに追加されるのを待つ + await waitForPushToTl(); const res = await api('/users/notes', { userId: bob.id }, alice); From ca515d5a7ea164582c4917c0e1f01aa66c5b6a13 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 4 Oct 2023 16:43:24 +0900 Subject: [PATCH 2/7] tweak timelines --- packages/backend/src/misc/is-user-related.ts | 4 ++-- packages/backend/src/server/api/endpoints/users/notes.ts | 9 +++++++++ packages/backend/test/e2e/timelines.ts | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/misc/is-user-related.ts b/packages/backend/src/misc/is-user-related.ts index edd65a3c1..ae8f4116c 100644 --- a/packages/backend/src/misc/is-user-related.ts +++ b/packages/backend/src/misc/is-user-related.ts @@ -3,8 +3,8 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -export function isUserRelated(note: any, userIds: Set): boolean { - if (userIds.has(note.userId)) { +export function isUserRelated(note: any, userIds: Set, ignoreAuthor = false): boolean { + if (userIds.has(note.userId) && !ignoreAuthor) { return true; } diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index 6be391be4..09adcf20a 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -13,6 +13,7 @@ import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { CacheService } from '@/core/CacheService.js'; import { IdService } from '@/core/IdService.js'; +import { isUserRelated } from '@/misc/is-user-related.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -70,6 +71,12 @@ export default class extends Endpoint { // eslint- private idService: IdService, ) { super(meta, paramDef, async (ps, me) => { + const [ + userIdsWhoMeMuting, + ] = me ? await Promise.all([ + this.cacheService.userMutingsCache.fetch(me.id), + ]) : [new Set()]; + let timeline: MiNote[] = []; const limit = ps.limit + (ps.untilId ? 1 : 0); // untilIdに指定したものも含まれるため+1 @@ -118,6 +125,8 @@ export default class extends Endpoint { // eslint- timeline = await query.getMany(); timeline = timeline.filter(note => { + if (me && isUserRelated(note, userIdsWhoMeMuting, true)) return false; + if (note.renoteId) { if (note.text == null && note.fileIds.length === 0 && !note.hasPoll) { if (ps.withRenotes === false) return false; diff --git a/packages/backend/test/e2e/timelines.ts b/packages/backend/test/e2e/timelines.ts index 08af5bf97..d606c6729 100644 --- a/packages/backend/test/e2e/timelines.ts +++ b/packages/backend/test/e2e/timelines.ts @@ -16,7 +16,7 @@ function genHost() { } function waitForPushToTl() { - return sleep(100); + return sleep(300); } let app: INestApplicationContext; From fb63fc12130347c90ead3b461cf78bdbcc357cbf Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 4 Oct 2023 16:48:34 +0900 Subject: [PATCH 3/7] tweak tl --- packages/backend/src/misc/is-user-related.ts | 4 ++-- packages/backend/test/e2e/timelines.ts | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/misc/is-user-related.ts b/packages/backend/src/misc/is-user-related.ts index ae8f4116c..6efb1194d 100644 --- a/packages/backend/src/misc/is-user-related.ts +++ b/packages/backend/src/misc/is-user-related.ts @@ -8,11 +8,11 @@ export function isUserRelated(note: any, userIds: Set, ignoreAuthor = fa return true; } - if (note.reply != null && userIds.has(note.reply.userId)) { + if (note.reply != null && note.reply.userId !== note.userId && userIds.has(note.reply.userId)) { return true; } - if (note.renote != null && userIds.has(note.renote.userId)) { + if (note.renote != null && note.renote.userId !== note.userId && userIds.has(note.renote.userId)) { return true; } diff --git a/packages/backend/test/e2e/timelines.ts b/packages/backend/test/e2e/timelines.ts index d606c6729..a82be6365 100644 --- a/packages/backend/test/e2e/timelines.ts +++ b/packages/backend/test/e2e/timelines.ts @@ -856,13 +856,17 @@ describe('Timelines', () => { await api('/mute/create', { userId: bob.id }, alice); await sleep(1000); - const bobNote = await post(bob, { text: 'hi' }); + const bobNote1 = await post(bob, { text: 'hi' }); + const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id }); + const bobNote3 = await post(bob, { text: 'hi', renoteId: bobNote1.id }); await waitForPushToTl(); const res = await api('/users/notes', { userId: bob.id }, alice); - assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), true); + assert.strictEqual(res.body.some((note: any) => note.id === bobNote1.id), true); + assert.strictEqual(res.body.some((note: any) => note.id === bobNote2.id), true); + assert.strictEqual(res.body.some((note: any) => note.id === bobNote3.id), true); }); }); From 55c14aec2c598af1ef3286573de28473f0960f9f Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 4 Oct 2023 16:50:06 +0900 Subject: [PATCH 4/7] perf(backend): delete useless indexes --- .../migration/1696405744672-clean-up.js | 18 ++++++++++++++++++ packages/backend/src/models/Note.ts | 2 -- 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 packages/backend/migration/1696405744672-clean-up.js diff --git a/packages/backend/migration/1696405744672-clean-up.js b/packages/backend/migration/1696405744672-clean-up.js new file mode 100644 index 000000000..5ec89b08f --- /dev/null +++ b/packages/backend/migration/1696405744672-clean-up.js @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class CleanUp1696405744672 { + name = 'CleanUp1696405744672' + + async up(queryRunner) { + await queryRunner.query(`DROP INDEX "public"."IDX_e7c0567f5261063592f022e9b5"`); + await queryRunner.query(`DROP INDEX "public"."IDX_25dfc71b0369b003a4cd434d0b"`); + } + + async down(queryRunner) { + await queryRunner.query(`CREATE INDEX "IDX_25dfc71b0369b003a4cd434d0b" ON "note" ("attachedFileTypes") `); + await queryRunner.query(`CREATE INDEX "IDX_e7c0567f5261063592f022e9b5" ON "note" ("createdAt") `); + } +} diff --git a/packages/backend/src/models/Note.ts b/packages/backend/src/models/Note.ts index ed86d4549..0d2422c4f 100644 --- a/packages/backend/src/models/Note.ts +++ b/packages/backend/src/models/Note.ts @@ -18,7 +18,6 @@ export class MiNote { @PrimaryColumn(id()) public id: string; - @Index() @Column('timestamp with time zone', { comment: 'The created date of the Note.', }) @@ -151,7 +150,6 @@ export class MiNote { }) public fileIds: MiDriveFile['id'][]; - @Index() @Column('varchar', { length: 256, array: true, default: '{}', }) From 0dbf5175dfea04a9405985faa1d18f8383b58cac Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 4 Oct 2023 19:55:35 +0900 Subject: [PATCH 5/7] enhance: improve moderation log --- CHANGELOG.md | 2 ++ packages/backend/src/core/AnnouncementService.ts | 4 ++++ packages/backend/src/types.ts | 3 +++ .../frontend/src/pages/admin/modlog.ModLog.vue | 14 ++++++++++++++ packages/misskey-js/src/consts.ts | 3 +++ 5 files changed, 26 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e525ace6..6959c8577 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ - Feat: ユーザーごとに他ユーザーへの返信をタイムラインに含めるか設定可能になりました - Feat: ユーザーリスト内のメンバーごとに他ユーザーへの返信をユーザーリストタイムラインに含めるか設定可能になりました - Enhance: ソフトワードミュートとハードワードミュートは統合されました +- Enhance: モデレーションログ機能の強化 +- Enhance: ローカリゼーションの更新 ### Client - Enhance: 二要素認証のバックアップコード一覧をテキストファイルでダウンロード可能に diff --git a/packages/backend/src/core/AnnouncementService.ts b/packages/backend/src/core/AnnouncementService.ts index ddacc0936..a5330db53 100644 --- a/packages/backend/src/core/AnnouncementService.ts +++ b/packages/backend/src/core/AnnouncementService.ts @@ -158,9 +158,13 @@ export class AnnouncementService { if (moderator) { if (announcement.userId) { + const user = await this.usersRepository.findOneByOrFail({ id: announcement.userId }); this.moderationLogService.log(moderator, 'deleteUserAnnouncement', { announcementId: announcement.id, announcement: announcement, + userId: announcement.userId, + userUsername: user.username, + userHost: user.host, }); } else { this.moderationLogService.log(moderator, 'deleteGlobalAnnouncement', { diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index a9b9a55bc..316073c99 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -171,6 +171,9 @@ export type ModerationLogPayloads = { deleteUserAnnouncement: { announcementId: string; announcement: any; + userId: string; + userUsername: string; + userHost: string | null; }; resetPassword: { userId: string; diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue index 66561c969..0af226f02 100644 --- a/packages/frontend/src/pages/admin/modlog.ModLog.vue +++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue @@ -29,8 +29,12 @@ SPDX-License-Identifier: AGPL-3.0-only : @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }} : {{ log.info.host }} : {{ log.info.host }} + : {{ log.info.announcement.title }} + : {{ log.info.before.title }} + : {{ log.info.announcement.title }} : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} + : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} : @{{ log.info.noteUserUsername }}{{ log.info.noteUserHost ? '@' + log.info.noteUserHost : '' }} : @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }} @@ -88,6 +92,16 @@ SPDX-License-Identifier: AGPL-3.0-only + +
raw diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts index 271a64274..ccc55537d 100644 --- a/packages/misskey-js/src/consts.ts +++ b/packages/misskey-js/src/consts.ts @@ -189,6 +189,9 @@ export type ModerationLogPayloads = { deleteUserAnnouncement: { announcementId: string; announcement: any; + userId: string; + userUsername: string; + userHost: string | null; }; resetPassword: { userId: string; From 89e4f28d06f8efe140601beb7c6d088051c6ded0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 4 Oct 2023 20:03:52 +0900 Subject: [PATCH 6/7] enhance(frontend): tweak ui --- packages/frontend/src/pages/settings/index.vue | 10 ---------- ...nce-mute.vue => mute-block.instance-mute.vue} | 10 ---------- .../frontend/src/pages/settings/mute-block.vue | 16 ++++++++++++++++ .../{word-mute.vue => mute-block.word-mute.vue} | 9 --------- packages/frontend/src/router.ts | 8 -------- 5 files changed, 16 insertions(+), 37 deletions(-) rename packages/frontend/src/pages/settings/{instance-mute.vue => mute-block.instance-mute.vue} (85%) rename packages/frontend/src/pages/settings/{word-mute.vue => mute-block.word-mute.vue} (94%) diff --git a/packages/frontend/src/pages/settings/index.vue b/packages/frontend/src/pages/settings/index.vue index f1bd50115..cfabbbbf6 100644 --- a/packages/frontend/src/pages/settings/index.vue +++ b/packages/frontend/src/pages/settings/index.vue @@ -139,21 +139,11 @@ const menuDef = computed(() => [{ text: i18n.ts.roles, to: '/settings/roles', active: currentPage?.route.name === 'roles', - }, { - icon: 'ti ti-planet-off', - text: i18n.ts.instanceMute, - to: '/settings/instance-mute', - active: currentPage?.route.name === 'instance-mute', }, { icon: 'ti ti-ban', text: i18n.ts.muteAndBlock, to: '/settings/mute-block', active: currentPage?.route.name === 'mute-block', - }, { - icon: 'ti ti-message-off', - text: i18n.ts.wordMute, - to: '/settings/word-mute', - active: currentPage?.route.name === 'word-mute', }, { icon: 'ti ti-api', text: 'API', diff --git a/packages/frontend/src/pages/settings/instance-mute.vue b/packages/frontend/src/pages/settings/mute-block.instance-mute.vue similarity index 85% rename from packages/frontend/src/pages/settings/instance-mute.vue rename to packages/frontend/src/pages/settings/mute-block.instance-mute.vue index b76fd2c90..4b5080ea8 100644 --- a/packages/frontend/src/pages/settings/instance-mute.vue +++ b/packages/frontend/src/pages/settings/mute-block.instance-mute.vue @@ -22,7 +22,6 @@ import MkButton from '@/components/MkButton.vue'; import * as os from '@/os.js'; import { $i } from '@/account.js'; import { i18n } from '@/i18n.js'; -import { definePageMetadata } from '@/scripts/page-metadata.js'; const instanceMutes = ref($i!.mutedInstances.join('\n')); const changed = ref(false); @@ -46,13 +45,4 @@ async function save() { watch(instanceMutes, () => { changed.value = true; }); - -const headerActions = $computed(() => []); - -const headerTabs = $computed(() => []); - -definePageMetadata({ - title: i18n.ts.instanceMute, - icon: 'ti ti-planet-off', -}); diff --git a/packages/frontend/src/pages/settings/mute-block.vue b/packages/frontend/src/pages/settings/mute-block.vue index 12a5ffec4..c6cbd424e 100644 --- a/packages/frontend/src/pages/settings/mute-block.vue +++ b/packages/frontend/src/pages/settings/mute-block.vue @@ -5,6 +5,20 @@ SPDX-License-Identifier: AGPL-3.0-only