import { AudioPlayerStatus, AudioResource, createAudioPlayer, createAudioResource, entersState, getVoiceConnection, joinVoiceChannel, PlayerSubscription, StreamType, VoiceConnection, VoiceConnectionStatus } from "@discordjs/voice"; import { ChannelType, Client, Guild, StageChannel, User, VoiceChannel } from "discord.js"; import { once } from "events"; import { JoinHovna, MuzikaFace, SRecord } from "./types"; import { Readable } from "node:stream"; const pripojeni: SRecord = {}; const timeAnouncability: Record = {}; export const oddiakritikovat = (a: string) => { return a .replace(/[àáâãäåæāăą]/g, "a") .replace(/[çćĉċč]/g, "c") .replace(/[ďđ]/g, "d") .replace(/[èéêëðēĕėęě]/g, "e") .replace(/[ĝğġģǵ]/g, "g") .replace(/[ĥħ]/g, "h") .replace(/[ìíîïĩīĭįı]/g, "i") .replace(/[ĵ]/g, "j") .replace(/[ķĸ]/g, "k") .replace(/[ĺļľŀł]/g, "l") .replace(/[ñńņňʼnŋ]/g, "n") .replace(/[òóôõöøōŏőœ]/g, "o") .replace(/[þ]/g, "p") .replace(/[ŕŗř]/g, "r") .replace(/[ßśŝşšſ]/g, "s") .replace(/[ţťŧ]/g, "t") .replace(/[ùúûüũūŭůűų]/g, "u") .replace(/[ŵ]/g, "w") .replace(/[ÿýŷ]/g, "y") .replace(/[źżž]/g, "z") .replace(/[ÀÁÂÃÄÅÆĀĂĄ]/g, "A") .replace(/[ÇĆĈĊČ]/g, "C") .replace(/[Ď]/g, "D") .replace(/[ÈÉÊËÐĒĔĖĘĚ]/g, "E") .replace(/[ĜĞĠĢ]/g, "G") .replace(/[Ĵ]/g, "J") .replace(/[Ķ]/g, "K") .replace(/[ĤĦ]/g, "H") .replace(/[ÌÍÎÏĨĪĬĮİ]/g, "I") .replace(/[ĹĻĽĿŁ]/g, "L") .replace(/[ÑŃŅŇŊ]/g, "N") .replace(/[ÒÓÔÕÖØŌŎŐŒ]/g, "O") .replace(/[Þ]/g, "P") .replace(/[ŔŖŘ]/g, "R") .replace(/[ŚŜŞŠ]/g, "S") .replace(/[ŢŤŦ]/g, "T") .replace(/[ÙÚÛÜŨŪŬŮŰŲ]/g, "U") .replace(/[Ŵ]/g, "W") .replace(/[ÝŶŸ]/g, "Y") .replace(/[ŹŻŽ]/g, "Z"); }; /** * returns relative time in format `x hodin x minut a x se kund` * @param cas Number of seconds to convert */ export const formatCas = (cas: number) => { const h = Math.floor(cas / 3600); const m = Math.floor(cas % 3600 / 60); const s = Math.floor(cas % 3600 % 60); return `${h} hodin ${m} mynut a ${s} se kund`; }; export async function joinVoice(channel: VoiceChannel | StageChannel): Promise; export async function joinVoice(channel: string, guild: Guild): Promise; export async function joinVoice(channel: VoiceChannel | StageChannel | string, guild?: Guild): Promise { const channelId = typeof channel === "string" ? channel : channel.id; const guildId = typeof channel === "string" ? guild!.id : channel.guildId; const guilda = typeof channel === "string" ? guild! : channel.guild; let conn = getVoiceConnection(guildId); let prev: boolean | string = false; if (conn) { if (conn.joinConfig.channelId === channelId) { await entersState(conn, VoiceConnectionStatus.Ready, 3e4) .catch(err => { conn!.destroy(); log("pri pripojovani do vojsu nastala chyba:"); throw err; }); return { conn, prev: true }; } prev = conn.joinConfig.channelId!; if (!prev) { log(new Error(`chci do kanelu "${channelId}", na serveru "${guildId}" a config channelid nen`)); throw new Error("Dement no"); } } conn = joinVoiceChannel({ channelId, guildId, adapterCreator: guilda.voiceAdapterCreator }); await entersState(conn, VoiceConnectionStatus.Ready, 3e4) .catch((err: Error) => { conn!.destroy(); throw err; }); if (!prev) { const player = createAudioPlayer(); player.on("error", e => log("chyba pri hrani", e)); pripojeni[guildId] = conn.subscribe(player)!; conn.on("error", e => { if (e.message.startsWith("Cannot perform IP discovery")) return; log("error nekde v conn", e); }); } return { conn, prev }; } const makeAudioPlayer = (co: string | MuzikaFace | Readable) => { if (typeof co == "string" || co instanceof Readable) return createAudioResource(co); const res = createAudioResource(co.name, { inlineVolume: true, inputType: co.type || StreamType.Arbitrary }); res.volume?.setVolume(co.volume); return res; }; export const play = (conn: VoiceConnection, co: string | string[] | MuzikaFace | MuzikaFace[] | Readable) => new Promise(async (res, rej) => { if (conn.state.status !== VoiceConnectionStatus.Ready) return rej("conn není ready"); const player = pripojeni[conn.joinConfig.guildId].player; if (!Array.isArray(co)) { const aud = makeAudioPlayer(co); player.play(aud); player.once(AudioPlayerStatus.Idle, () => res()); return; } const resources: AudioResource[] = []; co.forEach(c => { const res = makeAudioPlayer(c); resources.push(res); }); for (const res of resources) { await once(res.playStream, "readable"); } player.play(resources[0]); let i = 0; const funkce = () => { i++; if (i === resources.length) { res(); player.removeListener(AudioPlayerStatus.Idle, funkce); } else player.play(resources[i]); }; player.on(AudioPlayerStatus.Idle, funkce); }); const leave = (guildId: string) => { const conn = getVoiceConnection(guildId); if (!conn) return; conn.destroy(); delete pripojeni[guildId]; }; export const handlePrevVoice = (guild: Guild, prev: boolean | string) => { if (prev === true) return; // Byl jsem v tomdle vojsu if (prev === false) return leave(guild.id); // Nebyl jsem ve vojsu vůbec joinVoice(prev, guild); // Byl jsem jinde }; /** * Returns absolute date in format `d. m. h:mm:ss` * @param date Date object to convert */ export const formatter = new Intl.DateTimeFormat("cs", { day: "numeric", month: "short", hour: "numeric", minute: "numeric", second: "numeric" }).format; export const ping = /^<@!?\d+>$/; export function adminLog(client: Client, text: string) { if (process.env.adminChannel) { const adminChannel = client.channels.cache.get(process.env.adminChannel); if (adminChannel?.type == ChannelType.GuildText) adminChannel.send(text); } if (process.env.adminID) { const user = client.users.cache.get(process.env.adminID); if (user) sendDM(user, text); } } export const getCurrentPlayer = (guildId: string) => pripojeni[guildId]?.player; export const configureTimeAnouncment = (guild: string, state: boolean) => { timeAnouncability[guild] = state; }; export const canAnounceTime = (guild: string) => timeAnouncability[guild] ?? true; export function log(...content: (string | Error)[]) { const jo = content.map(h => { if (typeof h == "string") return h; return `\x1b[31m${h.stack || h}\x1b[0m`; }); const d = new Date(); console.log(`[${d.getDate()}.${d.getMonth() + 1}. ${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}]:`, ...jo); } export async function sendDM(user: User, txt: string) { user.send(txt).catch(() => console.log(`dementovi ${user} nejde poslat DM`)); }