172 lines
6.1 KiB
TypeScript
172 lines
6.1 KiB
TypeScript
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
|
|
|
|
import { APIEmbed, CommandInteractionOption, Message, TextBasedChannel } from "discord.js";
|
|
import { CClient, Modul } from "../utils/types";
|
|
import { bazenek, log, sendWithoutReply, strankovani } from "../utils/utils";
|
|
|
|
const zpracovatZpravu = (mes: Message) => new Promise<void>(async (res, rej) => {
|
|
if ([6, 7, 8, 9, 10, 11, 18, 23, 46].includes(mes.type)) return res();
|
|
if (mes.type != 0 && mes.type != 20 && mes.type != 19) throw new Error("Neznamej message type " + mes.type.toString());
|
|
|
|
const reference = mes.reference?.messageId;
|
|
const attachments: { name: string; file: string; }[] = [];
|
|
|
|
if (mes.attachments.size != 0) {
|
|
|
|
for (const [, attachment] of mes.attachments) {
|
|
attachments.push({ name: attachment.name, file: attachment.id });
|
|
}
|
|
}
|
|
|
|
const sql = `INSERT INTO Zpravy (ID, Content, Author ${reference ? ", Reference" : ""} , Attachments) VALUES (${mes.id}, ?, ${mes.author.id} ${reference ? `,${reference}` : ""} , ?)`;
|
|
|
|
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 ? ESCAPE "~"`, `%${utect(`${filtr.value}`)}%`];
|
|
case "regex": return [`Content REGEXP ?`, `${filtr.value}`];
|
|
case "uzivatel": return [`Author=?`, `${filtr.user!.id}`];
|
|
case "od":
|
|
case "do": {
|
|
const datum = new Date(filtr.value as string);
|
|
const cislo = (Number(datum) - 1420070400000) * 4194304;
|
|
return [`ID ${filtr.name == "od" ? ">" : "<"} ${cislo}`];
|
|
}
|
|
case "obrasek": return [`${filtr.value ? "" : " NOT "}Attachments REGEXP "\.(png|jpe?g|gif|webp)"`];
|
|
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 ? ESCAPE "~"`, `%${utect(`${filtr.value}`)}%`];
|
|
}
|
|
return [""];
|
|
};
|
|
|
|
const exp: Modul = {
|
|
more_komandy: {
|
|
vyhledej: {
|
|
slashRun: async int => {
|
|
const moznosti = int.options;
|
|
const filtry = moznosti.data;
|
|
if (!filtry.length) return "co takhle tam alespon jeden filtr";
|
|
|
|
// Nelgel kombinace a tak
|
|
if (moznosti.get("kontent") && moznosti.get("regex")) return "kontent a regex nejde kombynovat";
|
|
const od = moznosti.get("od");
|
|
if (od && isNaN(Number(new Date(od.value as string)))) return "od neny platni datum";
|
|
const dod = moznosti.get("do");
|
|
if (dod && isNaN(Number(new Date(dod.value as string)))) return "do neny platni datum";
|
|
|
|
const parsedFiltry: string[] = [];
|
|
const mista: string[] = [];
|
|
let seradit = "DESC";
|
|
|
|
for (const filtr of filtry) {
|
|
if (filtr.name != "seradit") {
|
|
const [parsed, misto] = porovnat(filtr);
|
|
parsedFiltry.push(parsed);
|
|
if (misto) mista.push(misto);
|
|
} else {
|
|
seradit = filtr.value as string;
|
|
}
|
|
}
|
|
|
|
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}`;
|
|
bazenek.query({ sql, values: mista }, (err, res?: { idcko: string; kontent: string; }[]) => {
|
|
if (!int.channel?.isSendable()) return int.reply("PIČOVINA");
|
|
|
|
if (err) return odpoved.edit(`chyba: ${err}`);
|
|
|
|
if (!res || !res.length) return odpoved.edit("nic takoviho sem nenasel");
|
|
|
|
odpoved.edit("nasel sem tuto:");
|
|
|
|
let celkovadylka = 0;
|
|
const stranky: string[][] = [[]];
|
|
let aktualniStranka = 0;
|
|
for (const row of res) {
|
|
const vlozka = `[${row.kontent}] https://discord.com/channels/555779161067749446/555779161067749448/${row.idcko}`;
|
|
|
|
const dylka = vlozka.length + 3;
|
|
celkovadylka += dylka;
|
|
if (celkovadylka > 1024 || stranky[aktualniStranka].length == 20) {
|
|
aktualniStranka++;
|
|
celkovadylka = dylka;
|
|
}
|
|
|
|
const stranka = stranky[aktualniStranka] ??= [];
|
|
|
|
stranka.push(vlozka);
|
|
}
|
|
|
|
const zacatekNazvu = "visltki";
|
|
const embed: APIEmbed = {
|
|
color: Math.random() * 16777215,
|
|
fields: [{ name: zacatekNazvu, value: `• ${stranky[0].join("\n• ")}` }]
|
|
};
|
|
|
|
if (stranky.length == 1) return sendWithoutReply(int.channel, { embeds: [embed] });
|
|
|
|
embed.fields![0].name += ` (1/${stranky.length})`;
|
|
|
|
strankovani(int.channel!, embed, zacatekNazvu, stranky);
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
on_clientReady: () => {
|
|
const client = module.exports.client as CClient;
|
|
|
|
if (process.env.noGeneralSync) return;
|
|
|
|
client.channels.fetch("555779161067749448")
|
|
.then(async ch => {
|
|
const channel = ch as TextBasedChannel;
|
|
let posledni: string | undefined;
|
|
|
|
while (true) {
|
|
const msgs = await (channel.messages.fetch(posledni ? { before: posledni } : undefined));
|
|
|
|
for (const [, mes] of msgs) {
|
|
|
|
try {
|
|
await zpracovatZpravu(mes);
|
|
} catch (e) {
|
|
if (!(e instanceof Error && e.message.includes("ER_DUP_ENTRY")))
|
|
log(e);
|
|
log("general sync ukoncen");
|
|
return;
|
|
}
|
|
}
|
|
|
|
posledni = msgs.last()!.id;
|
|
|
|
// Radši
|
|
await new Promise(res => setTimeout(res, 500));
|
|
}
|
|
|
|
});
|
|
},
|
|
|
|
on_messageCreate: mes => {
|
|
if (!process.env.noGeneralSync && mes.channelId == "555779161067749448")
|
|
zpracovatZpravu(mes);
|
|
}
|
|
};
|
|
|
|
module.exports = exp;
|