revoluce je tady doprdele!!

This commit is contained in:
Histmy 2023-03-04 17:09:53 +01:00
parent e8661ac39b
commit 6eca55d6d6
5 changed files with 226 additions and 89 deletions

View File

@ -1,6 +1,6 @@
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, Client, ComponentType, GatewayIntentBits, Message, Partials } from "discord.js"; import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, Client, CommandInteraction, ComponentType, GatewayIntentBits, Message, Partials } from "discord.js";
import { readdirSync } from "fs"; import { readdirSync } from "fs";
import { CUser, EventSOn, KomandNaExport, Komand, ListenerFunkce, Modul, SRecord, SuperListenerFunkce, RunFunkce, CClient, HelpServer } from "./utils/types"; import { CUser, EventSOn, KomandNaExport, Komand, ListenerFunkce, Modul, SRecord, SuperListenerFunkce, CClient, HelpServer, KomandRaw } from "./utils/types";
import { adminLog, formatCas, oddiakritikovat, log, rand } from "./utils/utils.js"; import { adminLog, formatCas, oddiakritikovat, log, rand } from "./utils/utils.js";
import levenshtein from "js-levenshtein"; import levenshtein from "js-levenshtein";
import { emouty } from "./utils/emotes"; import { emouty } from "./utils/emotes";
@ -26,7 +26,7 @@ const helpServer: HelpServer = require("./utils/helpServer");
client.komandy = {}; client.komandy = {};
client.aliasy = {}; client.aliasy = {};
function getFirstArg(fn: RunFunkce | string) { function getFirstArg(fn: KomandRaw["run"]) {
if (typeof fn != "function") return; if (typeof fn != "function") return;
return fn.toString() return fn.toString()
.match(/(?:function\s.*?)?\(([^)]*)\)|\w+ =>/)![1] .match(/(?:function\s.*?)?\(([^)]*)\)|\w+ =>/)![1]
@ -91,7 +91,7 @@ readdirSync(modulFolder).forEach(soubor => {
client.komandy[cmdName] = { run: value }; client.komandy[cmdName] = { run: value };
toCoExportuju.arg = getFirstArg(value); toCoExportuju.arg = getFirstArg(value);
} else { } else {
client.komandy[cmdName] = { run: value.run, cd: value.cd, DMUnsafe: value.DMUnsafe }; client.komandy[cmdName] = { run: value.run, slashRun: value.slashRun, cd: value.cd, DMUnsafe: value.DMUnsafe };
Object.assign(toCoExportuju, { als: value.als, arg: value.arg ?? getFirstArg(value.run) }); Object.assign(toCoExportuju, { als: value.als, arg: value.arg ?? getFirstArg(value.run) });
hide = !!value.hidden; hide = !!value.hidden;
value.als?.forEach(al => client.aliasy[al] = cmdName); value.als?.forEach(al => client.aliasy[al] = cmdName);
@ -215,23 +215,42 @@ function renderMessage(expression: string, args: string[]) {
} }
} }
async function runKomand(mes: Message, cmd: Komand, cmdName: string, arg: string): Promise<any>;
async function runKomand(interaction: CommandInteraction, cmd: Komand, cmdName: string): Promise<any>;
async function runKomand(mesOrInt: Message | CommandInteraction, cmd: Komand, cmdName: string, arg?: string) {
const jeMes = mesOrInt instanceof Message;
async function runKomand(mes: Message, cmd: Komand, cmdName: string, arg: string) { if (cmd.cd && jeMes) {
if (cmd.cd) { const zbyva = Math.round(maKuldan(mesOrInt.author.id, cmdName, cmd.cd));
const zbyva = Math.round(maKuldan(mes.author.id, cmdName, cmd.cd)); if (zbyva) return void mesOrInt.channel.send(`si kkt vole maz kuldan jeste ${formatCas(zbyva)}`);
if (zbyva) return void mes.channel.send(`si kkt vole maz kuldan jeste ${formatCas(zbyva)}`); }
const akce = jeMes
? cmd.run
: cmd.slashRun!;
if (typeof akce == "string") {
const res = renderMessage(akce, arg?.split(" ") || []);
if (mesOrInt instanceof Message) return mesOrInt.channel.send(res);
return mesOrInt.reply(res);
} }
const akce = cmd.run;
if (typeof akce == "string") return void mes.channel.send(renderMessage(akce, arg.split(" ")));
try { try {
const result = await akce(mes, arg); // @ts-ignore todle prostě musí fungovat a jestli náhodou ne, stejně je tu catch
if (result) mes.channel.send(result); const result = await akce(mesOrInt, arg);
if (!result) return;
if (mesOrInt instanceof Message) return mesOrInt.channel.send(result);
// @ts-ignore a zas ksd
mesOrInt.reply(result);
} catch (e) { } catch (e) {
if (process.env.dieOnError) throw e; if (process.env.dieOnError) throw e;
log("error pri spousteni akce", e as Error); log("error pri spousteni akce", e as Error);
const admin = process.env.adminID; const admin = process.env.adminID;
mes.channel.send(`pri spousteni thohoto komandu nastala chyba ${admin ? `<@${admin}> uz?` : ""}`);
const txt = `pri spousteni thohoto komandu nastala chyba ${admin ? `<@${admin}> uz?` : ""}`;
if (mesOrInt instanceof Message) return mesOrInt.channel.send(txt);
mesOrInt.reply(txt);
} }
} }
@ -305,4 +324,15 @@ client.on("presenceUpdate", (bef, aft) => {
runEvent("userPresenceUpdate", [bef, aft]); runEvent("userPresenceUpdate", [bef, aft]);
}); });
client.on("interactionCreate", async int => {
if (process.env.ignoreMess || !int.isCommand()) return;
const cmdName = int.commandName.slice(4);
const command = client.komandy[cmdName];
if (!command) int.reply(`komand nenalezen ${emouty.lukiw}`);
runKomand(int, command, cmdName);
});
client.login(process.env.token); client.login(process.env.token);

View File

@ -1,14 +1,97 @@
// Modul na komand "anketa" // Modul na komand "anketa"
import { ActionRowBuilder, APIEmbed, APIEmbedField, ButtonBuilder, ButtonStyle, ComponentType, Message, MessageComponentInteraction } from "discord.js"; import { ActionRowBuilder, APIEmbed, APIEmbedField, ButtonBuilder, ButtonStyle, CommandInteraction, ComponentType, InteractionResponse, Message, MessageComponentInteraction } from "discord.js";
import { Modul } from "../utils/types"; import { Modul, SRecord } from "../utils/types";
import { formatter } from "../utils/utils"; import { formatter } from "../utils/utils";
function parseMoznosti(moznostiStr: string) {
return moznostiStr.split(moznostiStr.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) {
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);
const embed: APIEmbed = {
title: "Hlasování",
description: settings.immediateShow ? `Končí ${formatter(konec)}` : `Výsledky se zobrazí ${formatter(konec)}`
};
const fildy: APIEmbedField[] = [];
const radky: ActionRowBuilder<ButtonBuilder>[] = [];
const odpovedi: SRecord<number> = {};
function prepocitat(int?: MessageComponentInteraction) {
const celkem = Object.keys(odpovedi).length;
fildy.forEach((f, i) => {
const hovn = Object.values(odpovedi).filter(n => n == i);
const dylka = hovn.length;
const p = Math.floor(dylka / celkem * 10) || 0;
const people = Object.keys(odpovedi).reduce<string[]>((pr, cur) => {
if (odpovedi[cur] == i) pr.push(cur);
return pr;
}, []);
const kindo = people.map(w => mesOrInt.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] });
}
moznosti.forEach((h, i) => {
const mnam = (i - (i % 5)) / 5;
if (i % 5 == 0) radky[mnam] = new ActionRowBuilder<ButtonBuilder>;
fildy.push({ name: h, value: "" });
radky[mnam].addComponents(new ButtonBuilder({ customId: `${i}`, label: h, style: ButtonStyle.Primary }));
});
prepocitat();
if (settings.immediateShow) embed.fields = fildy;
let zprava: Message<boolean> | InteractionResponse;
let edit: (c: any) => void;
if (jeMes) {
zprava = await mesOrInt.channel.send({ embeds: [embed], components: radky });
// @ts-ignore seru na to, logicky to musí fungovat a to že to typscript nechápe není můj problém
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 });
collector.on("collect", d => {
if (!(d.message instanceof Message)) return;
const i = Number(d.customId);
const prev = odpovedi[d.user.id];
if (prev == i) return void d.deferUpdate();
odpovedi[d.user.id] = i;
if (!settings.immediateShow) return void d.deferUpdate();
prepocitat();
d.update({ embeds: [embed] });
});
collector.on("end", () => {
embed.description = `Skončilo ${formatter(konec)}`;
prepocitat();
embed.fields = fildy;
edit({ components: [], embeds: [embed] });
});
}
const exp: Modul = { const exp: Modul = {
more_komandy: { more_komandy: {
anketa: { anketa: {
arg: "([nastaveni]) moznosti...", arg: "([nastaveni]) moznosti...",
DMUnsafe: true,
run: async (mes, arg) => { run: async (mes, arg) => {
const settings = { const settings = {
@ -31,70 +114,23 @@ const exp: Modul = {
} }
} }
const moznosti = arg.slice(huuuuuu + 1).split(arg.includes("|") ? "|" : ",").reduce<string[]>((acc, c) => { const moznosti = parseMoznosti(arg.slice(huuuuuu + 1));
if (c.length) acc.push(c.trim());
return acc;
}, []);
if (moznosti.length < 2) return "zadej alespo%n dve moznosti";
if (moznosti.length > 25) return "toje moc";
const konec = new Date(); return await zbytek(settings, moznosti, mes);
konec.setSeconds(konec.getSeconds() + settings.time); },
const embed: APIEmbed = { slashRun: async (int) => {
title: "Hlasování",
description: settings.immediateShow ? `Končí ${formatter(konec)}` : `Výsledky se zobrazí ${formatter(konec)}` 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 x5fxd55: APIEmbedField[] = [];
const radky: ActionRowBuilder<ButtonBuilder>[] = [];
const odpovedi: Record<string, number> = {};
function prepocitat(): void; const moznosti = parseMoznosti(opt.get("moznosti")!.value as string);
function prepocitat(int: MessageComponentInteraction): void;
function prepocitat(int?: MessageComponentInteraction) {
const celkem = Object.keys(odpovedi).length;
x5fxd55.forEach((f, i) => {
const hovn = Object.values(odpovedi).filter(n => n == i);
const dylka = hovn.length;
const p = Math.floor(dylka / celkem * 10) || 0;
const people = Object.keys(odpovedi).reduce<string[]>((pr, cur) => {
if (odpovedi[cur] == i) pr.push(cur);
return pr;
}, []);
const kindo = people.map(w => mes.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] });
}
moznosti.forEach((h, i) => { return await zbytek(settings, moznosti, int);
const mnam = (i - (i % 5)) / 5;
if (i % 5 == 0) radky[mnam] = new ActionRowBuilder<ButtonBuilder>;
x5fxd55.push({ name: h, value: "" });
radky[mnam].addComponents(new ButtonBuilder({ customId: `${i}`, label: h, style: ButtonStyle.Primary }));
});
prepocitat();
if (settings.immediateShow) embed.fields = x5fxd55;
const zprava = await mes.channel.send({ embeds: [embed], components: radky });
const collector = mes.channel.createMessageComponentCollector<ComponentType.Button>({ filter: i => i.message.id == zprava.id, time: settings.time * 1000 });
collector.on("collect", d => {
if (!(d.message instanceof Message)) return;
const i = Number(d.customId);
const prev = odpovedi[d.user.id];
if (prev == i) return void d.deferUpdate();
odpovedi[d.user.id] = i;
if (!settings.immediateShow) return void d.deferUpdate();
prepocitat();
d.update({ embeds: [embed] });
});
collector.on("end", () => {
embed.description = `Skončilo ${formatter(konec)}`;
prepocitat();
embed.fields = x5fxd55;
zprava.edit({ components: [], embeds: [embed] });
});
} }
} }

View File

@ -0,0 +1,62 @@
import { REST, RESTPostAPIChatInputApplicationCommandsJSONBody, Routes } from 'discord.js';
import { CClient, Modul } from '../utils/types';
const komandy: RESTPostAPIChatInputApplicationCommandsJSONBody[] = [
{
name: "moreanketa",
description: "udelam fajnonovou anketu haby sy moch myt zbitecny anzori ostatnich",
dm_permission: false,
options: [
{
name: "moznosti",
description: "mezi cim maj ty morove vibirat (odeluj carkama nebo pipama)",
type: 3, // String
required: true
},
{
name: "cas",
description: "jak dlouho budem cekat na ti bridili nez se rozhodnou",
type: 4 // Integer
},
{
name: "jmena",
description: "jestli chces strapnovat ostatni jejich vibjerem tak tuto zapni",
type: 5 // Boolean
},
{
name: "neprubezny",
description: "jestli chces haby bili visledky vydet hned nebo az potom co bude pozde sy to rozmyslet",
type: 5 // Boolean
}
]
}
];
const exp: Modul = {
on_ready: async () => {
// Construct and prepare an instance of the REST module
const rest = new REST({ version: '10' }).setToken(process.env.token!);
// and deploy your commands!
try {
console.log(`Started refreshing application (/) commands.`);
// The put method is used to fully refresh all commands in the guild with the current set
const data = (await rest.put(
Routes.applicationCommands(client.user!.id),
{ body: komandy },
)) as any;
console.log(data);
console.log(`Successfully reloaded ${data?.length} application (/) commands.`);
} catch (error) {
// And of course, make sure you catch and log any errors!
console.error("Chyba při refreshování aplikačních (/) komandů", error);
}
}
};
module.exports = exp;

View File

@ -197,7 +197,7 @@ const exp: Modul = {
if (mes.author.id === '831318260493844494') { if (mes.author.id === '831318260493844494') {
syncSpink(); syncSpink();
const uzivatel = mes.content.match(/(?<=discord_)\d+/)?.[0]; const uzivatel = mes.content.match(/(?<=discord_)\d+/)?.[0];
if (!uzivatel) return; if (!uzivatel) return false;
for (const [, guild] of mes.client.guilds.cache) { for (const [, guild] of mes.client.guilds.cache) {
const member = guild.members.cache.get(uzivatel); const member = guild.members.cache.get(uzivatel);
if (!member) continue; if (!member) continue;
@ -228,17 +228,22 @@ const exp: Modul = {
for (const [, member] of channel.members) { for (const [, member] of channel.members) {
if (member.id !== uzivatel) continue; if (member.id !== uzivatel) continue;
member.voice.disconnect("spinkacek"); member.voice.disconnect("spinkacek");
return; return false;
} }
} }
} }
} else if (spinkacky[mes.author.id]?.spinkacek && cmd != "vstavacek") { } else if (spinkacky[mes.author.id]?.spinkacek && cmd != "vstavacek") {
if (mes.channel.type == ChannelType.DM) return mes.channel.send("drz hubu"); if (mes.channel.type == ChannelType.DM) {
mes.channel.send("drz hubu");
return true;
}
mes.delete(); mes.delete();
sendDM(mes.author, "spis tak nepis"); sendDM(mes.author, "spis tak nepis");
return true; return true;
} }
return false;
}, },
on_userPresenceUpdate: async (bef: Presence | null, aft: Presence) => { on_userPresenceUpdate: async (bef: Presence | null, aft: Presence) => {

View File

@ -1,23 +1,25 @@
import { StreamType, VoiceConnection } from "@discordjs/voice"; import { StreamType, VoiceConnection } from "@discordjs/voice";
import { Client, ClientEvents, ClientPresenceStatusData, Message, MessageCreateOptions, MessagePayload, User } from "discord.js"; import { Awaitable, Client, ClientEvents, ClientPresenceStatusData, CommandInteraction, Message, MessageCreateOptions, MessagePayload, User } from "discord.js";
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { Readable } from "node:stream"; import { Readable } from "node:stream";
type OutputRunFunkce = string | MessagePayload | MessageCreateOptions | void; export type RunFunkce = (message: Message, argumenty: string) => Awaitable<string | MessagePayload | MessageCreateOptions | void>;
export type InteractionRunFunkce = (interaction: CommandInteraction) => Awaitable<string | void>;
export type RunFunkce = (message: Message, argumenty: string) => OutputRunFunkce | Promise<OutputRunFunkce>; export type BaseKomandProps = {
export interface BaseKomandProps {
als?: string[]; als?: string[];
arg?: string; arg?: string;
} };
type KomandRaw = { export type KomandRaw = BaseKomandProps &
{
run: string | RunFunkce; run: string | RunFunkce;
slashRun?: InteractionRunFunkce;
cd?: number; cd?: number;
hidden?: true; hidden?: true;
DMUnsafe?: true; DMUnsafe?: true;
} & BaseKomandProps; };
export type ListenerFunkce = (...args: any[]) => void; export type ListenerFunkce = (...args: any[]) => void;
@ -37,13 +39,15 @@ export type SRecord<T> = Record<string, T>;
export type Modul = { export type Modul = {
more_komandy?: SRecord<RunFunkce | KomandRaw | string>; more_komandy?: SRecord<RunFunkce | KomandRaw | string>;
client?: Client<boolean>; client?: Client<boolean>;
} & { [key in EventSOn]?: ListenerFunkce | SuperObject | SuperListenerFunkce; }; } & { [key in `on_${Eventy}`]?: ListenerFunkce }
& { [key in `super_on_${Eventy}`]?: SuperObject | SuperListenerFunkce; };
export interface Komand { export type Komand = {
run: RunFunkce | string; run: string | RunFunkce;
slashRun?: InteractionRunFunkce;
cd?: number; cd?: number;
DMUnsafe?: true; DMUnsafe?: true;
} };
export interface Spinkackar { export interface Spinkackar {
spinkacek: boolean; spinkacek: boolean;