/* * Vencord, a Discord client mod * Copyright (c) 2023 Vendicated, camila314, and contributors * SPDX-License-Identifier: GPL-3.0-or-later */ import "./style.css"; import { DataStore } from "@api/index"; import { definePluginSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; import { Flex } from "@components/Flex"; import { FormSwitch } from "@components/FormSwitch"; import { Heading, HeadingTertiary } from "@components/Heading"; import { DeleteIcon } from "@components/Icons"; import { EquicordDevs } from "@utils/constants"; import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import { useForceUpdater } from "@utils/react"; import definePlugin, { OptionType } from "@utils/types"; import { Message } from "@vencord/discord-types"; import { findByCodeLazy, findByPropsLazy } from "@webpack"; import { Button, ChannelStore, FluxDispatcher, Select, SelectedChannelStore, TabBar, TextInput, Tooltip, UserStore, useState } from "@webpack/common"; import type { JSX, PropsWithChildren } from "react"; type IconProps = JSX.IntrinsicElements["svg"]; type KeywordEntry = { regex: string, listIds: Array, listType: ListType, ignoreCase: boolean; }; let keywordEntries: Array = []; let keywordLog: Array = []; let interceptor: (e: any) => void; const recentMentionsPopoutClass = findByPropsLazy("recentMentionsPopout"); const tabClass = findByPropsLazy("inboxTitle", "tab"); const buttonClass = findByPropsLazy("size36"); const Popout = findByCodeLazy("getProTip", "canCloseAllMessages:"); const createMessageRecord = findByCodeLazy(".createFromServer(", ".isBlockedForMessage", "messageReference:"); const KEYWORD_ENTRIES_KEY = "KeywordNotify_keywordEntries"; const KEYWORD_LOG_KEY = "KeywordNotify_log"; const cl = classNameFactory("vc-keywordnotify-"); async function addKeywordEntry(forceUpdate: () => void) { keywordEntries.push({ regex: "", listIds: [], listType: ListType.BlackList, ignoreCase: false }); await DataStore.set(KEYWORD_ENTRIES_KEY, keywordEntries); forceUpdate(); } async function removeKeywordEntry(idx: number, forceUpdate: () => void) { keywordEntries.splice(idx, 1); await DataStore.set(KEYWORD_ENTRIES_KEY, keywordEntries); forceUpdate(); } function safeMatchesRegex(str: string, regex: string, flags: string) { try { return str.match(new RegExp(regex, flags)); } catch { return false; } } enum ListType { BlackList = "BlackList", Whitelist = "Whitelist" } interface BaseIconProps extends IconProps { viewBox: string; } function highlightKeywords(str: string, entries: Array) { let regexes: Array; try { regexes = entries.map(e => new RegExp(e.regex, "g" + (e.ignoreCase ? "i" : ""))); } catch (err) { return [str]; } const matches = regexes.map(r => str.match(r)).flat().filter(e => e != null) as Array; if (matches.length === 0) { return [str]; } const idx = str.indexOf(matches[0]); return [ <> {str.substring(0, idx)}, {matches[0]}, {str.substring(idx + matches[0].length)} ]; } function Collapsible({ title, children }) { const [isOpen, setIsOpen] = useState(false); return (
{isOpen && children}
); } function ListedIds({ listIds, setListIds }) { const update = useForceUpdater(); const [values] = useState(listIds); async function onChange(e: string, index: number) { values[index] = e.trim(); setListIds(values); update(); } const elements = values.map((currentValue: string, index: number) => { return ( <>
onChange(e, index)} />
); }); return ( <> {elements} ); } function ListTypeSelector({ listType, setListType }: { listType: ListType, setListType: (v: ListType) => void; }) { return (