diff --git a/src/plugins/contentWarning/index.tsx b/src/plugins/contentWarning/index.tsx
new file mode 100644
index 000000000..8f5f52ca9
--- /dev/null
+++ b/src/plugins/contentWarning/index.tsx
@@ -0,0 +1,144 @@
+import definePlugin, { OptionType } from "@utils/types";
+import { Button, Forms, useState, TextInput } from "@webpack/common";
+import { DataStore } from "@api/index";
+import { definePluginSettings } from "@api/Settings";
+import { DeleteIcon } from "@components/Icons";
+import { Devs } from "@utils/constants";
+import { Flex } from "@components/Flex";
+import { useForceUpdater } from "@utils/react";
+
+const WORDS_KEY = "ContentWarning_words";
+
+let triggerWords = [""];
+
+function safeMatchesRegex(s: string, r: string) {
+ if (r == "") return false;
+ try {
+ return s.match(new RegExp(r.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
+ } catch {
+ return false;
+ }
+}
+
+function TriggerContainer({ child }) {
+ const [visible, setVisible] = useState(false);
+
+ if (visible) {
+ return child;
+ } else {
+ return (
setVisible(true)}>
+
+ {child}
+
+
);
+ }
+}
+
+function FlaggedInput({ index, forceUpdate }) {
+ let [value, setValue] = useState(triggerWords[index]);
+
+ if (value != triggerWords[index]) {
+ setValue(triggerWords[index]);
+ }
+
+ let isLast = index == triggerWords.length - 1;
+
+ const updateValue = (v) => {
+ triggerWords[index] = v;
+ setValue(v);
+
+ if (isLast) {
+ triggerWords.push("");
+ forceUpdate();
+ }
+ };
+
+ const removeSelf = () => {
+ triggerWords = triggerWords.slice(0, index).concat(triggerWords.slice(index + 1));
+ forceUpdate();
+ };
+
+ return (
+
+
+
+
+
+ );
+}
+
+function FlaggedWords() {
+ const forceUpdate = useForceUpdater();
+
+ let inputs = triggerWords.map((_, idx) => {
+ return (
+
+ );
+ })
+
+ return (<>
+ Flagged Words
+ {inputs}
+ >);
+}
+
+const settings = definePluginSettings({
+ flagged: {
+ type: OptionType.COMPONENT,
+ component: () => ,
+ }
+});
+
+export default definePlugin({
+ name: "ContentWarning",
+ authors: [Devs.camila314],
+ description: "Allows you to specify certain trigger words that will be blurred by default. Clicking on the blurred content will reveal it.",
+ settings,
+ patches: [
+ {
+ find: ".VOICE_HANGOUT_INVITE?",
+ replacement: {
+ match: /(contentRef:\i}=(\i).+?)\(0,(.+]}\)]}\))/,
+ replace: "$1 $self.modify($2, (0, $3)"
+ }
+ }
+ ],
+
+ beforeSave() {
+ console.log(triggerWords);
+ DataStore.set(WORDS_KEY, triggerWords);
+ return true;
+ },
+
+ modify(e, c) {
+ if (triggerWords.some(w => safeMatchesRegex(e.message.content, w))) {
+ return
+ } else {
+ return c;
+ }
+ },
+
+ async start() {
+ triggerWords = await DataStore.get(WORDS_KEY) ?? [""];
+ console.log(triggerWords);
+ }
+});
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index 09fc0285b..e764cd55a 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -378,6 +378,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({
name: "ProffDea",
id: 609329952180928513n
},
+ camila314: {
+ name: "camila314",
+ id: 738592270617542716n
+ },
UlyssesZhan: {
name: "UlyssesZhan",
id: 586808226058862623n