diff --git a/src/app.ts b/src/app.ts index ed6510c..132c729 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,7 +1,7 @@ import { ButtonStyle, ChannelType, Client, ClientPresenceStatusData, CommandInteraction, GatewayIntentBits, InteractionReplyOptions, Message, Partials } from "discord.js"; import { readdirSync } from "fs"; import { CClient, CUser, HelpServer, Komand, KomandNaExport, KomandRaw, ListenerFunkce, Modul, SMessage, SRecord, SuperListenerFunkce } from "./utils/types"; -import { adminLog, areStatusesSame, formatCas, log, nabidni, oddiakritikovat, prefix, rand, send } from "./utils/utils.js"; +import { adminLog, areStatusesSame, formatCas, log, nabidni, oddiakritikovat, prefix, rand, messageReply } from "./utils/utils.js"; import levenshtein from "js-levenshtein"; import { emouty } from "./utils/emotes"; import { lidiCoMajDenimPremium, setClient } from "./utils/denim-Spravce"; @@ -229,7 +229,7 @@ function handle(e: unknown, mesOrInt: SMessage | CommandInteraction) { const admin = process.env.adminID; const txt = `pri spousteni thohoto komandu nastala chyba ${admin ? `<@${admin}> uz?` : ""}`; - if (mesOrInt instanceof Message) return void send(mesOrInt, txt); + if (mesOrInt instanceof Message) return void messageReply(mesOrInt, txt); mesOrInt.reply(txt); } @@ -241,23 +241,23 @@ async function runKomand(mesOrInt: SMessage | CommandInteraction, cmd: Komand, c if (jeMes && cmd.slashRun) { const nazev = `${prefix}${cmdName}`; const id = client.slashCommandy[nazev]; - return void send(mesOrInt, `tuto ejenom sleh komand `); + return void messageReply(mesOrInt, `tuto ejenom sleh komand `); } if (cmd.cd && jeMes) { const zbyva = Math.round(maKuldan(mesOrInt.author.id, cmdName, cmd.cd)); - if (zbyva) return send(mesOrInt, `si kkt vole maz kuldan jeste ${formatCas(zbyva)}`); + if (zbyva) return messageReply(mesOrInt, `si kkt vole maz kuldan jeste ${formatCas(zbyva)}`); } if (cmd.premium && !lidiCoMajDenimPremium.includes(jeMes ? mesOrInt.author.id : mesOrInt.member?.user.id || "")) { - return send(mesOrInt as SMessage, "sorka bracho tuto je koamnd jenom pro curaki co platy"); + return messageReply(mesOrInt as SMessage, "sorka bracho tuto je koamnd jenom pro curaki co platy"); } const akce = cmd.run ?? cmd.slashRun!; if (typeof akce == "string") { const res = renderMessage(akce, arg?.split(" ") || []); - if (jeMes) return send(mesOrInt, res); + if (jeMes) return messageReply(mesOrInt, res); return mesOrInt.reply(res); } @@ -266,7 +266,7 @@ async function runKomand(mesOrInt: SMessage | CommandInteraction, cmd: Komand, c const result = await akce(mesOrInt as never, arg || ""); if (!result) return; - if (jeMes) return send(mesOrInt, result) + if (jeMes) return messageReply(mesOrInt, result) .catch(e => handle(e, mesOrInt)); // další feklo mesOrInt.reply(result as InteractionReplyOptions); @@ -282,12 +282,12 @@ client.on("messageCreate", async mes => { const prefixDiff = levenshtein(oddiakritikovat(mesPrefix.toLowerCase()), prefix); if (prefixDiff > 0) { - if (!await runEvent("messageCreate", [mes]) && prefixDiff <= 1 && mes.author.id != client.user!.id) send(mes, `${prefix}*`); + if (!await runEvent("messageCreate", [mes]) && prefixDiff <= 1 && mes.author.id != client.user!.id) messageReply(mes, `${prefix}*`); return; } if (!komandSDiakritikou) { - if (!await runEvent("messageCreate", [mes])) send(mes, "coe voe"); + if (!await runEvent("messageCreate", [mes])) messageReply(mes, "coe voe"); return; } @@ -306,7 +306,7 @@ client.on("messageCreate", async mes => { if (await runEvent("messageCreate", [mes, cmdName])) return; const komand = client.komandy[cmdName]; - if (mes.channel.type == ChannelType.DM && komand?.DMUnsafe) return void send(mes, "tuten komand bohuzel v sz nefunkuje"); + if (mes.channel.type == ChannelType.DM && komand?.DMUnsafe) return void messageReply(mes, "tuten komand bohuzel v sz nefunkuje"); if (komand) return void runKomand(mes, komand, cmdName, celArgs); @@ -316,7 +316,7 @@ client.on("messageCreate", async mes => { const distance = levenshtein(cmd, cmdName); if (distance <= Math.ceil(cmdName.length * 0.3)) slova.push(cmd); }); - if (!slova.length) return void send(mes, "co to znamena ti gadzovko"); + if (!slova.length) return void messageReply(mes, "co to znamena ti gadzovko"); const nabidka = slova.sort().slice(0, 5); @@ -332,9 +332,9 @@ client.on("messageCreate", async mes => { radek.components.forEach((btn, i) => btn.setDisabled() && (i == lookupId && btn.setStyle(ButtonStyle.Success))); i.update({ content: `ok vole ${emouty.d3k}`, components: [radek] }); - if (!cmd) return void send(mes, "bohuzel negdo sy ze mi dela prel"); + if (!cmd) return void messageReply(mes, "bohuzel negdo sy ze mi dela prel"); - if (mes.channel.type == ChannelType.DM && cmd?.DMUnsafe) return void send(mes, "tuten komand bohuzel v sz nefunkuje"); + if (mes.channel.type == ChannelType.DM && cmd?.DMUnsafe) return void messageReply(mes, "tuten komand bohuzel v sz nefunkuje"); runKomand(mes, cmd, cmdName, celArgs); }, diff --git a/src/modules/custom.ts b/src/modules/custom.ts index 1607e3e..5e3b5ca 100644 --- a/src/modules/custom.ts +++ b/src/modules/custom.ts @@ -1,8 +1,8 @@ import { CClient, HelpServer, Komand, KomandNaExport, Modul, SMessage, SRecord } from "../utils/types"; import { join } from "path"; import { existsSync, readFileSync, writeFileSync } from "fs"; -import { oddiakritikovat, send, strankovani } from "../utils/utils"; -import { APIEmbed, Message } from "discord.js"; +import { oddiakritikovat, messageReply, strankovani } from "../utils/utils"; +import { APIEmbed } from "discord.js"; let client: CClient; const cesta = `${join(__dirname, "../../res/")}custom`; @@ -63,13 +63,13 @@ function zmrdovoAliasy(zacatek: string, owner: string, mes: SMessage) { let text = ""; arr.forEach(element => { if (text.length + element.length > 2000) { - send(mes, { content: text, allowedMentions: { users: [] } }); + messageReply(mes, { content: text, allowedMentions: { users: [] } }); text = ""; } text += `${element}\n`; }); - send(mes, { content: text, allowedMentions: { users: [] } }); + messageReply(mes, { content: text, allowedMentions: { users: [] } }); } const exp: Modul = { diff --git a/src/modules/denim-Dobroty.ts b/src/modules/denim-Dobroty.ts index 3a054ce..f8ad735 100644 --- a/src/modules/denim-Dobroty.ts +++ b/src/modules/denim-Dobroty.ts @@ -5,7 +5,7 @@ import { join } from "path"; import { Priority, novejPlay } from "../utils/voice"; import { lidiCoMajDenimPremium } from "../utils/denim-Spravce"; import { exec } from "child_process"; -import { log, send } from "../utils/utils"; +import { log, messageReply } from "../utils/utils"; const kmenovaCesta = join(__dirname, `../../zvuky/priVstupu`); const formaty = ["mp3", "wav", "ogg"]; @@ -42,14 +42,14 @@ const exp: Modul = { if (error) { log("chyba pri ffprobe", error); - send(mes, "bohuzel chiba"); + messageReply(mes, "bohuzel chiba"); vymaz(docasnaCesta); return; } // Maximum if (Number(stdout) > 13) { - send(mes, "13 se kund maks"); + messageReply(mes, "13 se kund maks"); vymaz(docasnaCesta); return; } @@ -62,7 +62,7 @@ const exp: Modul = { renameSync(docasnaCesta, `${zaklad}.${typ}`); - send(mes, "ej tot am"); + messageReply(mes, "ej tot am"); }); } } diff --git a/src/modules/komComplex.ts b/src/modules/komComplex.ts index 8f9e33d..5b79c03 100644 --- a/src/modules/komComplex.ts +++ b/src/modules/komComplex.ts @@ -3,7 +3,7 @@ import { ChannelType, Message, MessageReaction } from "discord.js"; import { emouty } from "../utils/emotes"; import { Modul, SRecord } from "../utils/types"; -import { formatter, ping, send, sendDM } from "../utils/utils"; +import { formatter, ping, messageReply, sendDM, sendWithoutReply } from "../utils/utils"; const exp: Modul = { more_komandy: { @@ -67,7 +67,7 @@ const exp: Modul = { argument.splice(0, 1); if (argument.length) setTimeout(() => randomshit(mes, argument), 1000); }; - send(mes, ":stop_button:").then(mes => randomshit(mes, [":five:", ":four:", ":three:", ":two:", ":one:", ":ok:"])); + messageReply(mes, ":stop_button:").then(mes => randomshit(mes, [":five:", ":four:", ":three:", ":two:", ":one:", ":ok:"])); }, pocasi: () => { @@ -92,7 +92,7 @@ const exp: Modul = { } try { - await mes.author.send(`test ${emouty.d3k}`); + await sendWithoutReply(await mes.author.createDM(), `test ${emouty.d3k}`); } catch { return "ja ti ale napsat nemuzu ti kundo"; } diff --git a/src/modules/magazin.ts b/src/modules/magazin.ts index 7c0c091..571aae2 100644 --- a/src/modules/magazin.ts +++ b/src/modules/magazin.ts @@ -1,6 +1,6 @@ import { TextChannel } from "discord.js"; import { CClient, Modul } from "../utils/types"; -import { log } from "../utils/utils"; +import { log, sendWithoutReply } from "../utils/utils"; let client: CClient; @@ -63,7 +63,7 @@ async function urobit() { const general = guilda.channels.cache.get("555779161067749448") as TextChannel; if (!general) return log(new Error("general nenalezen")); - general.send(`<@&1313491870231564318>\n${zprava}`); + sendWithoutReply(general, `<@&1313491870231564318>\n${zprava}`); naplanovat(); } diff --git a/src/modules/muzika.ts b/src/modules/muzika.ts index ac991c0..4461be0 100644 --- a/src/modules/muzika.ts +++ b/src/modules/muzika.ts @@ -6,7 +6,7 @@ import { search, validate, video_basic_info } from "play-dl"; import ytdlko from "@distube/ytdl-core"; import { emouty } from "../utils/emotes"; import { Modul } from "../utils/types"; -import { adminLog, log, send } from "../utils/utils"; +import { adminLog, log, messageReply } from "../utils/utils"; import { getConn, Hratelny, novejJoin, novejPlay, Priority, stopPlayer } from "../utils/voice"; import { array, record, safeParse, string } from "valibot"; @@ -91,16 +91,16 @@ const exp: Modul = { ajtem.name = soubor.name; ajtem.url = soubor.url; ajtem.special = true; - send(mes, `zahraju \`${soubor.name}\``); + messageReply(mes, `zahraju \`${soubor.name}\``); } else if (txt == "") return "co mam zahrat??"; else if (!druh) { ajtem.name = `nejaka picovina ot ${mes.author}`; ajtem.url = txt; ajtem.special = true; - send(mes, `zkusim to zahrat`); + messageReply(mes, `zkusim to zahrat`); } else if (druh == "search") { - const msg = send(mes, "hledam"); + const msg = messageReply(mes, "hledam"); const hledani = await search(txt, { limit: 1 }); if (!hledani[0]) return "nic sem nenašel"; ajtem.url = hledani[0].url; @@ -128,7 +128,7 @@ const exp: Modul = { const client: Client = module.exports.client; adminLog(client, "video nemá název"); } - send(mes, `zahraju \`${ajtem.name}\``); + messageReply(mes, `zahraju \`${ajtem.name}\``); } else return "tuto neumim zahrat"; if (!guildy.has(guildId)) { diff --git a/src/modules/sachy.ts b/src/modules/sachy.ts index e6d7713..970cd74 100644 --- a/src/modules/sachy.ts +++ b/src/modules/sachy.ts @@ -4,7 +4,7 @@ import { APIEmbed, Message } from "discord.js"; import { Modul } from "../utils/types"; import { fokinLookupTable, klikance, pocetKeStrane } from "../utils/sachyEtc"; import { emiter, sachyDomena } from "../utils/sachyServer"; -import { send } from "../utils/utils"; +import { messageReply } from "../utils/utils"; const hry = new Map(); // gameID -> Hra const hraci = new Map(); // hrac -> gameID @@ -533,7 +533,7 @@ const exp: Modul = { if (hraci.has(player)) return "zakaz symultanki"; } - const message = await send(mes, "hraj zopiciva"); + const message = await messageReply(mes, "hraj zopiciva"); const hra = createGame(++nextGameID, mes.author.id, druhej, message); hraci.set(mes.author.id, nextGameID); diff --git a/src/modules/spink.ts b/src/modules/spink.ts index fc65580..51c0a1a 100644 --- a/src/modules/spink.ts +++ b/src/modules/spink.ts @@ -3,7 +3,7 @@ import { ChannelType, Role, TextBasedChannel, User } from "discord.js"; import { emouty } from "../utils/emotes"; import { Modul, SRecord } from "../utils/types"; -import { formatCas, formatter, log, oddiakritikovat, ping, safeQuery, send, sendDM } from "../utils/utils"; +import { formatCas, formatter, log, oddiakritikovat, ping, safeQuery, messageReply, sendDM, sendWithoutReply } from "../utils/utils"; const enum Spinky { spinkacek, @@ -283,7 +283,7 @@ const exp: Modul = { const entry = await getLastEntry(mes.author.id); if ((entry && !entry.vstavacek) && cmd != "vstavacek") { if (mes.channel.type == ChannelType.DM) { - send(mes, "drz hubu"); + messageReply(mes, "drz hubu"); return true; } @@ -314,7 +314,7 @@ const exp: Modul = { // autospink, ne autoautospink if (prop[0]) delete autoSpinky[aft.userId]; const kanel = prop[1]; - if (kanel?.type == ChannelType.GuildText) kanel.send(await sendGmMessage(aft.member!.user)); + if (kanel?.type == ChannelType.GuildText) sendWithoutReply(kanel, await sendGmMessage(aft.member!.user)); } } }; diff --git a/src/modules/ultimatniAntispam.ts b/src/modules/ultimatniAntispam.ts index 9d8b6df..446fcde 100644 --- a/src/modules/ultimatniAntispam.ts +++ b/src/modules/ultimatniAntispam.ts @@ -1,7 +1,7 @@ // "Ulimatní" kapp import { Modul } from "../utils/types"; -import { send, messageLinks, wait } from "../utils/utils"; +import { messageReply, messageLinks, wait } from "../utils/utils"; const maxRecurseLength = 10; @@ -40,7 +40,7 @@ const exp: Modul = { if (getDepth(mes.id) == maxRecurseLength) { clear(mes.id); - send(mes, "nemam rat sarandu"); + messageReply(mes, "nemam rat sarandu"); return true; } diff --git a/src/modules/vordinace.ts b/src/modules/vordinace.ts index ad9d84c..db977ce 100644 --- a/src/modules/vordinace.ts +++ b/src/modules/vordinace.ts @@ -1,6 +1,6 @@ import { GuildScheduledEventEntityType, GuildScheduledEventPrivacyLevel, TextChannel } from "discord.js"; import { CClient, Modul } from "../utils/types"; -import { log } from "../utils/utils"; +import { log, sendWithoutReply } from "../utils/utils"; import { RawData, WebSocket } from "ws"; import { emouty } from "../utils/emotes"; @@ -212,7 +212,7 @@ async function urobit() { if (!general) return log(new Error("general nenalezen")); - general.send(`<@&1123186280843444274> ${event.url}`); + sendWithoutReply(general, `<@&1123186280843444274> ${event.url}`); canForceNotify = false; diff --git a/src/modules/vyhledavac.ts b/src/modules/vyhledavac.ts index d72ea7a..447b90b 100644 --- a/src/modules/vyhledavac.ts +++ b/src/modules/vyhledavac.ts @@ -2,7 +2,7 @@ import { APIEmbed, CommandInteractionOption, Message, TextBasedChannel } from "discord.js"; import { CClient, Modul } from "../utils/types"; -import { bazenek, log, strankovani } from "../utils/utils"; +import { bazenek, log, sendWithoutReply, strankovani } from "../utils/utils"; const zpracovatZpravu = (mes: Message) => new Promise(async (res, rej) => { if ([6, 7, 8, 9, 10, 11, 18, 23, 46].includes(mes.type)) return res(); @@ -118,7 +118,7 @@ const exp: Modul = { fields: [{ name: zacatekNazvu, value: `• ${stranky[0].join("\n• ")}` }] }; - if (stranky.length == 1) return int.channel?.send({ embeds: [embed] }); + if (stranky.length == 1) return sendWithoutReply(int.channel, { embeds: [embed] }); embed.fields![0].name += ` (1/${stranky.length})`; diff --git a/src/modules/zapniVypniSe.ts b/src/modules/zapniVypniSe.ts index a0190d6..493d481 100644 --- a/src/modules/zapniVypniSe.ts +++ b/src/modules/zapniVypniSe.ts @@ -1,7 +1,7 @@ import { getVoiceConnections } from "@discordjs/voice"; import { emouty } from "../utils/emotes"; import { Modul } from "../utils/types"; -import { prefix, send } from "../utils/utils"; +import { prefix, messageReply } from "../utils/utils"; import { novejLeave } from "../utils/voice"; let spim = false; @@ -15,9 +15,9 @@ const exp: Modul = { if (spim) { spim = false; mes.client.user?.setStatus("online"); - send(mes, "dobré ráno magoří"); + messageReply(mes, "dobré ráno magoří"); } - else send(mes, "tak jsi kokot?"); + else messageReply(mes, "tak jsi kokot?"); } else if (!spim) { if (cont == `${prefix} vypni se`) { mes.react(emouty.purfieRIP); diff --git a/src/modules/zbytek.ts b/src/modules/zbytek.ts index c4b2903..8c7578a 100644 --- a/src/modules/zbytek.ts +++ b/src/modules/zbytek.ts @@ -1,10 +1,10 @@ // Komandy nebo handelery který se nikam jinam nehodí import { getVoiceConnections } from "@discordjs/voice"; -import { Client, TextChannel, } from "discord.js"; +import { Client } from "discord.js"; import { createServer } from "http"; import { Modul } from "../utils/types"; -import { adminLog, formatCas, log, nabidni, send, sendDM } from "../utils/utils"; +import { adminLog, formatCas, log, nabidni, messageReply, sendDM, sendWithoutReply } from "../utils/utils"; import { emouty } from "../utils/emotes"; import { readFileSync } from "fs"; @@ -133,7 +133,7 @@ const exp: Modul = { (async () => { if (mes.author.id == client.user?.id) - return mes.content != "uz nechci" ? send(mes, "uz nechci") : ""; + return mes.content != "uz nechci" ? messageReply(mes, "uz nechci") : ""; const adminRole = mes.member?.roles.cache.find(r => r.name == "admin"); if (adminRole) { await mes.member?.roles.remove(adminRole).catch(e => log(mes.author.displayName, "nejde odebrat admin", e)); @@ -143,7 +143,7 @@ const exp: Modul = { if (adminRole) setTimeout(() => { mes.member?.roles.add(adminRole); }, 60_000); - send(mes, emouty.fu); + messageReply(mes, emouty.fu); })(); return true; @@ -174,7 +174,7 @@ const exp: Modul = { if (!user) return res.end("takovyho kkta neznam"); user.createDM().then(async dm => { - await dm.send(content); + await sendWithoutReply(dm, content); res.statusCode = 200; res.end("OK"); }).catch((e: Error) => { @@ -207,8 +207,14 @@ const exp: Modul = { on_userPresenceUpdate: (bef, aft) => { if (aft.user?.id != "355053867265818635" || bef?.status == "online" || aft.status != "online") return; - (client.channels.cache.get("555779161067749448") as TextChannel) - .send("https://tenor.com/view/pavel-is-online-gif-21604335"); + const channel = client.channels.cache.get("555779161067749448"); + + if (!channel || !channel.isSendable()) { + log("nelze poslat zpravu o Pavelovi, kanal nenalezen"); + return; + } + + sendWithoutReply(channel, "https://tenor.com/view/pavel-is-online-gif-21604335"); } }; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 66b421b..e2b1f92 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -81,7 +81,7 @@ 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); + sendWithoutReply(adminChannel, err ? `${text}\n\`\`\`${err}\`\`\`` : text); } if (process.env.adminID) { const user = client.users.cache.get(process.env.adminID); @@ -113,7 +113,8 @@ export function log(...content: unknown[]) { } export async function sendDM(user: User, txt: string) { - user.send(txt).catch(() => log(new Error(`dementovi ${user} nejde poslat DM ${txt}`))); + await sendWithoutReply(await user.createDM(), txt) + .catch(() => log(new Error(`dementovi ${user} nejde poslat DM ${txt}`))); } export const rand = (max: number) => Math.floor(Math.random() * max); @@ -151,12 +152,12 @@ export async function nabidni(nastaveni: Nastaveni) { radek.addComponents(component); }); - const zprava = await nastaveni.channel.send({ ...nastaveni.zpravec, components: [radek] }); + const zprava = await sendWithoutReply(nastaveni.channel, { ...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"); + if (isNaN(lookupId)) return void sendWithoutReply(nastaveni.channel, "neco nefunguje idk"); nastaveni.onCollect(i, lookupId, radek); }); @@ -228,8 +229,8 @@ export async function wait(mes: Message) { return; if (Date.now() - waitingFrom > 30_000) { - const err = new Error(`Zpráva s ID ${mes.id} nebyla zařazena do messageLinks do 30 sekund.`); - adminLog(mes.client, "Při čekání na zprávu jsem se nedočkal", err); + const err = new Error(`Zpráva ${mes.id} nebyla zařazena do messageLinks do 30 sekund`); + adminLog(mes.client, "při čekání na zprávu jsem se nedočkal", err); log(err); return; } @@ -238,14 +239,32 @@ export async function wait(mes: Message) { } } -export async function send(mes: SMessage, co: string | MessageCreateOptions) { - const nova = await mes.channel.send(co); +async function baseSend(channel: SendableChannels, co: string | MessageCreateOptions, orgId: string) { + const nova = await channel.send(co); - messageLinks.set(nova.id, mes.id); + messageLinks.set(nova.id, orgId); return nova; } +/** + * Slouží k odeslání zprávy jako odpověď na jinou zprávu a zajistí, anti-spam mechanismus bude fungovat. + * @param mes Zpráva na kterou se má odpovědět + * @param co Obsah zprávy, který se má odeslat + */ +export async function messageReply(mes: SMessage, co: string | MessageCreateOptions) { + return await baseSend(mes.channel, co, mes.id); +} + +/** + * Slouží k odeslání zprávy bez odpovědi na jinou zprávu a zajistí, anti-spam mechanismus bude fungovat. + * @param channel Kanál, kam se má zpráva odeslat + * @param co Obsah zprávy, který se má odeslat + */ +export async function sendWithoutReply(channel: SendableChannels, co: string | MessageCreateOptions) { + return await baseSend(channel, co, ""); +} + export const areStatusesSame = (object1?: ClientPresenceStatusData | null, object2?: ClientPresenceStatusData | null) => { if ((object1 === null || object1 === undefined) && (object2 === null || object2 === undefined)) return true;