Replace eris-fleet with a pm2-based cluster system, overhaul image handling, removed azure image api

This commit is contained in:
Essem 2022-09-21 00:05:03 -05:00
parent 5a3364736d
commit db0decf71a
No known key found for this signature in database
GPG key ID: 7D497397CC3A2A8C
45 changed files with 1777 additions and 857 deletions

View file

@ -7,20 +7,23 @@ class AvatarCommand extends Command {
const self = await this.client.getRESTUser(this.author.id);
if (this.type === "classic" && this.message.mentions[0]) {
return this.message.mentions[0].dynamicAvatarURL(null, 512);
} else if (await this.ipc.fetchUser(member)) {
let user = await this.ipc.fetchUser(member);
if (!user) user = await this.client.getRESTUser(member);
return user?.avatar ? this.client._formatImage(`/avatars/${user.id}/${user.avatar}`, null, 512) : `https://cdn.discordapp.com/embed/avatars/${user.discriminator % 5}.png`; // hacky "solution"
} else if (mentionRegex.test(member)) {
const id = member.match(mentionRegex)[1];
if (id < 21154535154122752n) {
this.success = false;
return "That's not a valid mention!";
}
try {
const user = await this.client.getRESTUser(id);
return user.avatar ? this.client._formatImage(`/avatars/${user.id}/${user.avatar}`, null, 512) : `https://cdn.discordapp.com/embed/avatars/${user.discriminator % 5}.png`; // repeat of hacky "solution" from above
} catch {
} else if (member) {
const user = await this.client.getRESTUser(member);
if (user) {
return user?.avatar ? this.client._formatImage(`/avatars/${user.id}/${user.avatar}`, null, 512) : `https://cdn.discordapp.com/embed/avatars/${user.discriminator % 5}.png`; // hacky "solution"
} else if (mentionRegex.text(member)) {
const id = member.match(mentionRegex)[1];
if (id < 21154535154122752n) {
this.success = false;
return "That's not a valid mention!";
}
try {
const user = await this.client.getRESTUser(id);
return user.avatar ? this.client._formatImage(`/avatars/${user.id}/${user.avatar}`, null, 512) : `https://cdn.discordapp.com/embed/avatars/${user.discriminator % 5}.png`; // repeat of hacky "solution" from above
} catch {
return self.dynamicAvatarURL(null, 512);
}
} else {
return self.dynamicAvatarURL(null, 512);
}
} else if (this.args.join(" ") !== "" && this.channel.guild) {

View file

@ -7,20 +7,24 @@ class BannerCommand extends Command {
const self = await this.client.getRESTUser(this.author.id);
if (this.type === "classic" && this.message.mentions[0]) {
return this.message.mentions[0].dynamicBannerURL(null, 512) ?? "This user doesn't have a banner!";
} else if (await this.ipc.fetchUser(member)) {
} else if (member) {
const user = await this.client.getRESTUser(member);
return user.dynamicBannerURL(null, 512) ?? "This user doesn't have a banner!";
} else if (mentionRegex.test(member)) {
const id = member.match(mentionRegex)[1];
if (id < 21154535154122752n) {
this.success = false;
return "That's not a valid mention!";
}
try {
const user = await this.client.getRESTUser(id);
if (user) {
return user.dynamicBannerURL(null, 512) ?? "This user doesn't have a banner!";
} catch {
return self.dynamicBannerURL(null, 512) ?? "You don't have a banner!";
} else if (mentionRegex.text(member)) {
const id = member.match(mentionRegex)[1];
if (id < 21154535154122752n) {
this.success = false;
return "That's not a valid mention!";
}
try {
const user = await this.client.getRESTUser(id);
return user.dynamicBannerURL(null, 512) ?? "This user doesn't have a banner!";
} catch {
return self.dynamicBannerURL(null, 512) ?? "You don't have a banner!";
}
} else {
return "This user doesn't have a banner!";
}
} else if (this.args.join(" ") !== "" && this.channel.guild) {
const searched = await this.channel.guild.searchMembers(this.args.join(" "));

View file

@ -1,32 +1,38 @@
import Command from "../../classes/command.js";
import { endBroadcast, startBroadcast } from "../../utils/misc.js";
class BroadcastCommand extends Command {
// yet another very hacky command
run() {
return new Promise((resolve) => {
const owners = process.env.OWNER.split(",");
if (!owners.includes(this.author.id)) {
this.success = false;
resolve("Only the bot owner can broadcast messages!");
return;
}
const message = this.options.message ?? this.args.join(" ");
if (message?.trim()) {
this.ipc.centralStore.set("broadcast", message);
this.ipc.broadcast("playbroadcast", message);
this.ipc.register("broadcastSuccess", () => {
this.ipc.unregister("broadcastSuccess");
resolve("Successfully broadcasted message.");
});
} else {
this.ipc.centralStore.delete("broadcast");
this.ipc.broadcast("broadcastend");
this.ipc.register("broadcastEnd", () => {
this.ipc.unregister("broadcastEnd");
resolve("Successfully ended broadcast.");
async run() {
const owners = process.env.OWNER.split(",");
if (!owners.includes(this.author.id)) {
this.success = false;
return "Only the bot owner can broadcast messages!";
}
const message = this.options.message ?? this.args.join(" ");
if (message?.trim()) {
startBroadcast(this.client, message);
if (process.env.PM2_USAGE) {
process.send({
type: "process:msg",
data: {
type: "broadcastStart",
message
}
});
}
});
return "Started broadcast.";
} else {
endBroadcast(this.client);
if (process.env.PM2_USAGE) {
process.send({
type: "process:msg",
data: {
type: "broadcastEnd"
}
});
}
return "Ended broadcast.";
}
}
static flags = [{

View file

@ -1,4 +1,5 @@
import Command from "../../classes/command.js";
import { reloadImageConnections } from "../../utils/image.js";
class ImageReloadCommand extends Command {
async run() {
@ -7,9 +8,18 @@ class ImageReloadCommand extends Command {
this.success = false;
return "Only the bot owner can reload the image servers!";
}
const amount = await this.ipc.serviceCommand("image", { type: "reload" }, true);
if (amount > 0) {
return `Successfully connected to ${amount} image servers.`;
await this.acknowledge();
const length = await reloadImageConnections();
if (!length) {
if (process.env.PM2_USAGE) {
process.send({
type: "process:msg",
data: {
type: "imagereload"
}
});
}
return `Successfully connected to ${length} image server(s).`;
} else {
return "I couldn't connect to any image servers!";
}

View file

@ -1,9 +1,9 @@
import Command from "../../classes/command.js";
import { connections } from "../../utils/image.js";
class ImageStatsCommand extends Command {
async run() {
await this.acknowledge();
const servers = await this.ipc.serviceCommand("image", { type: "stats" }, true);
const embed = {
embeds: [{
"author": {
@ -11,14 +11,17 @@ class ImageStatsCommand extends Command {
"icon_url": this.client.user.avatarURL
},
"color": 16711680,
"description": `The bot is currently connected to ${servers.length} image server(s).`,
"description": `The bot is currently connected to ${connections.size} image server(s).`,
"fields": []
}]
};
for (let i = 0; i < servers.length; i++) {
let i = 0;
for (const connection of connections.values()) {
const count = await connection.getCount();
if (!count) continue;
embed.embeds[0].fields.push({
name: `Server ${i + 1}`,
value: `Running Jobs: ${Math.min(servers[i].runningJobs, servers[i].max)}\nQueued: ${Math.max(0, servers[i].runningJobs - servers[i].max)}\nMax Jobs: ${servers[i].max}`
name: `Server ${i++}`,
value: `Running Jobs: ${count}`
});
}
return embed;

View file

@ -5,13 +5,14 @@ const { version } = JSON.parse(readFileSync(new URL("../../package.json", import
import Command from "../../classes/command.js";
import { exec as baseExec } from "child_process";
import { promisify } from "util";
import { getServers } from "../../utils/misc.js";
const exec = promisify(baseExec);
class InfoCommand extends Command {
async run() {
let owner = await this.ipc.fetchUser(process.env.OWNER.split(",")[0]);
if (!owner) owner = await this.client.getRESTUser(process.env.OWNER.split(",")[0]);
const stats = await this.ipc.getStats();
const owner = await this.client.getRESTUser(process.env.OWNER.split(",")[0]);
const servers = await getServers();
await this.acknowledge();
return {
embeds: [{
color: 16711680,
@ -30,7 +31,7 @@ class InfoCommand extends Command {
},
{
name: "💬 Total Servers:",
value: stats?.guilds ? stats.guilds : `${this.client.guilds.size} (for this cluster only)`
value: servers ? servers : `${this.client.guilds.size} (for this process only)`
},
{
name: "✅ Official Server:",

View file

@ -1,27 +1,29 @@
import Command from "../../classes/command.js";
import { load } from "../../utils/handler.js";
import { checkStatus } from "../../utils/soundplayer.js";
import { paths } from "../../utils/collections.js";
class ReloadCommand extends Command {
// quite possibly one of the hackiest commands in the bot
run() {
return new Promise((resolve) => {
const owners = process.env.OWNER.split(",");
if (!owners.includes(this.author.id)) return resolve("Only the bot owner can reload commands!");
const commandName = this.options.cmd ?? this.args.join(" ");
if (!commandName || !commandName.trim()) return resolve("You need to provide a command to reload!");
this.acknowledge().then(() => {
this.ipc.broadcast("reload", commandName);
this.ipc.register("reloadSuccess", () => {
this.ipc.unregister("reloadSuccess");
this.ipc.unregister("reloadFail");
resolve(`The command \`${commandName}\` has been reloaded.`);
});
this.ipc.register("reloadFail", (message) => {
this.ipc.unregister("reloadSuccess");
this.ipc.unregister("reloadFail");
resolve(message.result);
});
async run() {
const owners = process.env.OWNER.split(",");
if (!owners.includes(this.author.id)) return "Only the bot owner can reload commands!";
const commandName = this.options.cmd ?? this.args.join(" ");
if (!commandName || !commandName.trim()) return "You need to provide a command to reload!";
await this.acknowledge();
const path = paths.get(commandName);
if (!path) return "I couldn't find that command!";
const result = await load(this.client, path, await checkStatus(), true);
if (result !== commandName) return "I couldn't reload that command!";
if (process.env.PM2_USAGE) {
process.send({
type: "process:msg",
data: {
type: "reload",
message: commandName
}
});
});
}
return `The command \`${commandName}\` has been reloaded.`;
}
static flags = [{

View file

@ -10,8 +10,7 @@ class RestartCommand extends Command {
await this.client.createMessage(this.channel.id, Object.assign({
content: "esmBot is restarting."
}, this.reference));
this.ipc.restartAllClusters(true);
//this.ipc.broadcast("restart");
process.exit(1);
}
static description = "Restarts me";

View file

@ -1,29 +1,29 @@
import Command from "../../classes/command.js";
import { checkStatus, reload } from "../../utils/soundplayer.js";
class SoundReloadCommand extends Command {
// another very hacky command
run() {
return new Promise((resolve) => {
const owners = process.env.OWNER.split(",");
if (!owners.includes(this.author.id)) {
this.success = false;
return "Only the bot owner can reload Lavalink!";
async run() {
const owners = process.env.OWNER.split(",");
if (!owners.includes(this.author.id)) {
this.success = false;
return "Only the bot owner can reload Lavalink!";
}
await this.acknowledge();
const soundStatus = await checkStatus();
if (!soundStatus) {
const length = reload();
if (process.env.PM2_USAGE) {
process.send({
type: "process:msg",
data: {
type: "soundreload"
}
});
}
this.acknowledge().then(() => {
this.ipc.broadcast("soundreload");
this.ipc.register("soundReloadSuccess", (msg) => {
this.ipc.unregister("soundReloadSuccess");
this.ipc.unregister("soundReloadFail");
resolve(`Successfully connected to ${msg.length} Lavalink node(s).`);
});
this.ipc.register("soundReloadFail", () => {
this.ipc.unregister("soundReloadSuccess");
this.ipc.unregister("soundReloadFail");
resolve("I couldn't connect to any Lavalink nodes!");
});
});
});
return `Successfully connected to ${length} Lavalink node(s).`;
} else {
return "I couldn't connect to any Lavalink nodes!";
}
}
static description = "Attempts to reconnect to all available Lavalink nodes";

View file

@ -7,6 +7,8 @@ import Command from "../../classes/command.js";
import { VERSION } from "eris";
import { exec as baseExec } from "child_process";
import { promisify } from "util";
import pm2 from "pm2";
import { getServers } from "../../utils/misc.js";
const exec = promisify(baseExec);
class StatsCommand extends Command {
@ -14,7 +16,7 @@ class StatsCommand extends Command {
const uptime = process.uptime() * 1000;
const connUptime = this.client.uptime;
const owner = await this.client.getRESTUser(process.env.OWNER.split(",")[0]);
const stats = await this.ipc.getStats();
const servers = await getServers();
return {
embeds: [{
"author": {
@ -28,13 +30,13 @@ class StatsCommand extends Command {
"value": `v${version}${process.env.NODE_ENV === "development" ? `-dev (${(await exec("git rev-parse HEAD", { cwd: dirname(fileURLToPath(import.meta.url)) })).stdout.substring(0, 7)})` : ""}`
},
{
"name": "Cluster Memory Usage",
"value": stats?.clusters[this.cluster] ? `${stats.clusters[this.cluster].ram.toFixed(2)} MB` : `${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB`,
"name": "Process Memory Usage",
"value": `${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB`,
"inline": true
},
{
"name": "Total Memory Usage",
"value": stats?.totalRam ? `${stats.totalRam.toFixed(2)} MB` : "Unknown",
"value": process.env.PM2_USAGE ? `${((await this.list()).reduce((prev, cur) => prev + cur.monit.memory, 0) / 1024 / 1024).toFixed(2)} MB` : "Unknown",
"inline": true
},
{
@ -65,14 +67,9 @@ class StatsCommand extends Command {
"value": this.channel.guild ? this.client.guildShardMap[this.channel.guild.id] : "N/A",
"inline": true
},
{
"name": "Cluster",
"value": this.cluster,
"inline": true
},
{
"name": "Servers",
"value": stats?.guilds ? stats.guilds : `${this.client.guilds.size} (for this cluster only)`,
"value": servers ? servers : `${this.client.guilds.size} (for this process only)`,
"inline": true
}
]
@ -80,6 +77,15 @@ class StatsCommand extends Command {
};
}
list() {
return new Promise((resolve, reject) => {
pm2.list((err, list) => {
if (err) return reject(err);
resolve(list.filter((v) => v.name === "esmBot"));
});
});
}
static description = "Gets some statistics about me";
static aliases = ["status", "stat"];
}

View file

@ -2,7 +2,7 @@ import Command from "../../classes/command.js";
class UserInfoCommand extends Command {
async run() {
const getUser = this.message.mentions.length >= 1 ? this.message.mentions[0] : (this.args.length !== 0 ? await this.ipc.fetchUser(this.args[0]) : this.author);
const getUser = this.message.mentions.length >= 1 ? this.message.mentions[0] : (this.args.length !== 0 ? this.client.users.get(this.args[0]) : this.author);
let user;
if (getUser) {
user = getUser;