// Modul dedikovaný funkci spinkáček import { ChannelType, Message, Role, TextBasedChannel, User } from "discord.js"; import fetch from "node-fetch"; import { emouty } from "../utils/emotes"; import { Modul, Spinkackar, SRecord } from "../utils/types"; import { formatCas, formatter, log, oddiakritikovat, ping, sendDM } from "../utils/utils"; let spinkacky: SRecord; const budouciSpinky: SRecord = {}; const autoSpinky: SRecord<[boolean, TextBasedChannel]> = {}; const contactSpinkServer = async (akce: string, id: string, nick: string = "", avatar: string | null = "") => { const options = `heslo=${process.env.spinkPass}&akce=${akce}&id=${id}&nick=${encodeURIComponent(nick)}&avatar=${encodeURIComponent(avatar ?? "")}`; return fetch(`https://spinkacek.deadfish.cz/extapi.php?${options}`) .then(r => r.text()); }; const syncSpink = () => { fetch("https://spinkacek.deadfish.cz/api/spinkacky") .then(r => r.json() as Promise<{ spinkacky: SRecord; }>) .then(d => { const data = d.spinkacky; const keys = Object.keys(data); const values = Object.values(data); spinkacky = {}; for (let i = 0; i < keys.length; i++) { const k = keys[i]; if (k[0] != "d") continue; const vstav = values[i].timeup; spinkacky[k.slice(8)] = { spinkacek: values[i].spinkacek, timeup: vstav === false ? false : vstav * 1000 }; } }); }; if (!process.env.ignoreSpink) syncSpink(); const handleSpink = async (act: "spinkacek" | "vstavacek", user: User) => { const ok = act == "spinkacek" ? await contactSpinkServer(act, user.id, user.username, user.avatarURL()) : await contactSpinkServer(act, user.id); return ok.startsWith("OK") ? ok : false; }; const ifUzRemove = (m: Message) => { const id = m.author.id; const uzPgn = budouciSpinky[id]; if (uzPgn) { clearTimeout(uzPgn); delete budouciSpinky[id]; return true; } return false; }; const tovjemamvolepreceroliky = async (roliky: User) => { const odpoved = await handleSpink("vstavacek", roliky); if (!odpoved) return "uz jsi vzhuru ty hajzle"; const cas = Number(odpoved.slice(3)); const formatedCas = formatCas(cas); let zpr = ""; if (cas >= 57600) zpr = "mas dat more vstavacek uz kdyz vstanes retarde"; else if (cas >= 43200) zpr = "extrémní bídák"; else if (cas >= 36000) zpr = "fakt bídák"; else if (cas < 30) zpr = "dobrej mikrospánek debile"; else if (cas < 10800) zpr = "dobrej fake spink debile"; return `dobry rano hajzle ${roliky}\nspal sy ${formatedCas}\n${zpr}`; }; function hmsToCislo(reg: RegExpExecArray | null) { if (!reg || reg.input == "") return NaN; const g = reg.groups!; return (Number(g.h) * 3600 || 0) + (Number(g.m) * 60 || 0) + (Number(g.s) || 0); } const exp: Modul = { more_komandy: { spinkacek: { als: ["spink", "spoink", "spinkake", "spoinkacek", "gn", emouty.spinkacek, emouty.gn], run: async mes => { if (mes.author.bot) return `až někdy${emouty.kapp}`; if (await handleSpink("spinkacek", mes.author)) { mes.react(emouty.spinkacek); ifUzRemove(mes); } else return 'nespis uz?????'; } }, vstavacek: { als: ["vstavcacek", "gm", "unspinkacek"], run: async mes => { if (mes.author.bot) return emouty.sjeta; return tovjemamvolepreceroliky(mes.author); } }, pgn: { als: [`p${emouty.gn}`], run: (mes, kdy) => { if (mes.author.bot) return emouty.sjeta; const ted = new Date(); const tedT = Number(ted); const spink = new Date(); let random = false; if (kdy.startsWith("random")) { random = true; let rozdil = 540; let min = 60; if (kdy.length > 7) { const t = kdy.slice(7).replace(/ /g, "").split("-"); if (t.length != 2) return "cos to napsal kkte"; const regex = /^(?:(?\d+)h)?(?:(?\d+)m)?(?:(?\d+)s?)?$/; const [from, to] = [regex.exec(t[0]), regex.exec(t[1])].map(v => hmsToCislo(v)); if (Number.isNaN(from) || Number.isNaN(to)) return "cislo musy bit v formate xh xm xs"; if (to <= from) return "ja teda nevim jestli ti vys jak funguje cas ael vym ze tam mas chibu"; rozdil = to - from; min = from; } spink.setTime(tedT + (Math.random() * rozdil + min) * 1000); log(`random spink pro ${oddiakritikovat(mes.member?.displayName || "neznamejmeno")} byl nastaven na ${formatter(spink)}`); } else if (/^\d+$/.test(kdy) || !kdy) spink.setTime(tedT + Number(kdy || 7200) * 1000); else { const cojavim = /^((?\d+)\. ?((?\d+)\.)? ?)?(?\d+)(:(?\d+)(:(?\d+))?)? ?(?

am|pm)?$/.exec(kdy.toLowerCase()); if (!cojavim) return `cos to tam napsal ty kokote?`; const g = cojavim.groups!; if (g.d) spink.setDate(Number(g.d)); if (g.mo) spink.setMonth(Number(g.mo) - 1); const h = Number(g.h); spink.setHours(g.p == "pm" && h < 12 ? h + 12 : h); spink.setMinutes(Number(g.m) || 0); spink.setSeconds(Number(g.s) || 0); if (Number(spink) < tedT) spink.setDate(ted.getDate() + 1); } ifUzRemove(mes); budouciSpinky[mes.author.id] = setTimeout(() => { handleSpink("spinkacek", mes.author); mes.react(emouty.spinkacek); }, Number(spink) - tedT); if (!random) return `tvuj spinkacek byl naplanovan na ${formatter(spink)}`; mes.react(emouty.lajk); } }, ps: { als: ["poslednispink"], arg: "kdo (nepovinné)", run: (mes, arg) => { const f = arg != ""; if (!ping.test(arg) && f) return "sikkt"; const id = f ? mes.mentions.members?.first()?.id : mes.author.id; const tajmUp = spinkacky[id ?? ""]?.timeup; if (tajmUp == undefined) return `tuten kkt jeste nespal ${emouty.lukiw}`; if (!tajmUp) return "ten kkt jiz ickon spi"; const cas = Number(new Date()) - Number(new Date(tajmUp)); return `uz ${f ? "je" : "jsi"} vzhuru ${formatCas(cas / 1000)}`; } }, zruspgn: { als: ["zpgn", "cancelpgn", "cpgn", "unpgn", `unp${emouty.gn}`], run: mes => { if (!ifUzRemove(mes)) return `spinkacek ale nemas naplanovanej ty kkte ${mes.author}`; return "to bylo teda trapny debile"; } }, autospink: mes => `autospink je ${autoSpinky[mes.author.id] ? (delete autoSpinky[mes.author.id], "vypnut") : (autoSpinky[mes.author.id] = [true, mes.channel], "zapnut")}`, autoautospink: { als: ["🚗🚗spink"], run: mes => `autoautospink je ${autoSpinky[mes.author.id] ? (delete autoSpinky[mes.author.id], "vypnut") : (autoSpinky[mes.author.id] = [false, mes.channel], "zapnut")}` } }, on_voiceStateUpdate: (bef, aft) => { if (!aft.channel || bef.channel) return; if (spinkacky[aft.id]?.spinkacek) aft.disconnect("spinkacek") .catch(err => log("spinkacek odpojit se nepovedlo nebo co:", err)); }, super_on_messageCreate: (mes, cmd?: string) => { if (mes.author.id === '831318260493844494') { syncSpink(); const uzivatel = mes.content.match(/(?<=discord_)\d+/)?.[0]; if (!uzivatel) return false; for (const [, guild] of mes.client.guilds.cache) { const member = guild.members.cache.get(uzivatel); if (!member) continue; const c = guild.roles.cache; const spinkRole = c.find(r => r.name == "spink"); const adminRole = c.find(r => r.name == "admin"); const make = (akce: "a" | "r", role: Role) => { const handle = (e: Error) => { if (["Missing Permissions", "Missing Access"].includes(e.message)) return; log("chyba pri davani/odebirani role", e); }; if (akce == "a") member.roles.add(role).catch(handle); else member.roles.remove(role).catch(handle); }; if (mes.content[0] == "s") { if (spinkRole) make("a", spinkRole); if (adminRole) make("r", adminRole); } else { if (spinkRole) make("r", spinkRole); if (adminRole) make("a", adminRole); continue; } for (const [, channel] of guild.channels.cache) { if (channel.type != ChannelType.GuildVoice) continue; for (const [, member] of channel.members) { if (member.id !== uzivatel) continue; member.voice.disconnect("spinkacek"); return false; } } } } else if (spinkacky[mes.author.id]?.spinkacek && cmd != "vstavacek") { if (mes.channel.type == ChannelType.DM) { mes.channel.send("drz hubu"); return true; } mes.delete().catch((e: Error) => { if (e.name == "DiscordAPIError[5OO13]") return; log("chyba pri mazani", e); }); sendDM(mes.author, "spis tak nepis"); return true; } return false; }, on_userPresenceUpdate: async (bef, aft) => { if (!bef) return; const befoff = bef.status == "offline"; const aftoff = aft.status == "offline"; const prop = autoSpinky[aft.userId]; if (!prop) return; if (!befoff && aftoff) { handleSpink("spinkacek", aft.member!.user); } if (befoff && !aftoff) { if (prop[0]) delete autoSpinky[aft.userId]; const kanel = prop[1]; if (kanel?.type == ChannelType.GuildText) kanel.send(await tovjemamvolepreceroliky(aft.member!.user)); } } }; if (!process.env.ignoreSpink) module.exports = exp;