From 9dbdb97bb52189fb0c74c9dbdb171b984468619e Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sat, 10 May 2025 22:32:06 -0400 Subject: [PATCH 1/6] allow checkWordMute to accept raw strings --- packages/frontend/src/utility/check-word-mute.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/utility/check-word-mute.ts b/packages/frontend/src/utility/check-word-mute.ts index 37ad678555..26bf593f7b 100644 --- a/packages/frontend/src/utility/check-word-mute.ts +++ b/packages/frontend/src/utility/check-word-mute.ts @@ -4,12 +4,12 @@ */ import * as Misskey from 'misskey-js'; -export function checkWordMute(note: Misskey.entities.Note, me: Misskey.entities.UserLite | null | undefined, mutedWords: Array): Array | false { +export function checkWordMute(note: string | Misskey.entities.Note, me: Misskey.entities.UserLite | null | undefined, mutedWords: Array): Array | false { // 自分自身 - if (me && (note.userId === me.id)) return false; + if (me && typeof(note) === 'object' && (note.userId === me.id)) return false; if (mutedWords.length > 0) { - const text = getNoteText(note); + const text = typeof(note) === 'object' ? getNoteText(note) : note; if (text === '') return false; From 32b860c352615d3c2d0902c1efeb24aee30a09cf Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sat, 10 May 2025 22:32:19 -0400 Subject: [PATCH 2/6] add UI for testing word mutes --- locales/index.d.ts | 24 ++++ .../pages/settings/mute-block.word-mute.vue | 105 ++++++++++++------ sharkey-locales/en-US.yml | 7 ++ 3 files changed, 102 insertions(+), 34 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index 9679cc3acf..2beb0ae454 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -12969,6 +12969,30 @@ export interface Locale extends ILocale { */ "text": string; }; + /** + * Test word mutes + */ + "wordMuteTestLabel": string; + /** + * Enter some text here to test your word mute patterns. The matched words, if any, will be displayed below. + */ + "wordMuteTestDescription": string; + /** + * Test + */ + "wordMuteTestTest": string; + /** + * Matched words: {words} + */ + "wordMuteTestMatch": ParameterizedString<"words">; + /** + * No results yet, enter some text and click "Test" to check it. + */ + "wordMuteTestNoResults": string; + /** + * Text does not match any word mutes. + */ + "wordMuteTestNoMatch": string; } declare const locales: { [lang: string]: Locale; diff --git a/packages/frontend/src/pages/settings/mute-block.word-mute.vue b/packages/frontend/src/pages/settings/mute-block.word-mute.vue index f5837abe98..52aa2ff230 100644 --- a/packages/frontend/src/pages/settings/mute-block.word-mute.vue +++ b/packages/frontend/src/pages/settings/mute-block.word-mute.vue @@ -11,16 +11,33 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + +
+ + + +
{{ i18n.ts.wordMuteTestTest }}
+
{{ i18n.ts.wordMuteTestNoResults}}
+
{{ i18n.ts.wordMuteTestNoMatch }}
+
{{ i18n.tsx.wordMuteTestMatch({ words: testMatches }) }}
+
+
+ {{ i18n.ts.save }} diff --git a/sharkey-locales/en-US.yml b/sharkey-locales/en-US.yml index 034d995b01..a42486c4d1 100644 --- a/sharkey-locales/en-US.yml +++ b/sharkey-locales/en-US.yml @@ -543,3 +543,10 @@ enableProxyAccountDescription: "If disabled, then the proxy account will not be _confirmPollEdit: title: Are you sure you want to edit this poll text: Editing this poll will cause it to lose all previous votes + +wordMuteTestLabel: "Test word mutes" +wordMuteTestDescription: "Enter some text here to test your word mute patterns. The matched words, if any, will be displayed below." +wordMuteTestTest: "Test" +wordMuteTestMatch: "Matched words: {words}" +wordMuteTestNoResults: "No results yet, enter some text and click \"Test\" to check it." +wordMuteTestNoMatch: "Text does not match any word mutes." From b4bc58ae4c264aa10e3ccbdc7272b2bc37f0af3d Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sat, 10 May 2025 22:36:49 -0400 Subject: [PATCH 3/6] move parseMutes to a utility file --- .../pages/settings/mute-block.word-mute.vue | 34 +-------------- packages/frontend/src/utility/parse-mutes.ts | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+), 33 deletions(-) create mode 100644 packages/frontend/src/utility/parse-mutes.ts diff --git a/packages/frontend/src/pages/settings/mute-block.word-mute.vue b/packages/frontend/src/pages/settings/mute-block.word-mute.vue index 52aa2ff230..97ddd91d30 100644 --- a/packages/frontend/src/pages/settings/mute-block.word-mute.vue +++ b/packages/frontend/src/pages/settings/mute-block.word-mute.vue @@ -34,10 +34,10 @@ SPDX-License-Identifier: AGPL-3.0-only import { computed, ref, watch } from 'vue'; import MkTextarea from '@/components/MkTextarea.vue'; import MkButton from '@/components/MkButton.vue'; -import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; import MkFolder from '@/components/MkFolder.vue'; import { checkWordMute } from '@/utility/check-word-mute'; +import { parseMutes } from '@/utility/parse-mutes'; const props = defineProps<{ muted: (string[] | string)[]; @@ -66,38 +66,6 @@ watch(mutedWords, () => { changed.value = true; }); -function parseMutes(mutes: string) { - // split into lines, remove empty lines and unnecessary whitespace - const lines = mutes.trim().split('\n').map(line => line.trim()).filter(line => line !== ''); - const outLines = Array.from(lines) as (string | string[])[]; - - // check each line if it is a RegExp or not - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - const regexp = line.match(/^\/(.+)\/(.*)$/); - if (regexp) { - // check that the RegExp is valid - try { - new RegExp(regexp[1], regexp[2]); - // note that regex lines will not be split by spaces! - } catch (err: any) { - // invalid syntax: do not save, do not reset changed flag - os.alert({ - type: 'error', - title: i18n.ts.regexpError, - text: i18n.tsx.regexpErrorDescription({ tab: 'word mute', line: i + 1 }) + '\n' + err.toString(), - }); - // re-throw error so these invalid settings are not saved - throw err; - } - } else { - outLines[i] = line.split(' '); - } - } - - return outLines; -} - async function save() { try { const parsed = parseMutes(mutedWords.value); diff --git a/packages/frontend/src/utility/parse-mutes.ts b/packages/frontend/src/utility/parse-mutes.ts new file mode 100644 index 0000000000..1ebd5bcf83 --- /dev/null +++ b/packages/frontend/src/utility/parse-mutes.ts @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import * as os from '@/os'; +import { i18n } from '@/i18n'; + +export type Mutes = (string | string[])[]; + +export function parseMutes(mutes: string): Mutes { + // split into lines, remove empty lines and unnecessary whitespace + const lines = mutes.trim().split('\n').map(line => line.trim()).filter(line => line !== ''); + const outLines: Mutes = Array.from(lines); + + // check each line if it is a RegExp or not + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + const regexp = line.match(/^\/(.+)\/(.*)$/); + if (regexp) { + // check that the RegExp is valid + try { + new RegExp(regexp[1], regexp[2]); + // note that regex lines will not be split by spaces! + } catch (err: any) { + // invalid syntax: do not save, do not reset changed flag + os.alert({ + type: 'error', + title: i18n.ts.regexpError, + text: i18n.tsx.regexpErrorDescription({ tab: 'word mute', line: i + 1 }) + '\n' + err.toString(), + }); + // re-throw error so these invalid settings are not saved + throw err; + } + } else { + outLines[i] = line.split(' '); + } + } + + return outLines; +} From 32e2a07d669ccd621e0e185799fc34a0edd871fe Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sat, 10 May 2025 22:39:13 -0400 Subject: [PATCH 4/6] extract SkWordMuteTest --- .../src/components/SkWordMuteTest.vue | 57 +++++++++++++++++++ .../pages/settings/mute-block.word-mute.vue | 39 +------------ 2 files changed, 60 insertions(+), 36 deletions(-) create mode 100644 packages/frontend/src/components/SkWordMuteTest.vue diff --git a/packages/frontend/src/components/SkWordMuteTest.vue b/packages/frontend/src/components/SkWordMuteTest.vue new file mode 100644 index 0000000000..2ed2b3fdc3 --- /dev/null +++ b/packages/frontend/src/components/SkWordMuteTest.vue @@ -0,0 +1,57 @@ + + + + + + + diff --git a/packages/frontend/src/pages/settings/mute-block.word-mute.vue b/packages/frontend/src/pages/settings/mute-block.word-mute.vue index 97ddd91d30..cbd943f807 100644 --- a/packages/frontend/src/pages/settings/mute-block.word-mute.vue +++ b/packages/frontend/src/pages/settings/mute-block.word-mute.vue @@ -12,32 +12,19 @@ SPDX-License-Identifier: AGPL-3.0-only - - - -
- - - -
{{ i18n.ts.wordMuteTestTest }}
-
{{ i18n.ts.wordMuteTestNoResults}}
-
{{ i18n.ts.wordMuteTestNoMatch }}
-
{{ i18n.tsx.wordMuteTestMatch({ words: testMatches }) }}
-
-
+ {{ i18n.ts.save }} From f6796a99ecda17f970454a6ad966b47589969763 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sat, 10 May 2025 22:48:50 -0400 Subject: [PATCH 5/6] add SkWordMuteTest to moderation control panel --- locales/index.d.ts | 6 +++--- packages/frontend/src/pages/admin/moderation.vue | 13 +++++++++++++ sharkey-locales/en-US.yml | 6 +++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index 2beb0ae454..4d9c6fb972 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -12970,11 +12970,11 @@ export interface Locale extends ILocale { "text": string; }; /** - * Test word mutes + * Test patterns */ "wordMuteTestLabel": string; /** - * Enter some text here to test your word mute patterns. The matched words, if any, will be displayed below. + * Enter some text here to test your word patterns. The matched words, if any, will be displayed below. */ "wordMuteTestDescription": string; /** @@ -12990,7 +12990,7 @@ export interface Locale extends ILocale { */ "wordMuteTestNoResults": string; /** - * Text does not match any word mutes. + * Text does not match any patterns. */ "wordMuteTestNoMatch": string; } diff --git a/packages/frontend/src/pages/admin/moderation.vue b/packages/frontend/src/pages/admin/moderation.vue index 9675bdc21a..9ba256e89f 100644 --- a/packages/frontend/src/pages/admin/moderation.vue +++ b/packages/frontend/src/pages/admin/moderation.vue @@ -47,6 +47,9 @@ SPDX-License-Identifier: AGPL-3.0-only + + + {{ i18n.ts.save }} @@ -71,6 +74,9 @@ SPDX-License-Identifier: AGPL-3.0-only + + + {{ i18n.ts.save }} @@ -83,6 +89,9 @@ SPDX-License-Identifier: AGPL-3.0-only + + + {{ i18n.ts.save }} @@ -95,6 +104,9 @@ SPDX-License-Identifier: AGPL-3.0-only + + + {{ i18n.ts.save }} @@ -166,6 +178,7 @@ import { definePage } from '@/page.js'; import MkButton from '@/components/MkButton.vue'; import FormLink from '@/components/form/link.vue'; import MkFolder from '@/components/MkFolder.vue'; +import SkWordMuteTest from '@/components/SkWordMuteTest.vue'; const enableRegistration = ref(false); const emailRequiredForSignup = ref(false); diff --git a/sharkey-locales/en-US.yml b/sharkey-locales/en-US.yml index a42486c4d1..cd18e2eeef 100644 --- a/sharkey-locales/en-US.yml +++ b/sharkey-locales/en-US.yml @@ -544,9 +544,9 @@ _confirmPollEdit: title: Are you sure you want to edit this poll text: Editing this poll will cause it to lose all previous votes -wordMuteTestLabel: "Test word mutes" -wordMuteTestDescription: "Enter some text here to test your word mute patterns. The matched words, if any, will be displayed below." +wordMuteTestLabel: "Test patterns" +wordMuteTestDescription: "Enter some text here to test your word patterns. The matched words, if any, will be displayed below." wordMuteTestTest: "Test" wordMuteTestMatch: "Matched words: {words}" wordMuteTestNoResults: "No results yet, enter some text and click \"Test\" to check it." -wordMuteTestNoMatch: "Text does not match any word mutes." +wordMuteTestNoMatch: "Text does not match any patterns." From c6ef944fc6e35f145c8924a22780638ed0159927 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sat, 10 May 2025 22:49:23 -0400 Subject: [PATCH 6/6] rename SkWordMuteTest to SkPatternTest --- .../{SkWordMuteTest.vue => SkPatternTest.vue} | 0 packages/frontend/src/pages/admin/moderation.vue | 10 +++++----- .../src/pages/settings/mute-block.word-mute.vue | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) rename packages/frontend/src/components/{SkWordMuteTest.vue => SkPatternTest.vue} (100%) diff --git a/packages/frontend/src/components/SkWordMuteTest.vue b/packages/frontend/src/components/SkPatternTest.vue similarity index 100% rename from packages/frontend/src/components/SkWordMuteTest.vue rename to packages/frontend/src/components/SkPatternTest.vue diff --git a/packages/frontend/src/pages/admin/moderation.vue b/packages/frontend/src/pages/admin/moderation.vue index 9ba256e89f..6845bd7ad0 100644 --- a/packages/frontend/src/pages/admin/moderation.vue +++ b/packages/frontend/src/pages/admin/moderation.vue @@ -48,7 +48,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + {{ i18n.ts.save }} @@ -75,7 +75,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + {{ i18n.ts.save }} @@ -90,7 +90,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + {{ i18n.ts.save }} @@ -105,7 +105,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + {{ i18n.ts.save }} @@ -178,7 +178,7 @@ import { definePage } from '@/page.js'; import MkButton from '@/components/MkButton.vue'; import FormLink from '@/components/form/link.vue'; import MkFolder from '@/components/MkFolder.vue'; -import SkWordMuteTest from '@/components/SkWordMuteTest.vue'; +import SkPatternTest from '@/components/SkPatternTest.vue'; const enableRegistration = ref(false); const emailRequiredForSignup = ref(false); diff --git a/packages/frontend/src/pages/settings/mute-block.word-mute.vue b/packages/frontend/src/pages/settings/mute-block.word-mute.vue index cbd943f807..36b388b848 100644 --- a/packages/frontend/src/pages/settings/mute-block.word-mute.vue +++ b/packages/frontend/src/pages/settings/mute-block.word-mute.vue @@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + {{ i18n.ts.save }} @@ -24,7 +24,7 @@ import MkTextarea from '@/components/MkTextarea.vue'; import MkButton from '@/components/MkButton.vue'; import { i18n } from '@/i18n.js'; import { parseMutes } from '@/utility/parse-mutes'; -import SkWordMuteTest from '@/components/SkWordMuteTest.vue'; +import SkPatternTest from '@/components/SkPatternTest.vue'; const props = defineProps<{ muted: (string[] | string)[];