// 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, messageReply } 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(); const searchScema = array(record(string(), string())); async function createHratelny(url: string): Promise { /* 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; messageReply(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; messageReply(mes, `zkusim to zahrat`); } else if (druh == "search") { const msg = messageReply(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"); } messageReply(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>/gs)) { text += `${radek[1].replace(/
/g, "")}\n`; } return text; }, } } }; module.exports = exp;