From cb43994841935c6512c530c96ee409ffbd9f00f8 Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 7 Jun 2024 11:40:44 +0100 Subject: [PATCH 1/3] only allow a single boost via hotkey - fixes #467 #468 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As usual, have to write the same thing four times ☹ The parentheses around `q` tell the hotkey/keymap code to ignore auto-repeat events (which works fine in Chrome but not in Firefox, I reported the bug https://bugzilla.mozilla.org/show_bug.cgi?id=1900397 ) In addition, I've added a guard variable that is true while calling the backend to boost/renote, and false otherwise. This way, even in Firefox we don't spam-boost. Unboosting is still *only with the mouse*, I have not added that functionality. --- packages/frontend/src/components/MkNote.vue | 8 +++++--- packages/frontend/src/components/MkNoteDetailed.vue | 8 +++++--- packages/frontend/src/components/SkNote.vue | 8 +++++--- packages/frontend/src/components/SkNoteDetailed.vue | 8 +++++--- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 9a667c3118..a1d241690f 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -328,10 +328,12 @@ function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array reply(true), 'e|a|plus': () => react(true), - 'q': () => renote(appearNote.value.visibility), + '(q)': () => { if (canRenote && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility) } }, 'up|k|shift+tab': focusBefore, 'down|j|tab': focusAfter, 'esc': blur, @@ -436,7 +438,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }); + }).then(() => { renoting = false }); } } else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) { const el = renoteButton.value as HTMLElement | null | undefined; @@ -455,7 +457,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }); + }).then(() => renoting = false); } } } diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index 3d15f69f73..ec3c3ea3dc 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -336,10 +336,12 @@ if ($i) { }); } +let renoting = false; + const keymap = { 'r': () => reply(true), 'e|a|plus': () => react(true), - 'q': () => renote(appearNote.value.visibility), + '(q)': () => { if (canRenote && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility) } }, 'esc': blur, 'm|o': () => showMenu(true), 's': () => showContent.value !== showContent.value, @@ -457,7 +459,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }); + }).then(() => { renoting = false }); } else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) { const el = renoteButton.value as HTMLElement | null | undefined; if (el) { @@ -474,7 +476,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }); + }).then(() => { renoting = false }); } } diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue index 09decad1a2..fe14b1eafd 100644 --- a/packages/frontend/src/components/SkNote.vue +++ b/packages/frontend/src/components/SkNote.vue @@ -329,10 +329,12 @@ function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array reply(true), 'e|a|plus': () => react(true), - 'q': () => renote(appearNote.value.visibility), + '(q)': () => { if (canRenote && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility) } }, 'up|k|shift+tab': focusBefore, 'down|j|tab': focusAfter, 'esc': blur, @@ -437,7 +439,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }); + }).then(() => { renoting = false }); } } else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) { const el = renoteButton.value as HTMLElement | null | undefined; @@ -456,7 +458,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }); + }).then(() => { renoting = false }); } } } diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue index ced7e7a176..084c46ddcd 100644 --- a/packages/frontend/src/components/SkNoteDetailed.vue +++ b/packages/frontend/src/components/SkNoteDetailed.vue @@ -345,10 +345,12 @@ if ($i) { }); } +let renoting = false; + const keymap = { 'r': () => reply(true), 'e|a|plus': () => react(true), - 'q': () => renote(appearNote.value.visibility), + '(q)': () => { if (canRenote && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility) } }, 'esc': blur, 'm|o': () => showMenu(true), 's': () => showContent.value !== showContent.value, @@ -466,7 +468,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }); + }).then(() => { renoting = false }); } else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) { const el = renoteButton.value as HTMLElement | null | undefined; if (el) { @@ -483,7 +485,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }); + }).then(() => { renoting = false }); } } From 388926775ec14e58bf9daf447c28d197f925ee60 Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 7 Jun 2024 14:47:16 +0100 Subject: [PATCH 2/3] I meant `finally`, not `then`, thanks fEmber --- packages/frontend/src/components/MkNote.vue | 4 ++-- packages/frontend/src/components/MkNoteDetailed.vue | 4 ++-- packages/frontend/src/components/SkNote.vue | 4 ++-- packages/frontend/src/components/SkNoteDetailed.vue | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index a1d241690f..556fedbc30 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -438,7 +438,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }).then(() => { renoting = false }); + }).finally(() => { renoting = false }); } } else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) { const el = renoteButton.value as HTMLElement | null | undefined; @@ -457,7 +457,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }).then(() => renoting = false); + }).finally(() => renoting = false); } } } diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index ec3c3ea3dc..ca017bf63b 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -459,7 +459,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }).then(() => { renoting = false }); + }).finally(() => { renoting = false }); } else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) { const el = renoteButton.value as HTMLElement | null | undefined; if (el) { @@ -476,7 +476,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }).then(() => { renoting = false }); + }).finally(() => { renoting = false }); } } diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue index fe14b1eafd..3291390682 100644 --- a/packages/frontend/src/components/SkNote.vue +++ b/packages/frontend/src/components/SkNote.vue @@ -439,7 +439,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }).then(() => { renoting = false }); + }).finally(() => { renoting = false }); } } else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) { const el = renoteButton.value as HTMLElement | null | undefined; @@ -458,7 +458,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }).then(() => { renoting = false }); + }).finally(() => { renoting = false }); } } } diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue index 084c46ddcd..1acd177e87 100644 --- a/packages/frontend/src/components/SkNoteDetailed.vue +++ b/packages/frontend/src/components/SkNoteDetailed.vue @@ -468,7 +468,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }).then(() => { renoting = false }); + }).finally(() => { renoting = false }); } else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) { const el = renoteButton.value as HTMLElement | null | undefined; if (el) { @@ -485,7 +485,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { }).then(() => { os.toast(i18n.ts.renoted); renoted.value = true; - }).then(() => { renoting = false }); + }).finally(() => { renoting = false }); } } From 079abfd7135e88562127b06135b0eb6aabee81b0 Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 7 Jun 2024 15:10:16 +0100 Subject: [PATCH 3/3] rate limit note/reply/boost creation more tightly 5/minute is the same as 300/hour on average, and still high enough that it shouldn't be a problem for most people --- packages/backend/src/server/api/endpoints/notes/create.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 95ebda2f21..cc44721133 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -30,8 +30,8 @@ export const meta = { prohibitMoved: true, limit: { - duration: ms('1hour'), - max: 300, + duration: ms('1minute'), + max: 5, }, kind: 'write:notes',