{isOpen ? "▼" : "▶"}
{title}
@@ -130,7 +131,7 @@ function ListedIds({ listIds, setListIds }) {
}}
look={Button.Looks.BLANK}
size={Button.Sizes.ICON}
- className="keywordnotify-delete">
+ className={cl("delete")}>
@@ -200,18 +201,18 @@ function KeywordEntries() {
onClick={() => removeKeywordEntry(i, update)}
look={Button.Looks.BLANK}
size={Button.Sizes.ICON}
- className="keywordnotify-delete">
+ className={cl("delete")}>
-
+
Whitelist/Blacklist
setListIds(i, e)}/>
-
+
{
values[i].listIds.push("");
@@ -242,7 +243,6 @@ const settings = definePluginSettings({
},
keywords: {
type: OptionType.COMPONENT,
- description: "",
component: () =>
}
});
@@ -254,7 +254,7 @@ export default definePlugin({
settings,
patches: [
{
- find: "}_dispatch(",
+ find: "Dispatch.dispatch(...) called without an action type",
replacement: {
match: /}_dispatch\((\i),\i\){/,
replace: "$&$1=$self.modify($1);"
@@ -268,9 +268,9 @@ export default definePlugin({
}
},
{
- find: "InboxTab.TODOS?(",
+ find: "location:\"RecentsPopout\"",
replacement: {
- match: /:\i&&(\i)===\i\.InboxTab\.TODOS.{1,50}setTab:(\i),onJump:(\i),closePopout:(\i)/,
+ match: /:(\i)===\i\.\i\.MENTIONS\?\(0,.+?setTab:(\i),onJump:(\i),badgeState:\i,closePopout:(\i)/,
replace: ": $1 === 5 ? $self.tryKeywordMenu($2, $3, $4) $&"
}
},
@@ -280,12 +280,19 @@ export default definePlugin({
match: /function (\i)\(\i\){let{message:\i,gotoMessage/,
replace: "$self.renderMsg = $1; $&"
}
+ },
+ {
+ find: ".guildFilter:null",
+ replacement: {
+ match: /onClick:\(\)=>(\i\.\i\.deleteRecentMention\((\i)\.id\))/,
+ replace: "onClick: () => $2._keyword ? $self.deleteKeyword($2.id) : $1"
+ }
}
],
async start() {
keywordEntries = await DataStore.get(KEYWORD_ENTRIES_KEY) ?? [];
- currentUser = await UserUtils.getUser(UserStore.getCurrentUser().id);
+ currentUser = UserStore.getCurrentUser();
this.onUpdate = () => null;
(await DataStore.get(KEYWORD_LOG_KEY) ?? []).map(e => JSON.parse(e)).forEach(e => {
@@ -341,7 +348,6 @@ export default definePlugin({
});
if (matches) {
- // @ts-ignore
m.mentions.push(currentUser);
if (m.author.id !== currentUser.id)
@@ -353,6 +359,10 @@ export default definePlugin({
if (m == null || keywordLog.some(e => e.id === m.id))
return;
+ DataStore.get(KEYWORD_LOG_KEY).then(log => {
+ DataStore.set(KEYWORD_LOG_KEY, [...log, JSON.stringify(m)]);
+ });
+
const thing = createMessageRecord(m);
keywordLog.push(thing);
keywordLog.sort((a, b) => b.timestamp - a.timestamp);
@@ -363,6 +373,10 @@ export default definePlugin({
this.onUpdate();
},
+ deleteKeyword(id) {
+ keywordLog = keywordLog.filter(e => e.id !== id);
+ this.onUpdate();
+ },
keywordTabBar() {
return (
@@ -381,32 +395,23 @@ export default definePlugin({
const [tempLogs, setKeywordLog] = useState(keywordLog);
this.onUpdate = () => {
- const newLog = [...keywordLog];
+ const newLog = Array.from(keywordLog);
setKeywordLog(newLog);
-
- DataStore.set(KEYWORD_LOG_KEY, newLog.map(e => JSON.stringify(e)));
- };
-
- const onDelete = m => {
- keywordLog = keywordLog.filter(e => e.id !== m.id);
- this.onUpdate();
};
const messageRender = (e, t) => {
+ e._keyword = true;
+
+ e.customRenderedContent = {
+ content: highlightKeywords(e.content, keywordEntries.map(e => e.regex))
+ };
+
const msg = this.renderMsg({
message: e,
gotoMessage: t,
dismissible: true
});
- if (msg == null)
- return [null];
-
- msg.props.children[0].props.children.props.onClick = () => onDelete(e);
- msg.props.children[1].props.children[1].props.message.customRenderedContent = {
- content: highlightKeywords(e.content, keywordEntries.map(e => e.regex))
- };
-
return [msg];
};
@@ -419,7 +424,7 @@ export default definePlugin({
channel={channel}
onJump={onJump}
onFetch={() => null}
- onCloseMessage={onDelete}
+ onCloseMessage={this.deleteKeyword}
loadMore={() => null}
messages={tempLogs}
renderEmptyState={() => null}
diff --git a/src/plugins/keywordNotify/style.css b/src/plugins/keywordNotify/style.css
index d549b694d..7ddd397d2 100644
--- a/src/plugins/keywordNotify/style.css
+++ b/src/plugins/keywordNotify/style.css
@@ -1,14 +1,14 @@
-.keywordnotify-delete:hover {
+.vc-keywordnotify-delete:hover {
color: var(--status-danger);
}
-.keywordnotify-delete {
+.vc-keywordnotify-delete {
padding: 0;
color: var(--primary-400);
transition: color 0.2s ease-in-out;
}
-.keywordnotify-collapsible {
+.vc-keywordnotify-collapsible {
display: flex;
align-items: center;
padding: 8px;
From 4e7e09f4ffeb6aa79fadc6f7f35806cd740b3550 Mon Sep 17 00:00:00 2001
From: camila314 <47485054+camila314@users.noreply.github.com>
Date: Sun, 23 Jun 2024 14:33:11 -0500
Subject: [PATCH 23/26] review changes
---
src/plugins/keywordNotify/index.tsx | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/plugins/keywordNotify/index.tsx b/src/plugins/keywordNotify/index.tsx
index f9c556078..da7da2c7b 100644
--- a/src/plugins/keywordNotify/index.tsx
+++ b/src/plugins/keywordNotify/index.tsx
@@ -7,7 +7,7 @@
import "./style.css";
import definePlugin, { OptionType } from "@utils/types";
-import { Button, ChannelStore, Forms, SearchableSelect,SelectedChannelStore, TabBar, TextInput, UserStore, UserUtils, useState } from "@webpack/common";
+import { Button, ChannelStore, Forms, Select,SelectedChannelStore, TabBar, TextInput, UserStore, UserUtils, useState } from "@webpack/common";
import { classNameFactory } from "@api/Styles";
import { DataStore } from "@api/index";
import { definePluginSettings } from "@api/Settings";
@@ -147,16 +147,17 @@ function ListedIds({ listIds, setListIds }) {
function ListTypeSelector({ listType, setListType }) {
return (
- v === listType}
closeOnSelect={true}
value={listType}
- onChange={setListType}
+ select={setListType}
+ serialize={v => v}
/>
);
}
@@ -303,7 +304,7 @@ export default definePlugin({
applyKeywordEntries(m: Message) {
let matches = false;
- keywordEntries.forEach(entry => {
+ for (let entry of keywordEntries) {
if (entry.regex === "") {
return;
}
@@ -345,7 +346,7 @@ export default definePlugin({
}
}
}
- });
+ }
if (matches) {
m.mentions.push(currentUser);
From bac0ac1b6b2ea786fc7d7cb58a5e3fa51e9f94dd Mon Sep 17 00:00:00 2001
From: camila314 <47485054+camila314@users.noreply.github.com>
Date: Mon, 24 Jun 2024 01:56:14 -0500
Subject: [PATCH 24/26] do good changes
---
src/plugins/keywordNotify/index.tsx | 30 ++++++++++++++---------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/src/plugins/keywordNotify/index.tsx b/src/plugins/keywordNotify/index.tsx
index da7da2c7b..6b2db721b 100644
--- a/src/plugins/keywordNotify/index.tsx
+++ b/src/plugins/keywordNotify/index.tsx
@@ -44,9 +44,9 @@ async function removeKeywordEntry(idx: number, forceUpdate: () => void) {
forceUpdate();
}
-function safeMatchesRegex(s: string, r: string) {
+function safeMatchesRegex(str: string, regex: string) {
try {
- return s.match(new RegExp(r));
+ return str.match(new RegExp(regex));
} catch {
return false;
}
@@ -57,24 +57,24 @@ enum ListType {
Whitelist = "Whitelist"
}
-function highlightKeywords(s: string, r: Array) {
+function highlightKeywords(str: string, regexes: Array) {
let regex: RegExp;
try {
- regex = new RegExp(r.join("|"), "g");
+ regex = new RegExp(regexes.join("|"), "g");
} catch {
- return [s];
+ return [str];
}
- const matches = s.match(regex);
+ const matches = str.match(regex);
if (!matches)
- return [s];
+ return [str];
const parts = [...matches.map(e => {
- const idx = s.indexOf(e);
- const before = s.substring(0, idx);
- s = s.substring(idx + e.length);
+ const idx = str.indexOf(e);
+ const before = str.substring(0, idx);
+ str = str.substring(idx + e.length);
return before;
- }, s), s];
+ }, str), str];
return parts.map(e => [
({e} ),
@@ -318,17 +318,15 @@ export default definePlugin({
}
const whitelistMode = entry.listType === ListType.Whitelist;
+
if (!whitelistMode && listed) {
return;
}
if (whitelistMode && !listed) {
return;
}
-
- if (settings.store.ignoreBots && m.author.bot) {
- if (!whitelistMode || !entry.listIds.includes(m.author.id)) {
- return;
- }
+ if (settings.store.ignoreBots && m.author.bot && (!whitelistMode || !entry.listIds.includes(m.author.id))) {
+ return;
}
if (safeMatchesRegex(m.content, entry.regex)) {
From a572da18f5a445bf629ec7d422d32d76e1d1e4e6 Mon Sep 17 00:00:00 2001
From: camila314 <47485054+camila314@users.noreply.github.com>
Date: Mon, 24 Jun 2024 02:46:52 -0500
Subject: [PATCH 25/26] Ignore case toggle
---
src/plugins/keywordNotify/index.tsx | 61 +++++++++++++++++------------
1 file changed, 36 insertions(+), 25 deletions(-)
diff --git a/src/plugins/keywordNotify/index.tsx b/src/plugins/keywordNotify/index.tsx
index 6b2db721b..8718337be 100644
--- a/src/plugins/keywordNotify/index.tsx
+++ b/src/plugins/keywordNotify/index.tsx
@@ -7,7 +7,7 @@
import "./style.css";
import definePlugin, { OptionType } from "@utils/types";
-import { Button, ChannelStore, Forms, Select,SelectedChannelStore, TabBar, TextInput, UserStore, UserUtils, useState } from "@webpack/common";
+import { Button, ChannelStore, Forms, Select, Switch, SelectedChannelStore, TabBar, TextInput, UserStore, UserUtils, useState } from "@webpack/common";
import { classNameFactory } from "@api/Styles";
import { DataStore } from "@api/index";
import { definePluginSettings } from "@api/Settings";
@@ -19,7 +19,9 @@ import { Margins } from "@utils/margins";
import { Message, User } from "discord-types/general/index.js";
import { useForceUpdater } from "@utils/react";
-let keywordEntries: Array<{ regex: string, listIds: Array, listType: ListType }> = [];
+type KeywordEntry = { regex: string, listIds: Array, listType: ListType, ignoreCase: boolean };
+
+let keywordEntries: Array = [];
let currentUser: User;
let keywordLog: Array = [];
@@ -33,7 +35,7 @@ const KEYWORD_LOG_KEY = "KeywordNotify_log";
const cl = classNameFactory("vc-keywordnotify-");
async function addKeywordEntry(forceUpdate: () => void) {
- keywordEntries.push({ regex: "", listIds: [], listType: ListType.BlackList });
+ keywordEntries.push({ regex: "", listIds: [], listType: ListType.BlackList, ignoreCase: false });
await DataStore.set(KEYWORD_ENTRIES_KEY, keywordEntries);
forceUpdate();
}
@@ -44,9 +46,9 @@ async function removeKeywordEntry(idx: number, forceUpdate: () => void) {
forceUpdate();
}
-function safeMatchesRegex(str: string, regex: string) {
+function safeMatchesRegex(str: string, regex: string, flags: string) {
try {
- return str.match(new RegExp(regex));
+ return str.match(new RegExp(regex, flags));
} catch {
return false;
}
@@ -57,29 +59,26 @@ enum ListType {
Whitelist = "Whitelist"
}
-function highlightKeywords(str: string, regexes: Array) {
- let regex: RegExp;
+function highlightKeywords(str: string, entries: Array) {
+ let regexes: Array;
try {
- regex = new RegExp(regexes.join("|"), "g");
- } catch {
+ regexes = entries.map(e => new RegExp(e.regex, "g" + (e.ignoreCase ? "i" : "")));
+ } catch (err) {
return [str];
}
- const matches = str.match(regex);
- if (!matches)
+ const matches = regexes.map(r => str.match(r)).flat().filter(e => e != null);
+ if (matches.length == 0) {
return [str];
+ }
- const parts = [...matches.map(e => {
- const idx = str.indexOf(e);
- const before = str.substring(0, idx);
- str = str.substring(idx + e.length);
- return before;
- }, str), str];
+ const idx = str.indexOf(matches[0]);
- return parts.map(e => [
- ({e} ),
- matches!.length ? ({matches!.splice(0, 1)[0]} ) : []
- ]);
+ return [
+ {str.substring(0, idx)} ,
+ {matches[0]} ,
+ {str.substring(idx + matches[0].length)}
+ ];
}
function Collapsible({ title, children }) {
@@ -206,6 +205,16 @@ function KeywordEntries() {
+
{
+ values[i].ignoreCase = !values[i].ignoreCase;
+ update();
+ }}
+ style={{ marginTop: "0.5em", marginRight: "40px" }}
+ >
+ Ignore Case
+
Whitelist/Blacklist
@@ -325,20 +334,22 @@ export default definePlugin({
if (whitelistMode && !listed) {
return;
}
+
if (settings.store.ignoreBots && m.author.bot && (!whitelistMode || !entry.listIds.includes(m.author.id))) {
return;
}
- if (safeMatchesRegex(m.content, entry.regex)) {
+ const flags = entry.ignoreCase ? "i" : "";
+ if (safeMatchesRegex(m.content, entry.regex, flags)) {
matches = true;
}
for (const embed of m.embeds as any) {
- if (safeMatchesRegex(embed.description, entry.regex) || safeMatchesRegex(embed.title, entry.regex)) {
+ if (safeMatchesRegex(embed.description, entry.regex, flags) || safeMatchesRegex(embed.title, entry.regex, flags)) {
matches = true;
} else if (embed.fields != null) {
for (const field of embed.fields as Array<{ name: string, value: string }>) {
- if (safeMatchesRegex(field.value, entry.regex) || safeMatchesRegex(field.name, entry.regex)) {
+ if (safeMatchesRegex(field.value, entry.regex, flags) || safeMatchesRegex(field.name, entry.regex, flags)) {
matches = true;
}
}
@@ -402,7 +413,7 @@ export default definePlugin({
e._keyword = true;
e.customRenderedContent = {
- content: highlightKeywords(e.content, keywordEntries.map(e => e.regex))
+ content: highlightKeywords(e.content, keywordEntries)
};
const msg = this.renderMsg({
From bfbb1f1aadbb890521a3eb94ae892d0919735049 Mon Sep 17 00:00:00 2001
From: x3rt
Date: Mon, 24 Jun 2024 10:35:24 -0600
Subject: [PATCH 26/26] Add x3rt to authors
---
src/plugins/keywordNotify/index.tsx | 2 +-
src/utils/constants.ts | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/plugins/keywordNotify/index.tsx b/src/plugins/keywordNotify/index.tsx
index 8718337be..411930f37 100644
--- a/src/plugins/keywordNotify/index.tsx
+++ b/src/plugins/keywordNotify/index.tsx
@@ -259,7 +259,7 @@ const settings = definePluginSettings({
export default definePlugin({
name: "KeywordNotify",
- authors: [Devs.camila314],
+ authors: [Devs.camila314, Devs.x3rt],
description: "Sends a notification if a given message matches certain keywords or regexes",
settings,
patches: [
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index e764cd55a..39f1cfef3 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -382,6 +382,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "camila314",
id: 738592270617542716n
},
+ x3rt: {
+ name: "x3rt",
+ id: 131602100332396544n
+ },
UlyssesZhan: {
name: "UlyssesZhan",
id: 586808226058862623n