diff --git a/src/core/useConfig.ts b/src/core/useConfig.ts index c9fbea4..922efb3 100644 --- a/src/core/useConfig.ts +++ b/src/core/useConfig.ts @@ -1,4 +1,4 @@ -import { createRoot, type Accessor, type Setter } from 'solid-js'; +import { createRoot, type Accessor, type Setter, createMemo } from 'solid-js'; import sortBy from 'lodash/sortBy'; import uniq from 'lodash/uniq'; @@ -21,6 +21,7 @@ import { } from '@/hooks/createSignalWithStorage'; import { useTranslation } from '@/i18n/useTranslation'; import { genericEvent } from '@/nostr/event'; +import { asCaseInsensitive, wordsRegex } from '@/utils/regex'; export type CustomEmojiConfig = { shortcode: string; @@ -218,11 +219,13 @@ const useConfig = (): UseConfig => { [(e) => e.shortcode.length], ); - const isPubkeyMuted = (pubkey: string) => config.mutedPubkeys.includes(pubkey); + const mutedPubkeySet = createMemo(() => new Set(config.mutedPubkeys)); + const isPubkeyMuted = (pubkey: string) => mutedPubkeySet().has(pubkey); + const mutedKeywordsRegex = createMemo(() => asCaseInsensitive(wordsRegex(config.mutedKeywords))); const hasMutedKeyword = (event: NostrEvent) => { if (event.kind === Kind.ShortTextNote) { - return config.mutedKeywords.some((keyword) => event.content.includes(keyword)); + return mutedKeywordsRegex().test(event.content); } return false; }; diff --git a/src/nostr/useEvent.ts b/src/nostr/useEvent.ts index 33ab9bf..74a4b57 100644 --- a/src/nostr/useEvent.ts +++ b/src/nostr/useEvent.ts @@ -28,6 +28,7 @@ const useEvent = (propsProvider: () => UseEventProps | null): UseEvent => { const promise = task.firstEventPromise().catch(() => { throw new Error(`event not found: ${eventId}`); }); + console.log('useEvent', props()); registerTask({ task, signal }); return timeout(15000, `useEvent: ${eventId}`)(promise); }, diff --git a/src/utils/regex.test.ts b/src/utils/regex.test.ts new file mode 100644 index 0000000..98b10d8 --- /dev/null +++ b/src/utils/regex.test.ts @@ -0,0 +1,15 @@ +import assert from 'assert'; + +import { describe, it } from 'vitest'; + +import { escapeRegExpSymbols } from '@/utils/regex'; + +describe('escapeRegExpString', () => { + it.each<{ given: string; expected: string }>([ + { given: '^hello$', expected: '\\^hello\\$' }, + { given: '.*+?^${}()|[]\\', expected: '\\.\\*\\+\\?\\^\\$\\{\\}\\(\\)\\|\\[\\]\\\\' }, + ])('should return $expected for $given', ({ given, expected }) => { + const actual = escapeRegExpSymbols(given); + assert.deepStrictEqual(actual, expected); + }); +}); diff --git a/src/utils/regex.ts b/src/utils/regex.ts new file mode 100644 index 0000000..5623f1a --- /dev/null +++ b/src/utils/regex.ts @@ -0,0 +1,8 @@ +export const escapeRegExpSymbols = (s: string): string => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + +export const wordsRegex = (words: string[]) => new RegExp(words.map(escapeRegExpSymbols).join('|')); + +export const asCaseInsensitive = (regex: RegExp) => { + if (regex.flags.indexOf('i') >= 0) return regex; + return new RegExp(regex.source, `${regex.flags}i`); +};