Denim-Bot/src/utils/utils.ts
2022-12-02 17:45:36 +01:00

209 lines
7.0 KiB
TypeScript

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<PlayerSubscription> = {};
const timeAnouncability: Record<string, boolean> = {};
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<JoinHovna>;
export async function joinVoice(channel: string, guild: Guild): Promise<JoinHovna>;
export async function joinVoice(channel: VoiceChannel | StageChannel | string, guild?: Guild): Promise<JoinHovna> {
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<void>(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`));
}