Veliký update. Těžko říct proč tohle všechno nešlo rovnou do mainu (#6)

This commit is contained in:
Histmy 2024-01-04 16:46:43 +01:00 committed by GitHub
parent 52900c0e94
commit dc3a0282b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 444 additions and 4199 deletions

View File

@ -8,5 +8,7 @@
"adminID": "nepovinné, string - ID uživatele, který bude moci spustit komand update a pokud je bot spuštěn přes start.sh a bot spadne po 24 hodinách, pošle mu zprávu, která o tom informuje",
"dieOnError": "nepovinné, boolean - pokud nastane chyba při exekutování komandu, která by bota normálně shodila, bot se vypne",
"DBUser": "povinné, string - uživatelské jméno pro připojení do databáze",
"DBPwd": "povinné, string - heslo pro připojení do databáze"
"DBPwd": "povinné, string - heslo pro připojení do databáze",
"noGeneralSync": "nepovinné, boolean - nezálohovat generál dobytčárny do databáze",
"ignoreUnknownKeys": "nepovinné, boolean - vypne hlášení neznámých klíčů v config.json"
}

3985
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "denim_3001",
"version": "3001.54.4",
"version": "3001.55.0",
"description": "Toto je velmi kvalitní bot.",
"repository": {
"url": "https://github.com/Histmy/Denim-Bot/"
@ -8,28 +8,23 @@
"main": "out/app.js",
"scripts": {
"start": "node .",
"test": "tsc && node .",
"jest": "jest"
"test": "tsc && node ."
},
"author": "Histmy + det-fys",
"license": "ISC",
"dependencies": {
"@discordjs/voice": "^0.16.0",
"discord.js": "^14.13.0",
"@discordjs/voice": "^0.16.1",
"discord.js": "^14.14.1",
"js-levenshtein": "^1.1.6",
"mysql": "^2.18.1",
"node-fetch": "^2.6.1",
"opusscript": "^0.1.0",
"play-dl": "^1.9.6",
"opusscript": "^0.1.1",
"play-dl": "^1.9.7",
"tiny-typed-emitter": "^2.1.0",
"tweetnacl": "^1.0.3",
"valibot": "^0.14.0"
"valibot": "^0.20.1"
},
"devDependencies": {
"@types/jest": "^29.5.4",
"@types/js-levenshtein": "^1.1.1",
"@types/mysql": "^2.15.21",
"@types/node-fetch": "^2.6.4",
"jest": "^29.6.4"
"@types/js-levenshtein": "^1.1.3",
"@types/mysql": "^2.15.24"
}
}

View File

@ -19,6 +19,11 @@ const kuldan_log: SRecord<SRecord<number>> = {};
const komandyNaPoslani: KomandNaExport[] = [];
const helpServer: HelpServer = require("./utils/helpServer");
client.on("error", err => {
log(err);
adminLog(client, "nejaka chyba na klijentovi", err);
});
client.komandy = {};
client.aliasy = {};
setClient(client);
@ -31,7 +36,7 @@ function getFirstArg(fn: KomandRaw["run"]) {
?.trim();
}
const runEvent = (name: string, args: unknown[]) => {
const runEvent = async (name: string, args: unknown[]) => {
for (const listener of superEventy[name] || []) {
if (!listener) continue; // [after] pozice v superEventy arrayi se dají nastavovat a teoreticky může nastat mezera
try {
@ -58,7 +63,7 @@ const runEvent = (name: string, args: unknown[]) => {
readdirSync(modulFolder).forEach(soubor => {
if (!soubor.endsWith(".js")) return;
const modul: Modul = require(`${modulFolder}${soubor}`);
log(`Loaded: ${modulFolder}${soubor}`);
log(`Loaded: ${soubor.slice(0, -3)}`);
modul.client = client;
for (const klic in modul) {
@ -237,9 +242,7 @@ async function runKomand(mesOrInt: Message | CommandInteraction, cmd: Komand, cm
return void mesOrInt.channel?.send("sorka bracho tuto je koamnd jenom pro curaki co platy");
}
const akce = jeMes
? cmd.run
: cmd.slashRun!;
const akce = cmd.run ?? cmd.slashRun!;
if (typeof akce == "string") {
const res = renderMessage(akce, arg?.split(" ") || []);
@ -268,12 +271,12 @@ client.on("messageCreate", async mes => {
const prefixDiff = levenshtein(oddiakritikovat(mesPrefix.toLowerCase()), prefix);
if (prefixDiff > 0) {
if (!runEvent("messageCreate", [mes]) && prefixDiff <= 1 && mes.author.id != client.user!.id) mes.channel.send(`${prefix}*`);
if (!await runEvent("messageCreate", [mes]) && prefixDiff <= 1 && mes.author.id != client.user!.id) mes.channel.send(`${prefix}*`);
return;
}
if (!komandSDiakritikou) {
if (!runEvent("messageCreate", [mes])) mes.channel.send("coe voe");
if (!await runEvent("messageCreate", [mes])) mes.channel.send("coe voe");
return;
}
@ -281,7 +284,7 @@ client.on("messageCreate", async mes => {
const komandBez = oddiakritikovat(komandSDiakritikou).toLowerCase();
const cmdName = client.aliasy[komandBez] ?? komandBez;
if (runEvent("messageCreate", [mes, cmdName])) return;
if (await runEvent("messageCreate", [mes, cmdName])) return;
const komand = client.komandy[cmdName];
if (mes.channel.type == ChannelType.DM && komand?.DMUnsafe) return void mes.channel.send("tuten komand bohuzel v sz nefunkuje");

View File

@ -9,7 +9,7 @@ const pomoc: [string[], Record<string, unknown>] = require("../../res/pomoc.json
const ftipy: string[] = require("../../res/ftipy.json");
const delAndReturn = (mes: Message, co: string) => {
if (mes.channel.type != ChannelType.DM) mes.delete();
if (mes.channel.type != ChannelType.DM) mes.delete().catch();
return co;
};

View File

@ -1,22 +1,38 @@
// Modul na komand "anketa"
import { ActionRowBuilder, APIEmbed, APIEmbedField, ButtonBuilder, ButtonStyle, CommandInteraction, ComponentType, InteractionResponse, Message, MessageComponentInteraction, MessageEditOptions } from "discord.js";
import { ActionRowBuilder, APIEmbed, APIEmbedField, ButtonBuilder, ButtonStyle, CommandInteraction, ComponentType, Message, MessageComponentInteraction } from "discord.js";
import { Modul, SRecord } from "../utils/types";
import { formatter } from "../utils/utils";
function parseMoznosti(moznostiStr: string) {
return moznostiStr.split(moznostiStr.includes("|") ? "|" : ",").reduce<string[]>((acc, c) => {
function lookup<T>(opt: CommandInteraction["options"], item: string) {
return opt.get(item)?.value as T | undefined;
}
const exp: Modul = {
more_komandy: {
anketa: {
arg: "([nastaveni]) moznosti...",
DMUnsafe: true,
slashRun: async int => {
const opt = int.options;
const settings = {
time: lookup<number>(opt, "cas") || 60,
immediateShow: lookup<boolean>(opt, "neprubezny"),
listNames: lookup<boolean>(opt, "jmena")
};
const str = lookup<string>(opt, "moznosti")!;
const moznosti = str.split(str.includes("|") ? "|" : ",").reduce<string[]>((acc, c) => {
if (c.length) acc.push(c.trim());
return acc;
}, []);
}
async function zbytek(settings: { time: number; immediateShow: boolean; listNames: boolean; }, moznosti: string[], mesOrInt: Message | CommandInteraction) {
// return await zbytek(settings, moznosti, int);
if (moznosti.length < 2) return "zadej alespo%n dve moznosti";
if (moznosti.length > 25) return "toje moc";
const jeMes = mesOrInt instanceof Message;
const konec = new Date();
konec.setSeconds(konec.getSeconds() + settings.time);
@ -28,7 +44,7 @@ async function zbytek(settings: { time: number; immediateShow: boolean; listName
const radky: ActionRowBuilder<ButtonBuilder>[] = [];
const odpovedi: SRecord<number> = {};
function prepocitat(int?: MessageComponentInteraction) {
function prepocitat(interaction?: MessageComponentInteraction) {
const celkem = Object.keys(odpovedi).length;
fildy.forEach((f, i) => {
const hovn = Object.values(odpovedi).filter(n => n == i);
@ -38,10 +54,10 @@ async function zbytek(settings: { time: number; immediateShow: boolean; listName
if (odpovedi[cur] == i) pr.push(cur);
return pr;
}, []);
const kindo = people.map(w => mesOrInt.guild?.members.cache.get(w)?.displayName);
const kindo = people.map(w => int.guild?.members.cache.get(w)?.displayName);
f.value = `${"█".repeat(p)}${"░".repeat(10 - p)} ${Math.round(dylka / celkem * 100) || 0}% (${dylka}) ${settings.listNames ? " (" + kindo.join(", ") + ")" : ""}`;
});
int?.update({ embeds: [embed] });
interaction?.update({ embeds: [embed] });
}
moznosti.forEach((h, i) => {
@ -52,19 +68,8 @@ async function zbytek(settings: { time: number; immediateShow: boolean; listName
});
prepocitat();
if (settings.immediateShow) embed.fields = fildy;
let zprava: Message<boolean> | InteractionResponse;
let edit: (c: MessageEditOptions) => void;
if (jeMes) {
zprava = await mesOrInt.channel.send({ embeds: [embed], components: radky });
edit = content => { zprava.edit(content); };
} else {
zprava = await mesOrInt.reply({ embeds: [embed], components: radky });
zprava;
edit = content => { mesOrInt.editReply(content); };
}
const collector = zprava.createMessageComponentCollector<ComponentType.Button>({ time: settings.time * 1000 });
const zprava = await int.reply({ embeds: [embed], components: radky });
const collector = zprava.createMessageComponentCollector<ComponentType.Button>({ filter: i => i.message.id == zprava.id, time: settings.time * 1000 });
collector.on("collect", d => {
if (!(d.message instanceof Message)) return;
@ -81,57 +86,9 @@ async function zbytek(settings: { time: number; immediateShow: boolean; listName
embed.description = `Skončilo ${formatter(konec)}`;
prepocitat();
embed.fields = fildy;
edit({ components: [], embeds: [embed] });
int.editReply({ components: [], embeds: [embed] });
});
}
const exp: Modul = {
more_komandy: {
anketa: {
arg: "([nastaveni]) moznosti...",
DMUnsafe: true,
run: async (mes, arg) => {
const settings = {
time: 60,
immediateShow: true,
listNames: false
};
let huuuuuu = -1;
if (arg.startsWith("[")) {
huuuuuu = arg.indexOf("]");
const hovn = arg.slice(1, huuuuuu);
const f = hovn.split(" ");
for (const s of f) {
const t = Number(s);
if (!Number.isNaN(t)) settings.time = t;
else if (s == "jmena") settings.listNames = true;
else if (s == "neprubezny") settings.immediateShow = false;
else return `"${s}" neznam znam jenom jmena a neprubezny`;
}
}
const moznosti = parseMoznosti(arg.slice(huuuuuu + 1));
return await zbytek(settings, moznosti, mes);
},
slashRun: async int => {
const opt = int.options;
const settings = {
time: opt.get("cas")?.value as number || 60,
immediateShow: !opt.get("neprubezny")?.value as boolean,
listNames: !!opt.get("jmena")?.value as boolean
};
const moznosti = parseMoznosti(opt.get("moznosti")!.value as string);
return await zbytek(settings, moznosti, int);
}
}
}
};

View File

@ -1,8 +1,8 @@
import { CClient, HelpServer, Komand, KomandNaExport, Modul, SRecord } from "../utils/types";
import { join } from "path";
import { existsSync, readFileSync, writeFileSync } from "fs";
import { oddiakritikovat, prefix, strankovani } from "../utils/utils";
import { APIEmbed } from "discord.js";
import { oddiakritikovat, strankovani } from "../utils/utils";
import { APIEmbed, Message } from "discord.js";
let client: CClient;
const cesta = `${join(__dirname, "../../res/")}custom`;
@ -47,6 +47,31 @@ function komandNeboAlias(nazev: string) {
return { jeKomand: false };
}
function zmrdovoAliasy(zacatek: string, owner: string, mes: Message) {
const arr = [`${zacatek}:\n`];
for (const key in customKomandy) {
if (customKomandy[key].owner == owner) arr.push(key);
}
arr.push("\najilasy:\n");
for (const key in customAliasy) {
if (customAliasy[key].owner == owner) arr.push(key);
}
let text = "";
arr.forEach(element => {
if (text.length + element.length > 2000) {
mes.channel.send({ content: text, allowedMentions: { users: [] } });
text = "";
}
text += `${element}\n`;
});
mes.channel.send({ content: text, allowedMentions: { users: [] } });
}
const exp: Modul = {
more_komandy: {
naucse: {
@ -123,74 +148,18 @@ const exp: Modul = {
}
},
mojekomandy: async mes => {
const arr = ["tovje koamdy:\n"];
for (const key in customKomandy) {
if (customKomandy[key].owner == mes.author.id) arr.push(key);
}
arr.push("\ntovje ajilasy:\n");
for (const key in customAliasy) {
if (customAliasy[key].owner == mes.author.id) arr.push(key);
}
let text = "";
arr.forEach(element => {
if (text.length + element.length > 2000) {
mes.channel.send({ content: text, allowedMentions: { users: [] } });
text = "";
}
text += `${element}\n`;
});
return { content: text, allowedMentions: { users: [] } };
mojekomandy: mes => {
zmrdovoAliasy("tovje koamdy", mes.author.id, mes);
},
jehokomandy: {
DMUnsafe: true,
run: () => {
const client: CClient = module.exports.client;
run: mes => {
const kdo = mes.mentions.members?.first();
return `tuto je novej komand a histmaj mrdal aby to slo i takhle proste pouzij </${prefix}jehokomandy:${client.slashCommandy[`${prefix}jehokomandy`]}>`;
},
if (!kdo) return "ael koho";
slashRun: int => {
const kdoId = int.options.get("gdo")!.value as string;
const kdo = client.users.cache.get(kdoId);
if (!kdo) return "tutoko kokota neznam";
const arr = [`koamdy kkta ${kdo.username}:\n`];
for (const key in customKomandy) {
if (customKomandy[key].owner == kdo.id) arr.push(key);
}
arr.push("\njeho ajilasy:\n");
for (const key in customAliasy) {
if (customAliasy[key].owner == kdo.id) arr.push(key);
}
function send(text: string, i: number) {
if (i == 0) int.reply({ content: text, allowedMentions: { users: [] } });
else int.channel!.send({ content: text, allowedMentions: { users: [] } });
}
let text = "";
let i = 0;
arr.forEach(element => {
if (text.length + element.length > 2000) {
send(text, i);
text = "";
i++;
}
text += `${element}\n`;
});
send(text, i);
zmrdovoAliasy(`koamdy kkta ${kdo.nickname}`, kdo.id, mes);
}
},

View File

@ -4,7 +4,6 @@ import { renameSync, rmSync, readdirSync, writeFileSync } from "fs";
import { join } from "path";
import { Priority, novejPlay } from "../utils/voice";
import { lidiCoMajDenimPremium } from "../utils/denim-Spravce";
import fetch from "node-fetch";
import { exec } from "child_process";
import { log } from "../utils/utils";
@ -55,7 +54,7 @@ const exp: Modul = {
return;
}
// Smazat starej (nevíme formát, tak musíme zkust všechny)
// Smazat starej (nevíme formát, tak musíme zkusit všechny)
const zaklad = `${kmenovaCesta}/${mes.author.id}`;
for (const format of formaty) {
vymaz(`${zaklad}.${format}`);

View File

@ -107,20 +107,6 @@ const komandy: RESTPostAPIChatInputApplicationCommandsJSONBody[] = [
required: false
},
]
},
{
name: `${prefix}jehokomandy`,
description: "napysu ti koamndy kteri udelal kkt kteriho viberes",
dm_permission: false,
options: [
{
name: "gdo",
description: "ten kkt",
type: ApplicationCommandOptionType.User,
required: true
}
]
}
];

View File

@ -1,51 +1,32 @@
// Modul dedikovaný funkci spinkáček
import { ChannelType, Message, Role, TextBasedChannel, User } from "discord.js";
import fetch from "node-fetch";
import { ChannelType, Role, TextBasedChannel, User } from "discord.js";
import { emouty } from "../utils/emotes";
import { Modul, Spinkackar, SRecord } from "../utils/types";
import { formatCas, formatter, log, oddiakritikovat, ping, sendDM } from "../utils/utils";
import { Modul, SRecord } from "../utils/types";
import { formatCas, formatter, log, oddiakritikovat, ping, safeQuery, sendDM } from "../utils/utils";
const enum Spinky {
vstavacek,
spinkacek
}
let spinkacky: SRecord<Spinkackar>;
const budouciSpinky: SRecord<NodeJS.Timeout> = {};
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 contactSpinkServer = async (druh: Spinky, user: User) => {
handleSpink(druh, user);
const sql = druh == Spinky.spinkacek
? "INSERT INTO spinkacky (discord_id) VALUE (?)"
: "UPDATE spinkacky SET vstavacek = curtime() WHERE discord_id = ? ORDER BY id DESC LIMIT 1";
const odpoved = await safeQuery(sql, [user.id]);
return odpoved.err;
};
const syncSpink = () => {
fetch("https://spinkacek.deadfish.cz/api/spinkacky")
.then(r => r.json() as Promise<{ spinkacky: SRecord<Spinkackar>; }>)
.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 ifUzRemove = (id: string) => {
const uzPgn = budouciSpinky[id];
if (uzPgn) {
clearTimeout(uzPgn);
@ -55,14 +36,30 @@ const ifUzRemove = (m: Message) => {
return false;
};
const tovjemamvolepreceroliky = async (roliky: User, rictCas?: boolean) => {
const odpoved = await handleSpink("vstavacek", roliky);
if (!odpoved) return "uz jsi vzhuru ty hajzle";
const cas = Number(odpoved.slice(3));
const formatedCas = formatCas(cas);
async function getLastEntry(id: string) {
const odpoved = await safeQuery<{ spinkacek: string; vstavacek: string | undefined; }>(`SELECT spinkacek, vstavacek FROM spinkacky WHERE discord_id = ? ORDER BY spinkacek DESC LIMIT 1; `, [id]);
const zacatek = `dobry rano hajzle ${roliky}`;
if (!rictCas) return zacatek;
if (odpoved.err || !odpoved.data.length) return false;
return odpoved.data[0];
}
/*
R.I.P.
async tovjemamvolepreceroliky(roliky: User, rictCas?: boolean)
* 20. 11. 2021 19. 11. 2023
Vzpomínáme!
*/
const sendGmMessage = async (user: User, rictCas?: boolean) => {
const odpoved = await contactSpinkServer(Spinky.vstavacek, user);
if (odpoved) return "uz jsi vzhuru ty hajzle";
const zapis = await getLastEntry(user.id);
const zacatek = `dobry rano hajzle ${user}`;
if (!rictCas || zapis === false) return zacatek;
const cas = (Number(new Date(zapis.vstavacek ?? Date.now())) - Number(new Date(zapis.spinkacek))) / 1000;
const formatedCas = formatCas(cas);
let zpr = "";
if (cas >= 57600) zpr = "mas dat more vstavacek uz kdyz vstanes retarde";
@ -80,6 +77,44 @@ function hmsToCislo(reg: RegExpExecArray | null) {
return (Number(g.h) * 3600 || 0) + (Number(g.m) * 60 || 0) + (Number(g.s) || 0);
}
function handleSpink(stav: Spinky, uzivatel: User) {
for (const [, guild] of uzivatel.client.guilds.cache) {
const member = guild.members.cache.get(uzivatel.id);
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 (stav == Spinky.spinkacek) {
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.id) continue;
member.voice.disconnect("spinkacek");
return false;
}
}
}
}
const exp: Modul = {
more_komandy: {
@ -87,9 +122,11 @@ const exp: Modul = {
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)) {
const odpoved = await contactSpinkServer(Spinky.spinkacek, mes.author);
if (!odpoved) {
mes.react(emouty.spinkacek);
ifUzRemove(mes);
ifUzRemove(mes.author.id);
}
else return 'nespis uz?????';
}
@ -100,7 +137,7 @@ const exp: Modul = {
run: async (mes, arg) => {
if (mes.author.bot) return emouty.sjeta;
return tovjemamvolepreceroliky(mes.author, arg.toLowerCase() != "fejk");
return sendGmMessage(mes.author, arg.toLowerCase() != "fejk");
}
},
@ -119,10 +156,10 @@ const exp: Modul = {
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 zadani = kdy.slice(7).replace(/ /g, "").split("-");
if (zadani.length != 2) return "cos to napsal kkte";
const regex = /^(?:(?<h>\d+)h)?(?:(?<m>\d+)m)?(?:(?<s>\d+)s?)?$/;
const [from, to] = [regex.exec(t[0]), regex.exec(t[1])].map(v => hmsToCislo(v));
const [from, to] = [regex.exec(zadani[0]), regex.exec(zadani[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";
@ -147,10 +184,10 @@ const exp: Modul = {
if (Number(spink) < tedT) spink.setDate(ted.getDate() + 1);
}
ifUzRemove(mes);
ifUzRemove(mes.author.id);
budouciSpinky[mes.author.id] = setTimeout(() => {
handleSpink("spinkacek", mes.author);
contactSpinkServer(Spinky.spinkacek, mes.author);
mes.react(emouty.spinkacek);
}, Number(spink) - tedT);
if (!random) return `tvuj spinkacek byl naplanovan na ${formatter(spink)}`;
@ -161,22 +198,24 @@ const exp: Modul = {
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)}`;
run: async (mes, arg) => {
const prazdno = arg == "";
if (!ping.test(arg) && !prazdno) return "sikkt";
const id = prazdno ? mes.author.id : mes.mentions.members?.first()?.id ?? "";
const entry = await getLastEntry(id);
if (entry === false) return `tuten kkt jeste nespal ${emouty.lukiw}`;
if (!entry.vstavacek) return "ten kkt jiz ickon spi";
const cas = Number(new Date()) - Number(new Date(entry.vstavacek));
return `uz ${prazdno ? "jsi" : "je"} 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}`;
if (!ifUzRemove(mes.author.id)) return `spinkacek ale nemas naplanovanej ty kkte ${mes.author}`;
return "to bylo teda trapny debile";
}
},
@ -191,52 +230,18 @@ const exp: Modul = {
}
},
on_voiceStateUpdate: (bef, aft) => {
on_voiceStateUpdate: async (bef, aft) => {
if (!aft.channel || bef.channel) return;
if (spinkacky[aft.id]?.spinkacek) aft.disconnect("spinkacek")
const entry = await getLastEntry(aft.id);
if (entry && !entry.vstavacek) 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") {
super_on_messageCreate: async (mes, cmd?: string) => {
const entry = await getLastEntry(mes.author.id);
if ((entry && !entry.vstavacek) && cmd != "vstavacek") {
if (mes.channel.type == ChannelType.DM) {
mes.channel.send("drz hubu");
return true;
@ -260,13 +265,16 @@ const exp: Modul = {
const aftoff = aft.status == "offline";
const prop = autoSpinky[aft.userId];
if (!prop) return;
if (!befoff && aftoff) {
handleSpink("spinkacek", aft.member!.user);
return contactSpinkServer(Spinky.spinkacek, aft.member!.user);
}
if (befoff && !aftoff) {
// autospink, ne autoautospink
if (prop[0]) delete autoSpinky[aft.userId];
const kanel = prop[1];
if (kanel?.type == ChannelType.GuildText) kanel.send(await tovjemamvolepreceroliky(aft.member!.user));
if (kanel?.type == ChannelType.GuildText) kanel.send(await sendGmMessage(aft.member!.user));
}
}
};

View File

@ -1,6 +1,5 @@
// Trekování statusů všech lidí o kterých bot ví
import { Client, Guild, Presence } from "discord.js";
import fetch from "node-fetch";
import { FakePresence, Modul, SRecord, StatusyINaFounu, UserChange, ZmenovejObjekt } from "../utils/types";
import { adminLog, log } from "../utils/utils";

View File

@ -1,5 +1,4 @@
import { GuildScheduledEventEntityType, GuildScheduledEventPrivacyLevel, TextChannel } from "discord.js";
import fetch from "node-fetch";
import { CClient, Modul } from "../utils/types";
import { log } from "../utils/utils";
@ -62,7 +61,7 @@ async function urobit() {
const exp: Modul = {
more_komandy: {
dalsiordinacka: () => `dalsi ordnacka <t:${Math.ceil((Date.now() - 410400000) / 604800000) * 604800 + 410400}:R>`
dalsiordinacka: () => `dalsi ordnacka <t:${Math.ceil((Date.now() - 414000000) / 604800000) * 604800 + 414000}:R>`
},
on_ready: () => {

View File

@ -2,17 +2,7 @@
import { APIEmbed, CommandInteractionOption, Message, TextBasedChannel } from "discord.js";
import { CClient, Modul } from "../utils/types";
import { createPool } from "mysql";
import { log, strankovani } from "../utils/utils";
// Připojení do databáze
const pool = createPool({
host: "127.0.0.1",
user: process.env.DBUser,
password: process.env.DBPwd,
database: "zalohaGeneralu",
charset: "utf8mb4_unicode_ci"
});
import { bazenek, log, strankovani } from "../utils/utils";
const zpracovatZpravu = (mes: Message) => new Promise<void>(async (res, rej) => {
if ([6, 7, 8, 9, 10, 11, 18, 23].includes(mes.type)) return res();
@ -30,15 +20,22 @@ const zpracovatZpravu = (mes: Message) => new Promise<void>(async (res, rej) =>
const sql = `INSERT INTO Zpravy (ID, Content, Author ${reference ? ", Reference" : ""} , Attachments) VALUES (${mes.id}, ?, ${mes.author.id} ${reference ? `,${reference}` : ""} , ?)`;
pool.query({ sql, values: [mes.content, JSON.stringify(attachments)] }, err => {
bazenek.query({ sql, values: [mes.content, JSON.stringify(attachments)] }, err => {
if (err) rej(err);
res();
});
});
function utect(string: string) {
return string
.replace(/~/g, "~~")
.replace(/%/g, "~%")
.replace(/_/g, "~_");
}
const porovnat = (filtr: CommandInteractionOption): string[] => {
switch (filtr.name) {
case "kontent": return [`Content LIKE ?`, `%${filtr.value}%`];
case "kontent": return [`Content LIKE ? ESCAPE "~"`, `%${utect(`${filtr.value}`)}%`];
case "regex": return [`Content REGEXP ?`, `${filtr.value}`];
case "uzivatel": return [`Author=?`, `${filtr.user!.id}`];
case "od":
@ -51,7 +48,7 @@ const porovnat = (filtr: CommandInteractionOption): string[] => {
case "obrazekOdkaz": return [`${filtr.value ? "" : " NOT "}Content REGEXP "\.(png|jpe?g|gif|webp)"`];
case "link": return [`${filtr.value ? "" : " NOT "}Content REGEXP "https?://"`];
case "ma_soubor": return [`${filtr.value ? "" : " NOT "}Attachments != "[]"`];
case "nazev_souboru": return [`Attachments LIKE ?`, `%${filtr.value}%`];
case "nazev_souboru": return [`Attachments LIKE ? ESCAPE "~"`, `%${utect(`${filtr.value}`)}%`];
}
return [""];
};
@ -59,12 +56,6 @@ const porovnat = (filtr: CommandInteractionOption): string[] => {
const exp: Modul = {
more_komandy: {
vyhledej: {
run: () => {
const client: CClient = module.exports.client;
return `tuto je novej komand a histmaj mrdal aby to slo i takhle proste pouzij </morevyhledej:${client.slashCommandy["morevyhledej"]}>`;
},
slashRun: async int => {
const moznosti = int.options;
const filtry = moznosti.data;
@ -94,7 +85,7 @@ const exp: Modul = {
const odpoved = await int.reply("hledam");
const sql = `SELECT CONVERT(ID, CHAR) as idcko, SUBSTRING(Content, 1, 20) AS kontent FROM Zpravy WHERE ${parsedFiltry.join(" AND ")} ORDER BY ID ${seradit}`;
pool.query({ sql, values: mista }, (err, res?: { idcko: string; kontent: string; }[]) => {
bazenek.query({ sql, values: mista }, (err, res?: { idcko: string; kontent: string; }[]) => {
if (err) return odpoved.edit(`chyba: ${err}`);
if (!res || !res.length) return odpoved.edit("nic takoviho sem nenasel");
@ -138,6 +129,8 @@ const exp: Modul = {
on_ready: () => {
const client = module.exports.client as CClient;
if (process.env.noGeneralSync) return;
client.channels.fetch("555779161067749448")
.then(async ch => {
const channel = ch as TextBasedChannel;
@ -150,8 +143,9 @@ const exp: Modul = {
try {
await zpracovatZpravu(mes);
} catch {
log("general sync kompletni");
} catch (e) {
log(e);
log("general sync ukoncen");
return;
}
}
@ -166,7 +160,7 @@ const exp: Modul = {
},
on_messageCreate: mes => {
if (mes.channelId == "555779161067749448")
if (!process.env.noGeneralSync && mes.channelId == "555779161067749448")
zpracovatZpravu(mes);
}
};

View File

@ -4,7 +4,6 @@ import { getVoiceConnections } from "@discordjs/voice";
import { Client, TextChannel, } from "discord.js";
import { createServer } from "http";
import { Modul } from "../utils/types";
import fetch from "node-fetch";
import { adminLog, formatCas, log, nabidni, sendDM } from "../utils/utils";
import { emouty } from "../utils/emotes";
import { readFileSync } from "fs";

View File

@ -1,4 +1,3 @@
import fetch from "node-fetch";
import { array, safeParse, string } from "valibot";
import { adminLog, log } from "./utils";
import { Client } from "discord.js";

View File

@ -4,7 +4,6 @@ import { createServer, IncomingMessage, ServerResponse } from "http";
import { SRecord } from "./types";
import { join } from "path";
import { readFileSync } from "fs";
import fetch from "node-fetch";
import { TypedEmitter } from "tiny-typed-emitter";
import { log } from "./utils";

View File

@ -12,18 +12,25 @@ export type BaseKomandProps = {
export type KomandRaw = BaseKomandProps &
{
run: string | RunFunkce;
slashRun?: InteractionRunFunkce;
cd?: number;
hidden?: true;
DMUnsafe?: true;
premium?: true;
};
} & (
{
run: string | RunFunkce;
slashRun?: never;
}
| {
run?: never;
slashRun: InteractionRunFunkce;
}
);
export type ListenerFunkce<T extends keyof ClientEvents> = (...args: ClientEvents[T]) => void;
export type SuperListenerFunkce<T extends keyof ClientEvents> = (...args: ClientEvents[T]) => boolean;
export type SuperListenerFunkce<T extends keyof ClientEvents> = (...args: ClientEvents[T]) => Awaitable<boolean>;
interface SuperObject<T extends keyof ClientEvents> {
pos: number;
@ -40,7 +47,7 @@ export type Modul = {
& { [key in keyof ClientEvents as `super_on_${key}`]?: SuperObject<key> | SuperListenerFunkce<key>; };
export type Komand = {
run: string | RunFunkce;
run?: string | RunFunkce;
slashRun?: InteractionRunFunkce;
cd?: number;
DMUnsafe?: true;

View File

@ -1,8 +1,14 @@
import { APIEmbed, ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, CacheType, ChannelType, Client, Collection, ComponentType, MessageCreateOptions, TextBasedChannel, User } from "discord.js";
import { existsSync } from "fs";
import { MysqlError, createPool } from "mysql";
if (!existsSync("config.json")) throw new Error("config.json neexistuje");
process.env = { ...process.env, ...require("../../config.json") };
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", "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
@ -176,3 +182,18 @@ export const strankovani = (channel: TextBasedChannel, embed: APIEmbed, zacatekN
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 = <T>(query: string, parametry?: string[]) => new Promise<{ data: T[]; err: MysqlError | null; }>(res => {
bazenek.query({ sql: query, values: parametry }, (err, odpoved) => {
res({ data: odpoved, err });
});
});