add: Moyai plugin (fixed)

This commit is contained in:
kmmiio99o 2026-07-02 13:14:54 +02:00
parent b2233e9bcf
commit a98461ade0
No known key found for this signature in database
GPG key ID: AC9D7747D423B9BF
3 changed files with 151 additions and 0 deletions

View file

@ -0,0 +1,18 @@
{
"name": "🗿",
"description": "🗿",
"authors": [
{
"name": "Cynosphere",
"id": "150745989836308480"
},
{
"name": "kmmiio99o",
"id": "879393496627306587"
}
],
"main": "src/index.ts",
"vendetta": {
"icon": "ic_speaker"
}
}

101
plugins/Moyai/src/index.ts Normal file
View file

@ -0,0 +1,101 @@
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() {
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;
DCDSoundManager.stop(SOUND_ID);
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,
};

View file

@ -0,0 +1,32 @@
import { plugin } from "@vendetta";
import { findByProps } from "@vendetta/metro";
import { React } from "@vendetta/metro/common";
const { ScrollView } = findByProps("ScrollView");
const { TableRowGroup, TableSwitchRow, Stack } = findByProps(
"TableSwitchRow",
"TableRowGroup",
"Stack",
);
export default function MoyaiSettings() {
const [, forceUpdate] = React.useReducer((x: number) => ~x, 0);
return (
<ScrollView style={{ flex: 1 }}>
<Stack style={{ padding: 16 }} spacing={16}>
<TableRowGroup title="General">
<TableSwitchRow
label="Play on reactions"
subLabel="Play the sound when someone reacts with moyai"
value={plugin.storage.allowReactions ?? true}
onValueChange={(v: boolean) => {
plugin.storage.allowReactions = v;
forceUpdate();
}}
/>
</TableRowGroup>
</Stack>
</ScrollView>
);
}