import { APIEmbed, ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, CacheType, ChannelType, Client, ComponentType, MessageCreateOptions, ReadonlyCollection, TextBasedChannel, User } from "discord.js"; import { existsSync } from "fs"; import { MysqlError, createPool } from "mysql"; if (!existsSync("config.json")) throw new Error("config.json neexistuje"); const konfig = require("../../config.json"); if (!konfig.ignoreUnknownKeys) for (const klic of Object.keys(konfig)) { if (!["adminChannel", "adminID", "DBPwd", "DBUser", "dieOnError", "ignoreMess", "ignorePresence", "ignoreSpink", "ignoreUnknownKeys", "noGeneralSync", "prefix", "sachyDomena", "statPass", "token"].includes(klic)) throw new Error(`config.json obsahuje neznámý klíč: ${klic}`); } process.env = { ...process.env, ...konfig }; 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`; }; /** * 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, err?: string | Error) { if (process.env.adminChannel) { const adminChannel = client.channels.cache.get(process.env.adminChannel); if (adminChannel?.type == ChannelType.GuildText) adminChannel.send(err ? `${text}\n\`\`\`${err}\`\`\`` : text); } if (process.env.adminID) { const user = client.users.cache.get(process.env.adminID); if (user) sendDM(user, err ? `${text}\n\`\`\`${err}\`\`\`` : text); } } export function log(...content: unknown[]) { const jo = content.map(h => { if (h instanceof Error) return `\x1b[31m${h.stack || h}\x1b[0m`; return h; }); 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(() => log(new Error(`dementovi ${user} nejde poslat DM`))); } export const rand = (max: number) => Math.floor(Math.random() * max); export const prefix = process.env.prefix || "more"; type Nastaveni = { nabidka: (string | (({ val: string; } | { emoji: string; }) & { disabled?: boolean; }))[]; channel: TextBasedChannel; zpravec: MessageCreateOptions; onCollect: (i: ButtonInteraction, id: number, radek: ActionRowBuilder) => void; timeout?: number; } & ({ onEnd: (c: ReadonlyCollection>) => void; } | { konecnaZprava: string; stejne?: boolean; }); export async function nabidni(nastaveni: Nastaveni) { const radek = new ActionRowBuilder(); nastaveni.nabidka.forEach((moznost, i) => { const component = new ButtonBuilder({ customId: `${i}`, style: ButtonStyle.Primary }); const ejtoString = typeof moznost == "string"; if (ejtoString || "val" in moznost) { const value = ejtoString ? moznost : moznost.val; const nazev = value.length > 80 ? `${value.slice(0, 77)}...` : value; component.setLabel(nazev); } else { component.setEmoji(moznost.emoji); } if (!ejtoString && moznost.disabled) component.setDisabled(); radek.addComponents(component); }); const zprava = await nastaveni.channel.send({ ...nastaveni.zpravec, components: [radek] }); const collector = nastaveni.channel.createMessageComponentCollector({ filter: i => i.message.id == zprava.id, time: nastaveni.timeout ?? 18e4 }); collector.on("collect", i => { const lookupId = Number(i.customId); if (isNaN(lookupId)) return void nastaveni.channel.send("neco nefunguje idk"); nastaveni.onCollect(i, lookupId, radek); }); collector.on("end", c => { if ("onEnd" in nastaveni) nastaveni.onEnd(c); else if (!c.size || nastaveni.stejne) { radek.components.forEach(btn => btn.setDisabled()); zprava.edit({ content: nastaveni.konecnaZprava, components: [radek] }); } }); } export const strankovani = (channel: TextBasedChannel, embed: APIEmbed, zacatekNazvu: string, stranky: string[][]) => { let aktualniStranka = 0; nabidni({ channel: channel, nabidka: [{ emoji: "⬅️", disabled: true }, { emoji: "➡️" }], zpravec: { embeds: [embed] }, onCollect: (i, id, radek) => { // Výpočet nový stánky aktualniStranka += (!id) ? -1 : 1; // Úprava aktivnosti tlačítek radek.components[0].setDisabled(!aktualniStranka); radek.components[1].setDisabled(aktualniStranka + 1 == stranky.length); // Úprava embedu embed.fields![0] = { name: `${zacatekNazvu} (${aktualniStranka + 1}/${stranky.length})`, value: `• ${stranky[aktualniStranka].join("\n• ")}` }; // Odeslání i.update({ embeds: [embed], components: [radek] }); }, konecnaZprava: "", stejne: true }); }; // Připojení do databáze export const bazenek = createPool({ host: "127.0.0.1", user: process.env.DBUser, password: process.env.DBPwd, database: "denim", charset: "utf8mb4_unicode_ci" }); export const safeQuery = (query: string, parametry?: string[]) => new Promise<{ data: T[]; err: MysqlError | null; }>(res => { bazenek.query({ sql: query, values: parametry }, (err, odpoved) => { res({ data: odpoved, err }); }); });