vd-plugins/plugins/Moyai/src/index.ts

103 lines
2.9 KiB
TypeScript
Raw Normal View History

2026-07-02 13:14:54 +02:00
import { storage } from "@vendetta/plugin";
import { findByStoreName } from "@vendetta/metro";
import { ReactNative, FluxDispatcher } from "@vendetta/metro/common";
import MoyaiSettings from "./settings";
const { DCDSoundManager } = ReactNative.NativeModules;
const SelectedChannelStore = findByStoreName("SelectedChannelStore");
const THUD_URL =
"https://raw.githubusercontent.com/Metastruct/garrysmod-chatsounds/master/sound/chatsounds/autoadd/memes/overused%20thud.ogg";
const SOUND_ID = 6969;
let SOUND_DURATION = -1;
const prepareSound = () =>
new Promise((resolve) => {
try {
DCDSoundManager.prepare(THUD_URL, "media", SOUND_ID, (_, meta) =>
resolve(meta)
);
} catch {
resolve({ duration: 1000 });
}
});
let playingTimeout: ReturnType<typeof setTimeout> | null = null;
let playing = false;
async function playSound() {
2026-07-02 13:18:23 +02:00
if (!soundPrepared) return;
2026-07-02 13:14:54 +02:00
try {
if (playing) {
if (playingTimeout != null) clearTimeout(playingTimeout);
DCDSoundManager.stop(SOUND_ID);
playing = false;
}
playing = true;
await DCDSoundManager.play(SOUND_ID);
playingTimeout = setTimeout(() => {
playing = false;
2026-07-02 13:18:23 +02:00
if (soundPrepared) DCDSoundManager.stop(SOUND_ID);
2026-07-02 13:14:54 +02:00
playingTimeout = null;
}, SOUND_DURATION);
} catch {
playing = false;
}
}
const moyaiRegex = /🗿|<a?:.*?moy?ai.*?:\d+>/gi;
function onMessage(event) {
try {
if (
event.message?.content &&
event.channelId == SelectedChannelStore.getChannelId() &&
!event.message.state
) {
const matches = event.message.content.match(moyaiRegex);
if (matches) {
for (let i = 0; i < matches.length; i++) {
setTimeout(playSound, i * 350);
}
}
}
} catch {
// ignore
}
}
function onReaction(event) {
try {
if (
(storage.allowReactions ?? true) &&
event.channelId == SelectedChannelStore.getChannelId() &&
!event.optimistic
) {
const name = event.emoji?.name;
if (name === "🗿" || (name && /moy?ai/i.test(name))) {
playSound();
}
}
} catch {
// ignore
}
}
let soundPrepared = false;
export default {
onLoad: () => {
if (!soundPrepared) {
prepareSound().then((meta: Record<string, number>) => {
soundPrepared = true;
SOUND_DURATION = meta.duration;
});
}
FluxDispatcher.subscribe("MESSAGE_CREATE", onMessage);
FluxDispatcher.subscribe("MESSAGE_REACTION_ADD", onReaction);
},
onUnload: () => {
FluxDispatcher.unsubscribe("MESSAGE_CREATE", onMessage);
FluxDispatcher.unsubscribe("MESSAGE_REACTION_ADD", onReaction);
},
settings: MoyaiSettings,
};