260 lines
7.2 KiB
TypeScript
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;
|