Restore Missing Plugins
This commit is contained in:
parent
dd9811147b
commit
630fdb0119
5 changed files with 421 additions and 211 deletions
243
src/equicordplugins/animalese/index.ts
Normal file
243
src/equicordplugins/animalese/index.ts
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { SelectedChannelStore, UserStore } from "@webpack/common";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
volume: {
|
||||
type: OptionType.SLIDER,
|
||||
description: "Volume of the animalese sound",
|
||||
default: 0.5,
|
||||
markers: [0, 0.1, 0.25, 0.5, 0.6, 0.75, 1],
|
||||
},
|
||||
speed: {
|
||||
type: OptionType.SLIDER,
|
||||
description: "Speed of the animalese sound",
|
||||
default: 1,
|
||||
markers: [0.5, 0.75, 1, 1.25, 1.5],
|
||||
},
|
||||
pitch: {
|
||||
type: OptionType.SLIDER,
|
||||
description: "Pitch multiplier",
|
||||
default: 1,
|
||||
markers: [0.75, 0.8, 0.85, 1, 1.15, 1.25, 1.35, 1.5],
|
||||
},
|
||||
messageLengthLimit: {
|
||||
type: OptionType.NUMBER,
|
||||
description: "Maximum length of message to process",
|
||||
default: 50,
|
||||
},
|
||||
processOwnMessages: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Enable to yap your own messages too",
|
||||
default: true,
|
||||
},
|
||||
soundQuality: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Quality of sound to use",
|
||||
options: [
|
||||
{
|
||||
label: "High",
|
||||
value: "high",
|
||||
default: true
|
||||
},
|
||||
{
|
||||
label: "Medium",
|
||||
value: "med"
|
||||
},
|
||||
{
|
||||
label: "Low",
|
||||
value: "low"
|
||||
},
|
||||
{
|
||||
label: "Lowest",
|
||||
value: "low"
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
let audioContext: AudioContext | null = null;
|
||||
|
||||
// better than my old hardcoded garbage
|
||||
const highSounds = Array.from(
|
||||
{ length: 30 },
|
||||
(_, i) => `sound${String(i + 1).padStart(2, "0")}.wav`
|
||||
);
|
||||
const soundBuffers: Record<string, AudioBuffer> = {};
|
||||
|
||||
const BASE_URL_HIGH = "https://raw.githubusercontent.com/Equicord/Equibored/main/sounds/animalese";
|
||||
|
||||
async function initSoundBuffers() {
|
||||
if (!audioContext) audioContext = new AudioContext();
|
||||
const quality = settings.store.soundQuality;
|
||||
for (const file of highSounds) {
|
||||
const nameWithoutExt = file.replace(".wav", "");
|
||||
soundBuffers[nameWithoutExt] = await loadSound(
|
||||
`${BASE_URL_HIGH}/${quality}/${file}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSound(url: string): Promise<AudioBuffer> {
|
||||
if (!audioContext) audioContext = new AudioContext();
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error("Network response was not OK");
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
return audioContext.decodeAudioData(arrayBuffer);
|
||||
}
|
||||
|
||||
async function generateAnimalese(text: string): Promise<AudioBuffer | null> {
|
||||
if (!audioContext) audioContext = new AudioContext();
|
||||
|
||||
const soundIndices: string[] = [];
|
||||
const text_lower = text.toLowerCase();
|
||||
|
||||
for (let i = 0; i < text_lower.length; i++) {
|
||||
const char = text_lower[i];
|
||||
if (char === "s" && text_lower[i + 1] === "h") {
|
||||
soundIndices.push("sound27");
|
||||
i++;
|
||||
} else if (char === "t" && text_lower[i + 1] === "h") {
|
||||
soundIndices.push("sound28");
|
||||
i++;
|
||||
} else if (
|
||||
char === "h" &&
|
||||
(text_lower[i - 1] === "s" || text_lower[i - 1] === "t")
|
||||
) {
|
||||
continue;
|
||||
} else if (char === "," || char === "?") {
|
||||
soundIndices.push("sound30");
|
||||
} else if (char === text_lower[i - 1]) {
|
||||
continue;
|
||||
} else if (char.match(/[a-z]/)) {
|
||||
const index = char.charCodeAt(0) - 96;
|
||||
soundIndices.push(`sound${String(index).padStart(2, "0")}`);
|
||||
}
|
||||
}
|
||||
|
||||
// No valid characters? Just return null
|
||||
if (soundIndices.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const totalDuration = soundIndices.length * 0.1;
|
||||
const frameCount = Math.max(1, Math.floor(audioContext.sampleRate * totalDuration));
|
||||
|
||||
const outputBuffer = audioContext.createBuffer(
|
||||
1,
|
||||
frameCount,
|
||||
audioContext.sampleRate
|
||||
);
|
||||
const outputData = outputBuffer.getChannelData(0);
|
||||
|
||||
let offset = 0;
|
||||
const baseLetterDuration = audioContext.sampleRate * (0.09 / settings.store.speed);
|
||||
// ~90ms per letter at 1x speed (tweakable!)
|
||||
|
||||
for (let i = 0; i < soundIndices.length; i++) {
|
||||
const buffer = soundBuffers[soundIndices[i]];
|
||||
if (!buffer) continue;
|
||||
|
||||
const variation = 0.15;
|
||||
let pitchShift = (2.8 * settings.store.pitch) + (Math.random() * variation);
|
||||
|
||||
const isQuestion = text_lower.endsWith("?");
|
||||
if (isQuestion && i >= soundIndices.length * 0.8) {
|
||||
const progress =
|
||||
(i - soundIndices.length * 0.8) / (soundIndices.length * 0.2);
|
||||
pitchShift += progress * 0.1 + 0.1;
|
||||
}
|
||||
|
||||
const inputData = buffer.getChannelData(0);
|
||||
const inputLength = inputData.length;
|
||||
const outputLength = Math.floor(inputLength / pitchShift);
|
||||
|
||||
// copy sound into the slot
|
||||
for (let j = 0; j < outputLength; j++) {
|
||||
const inputIndex = Math.floor(j * pitchShift);
|
||||
const targetIndex = offset + j;
|
||||
if (inputIndex < inputLength && targetIndex < outputData.length) {
|
||||
outputData[targetIndex] = inputData[inputIndex];
|
||||
}
|
||||
}
|
||||
|
||||
// instead of stacking lengths, jump forward a *fixed slot* per character
|
||||
offset += Math.floor(baseLetterDuration);
|
||||
}
|
||||
|
||||
return outputBuffer;
|
||||
}
|
||||
|
||||
async function playSound(buffer: AudioBuffer, volume: number) {
|
||||
if (!audioContext) audioContext = new AudioContext();
|
||||
const source = audioContext.createBufferSource();
|
||||
const gainNode = audioContext.createGain();
|
||||
|
||||
source.buffer = buffer;
|
||||
source.playbackRate.value = settings.store.pitch;
|
||||
gainNode.gain.value = volume;
|
||||
|
||||
source.connect(gainNode);
|
||||
gainNode.connect(audioContext.destination);
|
||||
|
||||
source.start();
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "Animalese",
|
||||
description: "Plays animal crossing animalese for every message sent (they yap a lot)",
|
||||
authors: [EquicordDevs.ryanamay, EquicordDevs.Mocha],
|
||||
settings,
|
||||
|
||||
flux: {
|
||||
async MESSAGE_CREATE({ optimistic, type, message, channelId }) {
|
||||
if (optimistic || type !== "MESSAGE_CREATE") return;
|
||||
if (message.state === "SENDING") return;
|
||||
if (!message.content || message.author?.bot || channelId !== SelectedChannelStore.getChannelId()) return;
|
||||
|
||||
const urlPattern = /https?:\/\/[^\s]+/;
|
||||
const maxLength = settings.store.messageLengthLimit || 100;
|
||||
const processOwnMessages = settings.store.processOwnMessages ?? true;
|
||||
|
||||
if (
|
||||
urlPattern.test(message.content)
|
||||
|| message.content.length > maxLength
|
||||
|| !processOwnMessages
|
||||
&& String(message.author.id) === String(UserStore.getCurrentUser().id)
|
||||
) return;
|
||||
|
||||
try {
|
||||
const buffer = await generateAnimalese(message.content);
|
||||
if (buffer) await playSound(buffer, settings.store.volume);
|
||||
} catch (err) {
|
||||
console.error("[Animalese]", err);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
start() {
|
||||
// Only subscribe once!
|
||||
const init = async () => {
|
||||
if (!audioContext) {
|
||||
audioContext = new AudioContext();
|
||||
await initSoundBuffers();
|
||||
}
|
||||
init();
|
||||
};
|
||||
init();
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (audioContext) {
|
||||
audioContext.close();
|
||||
audioContext = null;
|
||||
}
|
||||
},
|
||||
});
|
||||
3
src/equicordplugins/equissant/README.md
Normal file
3
src/equicordplugins/equissant/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Equissant
|
||||
|
||||
Plays crossant every specified amount of clicks
|
||||
174
src/equicordplugins/moyai/index.ts
Normal file
174
src/equicordplugins/moyai/index.ts
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Vencord, a modification for Discord's desktop app
|
||||
* Copyright (c) 2022 Vendicated and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { sleep } from "@utils/misc";
|
||||
import definePlugin, { makeRange, OptionType } from "@utils/types";
|
||||
import { Message, ReactionEmoji } from "@vencord/discord-types";
|
||||
import { RelationshipStore, SelectedChannelStore, UserStore } from "@webpack/common";
|
||||
|
||||
interface IMessageCreate {
|
||||
type: "MESSAGE_CREATE";
|
||||
optimistic: boolean;
|
||||
isPushNotification: boolean;
|
||||
channelId: string;
|
||||
message: Message;
|
||||
}
|
||||
|
||||
interface IReactionAdd {
|
||||
type: "MESSAGE_REACTION_ADD";
|
||||
optimistic: boolean;
|
||||
channelId: string;
|
||||
messageId: string;
|
||||
messageAuthorId: string;
|
||||
userId: "195136840355807232";
|
||||
emoji: ReactionEmoji;
|
||||
}
|
||||
|
||||
interface IVoiceChannelEffectSendEvent {
|
||||
type: string;
|
||||
emoji?: ReactionEmoji; // Just in case...
|
||||
channelId: string;
|
||||
userId: string;
|
||||
animationType: number;
|
||||
animationId: number;
|
||||
}
|
||||
|
||||
const MOYAI = "🗿";
|
||||
const MOYAI_URL = "https://github.com/Equicord/Equibored/raw/main/sounds/moyai/moyai.mp3";
|
||||
const MOYAI_URL_HD = "https://github.com/Equicord/Equibored/raw/main/sounds/moyai/moyai.wav";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
volume: {
|
||||
description: "Volume of the 🗿🗿🗿",
|
||||
type: OptionType.SLIDER,
|
||||
markers: makeRange(0, 1, 0.1),
|
||||
default: 0.5,
|
||||
stickToMarkers: false
|
||||
},
|
||||
quality: {
|
||||
description: "Quality of the 🗿🗿🗿",
|
||||
type: OptionType.SELECT,
|
||||
options: [
|
||||
{ label: "Normal", value: "Normal", default: true },
|
||||
{ label: "HD", value: "HD" }
|
||||
],
|
||||
},
|
||||
triggerWhenUnfocused: {
|
||||
description: "Trigger the 🗿 even when the window is unfocused",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true
|
||||
},
|
||||
ignoreBots: {
|
||||
description: "Ignore bots",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true
|
||||
},
|
||||
ignoreBlocked: {
|
||||
description: "Ignore blocked users",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "Moyai",
|
||||
authors: [Devs.Megu, Devs.Nuckyz],
|
||||
description: "🗿🗿🗿🗿🗿🗿🗿🗿",
|
||||
settings,
|
||||
|
||||
flux: {
|
||||
async MESSAGE_CREATE({ optimistic, type, message, channelId }: IMessageCreate) {
|
||||
if (optimistic || type !== "MESSAGE_CREATE") return;
|
||||
if (message.state === "SENDING") return;
|
||||
if (settings.store.ignoreBots && message.author?.bot) return;
|
||||
if (settings.store.ignoreBlocked && RelationshipStore.isBlocked(message.author?.id)) return;
|
||||
if (!message.content) return;
|
||||
if (channelId !== SelectedChannelStore.getChannelId()) return;
|
||||
|
||||
const moyaiCount = getMoyaiCount(message.content);
|
||||
|
||||
for (let i = 0; i < moyaiCount; i++) {
|
||||
boom();
|
||||
await sleep(300);
|
||||
}
|
||||
},
|
||||
|
||||
MESSAGE_REACTION_ADD({ optimistic, type, channelId, userId, messageAuthorId, emoji }: IReactionAdd) {
|
||||
if (optimistic || type !== "MESSAGE_REACTION_ADD") return;
|
||||
if (settings.store.ignoreBots && UserStore.getUser(userId)?.bot) return;
|
||||
if (settings.store.ignoreBlocked && RelationshipStore.isBlocked(messageAuthorId)) return;
|
||||
if (channelId !== SelectedChannelStore.getChannelId()) return;
|
||||
|
||||
const name = emoji.name.toLowerCase();
|
||||
if (name !== MOYAI && !name.includes("moyai") && !name.includes("moai")) return;
|
||||
|
||||
boom();
|
||||
},
|
||||
|
||||
VOICE_CHANNEL_EFFECT_SEND({ emoji }: IVoiceChannelEffectSendEvent) {
|
||||
if (!emoji?.name) return;
|
||||
const name = emoji.name.toLowerCase();
|
||||
if (name !== MOYAI && !name.includes("moyai") && !name.includes("moai")) return;
|
||||
|
||||
boom();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function countOccurrences(sourceString: string, subString: string) {
|
||||
let i = 0;
|
||||
let lastIdx = 0;
|
||||
while ((lastIdx = sourceString.indexOf(subString, lastIdx) + 1) !== 0)
|
||||
i++;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
function countMatches(sourceString: string, pattern: RegExp) {
|
||||
if (!pattern.global)
|
||||
throw new Error("pattern must be global");
|
||||
|
||||
let i = 0;
|
||||
while (pattern.test(sourceString))
|
||||
i++;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
const customMoyaiRe = /<a?:\w*moy?ai\w*:\d{17,20}>/gi;
|
||||
|
||||
function getMoyaiCount(message: string) {
|
||||
const count = countOccurrences(message, MOYAI)
|
||||
+ countMatches(message, customMoyaiRe);
|
||||
|
||||
return Math.min(count, 10);
|
||||
}
|
||||
|
||||
function boom() {
|
||||
if (!settings.store.triggerWhenUnfocused && !document.hasFocus()) return;
|
||||
const audioElement = document.createElement("audio");
|
||||
|
||||
audioElement.src = settings.store.quality === "HD"
|
||||
? MOYAI_URL_HD
|
||||
: MOYAI_URL;
|
||||
|
||||
audioElement.volume = settings.store.volume;
|
||||
audioElement.play();
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import { addMessagePreSendListener, MessageSendListener, removeMessagePreSendListener } from "@api/MessageEvents";
|
||||
import { definePluginSettings, Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { disableStyle, enableStyle } from "@api/Styles";
|
||||
import { PaintbrushIcon } from "@components/Icons";
|
||||
import { EquicordDevs } from "@utils/constants";
|
||||
|
|
@ -133,10 +133,6 @@ export default definePlugin({
|
|||
await requireSettingsMenu();
|
||||
|
||||
enableStyle(css);
|
||||
if (Settings.plugins?.RemixMe?.enabled) {
|
||||
Settings.plugins.RemixMe.enabled = false;
|
||||
settings.store.remixMe = true;
|
||||
}
|
||||
if (settings.store.remixMe) {
|
||||
addMessagePreSendListener(handleMessage);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,206 +0,0 @@
|
|||
/*
|
||||
* Vencord, a modification for Discord's desktop app
|
||||
* Copyright (c) 2022 exhq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { findOption, RequiredMessageOption } from "@api/Commands";
|
||||
import { addMessagePreEditListener, addMessagePreSendListener, MessageObject, removeMessagePreEditListener, removeMessagePreSendListener } from "@api/MessageEvents";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
const endings = [
|
||||
"rawr x3",
|
||||
"OwO",
|
||||
"UwU",
|
||||
"o.O",
|
||||
"-.-",
|
||||
">w<",
|
||||
"(⑅˘꒳˘)",
|
||||
"(ꈍᴗꈍ)",
|
||||
"(˘ω˘)",
|
||||
"(U ᵕ U❁)",
|
||||
"σωσ",
|
||||
"òωó",
|
||||
"(///ˬ///✿)",
|
||||
"(U ﹏ U)",
|
||||
"( ͡o ω ͡o )",
|
||||
"ʘwʘ",
|
||||
":3",
|
||||
":3", // important enough to have twice
|
||||
":3", // important enough to have thrice
|
||||
"XD",
|
||||
"nyaa~~",
|
||||
"mya",
|
||||
">_<",
|
||||
"😳",
|
||||
"🥺",
|
||||
"😳😳😳",
|
||||
"rawr",
|
||||
"^^",
|
||||
"^^;;",
|
||||
"(ˆ ﻌ ˆ)♡",
|
||||
"^•ﻌ•^",
|
||||
"/(^•ω•^)",
|
||||
"(✿oωo)"
|
||||
];
|
||||
|
||||
const replacements = [
|
||||
["small", "smol"],
|
||||
["cute", "kawaii"],
|
||||
["fluff", "floof"],
|
||||
["love", "luv"],
|
||||
["stupid", "baka"],
|
||||
["what", "nani"],
|
||||
["meow", "nya"],
|
||||
["hello", "hewwo"],
|
||||
];
|
||||
|
||||
const settings = definePluginSettings({
|
||||
uwuEveryMessage: {
|
||||
description: "Make every single message uwuified",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
restartNeeded: false
|
||||
},
|
||||
uwuEverything: {
|
||||
description: "Makes *all* text uwuified - really bad idea",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
restartNeeded: true
|
||||
}
|
||||
});
|
||||
|
||||
function selectRandomElement(arr) {
|
||||
// generate a random index based on the length of the array
|
||||
const randomIndex = Math.floor(Math.random() * arr.length);
|
||||
|
||||
// return the element at the randomly generated index
|
||||
return arr[randomIndex];
|
||||
}
|
||||
const isOneCharacterString = (str: string): boolean => {
|
||||
return str.split("").every((char: string) => char === str[0]);
|
||||
};
|
||||
|
||||
function replaceString(inputString) {
|
||||
let replaced = false;
|
||||
for (const replacement of replacements) {
|
||||
const regex = new RegExp(`\\b${replacement[0]}\\b`, "gi");
|
||||
if (regex.test(inputString)) {
|
||||
inputString = inputString.replace(regex, replacement[1]);
|
||||
replaced = true;
|
||||
}
|
||||
}
|
||||
return replaced ? inputString : false;
|
||||
}
|
||||
|
||||
function uwuify(message: string): string {
|
||||
const rule = /\S+|\s+/g;
|
||||
const words: string[] | null = message.match(rule);
|
||||
let answer = "";
|
||||
|
||||
if (words === null) return "";
|
||||
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
if (isOneCharacterString(words[i]) || words[i].startsWith("https://")) {
|
||||
answer += words[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!replaceString(words[i])) {
|
||||
answer += words[i]
|
||||
.replace(/n(?=[aeo])/g, "ny")
|
||||
.replace(/l|r/g, "w");
|
||||
} else answer += replaceString(words[i]);
|
||||
|
||||
}
|
||||
|
||||
answer += " " + selectRandomElement(endings);
|
||||
return answer;
|
||||
}
|
||||
|
||||
function uwuifyArray(arr) {
|
||||
const newArr = [...arr];
|
||||
|
||||
newArr.forEach((item, index) => {
|
||||
if (Array.isArray(item)) {
|
||||
newArr[index] = uwuifyArray(item);
|
||||
} else if (typeof item === "string") {
|
||||
newArr[index] = uwuify(item);
|
||||
}
|
||||
});
|
||||
|
||||
return newArr;
|
||||
}
|
||||
|
||||
|
||||
// actual command declaration
|
||||
export default definePlugin({
|
||||
name: "UwUifier",
|
||||
description: "Make everything uwu",
|
||||
authors: [Devs.amy],
|
||||
dependencies: ["MessageEventsAPI"],
|
||||
settings,
|
||||
|
||||
commands: [
|
||||
{
|
||||
name: "uwuify",
|
||||
description: "uwuifies your messages",
|
||||
options: [RequiredMessageOption],
|
||||
|
||||
execute: opts => ({
|
||||
content: uwuify(findOption(opts, "message", "")),
|
||||
}),
|
||||
},
|
||||
],
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: ".isPureReactComponent=!0;",
|
||||
predicate: () => settings.store.uwuEverything,
|
||||
replacement: {
|
||||
match: /(?<=.defaultProps\)void 0.{0,60})(\i)\)/,
|
||||
replace: "$self.uwuifyProps($1))"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
uwuifyProps(props: any) {
|
||||
if (!props.children) return props;
|
||||
if (typeof props.children === "string") props.children = uwuify(props.children);
|
||||
else if (Array.isArray(props.children)) props.children = uwuifyArray(props.children);
|
||||
return props;
|
||||
},
|
||||
|
||||
onSend(msg: MessageObject) {
|
||||
// Only run when it's enabled
|
||||
if (settings.store.uwuEveryMessage) {
|
||||
msg.content = uwuify(msg.content);
|
||||
}
|
||||
},
|
||||
|
||||
start() {
|
||||
this.preSend = addMessagePreSendListener((_, msg) => this.onSend(msg));
|
||||
this.preEdit = addMessagePreEditListener((_cid, _mid, msg) =>
|
||||
this.onSend(msg)
|
||||
);
|
||||
},
|
||||
|
||||
stop() {
|
||||
removeMessagePreSendListener(this.preSend);
|
||||
removeMessagePreEditListener(this.preEdit);
|
||||
},
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue