Multiple things...

upgraded to newest version of discord.js
added anouncment about new ordinace
better music playing capability
bot doesn't die when spinking idiot PMs him
This commit is contained in:
Histmy 2022-08-08 19:34:27 +02:00
parent 14d88125e5
commit 6a2eef9b7a
10 changed files with 230 additions and 60 deletions

View File

@ -1,4 +1,4 @@
import { Client, Intents, Message, MessageActionRow, MessageButton } from "discord.js";
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, Client, GatewayIntentBits, Message, Partials } from "discord.js";
import { readdirSync } from "fs";
import { CUser, EventSOn, KomandNaExport, Komand, ListenerFunkce, Modul, SRecord, SuperListenerFunkce, CustomKomandy } from "./utils/types";
import { adminLog, getFirstArg, formatCas, loadEnv, oddiakritikovat, sortArr } from "./utils/utils.js";
@ -10,10 +10,10 @@ const custom: CustomKomandy = require("./utils/customCommands");
loadEnv();
const ints = Intents.FLAGS;
const ints = GatewayIntentBits;
const client = new Client({
partials: ["CHANNEL"],
intents: [ints.GUILDS, ints.GUILD_VOICE_STATES, ints.GUILD_PRESENCES, ints.GUILD_MESSAGES, ints.DIRECT_MESSAGES]
partials: [Partials.Channel],
intents: [ints.Guilds, ints.GuildVoiceStates, ints.GuildPresences, ints.GuildMessages, ints.DirectMessages, ints.MessageContent]
});
const prefix = process.env.prefix || "more";
const modulFolder = `${__dirname}/modules/`;
@ -80,7 +80,7 @@ readdirSync(modulFolder).forEach(soubor => {
const ev = groups.s ? superEventy : eventy;
if (!ev[groups.h]) {
ev[groups.h] = [];
if (!["message", "userPresenceUpdate"].includes(groups.h)) client.on(groups.h, (...args) => void runEvent(groups.h, args));
if (!["messageCreate", "userPresenceUpdate"].includes(groups.h)) client.on(groups.h, (...args) => void runEvent(groups.h, args));
}
const n = modul[name as EventSOn]!;
@ -154,9 +154,9 @@ client.on("messageCreate", async mes => {
if (process.env.ignoreMess) return;
const [mesPrefix, komandSDiakritikou, ...args] = mes.content.split(" ");
if (oddiakritikovat(mesPrefix.toLowerCase()) != prefix) return void runEvent("message", [mes]);
if (oddiakritikovat(mesPrefix.toLowerCase()) != prefix) return void runEvent("messageCreate", [mes]);
if (!komandSDiakritikou) {
if (!runEvent("message", [mes])) mes.channel.send("coe voe");
if (!runEvent("messageCreate", [mes])) mes.channel.send("coe voe");
return;
}
@ -164,10 +164,10 @@ client.on("messageCreate", async mes => {
const komandBez = oddiakritikovat(komandSDiakritikou).toLowerCase();
const cmdName = aliasy[komandBez] ?? customAliasy[komandBez] ?? komandBez;
if (runEvent("message", [mes, cmdName])) return;
if (runEvent("messageCreate", [mes, cmdName])) return;
const komand = komandy[cmdName] ?? customKomandy[cmdName];
if (mes.channel.type == "DM" && komand?.DMUnsafe) return void mes.channel.send("tuten komand bohuzel v sz nefunkuje");
if (mes.channel.type == ChannelType.DM && komand?.DMUnsafe) return void mes.channel.send("tuten komand bohuzel v sz nefunkuje");
if (komand) return void runKomand(mes, komand, cmdName, celArgs);
@ -180,10 +180,10 @@ client.on("messageCreate", async mes => {
if (!slova.length) return void mes.channel.send("co to znamena ti gadzovko");
const nabidka = slova.sort().slice(0, 5);
const radek = new MessageActionRow();
const radek = new ActionRowBuilder<ButtonBuilder>();
nabidka.forEach((cmd, i) => {
const nazev = cmd.length > 80 ? `${cmd.slice(0, 77)}...` : cmd;
radek.addComponents(new MessageButton({ customId: `${i}`, label: nazev, style: "PRIMARY" }));
radek.addComponents(new ButtonBuilder({ customId: `${i}`, label: nazev, style: ButtonStyle.Primary }));
});
const zprava = await mes.channel.send({ content: "nemnel sy na misli:", components: [radek] });

View File

@ -1,6 +1,6 @@
// Modul na komand "anketa"
import { Message, MessageActionRow, MessageButton, MessageComponentInteraction, MessageEmbedOptions } from "discord.js";
import { ActionRowBuilder, APIEmbed, ButtonBuilder, ButtonStyle, Message, MessageComponentInteraction } from "discord.js";
import { emouty } from "../utils/emotes";
import { Modul } from "../utils/types";
import { formatter } from "../utils/utils";
@ -35,12 +35,12 @@ const exp: Modul = {
const konec = new Date();
konec.setSeconds(konec.getSeconds() + settings.time);
const embed: MessageEmbedOptions = {
const embed: APIEmbed = {
title: "Hlasování",
description: settings.immediateShow ? `Končí ${formatter(konec)}` : `Výsledky se zobrazí ${formatter(konec)}`,
fields: []
};
const radek = new MessageActionRow();
const radek = new ActionRowBuilder<ButtonBuilder>();
const odpovedi: Record<string, number> = {};
function prepocitat(): void;
@ -58,7 +58,7 @@ const exp: Modul = {
moznosti.forEach((h, i) => {
if (settings.immediateShow) embed.fields?.push({ name: h, value: "" });
radek.addComponents(new MessageButton({ customId: `${i}`, label: h, style: "PRIMARY" }));
radek.addComponents(new ButtonBuilder({ customId: `${i}`, label: h, style: ButtonStyle.Primary }));
});
prepocitat();
const zprava = await mes.channel.send({ embeds: [embed], components: [radek] });
@ -68,9 +68,9 @@ const exp: Modul = {
if (!(d.message instanceof Message)) return;
const i = Number(d.customId);
const prev = odpovedi[d.user.id];
if (prev == i) return d.deferUpdate();
if (prev == i) return void d.deferUpdate();
odpovedi[d.user.id] = i;
if (!settings.immediateShow) return d.deferUpdate();
if (!settings.immediateShow) return void d.deferUpdate();
prepocitat(d);
});

View File

@ -1,10 +1,10 @@
// Komandy, který pošlou jenom celArgs a random hovno
import { Message } from "discord.js";
import { ChannelType, Message } from "discord.js";
import { emouty } from "../utils/emotes";
import { Modul } from "../utils/types";
const delAndReturn = (mes: Message, co: string) => {
if (mes.channel.type != "DM") mes.delete();
if (mes.channel.type != ChannelType.DM) mes.delete();
return co;
};

View File

@ -1,7 +1,7 @@
// Komandy, který buď nějakým způsobem mění funkci nebo "vzhled" bota
// nebo donutí bota něco udělat (odeslání zprávy nebo smazání originální zprávy se nepočítá)
import { ActivityType, Message, MessageReaction, PresenceStatusData } from "discord.js";
import { ActivityType, ChannelType, Message, MessageReaction, PresenceStatusData } from "discord.js";
import { emouty } from "../utils/emotes";
import { Modul, SRecord } from "../utils/types";
import { formatter, ping } from "../utils/utils";
@ -11,8 +11,8 @@ const changeStatus = (mes: Message, status: PresenceStatusData) => {
return "ano pane";
};
const changeActivity = (mes: Message, activity: Exclude<ActivityType, "CUSTOM"> | undefined = undefined, txt: string = "") => {
mes.client.user?.setActivity({ name: txt, type: activity });
const changeActivity = (mes: Message, activity: Exclude<ActivityType, ActivityType.Custom> | undefined = undefined, txt: string = "") => {
mes.client.user?.setActivity(txt, { type: activity });
mes.react(emouty.d3k);
return "ano pane";
};
@ -39,10 +39,10 @@ const exp: Modul = {
run: mes => changeStatus(mes, "invisible")
},
hraj: (mes, co) => changeActivity(mes, "PLAYING", co),
sleduj: (mes, co) => changeActivity(mes, "WATCHING", co),
poslouchej: (mes, co) => changeActivity(mes, "LISTENING", co),
soutez: (mes, vcem) => changeActivity(mes, "COMPETING", vcem),
hraj: (mes, co) => changeActivity(mes, ActivityType.Playing, co),
sleduj: (mes, co) => changeActivity(mes, ActivityType.Watching, co),
poslouchej: (mes, co) => changeActivity(mes, ActivityType.Listening, co),
soutez: (mes, vcem) => changeActivity(mes, ActivityType.Competing, vcem),
nedelej: mes => changeActivity(mes),
fight: {
@ -99,7 +99,7 @@ const exp: Modul = {
}
const reakce: Promise<void | MessageReaction>[] = [];
if (mes.channel.type != "DM") mes.delete();
if (mes.channel.type != ChannelType.DM) mes.delete();
emouty.forEach(emout => {
reakce.push(naCo.react(emout)
.catch(() => { }));

View File

@ -1,37 +1,128 @@
// Tady bude muzika, vole
import { AudioPlayerStatus, VoiceConnection } from "@discordjs/voice";
import { search, soundcloud, stream, validate, video_basic_info } from "play-dl";
import { Modul } from "../utils/types";
import { joinVoice, play } from "../utils/utils";
import { emouty } from "../utils/emotes";
import { Modul, SRecord } from "../utils/types";
import { configureTimeAnouncment, getCurrentPlayer, joinVoice, play } from "../utils/utils";
const kjus: SRecord<{ name: string; url: string; }[]> = {};
async function zahrat(conn: VoiceConnection, url: string, seek?: number) {
const src = await stream(url, { seek });
play(conn, { name: src.stream, volume: 1, type: src.type });
}
const exp: Modul = {
more_komandy: {
zahraj: {
DMUnsafe: true,
run: async (mes, txt) => {
let url: string;
const kanel = mes.member?.voice.channel;
if (!kanel) return "nejsi ve vojsu ty kkt";
const ajtem = { name: "", url: "" };
const druh = await validate(txt);
if (druh && druh != "search") {
if (druh != "yt_video" && druh != "so_track") return "tuto neumim zahrat";
url = txt;
ajtem.url = txt;
if (druh == "yt_video") {
video_basic_info(url).then(v => mes.channel.send(`hraju \`${v.video_details.title}\``));
video_basic_info(txt).then(v => {
ajtem.name = v.video_details.title!;
mes.channel.send(`zahraju \`${ajtem.name}\``);
});
} else {
soundcloud(url).then(s => mes.channel.send(`hraju \`${s.name}\``));
soundcloud(txt).then(s => {
ajtem.name = s.name;
mes.channel.send(`zahraju \`${s.name}\``);
});
}
} else {
const msg = mes.channel.send("hledam");
const hledani = await search(txt, { limit: 1 });
url = hledani[0].url;
msg.then(m => m.edit(`hraju \`${hledani[0].title}\``));
ajtem.url = hledani[0].url;
ajtem.name = hledani[0].title!;
msg.then(m => m.edit(`zahraju \`${ajtem.name}\``));
}
const kanel = mes.member?.voice.channel;
if (!kanel) return "nejsi ve vojsu ty kkt";
const { conn } = await joinVoice(kanel);
const kju = (kjus[mes.guildId!] ??= []);
kju.push(ajtem);
const src = await stream(url);
play(conn, { name: src.stream, volume: 1, type: src.type });
if (kju.length != 1) return;
configureTimeAnouncment(mes.guildId!, false);
const { conn } = await joinVoice(kanel);
const player = getCurrentPlayer(mes.guildId!)!;
zahrat(conn, ajtem.url);
player.on(AudioPlayerStatus.Idle, () => {
kju.splice(0, 1);
if (kju.length == 0) {
delete kjus[mes.guildId!];
configureTimeAnouncment(mes.guildId!, true);
return;
}
zahrat(conn, kju[0].url);
});
}
},
queue: {
als: ["q", "kju"],
DMUnsafe: true,
run: mes => {
const kju = kjus[mes.guildId!];
if (!kju) return "nehraje nic";
return `tuto je kurentni repertoar:\n${kju.reduce((acc, cur, i) => {
return `${acc}\n${i ? `${i}. ${cur.name}` : `-- *${cur.name}* --`}`;
}, "")}`;
}
},
skip: {
DMUnsafe: true,
run: mes => {
const kju = kjus[mes.guildId!];
if (!kju) return "nic nehraje";
const player = getCurrentPlayer(mes.guildId!);
player.stop();
mes.react(emouty.d3k);
}
},
remove: {
DMUnsafe: true,
als: ["odebrat"],
run: (mes, arg) => {
const numero = Number(arg);
if (isNaN(numero)) return "cokundo?";
const kju = kjus[mes.guildId!];
if (!kju) return "nic nehraje";
if (kju.length <= numero) return "tolik toho nehrae";
kju.splice(numero, 1);
mes.react(emouty.d3k);
}
},
seek: {
DMUnsafe: true,
run: (mes, arg) => {
const numero = Number(arg);
if (isNaN(numero)) return "huh?";
const kju = kjus[mes.guildId!];
if (!kju) return "nehraje nic";
const conn = getCurrentPlayer(mes.guildId!)!.playable[0];
zahrat(conn, kju[0].url, numero);
mes.react(emouty.d3k);
}
}
}

View File

@ -0,0 +1,62 @@
import { Client, TextChannel } from "discord.js";
import fetch from "node-fetch";
import { emouty } from "../utils/emotes";
import { Modul } from "../utils/types";
let posledniDatum = "";
let client: Client;
function naplanovat(): void;
function naplanovat(jesteNeska: true): void;
function naplanovat(jesteNeska?: true) {
const novyCas = new Date();
const den = novyCas.getDay();
if (jesteNeska && den == 4) return hendelieren();
novyCas.setDate(novyCas.getDate() + ((den < 4 ? 4 : 11) - den));
novyCas.setHours(15);
novyCas.setMinutes(0);
setTimeout(hendelieren, Number(novyCas) - Number(new Date()));
}
const padNula = (n: number) => n > 9 ? n : `0${n}`;
function hendelieren() {
fetch("https://sktorrent.eu/torrent/torrents_v2.php?search=ordinace")
.then(r => r.text())
.then(txt => {
const tabule = txt.match(/<table width="100%" class="lista">(?<kontent>.+)<\/table>/is);
if (!tabule) return console.log("nenašel jsem tabuleho");
const detaily = tabule.groups!.kontent.match(/<a href="(?<odkaz>details.+?)".+?Pridany (?<datum>\d\d\/\d\d\/\d{4})/is);
const datum = detaily?.groups!.datum!;
if (posledniDatum == "") {
const d = new Date();
if (`${padNula(d.getDate())}/${padNula(d.getMonth() + 1)}/${d.getFullYear()}` == datum) {
return naplanovat();
}
posledniDatum = datum;
return setTimeout(hendelieren, 18e4);
}
if (posledniDatum == datum) return setTimeout(hendelieren, 18e4);
(client.channels.cache.get("555779161067749448") as TextChannel).send(`<@&591306633196339261> vyšla nová vordinačka ${emouty.lajk}\nhttps://sktorrent.eu/${detaily?.groups?.odkaz}`);
naplanovat();
return;
});
}
const exp: Modul = {
on_ready: () => {
client = module.exports.client;
naplanovat(true);
}
};
module.exports = exp;

View File

@ -1,6 +1,6 @@
// Modul dedikovaný funkci spinkáček
import { Message, Presence, Role, TextBasedChannel, User, VoiceState } from "discord.js";
import { ChannelType, Message, Presence, Role, TextBasedChannel, User, VoiceState } from "discord.js";
import fetch from "node-fetch";
import { emouty } from "../utils/emotes";
import { Modul, Spinkackar, SRecord } from "../utils/types";
@ -174,7 +174,7 @@ const exp: Modul = {
.catch(err => console.log("spinkacek odpojit se nepovedlo nebo co:", err));
},
super_on_message: (mes: Message, cmd?: string) => {
super_on_messageCreate: (mes: Message, cmd?: string) => {
if (mes.author.id === '831318260493844494') {
syncSpink();
const uzivatel = mes.content.match(/(?<=discord_)\d+/)?.[0];
@ -205,7 +205,7 @@ const exp: Modul = {
continue;
}
for (const [, channel] of guild.channels.cache) {
if (channel.type !== "GUILD_VOICE") continue;
if (channel.type != ChannelType.GuildVoice) continue;
for (const [, member] of channel.members) {
if (member.id !== uzivatel) continue;
member.voice.disconnect("spinkacek");
@ -214,6 +214,8 @@ const exp: Modul = {
}
}
} else if (spinkacky[mes.author.id]?.spinkacek && cmd != "vstavacek") {
if (mes.channel.type == ChannelType.DM) return mes.channel.send("drz hubu");
mes.delete();
(async () => {
const chanel = mes.author.dmChannel ?? await mes.author.createDM();
@ -235,7 +237,7 @@ const exp: Modul = {
if (befoff && !aftoff) {
if (prop[0]) delete autoSpinky[aft.userId];
const kanel = prop[1];
if (kanel?.isText()) kanel.send(await tovjemamvolepreceroliky(aft.member!.user));
if (kanel?.type == ChannelType.GuildText) kanel.send(await tovjemamvolepreceroliky(aft.member!.user));
}
}
};

View File

@ -1,14 +1,14 @@
// Cokoliv co má něco společnýho s vojsem
import { getVoiceConnection, VoiceConnection, VoiceConnectionStatus } from "@discordjs/voice";
import { GuildMember, VoiceChannel } from "discord.js";
import { ChannelType, GuildMember, VoiceChannel } from "discord.js";
import { emouty } from "../utils/emotes";
import { Modul, MuzikaFace, SRecord } from "../utils/types";
import { handlePrevVoice, joinVoice, play } from "../utils/utils";
import { canAnounceTime, handlePrevVoice, joinVoice, play } from "../utils/utils";
const timeouty: SRecord<NodeJS.Timeout> = {};
const vypocitatCas = (conn: VoiceConnection) => {
const vypocitatCas = (guild: string, conn: VoiceConnection) => {
const c = new Date();
const d = new Date();
let hod = d.getHours();
@ -28,17 +28,19 @@ const vypocitatCas = (conn: VoiceConnection) => {
d.setMinutes(min);
d.setSeconds(0);
timeouty[conn.joinConfig.guildId] = setTimeout(() => rekniCas(conn, `${nula(hod)}${nula(min)}`), Number(d) - Number(c));
timeouty[conn.joinConfig.guildId] = setTimeout(() => rekniCas(guild, conn, `${nula(hod)}${nula(min)}`), Number(d) - Number(c));
};
const nula = (a: number) => a < 10 ? `0${a}` : a;
const rekniCas = (conn: VoiceConnection, cas: string) => {
play(conn, [{ name: "zvuky/intro.mp3", volume: 0.8 }, { name: `zvuky/${cas}.mp3`, volume: 2 }, { name: "zvuky/grg.mp3", volume: 0.5 }])
.then(() => {
vypocitatCas(conn);
})
.catch(err => { console.log("cas error:", err); });
const rekniCas = (guild: string, conn: VoiceConnection, cas: string) => {
if (canAnounceTime(guild))
play(conn, [{ name: "zvuky/intro.mp3", volume: 0.8 }, { name: `zvuky/${cas}.mp3`, volume: 2 }, { name: "zvuky/grg.mp3", volume: 0.5 }])
.then(() => {
vypocitatCas(guild, conn);
})
.catch(err => { console.log("cas error:", err); });
else vypocitatCas(guild, conn);
};
const vytahnout = (member: GuildMember, patro: number) => {
@ -50,7 +52,7 @@ const vytahnout = (member: GuildMember, patro: number) => {
if (patro < aktPatro) dalsiPatro--; else if (patro > aktPatro) dalsiPatro++; else return;
if (dalsiPatro === 0) dalsiPatro = "P";
const dalsiVojs = member.guild.channels.cache.filter(channel => channel.type === "GUILD_VOICE" && channel.name === String(dalsiPatro)).first() as VoiceChannel | undefined;
const dalsiVojs = member.guild.channels.cache.filter(channel => channel.type == ChannelType.GuildVoice && channel.name === String(dalsiPatro)).first() as VoiceChannel | undefined;
if (!dalsiVojs) return;
member.voice.setChannel(dalsiVojs);
@ -77,8 +79,8 @@ const exp: Modul = {
.then(obj => {
const { prev, conn } = obj;
if (!timeouty[mes.guildId!]) {
vypocitatCas(conn);
conn.on<"stateChange">("stateChange", (_, now) => {
vypocitatCas(mes.guildId!, conn);
conn.on("stateChange", (_, now) => {
if (now.status !== VoiceConnectionStatus.Disconnected && now.status !== VoiceConnectionStatus.Destroyed) return;
clearTimeout(timeouty[mes.guildId!]);
delete timeouty[mes.guildId!];

View File

@ -46,7 +46,7 @@ const exp: Modul = {
}
},
super_on_message: {
super_on_messageCreate: {
pos: 0,
fun: (mes: Message) => {
const cont = mes.content.toLowerCase();

View File

@ -1,11 +1,12 @@
import { AudioPlayerStatus, AudioResource, createAudioPlayer, createAudioResource, entersState, getVoiceConnection, joinVoiceChannel, PlayerSubscription, StreamType, VoiceConnection, VoiceConnectionStatus } from "@discordjs/voice";
import { Client, Guild, StageChannel, VoiceChannel } from "discord.js";
import { ChannelType, Client, Guild, StageChannel, VoiceChannel } from "discord.js";
import { once } from "events";
import { JoinHovna, KomandNaExport, MuzikaFace, RunFunkce, SRecord } from "./types";
import { existsSync } from "fs";
import { Readable } from "node:stream";
const pripojeni: SRecord<PlayerSubscription> = {};
const timeAnouncability: Record<string, boolean> = {};
export const oddiakritikovat = (a: string) => {
return a
@ -183,7 +184,7 @@ export const ping = /^<@!?\d+>$/;
export function adminLog(client: Client, text: string) {
if (process.env.adminChannel) {
const adminChannel = client.channels.cache.get(process.env.adminChannel);
if (adminChannel?.isText())
if (adminChannel?.type == ChannelType.GuildText)
adminChannel.send(text);
}
if (process.env.adminID) {
@ -202,3 +203,15 @@ export function getFirstArg(fn: RunFunkce | string) {
?.split(",")[1]
?.trim();
}
export function getCurrentPlayer(guildId: string) {
return pripojeni[guildId]?.player;
}
export function configureTimeAnouncment(guild: string, state: boolean) {
timeAnouncability[guild] = state;
}
export function canAnounceTime(guild: string) {
return (timeAnouncability[guild] ?? true);
}