Denim-Bot/src/modules/muzika.ts
Histmy bd0d0e9f2c
opět downgrade na ytdl-core (fuj)
+ vylepšení najditext
+ dependence update
2025-02-02 18:43:19 +01:00

260 lines
7.2 KiB
TypeScript

// Tady bude muzika, vole
import { AudioPlayerStatus, VoiceConnectionStatus } from "@discordjs/voice";
import { Client } from "discord.js";
import { search, validate, video_basic_info } from "play-dl";
import ytdlko from "@distube/ytdl-core";
import { emouty } from "../utils/emotes";
import { Modul } from "../utils/types";
import { adminLog, log, send } from "../utils/utils";
import { getConn, Hratelny, novejJoin, novejPlay, Priority, stopPlayer } from "../utils/voice";
import { array, record, safeParse, string } from "valibot";
type QueueItem = {
name: string;
url: string;
special?: true;
};
const guildy = new Map<string, { kju: QueueItem[]; loop: boolean; }>();
const searchScema = array(record(string(), string()));
async function createHratelny(url: string): Promise<Hratelny> {
/* Verze pro knihovnu play-dl */
/* const src = await stream(url);
return {
src: src.stream,
volume: 1,
type: src.type
};*/
/* Verze pro ytdl-core */
const src = ytdlko(url, { filter: "audioonly", highWaterMark: 1 << 25 });
return {
src: src,
volume: 1
};
}
async function playNext(guildId: string) {
try {
const guilda = guildy.get(guildId)!;
const kju = guilda.kju;
const item = kju[0];
let coZahrat: Hratelny;
if (!item.special) {
coZahrat = await createHratelny(item.url);
} else {
coZahrat = item.url;
}
novejPlay(guildId, coZahrat, Priority.Music)
.then(state => {
if (state.status != AudioPlayerStatus.Idle) return;
if (!guilda.loop) kju.shift();
if (kju.length)
return playNext(guildId);
})
.catch(e => {
log("chyba v hrani muziki", e);
});
} catch (e) {
if (e instanceof Error && e.message.startsWith("Seeking beyond limit"))
return stopPlayer(guildId, Priority.Music);
log(e);
const client: Client = module.exports.client;
adminLog(client, "error v hani muziky", e as Error);
}
}
const exp: Modul = {
more_komandy: {
zahraj: {
DMUnsafe: true,
run: async (mes, txt) => {
const kanel = mes.member?.voice.channelId;
if (!kanel) return "nejsi ve vojsu ty kkt";
const guildId = mes.guildId!;
const ajtem: QueueItem = { name: "", url: "" };
const druh = await validate(txt);
const soubor = mes.attachments.first();
if (soubor) {
ajtem.name = soubor.name;
ajtem.url = soubor.url;
ajtem.special = true;
send(mes, `zahraju \`${soubor.name}\``);
} else if (txt == "") return "co mam zahrat??";
else if (!druh) {
ajtem.name = `nejaka picovina ot ${mes.author}`;
ajtem.url = txt;
ajtem.special = true;
send(mes, `zkusim to zahrat`);
}
else if (druh == "search") {
const msg = send(mes, "hledam");
const hledani = await search(txt, { limit: 1 });
if (!hledani[0]) return "nic sem nenašel";
ajtem.url = hledani[0].url;
ajtem.name = hledani[0].title!;
msg.then(m => void m.edit(`zahraju \`${ajtem.name}\``));
} else if (druh == "yt_video") {
ajtem.url = txt;
try {
const video = await video_basic_info(txt);
ajtem.name = video.video_details.title!;
} catch (e) {
if (!(e instanceof Error)) {
log("chyba ale nechyba v mzike", e);
return "neco se fatk posralo";
}
if (e.message.includes("age"))
return "sorka bracho ael tuto je nesjpis ajdzreztrigtnuti";
log("chyba v hledani muziki", e);
return "doslo k random chybe";
}
if (typeof ajtem.name == "undefined") {
const client: Client = module.exports.client;
adminLog(client, "video nemá název");
}
send(mes, `zahraju \`${ajtem.name}\``);
} else return "tuto neumim zahrat";
if (!guildy.has(guildId)) {
guildy.set(guildId, { kju: [], loop: false });
}
const kju = guildy.get(guildId)!.kju;
kju.push(ajtem);
if (kju.length != 1) return;
await novejJoin(mes.guild!, kanel);
getConn(guildId)?.once(VoiceConnectionStatus.Destroyed, () => {
kju.length = 0;
});
playNext(guildId);
}
},
queue: {
als: ["q", "kju"],
DMUnsafe: true,
run: mes => {
const kju = guildy.get(mes.guildId!)?.kju;
if (!kju?.length) return "nehraje nic";
return `tuto je kurentni repertoar:\n${kju.reduce((acc, cur, i) => {
const jmeno = `${cur.name} (<${cur.url}>)`;
return `${acc}\n${i ? `${i}. ${jmeno}` : `-- *${jmeno}* --`}`;
}, "")}`;
}
},
skip: {
DMUnsafe: true,
run: mes => {
const kju = guildy.get(mes.guildId!)?.kju;
if (!kju?.length) return "nehraje nic";
stopPlayer(mes.guildId!, Priority.Music);
mes.react(emouty.d3k);
}
},
remove: {
DMUnsafe: true,
als: ["odebrat"],
arg: "pořadový číslo věci, kterou odebrat",
run: (mes, arg) => {
const numero = Number(arg);
if (isNaN(numero)) return "cokundo?";
const kju = guildy.get(mes.guildId!)?.kju;
if (!kju?.length) return "nehraje nic";
if (kju.length <= numero) return "tolik toho nehrae";
kju.splice(numero, 1);
mes.react(emouty.d3k);
}
},
seek: "nu tuto us nefunkuje pac ytdl-core je kokotina",
loop: {
DMUnsafe: true,
run: mes => {
if (!guildy.has(mes.guildId!)) {
guildy.set(mes.guildId!, { kju: [], loop: false });
}
const guilda = guildy.get(mes.guildId!)!;
guilda.loop = !guilda.loop;
return `lup je ${guilda.loop ? "zapnutej" : "ukoncen"}`;
}
},
najditext: {
DMUnsafe: true,
run: async mes => {
const kju = guildy.get(mes.guildId!)?.kju;
if (!kju?.length) return "nehraje nic";
const nameSplited = kju[0].name.split("-");
const query = nameSplited[1] ?? kju[0].name;
const res = await fetch(`https://search.karaoketexty.cz/index.php?q=${query}`)
.then(res => res.text())
.catch(log);
const json = res ? JSON.parse(res.slice(1, -1)) : [];
const vyhledavani = safeParse(searchScema, json);
if (!vyhledavani.success) return "KaraokeTexty se na mi visarly";
let vysledek;
const vyfiltrovano = vyhledavani.output.filter(result => nameSplited.length && result.label.includes(nameSplited[0]) && result.label.includes(nameSplited[1]));
if (vyfiltrovano.length) {
vysledek = vyfiltrovano[0];
} else {
vysledek = vyhledavani.output[0];
}
if (!vysledek) return "KaraokeTexty nic nenasli";
const res2 = await fetch(`https://www.karaoketexty.cz/texty-pisni/h/h-${vysledek.id}`)
.then(res => res.text())
.catch(log);
if (!res2) return "KaraokeTexty mi tekst nedali";
let text = "";
for (const radek of res2.matchAll(/<span class="para_1.+?">(.+?)<\/span>/gs)) {
text += `${radek[1].replace(/<br \/>/g, "")}\n`;
}
return text;
},
}
}
};
module.exports = exp;