Merge branch 'fleet'
This commit is contained in:
commit
e725c4d1eb
28 changed files with 851 additions and 544 deletions
|
@ -1,6 +1,5 @@
|
|||
require("dotenv").config();
|
||||
const os = require("os");
|
||||
//const { run } = require("../utils/image-runner.js");
|
||||
const { Worker } = require("worker_threads");
|
||||
const path = require("path");
|
||||
const http = require("http");
|
||||
|
|
108
app.js
108
app.js
|
@ -6,14 +6,54 @@ The bot will continue to run past this message, but keep in mind that it could b
|
|||
require("dotenv").config();
|
||||
|
||||
// main sharding manager
|
||||
const { Master } = require("eris-sharder");
|
||||
const { Fleet } = require("eris-fleet");
|
||||
const { isMaster } = require("cluster");
|
||||
// some utils
|
||||
const path = require("path");
|
||||
const winston = require("winston");
|
||||
// dbl posting
|
||||
const TopGG = require("@top-gg/sdk");
|
||||
const dbl = process.env.NODE_ENV === "production" && process.env.DBL !== "" ? new TopGG.Api(process.env.DBL) : null;
|
||||
|
||||
const master = new Master(`Bot ${process.env.TOKEN}`, "/shard.js", {
|
||||
name: "esmBot",
|
||||
stats: true,
|
||||
if (isMaster) {
|
||||
console.log(`
|
||||
,*\`$ z\`"v
|
||||
F zBw\`% A ,W "W
|
||||
,\` ,EBBBWp"%. ,-=~~==-,+* 4BBE T
|
||||
M BBBBBBBB* ,w=####Wpw 4BBBBB# 1
|
||||
F BBBBBBBMwBBBBBBBBBBBBB#wXBBBBBH E
|
||||
F BBBBBBkBBBBBBBBBBBBBBBBBBBBE4BL k
|
||||
# BFBBBBBBBBBBBBF" "RBBBW F
|
||||
V ' 4BBBBBBBBBBM TBBL F
|
||||
F BBBBBBBBBBF JBB L
|
||||
F FBBBBBBBEB BBL 4
|
||||
E [BB4BBBBEBL BBL 4
|
||||
I #BBBBBBBEB 4BBH *w
|
||||
A 4BBBBBBBBBEW, ,BBBB W [
|
||||
.A ,k 4BBBBBBBBBBBEBW####BBBBBBM BF F
|
||||
k <BBBw BBBBEBBBBBBBBBBBBBBBBBQ4BM #
|
||||
5, REBBB4BBBBB#BBBBBBBBBBBBP5BFF ,F
|
||||
*w \`*4BBW\`"FF#F##FFFF"\` , * +"
|
||||
*+, " F'"'*^~~~^"^\` V+*^
|
||||
\`"""
|
||||
|
||||
esmBot ${require("./package.json").version}, powered by eris-fleet ${require("./node_modules/eris-fleet/package.json").version}
|
||||
`);
|
||||
// a bit of a hacky way to get the eris-fleet version
|
||||
}
|
||||
|
||||
const Admiral = new Fleet({
|
||||
path: path.join(__dirname, "./shard.js"),
|
||||
token: `Bot ${process.env.TOKEN}`,
|
||||
startingStatus: {
|
||||
status: "idle",
|
||||
game: {
|
||||
name: "Starting esmBot..."
|
||||
}
|
||||
},
|
||||
whatToLog: {
|
||||
blacklist: ["stats_update"]
|
||||
},
|
||||
clientOptions: {
|
||||
disableEvents: {
|
||||
CHANNEL_DELETE: true,
|
||||
|
@ -45,16 +85,60 @@ const master = new Master(`Bot ${process.env.TOKEN}`, "/shard.js", {
|
|||
stats: {
|
||||
requestTimeout: 30000
|
||||
}
|
||||
}
|
||||
},
|
||||
services: [
|
||||
{ name: "prometheus", path: path.join(__dirname, "./utils/services/prometheus.js") },
|
||||
{ name: "image", path: path.join(__dirname, "./utils/services/image.js")}
|
||||
]
|
||||
});
|
||||
|
||||
master.on("stats", async (stats) => {
|
||||
master.broadcast(0, Object.assign(stats, { _eventName: "stat" }));
|
||||
// dbl posting
|
||||
if (isMaster) {
|
||||
const logger = winston.createLogger({
|
||||
levels: {
|
||||
error: 0,
|
||||
warn: 1,
|
||||
info: 2,
|
||||
main: 3,
|
||||
debug: 4
|
||||
},
|
||||
transports: [
|
||||
new winston.transports.Console({ format: winston.format.colorize({ all: true }) }),
|
||||
new winston.transports.File({ filename: "logs/error.log", level: "error" }),
|
||||
new winston.transports.File({ filename: "logs/main.log" })
|
||||
],
|
||||
level: "main",
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
|
||||
winston.format.printf((info) => {
|
||||
const {
|
||||
timestamp, level, message, ...args
|
||||
} = info;
|
||||
|
||||
return `[${timestamp}]: [${level.toUpperCase()}] - ${message} ${Object.keys(args).length ? JSON.stringify(args, null, 2) : ""}`;
|
||||
}),
|
||||
)
|
||||
});
|
||||
|
||||
winston.addColors({
|
||||
info: "green",
|
||||
main: "gray",
|
||||
debug: "purple",
|
||||
warn: "yellow",
|
||||
error: "red"
|
||||
});
|
||||
|
||||
Admiral.on("log", (m) => logger.main(m));
|
||||
Admiral.on("info", (m) => logger.info(m));
|
||||
Admiral.on("debug", (m) => logger.debug(m));
|
||||
Admiral.on("warn", (m) => logger.warn(m));
|
||||
Admiral.on("error", (m) => logger.error(m));
|
||||
|
||||
if (dbl) {
|
||||
await dbl.postStats({
|
||||
serverCount: stats.guilds,
|
||||
shardCount: await master.calculateShards()
|
||||
Admiral.on("stats", async (m) => {
|
||||
await dbl.postStats({
|
||||
serverCount: m.guilds,
|
||||
shardCount: m.shardCount
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
class Command {
|
||||
constructor(client, cluster, ipc, message, args, content, specialArgs) {
|
||||
constructor(client, cluster, worker, ipc, message, args, content, specialArgs) {
|
||||
this.client = client;
|
||||
this.cluster = cluster;
|
||||
this.worker = worker;
|
||||
this.ipc = ipc;
|
||||
this.message = message;
|
||||
this.args = args;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const Command = require("./command.js");
|
||||
const magick = require("../utils/image.js");
|
||||
const imageDetect = require("../utils/imagedetect.js");
|
||||
const collections = require("../utils/collections.js");
|
||||
const { emotes } = require("../messages.json");
|
||||
|
@ -99,12 +98,12 @@ class ImageCommand extends Command {
|
|||
}
|
||||
|
||||
try {
|
||||
const { buffer, type } = await magick.run(magickParams).catch(e => {
|
||||
const { buffer, type } = await this.ipc.command("image", { type: "run", obj: magickParams }, true).catch(e => {
|
||||
throw e;
|
||||
});
|
||||
if (type === "nogif" && this.constructor.requiresGIF) return "That isn't a GIF!";
|
||||
return {
|
||||
file: buffer,
|
||||
file: Buffer.from(buffer.data),
|
||||
name: `${this.constructor.command}.${type}`
|
||||
};
|
||||
} catch (e) {
|
||||
|
|
|
@ -2,8 +2,8 @@ const Command = require("./command.js");
|
|||
const soundPlayer = require("../utils/soundplayer.js");
|
||||
|
||||
class MusicCommand extends Command {
|
||||
constructor(client, cluster, ipc, message, args, content, specialArgs) {
|
||||
super(client, cluster, ipc, message, args, content, specialArgs);
|
||||
constructor(client, cluster, worker, ipc, message, args, content, specialArgs) {
|
||||
super(client, cluster, worker, ipc, message, args, content, specialArgs);
|
||||
this.connection = soundPlayer.players.get(message.channel.guild.id);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,9 @@
|
|||
const image = require("../../utils/image.js");
|
||||
const logger = require("../../utils/logger.js");
|
||||
const Command = require("../../classes/command.js");
|
||||
|
||||
class ImageReloadCommand extends Command {
|
||||
async run() {
|
||||
if (this.message.author.id !== process.env.OWNER) return "Only the bot owner can reload the image servers!";
|
||||
await image.disconnect();
|
||||
await image.repopulate();
|
||||
let amount = 0;
|
||||
for (const server of image.servers) {
|
||||
try {
|
||||
await image.connect(server);
|
||||
amount += 1;
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
const amount = await this.ipc.command("image", { type: "reload" }, true);
|
||||
if (amount > 0) {
|
||||
return `Successfully connected to ${amount} image servers.`;
|
||||
} else {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
const image = require("../../utils/image.js");
|
||||
const Command = require("../../classes/command.js");
|
||||
|
||||
class ImageStatsCommand extends Command {
|
||||
async run() {
|
||||
const servers = await this.ipc.command("image", { type: "stats" }, true);
|
||||
const embed = {
|
||||
embed: {
|
||||
"author": {
|
||||
|
@ -10,11 +10,10 @@ class ImageStatsCommand extends Command {
|
|||
"icon_url": this.client.user.avatarURL
|
||||
},
|
||||
"color": 16711680,
|
||||
"description": `The bot is currently connected to ${image.connections.size} image server(s).`,
|
||||
"description": `The bot is currently connected to ${servers.length} image server(s).`,
|
||||
"fields": []
|
||||
}
|
||||
};
|
||||
const servers = await image.getRunning();
|
||||
for (let i = 0; i < servers.length; i++) {
|
||||
embed.embed.fields.push({
|
||||
name: `Server ${i + 1}`,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
const { version } = require("../../package.json");
|
||||
const collections = require("../../utils/collections.js");
|
||||
const Command = require("../../classes/command.js");
|
||||
|
||||
class InfoCommand extends Command {
|
||||
async run() {
|
||||
const owner = await this.ipc.fetchUser(process.env.OWNER);
|
||||
const stats = await this.ipc.getStats();
|
||||
return {
|
||||
"embed": {
|
||||
"color": 16711680,
|
||||
|
@ -23,7 +23,7 @@ class InfoCommand extends Command {
|
|||
},
|
||||
{
|
||||
"name": "💬 Total Servers:",
|
||||
"value": collections.stats.guilds ? collections.stats.guilds : `${this.client.guilds.size} (for this cluster only)`
|
||||
"value": stats.guilds ? stats.guilds : `${this.client.guilds.size} (for this cluster only)`
|
||||
},
|
||||
{
|
||||
"name": "✅ Official Server:",
|
||||
|
|
|
@ -6,7 +6,7 @@ class ReloadCommand extends Command {
|
|||
return new Promise((resolve) => {
|
||||
if (this.message.author.id !== process.env.OWNER) resolve("Only the bot owner can reload commands!");
|
||||
if (this.args.length === 0) resolve("You need to provide a command to reload!");
|
||||
this.ipc.broadcast("reload", { cmd: this.args[0] });
|
||||
this.ipc.broadcast("reload", this.args[0]);
|
||||
this.ipc.register("reloadSuccess", () => {
|
||||
this.ipc.unregister("reloadSuccess");
|
||||
this.ipc.unregister("reloadFail");
|
||||
|
|
|
@ -11,7 +11,8 @@ class RestartCommand extends Command {
|
|||
for (const command of collections.commands) {
|
||||
await handler.unload(command);
|
||||
}
|
||||
this.ipc.broadcast("restart");
|
||||
this.ipc.restartAllClusters();
|
||||
//this.ipc.broadcast("restart");
|
||||
}
|
||||
|
||||
static description = "Restarts me";
|
||||
|
|
|
@ -10,7 +10,7 @@ class SoundReloadCommand extends Command {
|
|||
this.ipc.register("soundReloadSuccess", (msg) => {
|
||||
this.ipc.unregister("soundReloadSuccess");
|
||||
this.ipc.unregister("soundReloadFail");
|
||||
resolve(`Successfully connected to ${msg.length} Lavalink node(s).`);
|
||||
resolve(`Successfully connected to ${msg.msg.length} Lavalink node(s).`);
|
||||
});
|
||||
this.ipc.register("soundReloadFail", () => {
|
||||
this.ipc.unregister("soundReloadSuccess");
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const { version } = require("../../package.json");
|
||||
const collections = require("../../utils/collections.js");
|
||||
const day = require("dayjs");
|
||||
day.extend(require("dayjs/plugin/duration"));
|
||||
const os = require("os");
|
||||
|
@ -10,6 +9,7 @@ class StatsCommand extends Command {
|
|||
const duration = day.duration(this.client.uptime).format(" D [days], H [hrs], m [mins], s [secs]");
|
||||
const uptime = day.duration(process.uptime(), "seconds").format(" D [days], H [hrs], m [mins], s [secs]");
|
||||
const owner = await this.ipc.fetchUser(process.env.OWNER);
|
||||
const stats = await this.ipc.getStats();
|
||||
return {
|
||||
embed: {
|
||||
"author": {
|
||||
|
@ -24,12 +24,12 @@ class StatsCommand extends Command {
|
|||
},
|
||||
{
|
||||
"name": "Cluster Memory Usage",
|
||||
"value": `${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB`,
|
||||
"value": `${stats.clusters[this.cluster].ram.toFixed(2)} MB`,
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Total Memory Usage",
|
||||
"value": collections.stats.totalRam ? `${collections.stats.totalRam.toFixed(2)} MB` : "Unknown",
|
||||
"value": stats.totalRam ? `${stats.totalRam.toFixed(2)} MB` : "Unknown",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
|
@ -66,12 +66,12 @@ class StatsCommand extends Command {
|
|||
},
|
||||
{
|
||||
"name": "Servers",
|
||||
"value": collections.stats.guilds ? collections.stats.guilds : `${this.client.guilds.size} (for this cluster only)`,
|
||||
"value": stats.guilds ? stats.guilds : `${this.client.guilds.size} (for this cluster only)`,
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Users (approximation)",
|
||||
"value": collections.stats.users ? collections.stats.users : `${this.client.users.size} (for this cluster only)`,
|
||||
"value": stats.users ? stats.users : `${this.client.users.size} (for this cluster only)`,
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
|
|
|
@ -2,7 +2,7 @@ const db = require("../utils/database.js");
|
|||
const logger = require("../utils/logger.js");
|
||||
|
||||
// run when the bot is added to a guild
|
||||
module.exports = async (client, cluster, ipc, guild) => {
|
||||
logger.log("info", `[GUILD JOIN] ${guild.name} (${guild.id}) added the bot.`);
|
||||
module.exports = async (client, cluster, worker, ipc, guild) => {
|
||||
logger.log(`[GUILD JOIN] ${guild.name} (${guild.id}) added the bot.`);
|
||||
await db.addGuild(guild);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const logger = require("../utils/logger.js");
|
||||
|
||||
// run when the bot is removed from a guild
|
||||
module.exports = async (client, cluster, ipc, guild) => {
|
||||
module.exports = async (client, cluster, worker, ipc, guild) => {
|
||||
logger.log(`[GUILD LEAVE] ${guild.name} (${guild.id}) removed the bot.`);
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@ const collections = require("../utils/collections.js");
|
|||
const parseCommand = require("../utils/parseCommand.js");
|
||||
|
||||
// run when someone sends a message
|
||||
module.exports = async (client, cluster, ipc, message) => {
|
||||
module.exports = async (client, cluster, worker, ipc, message) => {
|
||||
// ignore dms and other bots
|
||||
if (message.author.bot) return;
|
||||
|
||||
|
@ -88,7 +88,7 @@ module.exports = async (client, cluster, ipc, message) => {
|
|||
await database.addCount(collections.aliases.has(command) ? collections.aliases.get(command) : command);
|
||||
const startTime = new Date();
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const commandClass = new cmd(client, cluster, ipc, message, parsed._, message.content.substring(prefix.length).trim().replace(command, "").trim(), (({ _, ...o }) => o)(parsed)); // we also provide the message content as a parameter for cases where we need more accuracy
|
||||
const commandClass = new cmd(client, cluster, worker, ipc, message, parsed._, message.content.substring(prefix.length).trim().replace(command, "").trim(), (({ _, ...o }) => o)(parsed)); // we also provide the message content as a parameter for cases where we need more accuracy
|
||||
const result = await commandClass.run();
|
||||
const endTime = new Date();
|
||||
if ((endTime - startTime) >= 180000) reference.allowedMentions.repliedUser = true;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const player = require("../utils/soundplayer.js");
|
||||
|
||||
// run when a raw packet is sent, used for sending data to lavalink
|
||||
module.exports = async (client, cluster, ipc, packet) => {
|
||||
module.exports = async (client, cluster, worker, ipc, packet) => {
|
||||
if (!player.manager) return;
|
||||
switch (packet.t) {
|
||||
case "VOICE_SERVER_UPDATE":
|
||||
|
|
|
@ -2,7 +2,8 @@ const soundPlayer = require("../utils/soundplayer.js");
|
|||
const AwaitRejoin = require("../utils/awaitrejoin.js");
|
||||
const { random } = require("../utils/misc.js");
|
||||
|
||||
module.exports = async (client, cluster, ipc, member, oldChannel) => {
|
||||
module.exports = async (client, cluster, worker, ipc, member, oldChannel) => {
|
||||
if (!oldChannel) return;
|
||||
const connection = soundPlayer.players.get(oldChannel.guild.id);
|
||||
if (connection && connection.type === "music" && oldChannel.id === connection.voiceChannel.id) {
|
||||
if (oldChannel.voiceMembers.filter((i) => i.id !== client.user.id).length === 0) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const leaveHandler = require("./voiceChannelLeave.js");
|
||||
|
||||
module.exports = async (client, cluster, ipc, member, newChannel, oldChannel) => {
|
||||
module.exports = async (client, cluster, worker, ipc, member, newChannel, oldChannel) => {
|
||||
await leaveHandler(client, cluster, ipc, member, oldChannel);
|
||||
};
|
431
package-lock.json
generated
431
package-lock.json
generated
|
@ -14,7 +14,8 @@
|
|||
"dayjs": "^1.10.4",
|
||||
"dotenv": "^9.0.2",
|
||||
"emoji-regex": "^9.2.2",
|
||||
"eris-sharder": "github:esmBot/eris-sharder#eris-dev",
|
||||
"eris": "^0.15.1",
|
||||
"eris-fleet": "github:esmBot/eris-fleet",
|
||||
"file-type": "^16.1.0",
|
||||
"jsqr": "^1.3.1",
|
||||
"lavacord": "^1.1.9",
|
||||
|
@ -22,7 +23,8 @@
|
|||
"node-emoji": "^1.10.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"qrcode": "^1.4.4",
|
||||
"sharp": "^0.28.2"
|
||||
"sharp": "^0.28.2",
|
||||
"winston": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.13.8",
|
||||
|
@ -463,6 +465,16 @@
|
|||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dabh/diagnostics": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz",
|
||||
"integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==",
|
||||
"dependencies": {
|
||||
"colorspace": "1.1.x",
|
||||
"enabled": "2.0.x",
|
||||
"kuler": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz",
|
||||
|
@ -596,17 +608,6 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-gray": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
|
||||
"integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=",
|
||||
"dependencies": {
|
||||
"ansi-wrap": "0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
|
@ -626,14 +627,6 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-wrap": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
|
||||
"integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/aproba": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
||||
|
@ -666,6 +659,11 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/async": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
|
||||
"integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
|
@ -990,14 +988,6 @@
|
|||
"simple-swizzle": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/color-support": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
|
||||
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
|
||||
"bin": {
|
||||
"color-support": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/colorette": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
|
||||
|
@ -1013,6 +1003,24 @@
|
|||
"node": ">=0.1.90"
|
||||
}
|
||||
},
|
||||
"node_modules/colorspace": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz",
|
||||
"integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==",
|
||||
"dependencies": {
|
||||
"color": "3.0.x",
|
||||
"text-hex": "1.0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/colorspace/node_modules/color": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz",
|
||||
"integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==",
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.1",
|
||||
"color-string": "^1.5.2"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
|
@ -1192,6 +1200,11 @@
|
|||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
|
||||
},
|
||||
"node_modules/enabled": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
|
||||
"integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
|
@ -1213,9 +1226,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eris": {
|
||||
"version": "0.15.2-dev",
|
||||
"resolved": "git+ssh://git@github.com/abalabahaha/eris.git#ea9d6700c8e3fedf5d966da4babe195c8cd681da",
|
||||
"license": "MIT",
|
||||
"version": "0.15.1",
|
||||
"resolved": "https://registry.npmjs.org/eris/-/eris-0.15.1.tgz",
|
||||
"integrity": "sha512-IQ3BPW6OjgFoqjdh+irPOa1jFlkotk+WNu2GQQ7QAQfbzQEPZgn+F+hpOxfMUXPHOZMX4sPKLkVDkMHAssBYhw==",
|
||||
"dependencies": {
|
||||
"ws": "^7.2.1"
|
||||
},
|
||||
|
@ -1227,17 +1240,12 @@
|
|||
"tweetnacl": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eris-sharder": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "git+ssh://git@github.com/esmBot/eris-sharder.git#3b7366e5d99012ca0e3350e4d81f384b48911c2d",
|
||||
"node_modules/eris-fleet": {
|
||||
"version": "0.3.7",
|
||||
"resolved": "git+ssh://git@github.com/esmBot/eris-fleet.git#7cf997d73f24c3ba3d17df978f0b672adaa021dd",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"colors": "^1.1.2",
|
||||
"eris": "github:abalabahaha/eris#dev",
|
||||
"fancy-log": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
"peerDependencies": {
|
||||
"eris": "^0.15.0"
|
||||
}
|
||||
},
|
||||
"node_modules/erlpack": {
|
||||
|
@ -1606,20 +1614,6 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/fancy-log": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz",
|
||||
"integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==",
|
||||
"dependencies": {
|
||||
"ansi-gray": "^0.1.1",
|
||||
"color-support": "^1.1.3",
|
||||
"parse-node-version": "^1.0.0",
|
||||
"time-stamp": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
|
@ -1638,6 +1632,16 @@
|
|||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-safe-stringify": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
|
||||
"integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
|
||||
},
|
||||
"node_modules/fecha": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz",
|
||||
"integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q=="
|
||||
},
|
||||
"node_modules/file-entry-cache": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
||||
|
@ -1702,6 +1706,11 @@
|
|||
"integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fn.name": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
|
||||
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
|
||||
},
|
||||
"node_modules/fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
|
@ -2000,6 +2009,14 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||
|
@ -2081,6 +2098,11 @@
|
|||
"integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/kuler": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
|
||||
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
|
||||
},
|
||||
"node_modules/lavacord": {
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/lavacord/-/lavacord-1.1.9.tgz",
|
||||
|
@ -2142,6 +2164,18 @@
|
|||
"integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/logform": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz",
|
||||
"integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==",
|
||||
"dependencies": {
|
||||
"colors": "^1.2.1",
|
||||
"fast-safe-stringify": "^2.0.4",
|
||||
"fecha": "^4.2.0",
|
||||
"ms": "^2.1.1",
|
||||
"triple-beam": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
|
@ -2367,8 +2401,7 @@
|
|||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"devOptional": true
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/nan": {
|
||||
"version": "2.14.2",
|
||||
|
@ -2477,6 +2510,14 @@
|
|||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/one-time": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
|
||||
"integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
|
||||
"dependencies": {
|
||||
"fn.name": "1.x.x"
|
||||
}
|
||||
},
|
||||
"node_modules/optional-require": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
|
||||
|
@ -2560,14 +2601,6 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-node-version": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
|
||||
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
|
@ -3218,6 +3251,14 @@
|
|||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/stack-trace": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
|
||||
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
|
@ -3414,20 +3455,17 @@
|
|||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/text-hex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
|
||||
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
|
||||
},
|
||||
"node_modules/text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/time-stamp": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz",
|
||||
"integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
|
@ -3461,6 +3499,11 @@
|
|||
"url": "https://github.com/sponsors/Borewit"
|
||||
}
|
||||
},
|
||||
"node_modules/triple-beam": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
|
||||
"integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
|
||||
},
|
||||
"node_modules/tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
|
@ -3606,6 +3649,50 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/winston": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz",
|
||||
"integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==",
|
||||
"dependencies": {
|
||||
"@dabh/diagnostics": "^2.0.2",
|
||||
"async": "^3.1.0",
|
||||
"is-stream": "^2.0.0",
|
||||
"logform": "^2.2.0",
|
||||
"one-time": "^1.0.0",
|
||||
"readable-stream": "^3.4.0",
|
||||
"stack-trace": "0.0.x",
|
||||
"triple-beam": "^1.3.0",
|
||||
"winston-transport": "^4.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/winston-transport": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz",
|
||||
"integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==",
|
||||
"dependencies": {
|
||||
"readable-stream": "^2.3.7",
|
||||
"triple-beam": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/winston/node_modules/readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/word-wrap": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||
|
@ -4108,6 +4195,16 @@
|
|||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@dabh/diagnostics": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz",
|
||||
"integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==",
|
||||
"requires": {
|
||||
"colorspace": "1.1.x",
|
||||
"enabled": "2.0.x",
|
||||
"kuler": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@eslint/eslintrc": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz",
|
||||
|
@ -4219,14 +4316,6 @@
|
|||
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-gray": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
|
||||
"integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=",
|
||||
"requires": {
|
||||
"ansi-wrap": "0.1.0"
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
|
@ -4240,11 +4329,6 @@
|
|||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"ansi-wrap": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
|
||||
"integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768="
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
||||
|
@ -4274,6 +4358,11 @@
|
|||
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"async": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
|
||||
"integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
|
@ -4520,11 +4609,6 @@
|
|||
"simple-swizzle": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"color-support": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
|
||||
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="
|
||||
},
|
||||
"colorette": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
|
||||
|
@ -4537,6 +4621,26 @@
|
|||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
|
||||
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
|
||||
},
|
||||
"colorspace": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz",
|
||||
"integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==",
|
||||
"requires": {
|
||||
"color": "3.0.x",
|
||||
"text-hex": "1.0.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"color": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz",
|
||||
"integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==",
|
||||
"requires": {
|
||||
"color-convert": "^1.9.1",
|
||||
"color-string": "^1.5.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
|
@ -4672,6 +4776,11 @@
|
|||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
|
||||
},
|
||||
"enabled": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
|
||||
"integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
|
||||
},
|
||||
"end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
|
@ -4690,22 +4799,19 @@
|
|||
}
|
||||
},
|
||||
"eris": {
|
||||
"version": "git+ssh://git@github.com/abalabahaha/eris.git#ea9d6700c8e3fedf5d966da4babe195c8cd681da",
|
||||
"from": "eris@github:abalabahaha/eris#dev",
|
||||
"version": "0.15.1",
|
||||
"resolved": "https://registry.npmjs.org/eris/-/eris-0.15.1.tgz",
|
||||
"integrity": "sha512-IQ3BPW6OjgFoqjdh+irPOa1jFlkotk+WNu2GQQ7QAQfbzQEPZgn+F+hpOxfMUXPHOZMX4sPKLkVDkMHAssBYhw==",
|
||||
"requires": {
|
||||
"opusscript": "^0.0.8",
|
||||
"tweetnacl": "^1.0.1",
|
||||
"ws": "^7.2.1"
|
||||
}
|
||||
},
|
||||
"eris-sharder": {
|
||||
"version": "git+ssh://git@github.com/esmBot/eris-sharder.git#3b7366e5d99012ca0e3350e4d81f384b48911c2d",
|
||||
"from": "eris-sharder@github:esmBot/eris-sharder#eris-dev",
|
||||
"requires": {
|
||||
"colors": "^1.1.2",
|
||||
"eris": "github:abalabahaha/eris#dev",
|
||||
"fancy-log": "^1.3.0"
|
||||
}
|
||||
"eris-fleet": {
|
||||
"version": "git+ssh://git@github.com/esmBot/eris-fleet.git#7cf997d73f24c3ba3d17df978f0b672adaa021dd",
|
||||
"from": "eris-fleet@github:esmBot/eris-fleet",
|
||||
"requires": {}
|
||||
},
|
||||
"erlpack": {
|
||||
"version": "git+ssh://git@github.com/abalabahaha/erlpack.git#5d0064f9e106841e1eead711a6451f99b0d289fd",
|
||||
|
@ -4975,17 +5081,6 @@
|
|||
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
||||
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="
|
||||
},
|
||||
"fancy-log": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz",
|
||||
"integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==",
|
||||
"requires": {
|
||||
"ansi-gray": "^0.1.1",
|
||||
"color-support": "^1.1.3",
|
||||
"parse-node-version": "^1.0.0",
|
||||
"time-stamp": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
|
@ -5004,6 +5099,16 @@
|
|||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||
"dev": true
|
||||
},
|
||||
"fast-safe-stringify": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
|
||||
"integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
|
||||
},
|
||||
"fecha": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz",
|
||||
"integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q=="
|
||||
},
|
||||
"file-entry-cache": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
||||
|
@ -5053,6 +5158,11 @@
|
|||
"integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
|
||||
"dev": true
|
||||
},
|
||||
"fn.name": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
|
||||
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
|
||||
},
|
||||
"fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
|
@ -5276,6 +5386,11 @@
|
|||
"is-extglob": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||
|
@ -5342,6 +5457,11 @@
|
|||
"integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==",
|
||||
"optional": true
|
||||
},
|
||||
"kuler": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
|
||||
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
|
||||
},
|
||||
"lavacord": {
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/lavacord/-/lavacord-1.1.9.tgz",
|
||||
|
@ -5393,6 +5513,18 @@
|
|||
"integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=",
|
||||
"dev": true
|
||||
},
|
||||
"logform": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz",
|
||||
"integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==",
|
||||
"requires": {
|
||||
"colors": "^1.2.1",
|
||||
"fast-safe-stringify": "^2.0.4",
|
||||
"fecha": "^4.2.0",
|
||||
"ms": "^2.1.1",
|
||||
"triple-beam": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
|
@ -5544,8 +5676,7 @@
|
|||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"devOptional": true
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.14.2",
|
||||
|
@ -5639,6 +5770,14 @@
|
|||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"one-time": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
|
||||
"integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
|
||||
"requires": {
|
||||
"fn.name": "1.x.x"
|
||||
}
|
||||
},
|
||||
"optional-require": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
|
||||
|
@ -5701,11 +5840,6 @@
|
|||
"callsites": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"parse-node-version": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
|
||||
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA=="
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
|
@ -6197,6 +6331,11 @@
|
|||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||
"dev": true
|
||||
},
|
||||
"stack-trace": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
|
||||
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
|
@ -6360,17 +6499,17 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"text-hex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
|
||||
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
|
||||
},
|
||||
"text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||
"dev": true
|
||||
},
|
||||
"time-stamp": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz",
|
||||
"integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM="
|
||||
},
|
||||
"to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
|
@ -6391,6 +6530,11 @@
|
|||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"triple-beam": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
|
||||
"integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
|
@ -6502,6 +6646,43 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"winston": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz",
|
||||
"integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==",
|
||||
"requires": {
|
||||
"@dabh/diagnostics": "^2.0.2",
|
||||
"async": "^3.1.0",
|
||||
"is-stream": "^2.0.0",
|
||||
"logform": "^2.2.0",
|
||||
"one-time": "^1.0.0",
|
||||
"readable-stream": "^3.4.0",
|
||||
"stack-trace": "0.0.x",
|
||||
"triple-beam": "^1.3.0",
|
||||
"winston-transport": "^4.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"winston-transport": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz",
|
||||
"integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==",
|
||||
"requires": {
|
||||
"readable-stream": "^2.3.7",
|
||||
"triple-beam": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"word-wrap": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
"dayjs": "^1.10.4",
|
||||
"dotenv": "^9.0.2",
|
||||
"emoji-regex": "^9.2.2",
|
||||
"eris-sharder": "github:esmBot/eris-sharder#eris-dev",
|
||||
"eris": "^0.15.1",
|
||||
"eris-fleet": "github:esmBot/eris-fleet",
|
||||
"file-type": "^16.1.0",
|
||||
"jsqr": "^1.3.1",
|
||||
"lavacord": "^1.1.9",
|
||||
|
@ -37,7 +38,8 @@
|
|||
"node-emoji": "^1.10.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"qrcode": "^1.4.4",
|
||||
"sharp": "^0.28.2"
|
||||
"sharp": "^0.28.2",
|
||||
"winston": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.13.8",
|
||||
|
|
159
shard.js
159
shard.js
|
@ -1,5 +1,5 @@
|
|||
// shard base
|
||||
const { Base } = require("eris-sharder");
|
||||
const { BaseClusterWorker } = require("eris-fleet");
|
||||
// path stuff
|
||||
const { readdir } = require("fs").promises;
|
||||
// fancy loggings
|
||||
|
@ -8,8 +8,6 @@ const logger = require("./utils/logger.js");
|
|||
const handler = require("./utils/handler.js");
|
||||
// lavalink stuff
|
||||
const sound = require("./utils/soundplayer.js");
|
||||
// image processing stuff
|
||||
const image = require("./utils/image.js");
|
||||
// database stuff
|
||||
const database = require("./utils/database.js");
|
||||
// command collections
|
||||
|
@ -21,11 +19,12 @@ const misc = require("./utils/misc.js");
|
|||
// generate help page
|
||||
const helpGenerator =
|
||||
process.env.OUTPUT !== "" ? require("./utils/help.js") : null;
|
||||
const http = require("http");
|
||||
|
||||
class Shard extends Base {
|
||||
class Shard extends BaseClusterWorker {
|
||||
constructor(bot) {
|
||||
super(bot);
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
async init() {
|
||||
|
@ -48,18 +47,7 @@ class Shard extends Base {
|
|||
logger.log("log", `Loading event from ${file}...`);
|
||||
const eventName = file.split(".")[0];
|
||||
const event = require(`./events/${file}`);
|
||||
this.bot.on(eventName, event.bind(null, this.bot, this.clusterID, this.ipc));
|
||||
}
|
||||
|
||||
// connect to image api if enabled
|
||||
if (process.env.API === "true") {
|
||||
for (const server of image.servers) {
|
||||
try {
|
||||
await image.connect(server);
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
this.bot.on(eventName, event.bind(null, this.bot, this.clusterID, this.workerID, this.ipc));
|
||||
}
|
||||
|
||||
// generate docs
|
||||
|
@ -71,55 +59,40 @@ class Shard extends Base {
|
|||
}
|
||||
}
|
||||
|
||||
if (process.env.METRICS !== "" && process.env.METRICS !== undefined) {
|
||||
const httpServer = http.createServer(async (req, res) => {
|
||||
if (req.method !== "GET") {
|
||||
res.statusCode = 405;
|
||||
return res.end("GET only");
|
||||
}
|
||||
res.write(`# HELP connected_workers Number of workers connected
|
||||
# TYPE connected_workers gauge
|
||||
connected_workers ${image.connections.size}
|
||||
# HELP running_jobs Number of running jobs on this worker
|
||||
# TYPE running_jobs gauge
|
||||
# HELP queued_jobs Number of queued jobs on this worker
|
||||
# TYPE queued_jobs gauge
|
||||
# HELP max_jobs Number of max allowed jobs on this worker
|
||||
# TYPE max_jobs gauge
|
||||
# HELP command_count Number of times a command has been run
|
||||
# TYPE command_count counter
|
||||
`);
|
||||
const servers = await image.getRunning();
|
||||
for (const [i, w] of servers.entries()) {
|
||||
res.write(`running_jobs{worker="${i}"} ${w.runningJobs}\n`);
|
||||
res.write(`queued_jobs{worker="${i}"} ${w.queued}\n`);
|
||||
res.write(`max_jobs{worker="${i}"} ${w.max}\n`);
|
||||
}
|
||||
const counts = await database.getCounts();
|
||||
for (const [i, w] of Object.entries(counts)) {
|
||||
res.write(`command_count{command="${i}"} ${w}\n`);
|
||||
}
|
||||
res.end();
|
||||
});
|
||||
httpServer.listen(process.env.METRICS, () => {
|
||||
logger.log("info", `Serving metrics at ${process.env.METRICS}`);
|
||||
});
|
||||
}
|
||||
|
||||
// handle process stop
|
||||
process.on("SIGINT", () => {
|
||||
logger.log("warn", "SIGINT detected, shutting down...");
|
||||
this.bot.editStatus("dnd", {
|
||||
name: "Restarting/shutting down..."
|
||||
});
|
||||
for (const command in collections.commands) {
|
||||
handler.unload(command);
|
||||
}
|
||||
this.bot.disconnect();
|
||||
require("./utils/database.js").stop();
|
||||
process.exit(0);
|
||||
this.ipc.register("reload", async (message) => {
|
||||
const result = await handler.unload(message.msg);
|
||||
if (result) return this.ipc.broadcast("reloadFail", { result: result });
|
||||
const result2 = await handler.load(collections.paths.get(message.msg));
|
||||
if (result2) return this.ipc.broadcast("reloadFail", { result: result2 });
|
||||
return this.ipc.broadcast("reloadSuccess");
|
||||
});
|
||||
return;
|
||||
|
||||
this.bot.privateChannels.limit = 0;
|
||||
|
||||
this.ipc.register("soundreload", async () => {
|
||||
const soundStatus = await sound.checkStatus();
|
||||
if (!soundStatus) {
|
||||
const length = await sound.connect(this.bot);
|
||||
return this.ipc.broadcast("soundReloadSuccess", { length });
|
||||
} else {
|
||||
return this.ipc.broadcast("soundReloadFail");
|
||||
}
|
||||
});
|
||||
|
||||
// connect to lavalink
|
||||
if (!sound.status && !sound.connected) sound.connect(this.bot);
|
||||
|
||||
database.setup();
|
||||
|
||||
// set activity (a.k.a. the gamer code)
|
||||
(async function activityChanger() {
|
||||
this.bot.editStatus("dnd", {
|
||||
name: `${misc.random(messages)} | @${this.bot.user.username} help`,
|
||||
});
|
||||
setTimeout(activityChanger.bind(this), 900000);
|
||||
}).bind(this)();
|
||||
|
||||
logger.log("info", `Started worker ${this.workerID}.`);
|
||||
}
|
||||
|
||||
async* getFiles(dir) {
|
||||
|
@ -133,54 +106,16 @@ connected_workers ${image.connections.size}
|
|||
}
|
||||
}
|
||||
|
||||
async launch() {
|
||||
await this.init();
|
||||
|
||||
this.ipc.register("stat", (message) => {
|
||||
collections.stats = message;
|
||||
shutdown(done) {
|
||||
logger.log("warn", "Shutting down...");
|
||||
this.bot.editStatus("dnd", {
|
||||
name: "Restarting/shutting down..."
|
||||
});
|
||||
|
||||
this.ipc.register("restart", async () => {
|
||||
this.bot.editStatus("dnd", {
|
||||
name: "esmBot is restarting, please stand by."
|
||||
});
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
this.ipc.register("reload", async (message) => {
|
||||
const result = await handler.unload(message.cmd);
|
||||
if (result) return this.ipc.broadcast("reloadFail", { result: result });
|
||||
const result2 = await handler.load(collections.paths.get(message.cmd));
|
||||
if (result2) return this.ipc.broadcast("reloadFail", { result: result2 });
|
||||
return this.ipc.broadcast("reloadSuccess");
|
||||
});
|
||||
|
||||
this.ipc.register("soundreload", async () => {
|
||||
const soundStatus = await sound.checkStatus();
|
||||
if (!soundStatus) {
|
||||
const length = await sound.connect(this.bot);
|
||||
return this.ipc.broadcast("soundReloadSuccess", { length });
|
||||
} else {
|
||||
return this.ipc.broadcast("soundReloadFail");
|
||||
}
|
||||
});
|
||||
|
||||
// connect to lavalink
|
||||
if (!sound.status && !sound.connected) await sound.connect(this.bot);
|
||||
|
||||
this.bot.privateChannels.limit = 0;
|
||||
|
||||
await database.setup();
|
||||
|
||||
// set activity (a.k.a. the gamer code)
|
||||
(async function activityChanger() {
|
||||
this.bot.editStatus("dnd", {
|
||||
name: `${misc.random(messages)} | @${this.bot.user.username} help`,
|
||||
});
|
||||
setTimeout(activityChanger.bind(this), 900000);
|
||||
}).bind(this)();
|
||||
|
||||
logger.log("info", `Started cluster ${this.clusterID}.`);
|
||||
for (const command in collections.commands) {
|
||||
handler.unload(command);
|
||||
}
|
||||
require("./utils/database.js").stop();
|
||||
done();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,4 @@ class Cache extends Map {
|
|||
}
|
||||
|
||||
exports.prefixCache = new Cache();
|
||||
exports.disabledCache = new Cache();
|
||||
|
||||
exports.stats = {};
|
||||
exports.disabledCache = new Cache();
|
230
utils/image.js
230
utils/image.js
|
@ -1,12 +1,6 @@
|
|||
const magick = require("../build/Release/image.node");
|
||||
const { Worker } = require("worker_threads");
|
||||
const fetch = require("node-fetch");
|
||||
const fs = require("fs");
|
||||
const WebSocket = require("ws");
|
||||
const fileType = require("file-type");
|
||||
const path = require("path");
|
||||
const { EventEmitter } = require("events");
|
||||
const logger = require("./logger.js");
|
||||
|
||||
const formats = ["image/jpeg", "image/png", "image/webp", "image/gif", "video/mp4", "video/webm", "video/mov"];
|
||||
|
||||
|
@ -16,183 +10,6 @@ exports.connections = new Map();
|
|||
|
||||
exports.servers = JSON.parse(fs.readFileSync("./servers.json", { encoding: "utf8" })).image;
|
||||
|
||||
const chooseServer = async (ideal) => {
|
||||
if (ideal.length === 0) throw "No available servers";
|
||||
const sorted = ideal.sort((a, b) => {
|
||||
return b.load - a.load;
|
||||
});
|
||||
return sorted[0];
|
||||
};
|
||||
|
||||
exports.repopulate = async () => {
|
||||
const data = await fs.promises.readFile("./servers.json", { encoding: "utf8" });
|
||||
this.servers = JSON.parse(data).image;
|
||||
return;
|
||||
};
|
||||
|
||||
exports.getRunning = async () => {
|
||||
let serversLeft = this.connections.size;
|
||||
const statuses = [];
|
||||
for (const address of this.connections.keys()) {
|
||||
const connection = this.connections.get(address);
|
||||
if (connection.readyState !== 0 && connection.readyState !== 1) {
|
||||
serversLeft--;
|
||||
continue;
|
||||
}
|
||||
const controller = new AbortController(); // eslint-disable-line no-undef
|
||||
const timeout = setTimeout(() => {
|
||||
controller.abort();
|
||||
}, 2000);
|
||||
try {
|
||||
const statusRequest = await fetch(`http://${address}:8080/running`, { signal: controller.signal });
|
||||
clearTimeout(timeout);
|
||||
const status = await statusRequest.json();
|
||||
serversLeft--;
|
||||
statuses.push(status);
|
||||
} catch (e) {
|
||||
if (e.name === "AbortError") {
|
||||
serversLeft--;
|
||||
continue;
|
||||
} else if (e.code === "ECONNREFUSED") {
|
||||
serversLeft--;
|
||||
continue;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
if (!serversLeft) {
|
||||
return statuses;
|
||||
} else {
|
||||
throw new Error("Loop ended before all servers could be checked");
|
||||
}
|
||||
};
|
||||
|
||||
exports.connect = async (server) => {
|
||||
const connection = new WebSocket(`ws://${server}:8080/sock`);
|
||||
connection.on("message", async (msg) => {
|
||||
const opcode = msg.readUint8(0);
|
||||
const req = msg.slice(37, msg.length);
|
||||
const uuid = msg.slice(1, 37).toString();
|
||||
if (opcode === 0x00) { // Job queued
|
||||
if (this.jobs[req]) {
|
||||
this.jobs[req].event.emit("uuid", uuid);
|
||||
}
|
||||
} else if (opcode === 0x01) { // Job completed successfully
|
||||
// the image API sends all job responses over the same socket; make sure this is ours
|
||||
if (this.jobs[uuid]) {
|
||||
const imageReq = await fetch(`http://${server}:8080/image?id=${uuid}`);
|
||||
const image = await imageReq.buffer();
|
||||
// The response data is given as the file extension/ImageMagick type of the image (e.g. "png"), followed
|
||||
// by a newline, followed by the image data.
|
||||
|
||||
this.jobs[uuid].event.emit("image", image, imageReq.headers.get("ext"));
|
||||
}
|
||||
} else if (opcode === 0x02) { // Job errored
|
||||
if (this.jobs[uuid]) {
|
||||
this.jobs[uuid].event.emit("error", new Error(req));
|
||||
}
|
||||
}
|
||||
});
|
||||
connection.on("error", (e) => {
|
||||
logger.error(e.toString());
|
||||
});
|
||||
connection.once("close", () => {
|
||||
for (const uuid of Object.keys(this.jobs)) {
|
||||
if (this.jobs[uuid].addr === server) {
|
||||
this.jobs[uuid].event.emit("error", "Job ended prematurely due to a closed connection; please run your image job again");
|
||||
delete this.jobs[uuid];
|
||||
}
|
||||
}
|
||||
//logger.log(`Lost connection to ${server}, attempting to reconnect...`);
|
||||
this.connections.delete(server);
|
||||
});
|
||||
this.connections.set(server, connection);
|
||||
};
|
||||
|
||||
exports.disconnect = async () => {
|
||||
for (const connection of this.connections.values()) {
|
||||
connection.close();
|
||||
}
|
||||
for (const uuid of Object.keys(this.jobs)) {
|
||||
this.jobs[uuid].event.emit("error", "Job ended prematurely (not really an error; just run your image job again)");
|
||||
delete this.jobs[uuid];
|
||||
}
|
||||
this.connections.clear();
|
||||
return;
|
||||
};
|
||||
|
||||
const getIdeal = async () => {
|
||||
let serversLeft = this.connections.size;
|
||||
if (serversLeft < this.servers.length) {
|
||||
for (const server of this.servers) {
|
||||
try {
|
||||
if (!this.connections.has(server)) await this.connect(server);
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
serversLeft = this.connections.size;
|
||||
}
|
||||
const idealServers = [];
|
||||
for (const address of this.connections.keys()) {
|
||||
const connection = this.connections.get(address);
|
||||
if (connection.readyState !== 0 && connection.readyState !== 1) {
|
||||
serversLeft--;
|
||||
continue;
|
||||
}
|
||||
const controller = new AbortController(); // eslint-disable-line no-undef
|
||||
const timeout = setTimeout(() => {
|
||||
controller.abort();
|
||||
}, 5000);
|
||||
try {
|
||||
const statusRequest = await fetch(`http://${address}:8080/status`, { signal: controller.signal });
|
||||
clearTimeout(timeout);
|
||||
const status = await statusRequest.text();
|
||||
serversLeft--;
|
||||
idealServers.push({
|
||||
addr: address,
|
||||
load: parseInt(status)
|
||||
});
|
||||
} catch (e) {
|
||||
if (e.name === "AbortError") {
|
||||
serversLeft--;
|
||||
continue;
|
||||
} else if (e.code === "ECONNREFUSED") {
|
||||
serversLeft--;
|
||||
continue;
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
}
|
||||
if (!serversLeft) {
|
||||
const server = await chooseServer(idealServers);
|
||||
return { addr: server.addr, sock: this.connections.get(server.addr) };
|
||||
} else {
|
||||
throw new Error("Loop ended before all servers could be checked");
|
||||
}
|
||||
};
|
||||
|
||||
const start = async (object, num) => {
|
||||
const currentServer = await getIdeal();
|
||||
const data = Buffer.concat([Buffer.from([0x01 /* queue job */]), Buffer.from(num.length.toString()), Buffer.from(num), Buffer.from(JSON.stringify(object))]);
|
||||
currentServer.sock.send(data);
|
||||
const event = new EventEmitter();
|
||||
this.jobs[num] = { event, addr: currentServer.addr };
|
||||
const uuid = await new Promise((resolve, reject) => {
|
||||
event.once("uuid", (uuid) => resolve(uuid));
|
||||
event.once("error", reject);
|
||||
});
|
||||
delete this.jobs[num];
|
||||
this.jobs[uuid] = { event: event, addr: currentServer.addr };
|
||||
return { uuid: uuid, event: event };
|
||||
};
|
||||
|
||||
exports.check = (cmd) => {
|
||||
return magick[cmd] ? true : false;
|
||||
};
|
||||
|
||||
exports.getType = async (image, extraReturnTypes) => {
|
||||
if (!image.startsWith("http")) {
|
||||
const imageType = await fileType.fromFile(image);
|
||||
|
@ -234,50 +51,3 @@ exports.getType = async (image, extraReturnTypes) => {
|
|||
}
|
||||
return type;
|
||||
};
|
||||
|
||||
exports.run = (object) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (process.env.API === "true") {
|
||||
// Connect to best image server
|
||||
const num = Math.floor(Math.random() * 100000).toString().slice(0, 5);
|
||||
const timeout = setTimeout(() => {
|
||||
if (this.jobs[num]) delete this.jobs[num];
|
||||
reject("the image request timed out after 25 seconds. Try uploading your image elsewhere.");
|
||||
}, 25000);
|
||||
start(object, num).catch(err => { // incredibly hacky code incoming
|
||||
clearTimeout(timeout);
|
||||
if (err instanceof Error) return reject(err);
|
||||
return err;
|
||||
}).then((data) => {
|
||||
clearTimeout(timeout);
|
||||
if (!data.event) reject("Not connected to image server");
|
||||
data.event.once("image", (image, type) => {
|
||||
delete this.jobs[data.uuid];
|
||||
const payload = {
|
||||
// Take just the image data
|
||||
buffer: image,
|
||||
type: type
|
||||
};
|
||||
resolve(payload);
|
||||
});
|
||||
data.event.once("error", (err) => {
|
||||
delete this.jobs[data.uuid];
|
||||
reject(err);
|
||||
});
|
||||
return;
|
||||
}).catch(err => reject(err));
|
||||
} else {
|
||||
// Called from command (not using image API)
|
||||
const worker = new Worker(path.join(__dirname, "image-runner.js"), {
|
||||
workerData: object
|
||||
});
|
||||
worker.once("message", (data) => {
|
||||
resolve({
|
||||
buffer: Buffer.from([...data.buffer]),
|
||||
type: data.fileExtension
|
||||
});
|
||||
});
|
||||
worker.once("error", reject);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
exports.log = (type, content) => content ? process.send({ name: type, msg: content }) : process.send({ name: "info", msg: type });
|
||||
exports.log = (type, content) => content ? process.send({ op: type, msg: content }) : process.send({ op: "info", msg: type });
|
||||
|
||||
exports.error = (...args) => this.log("error", ...args);
|
||||
|
||||
|
|
|
@ -39,16 +39,6 @@ module.exports = (input) => {
|
|||
} else {
|
||||
args[curr] += `${a} `;
|
||||
}
|
||||
} else if (a.startsWith("\"")) {
|
||||
if (a.endsWith("\"")) {
|
||||
args.push(a.slice(1).slice(0, -1));
|
||||
} else {
|
||||
concated += `${a.slice(1)} `;
|
||||
}
|
||||
} else if (a.endsWith("\"")) {
|
||||
concated += a.slice(0, -1);
|
||||
args._.push(concated);
|
||||
concated = "";
|
||||
} else {
|
||||
if (concated !== "") {
|
||||
concated += `${a} `;
|
||||
|
|
286
utils/services/image.js
Normal file
286
utils/services/image.js
Normal file
|
@ -0,0 +1,286 @@
|
|||
const { BaseServiceWorker } = require("eris-fleet");
|
||||
const logger = require("../logger.js");
|
||||
const fetch = require("node-fetch");
|
||||
const WebSocket = require("ws");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { Worker } = require("worker_threads");
|
||||
const { EventEmitter } = require("events");
|
||||
|
||||
class ImageWorker extends BaseServiceWorker {
|
||||
constructor(setup) {
|
||||
super(setup);
|
||||
|
||||
if (process.env.API === "true") {
|
||||
this.jobs = {};
|
||||
this.connections = new Map();
|
||||
this.servers = JSON.parse(fs.readFileSync("./servers.json", { encoding: "utf8" })).image;
|
||||
}
|
||||
|
||||
this.begin().then(() => this.serviceReady());
|
||||
}
|
||||
|
||||
async begin() {
|
||||
// connect to image api if enabled
|
||||
if (process.env.API === "true") {
|
||||
for (const server of this.servers) {
|
||||
try {
|
||||
await this.connect(server);
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async repopulate() {
|
||||
const data = await fs.promises.readFile("./servers.json", { encoding: "utf8" });
|
||||
this.servers = JSON.parse(data).image;
|
||||
return;
|
||||
}
|
||||
|
||||
async getRunning() {
|
||||
let serversLeft = this.connections.size;
|
||||
const statuses = [];
|
||||
for (const address of this.connections.keys()) {
|
||||
const connection = this.connections.get(address);
|
||||
if (connection.readyState !== 0 && connection.readyState !== 1) {
|
||||
serversLeft--;
|
||||
continue;
|
||||
}
|
||||
const controller = new AbortController(); // eslint-disable-line no-undef
|
||||
const timeout = setTimeout(() => {
|
||||
controller.abort();
|
||||
}, 2000);
|
||||
try {
|
||||
const statusRequest = await fetch(`http://${address}:8080/running`, { signal: controller.signal });
|
||||
clearTimeout(timeout);
|
||||
const status = await statusRequest.json();
|
||||
serversLeft--;
|
||||
statuses.push(status);
|
||||
} catch (e) {
|
||||
if (e.name === "AbortError") {
|
||||
serversLeft--;
|
||||
continue;
|
||||
} else if (e.code === "ECONNREFUSED") {
|
||||
serversLeft--;
|
||||
continue;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
if (!serversLeft) {
|
||||
return statuses;
|
||||
} else {
|
||||
throw new Error("Loop ended before all servers could be checked");
|
||||
}
|
||||
}
|
||||
|
||||
async chooseServer(ideal) {
|
||||
if (ideal.length === 0) throw "No available servers";
|
||||
const sorted = ideal.sort((a, b) => {
|
||||
return b.load - a.load;
|
||||
});
|
||||
return sorted[0];
|
||||
}
|
||||
|
||||
async getIdeal() {
|
||||
let serversLeft = this.connections.size;
|
||||
if (serversLeft < this.servers.length) {
|
||||
for (const server of this.servers) {
|
||||
try {
|
||||
if (!this.connections.has(server)) await this.connect(server);
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
serversLeft = this.connections.size;
|
||||
}
|
||||
const idealServers = [];
|
||||
for (const address of this.connections.keys()) {
|
||||
const connection = this.connections.get(address);
|
||||
if (connection.readyState !== 0 && connection.readyState !== 1) {
|
||||
serversLeft--;
|
||||
continue;
|
||||
}
|
||||
const controller = new AbortController(); // eslint-disable-line no-undef
|
||||
const timeout = setTimeout(() => {
|
||||
controller.abort();
|
||||
}, 5000);
|
||||
try {
|
||||
const statusRequest = await fetch(`http://${address}:8080/status`, { signal: controller.signal });
|
||||
clearTimeout(timeout);
|
||||
const status = await statusRequest.text();
|
||||
serversLeft--;
|
||||
idealServers.push({
|
||||
addr: address,
|
||||
load: parseInt(status)
|
||||
});
|
||||
} catch (e) {
|
||||
if (e.name === "AbortError") {
|
||||
serversLeft--;
|
||||
continue;
|
||||
} else if (e.code === "ECONNREFUSED") {
|
||||
serversLeft--;
|
||||
continue;
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
}
|
||||
if (!serversLeft) {
|
||||
const server = await this.chooseServer(idealServers);
|
||||
return { addr: server.addr, sock: this.connections.get(server.addr) };
|
||||
} else {
|
||||
throw new Error("Loop ended before all servers could be checked");
|
||||
}
|
||||
}
|
||||
|
||||
async connect(server) {
|
||||
const connection = new WebSocket(`ws://${server}:8080/sock`);
|
||||
connection.on("message", async (msg) => {
|
||||
const opcode = msg.readUint8(0);
|
||||
const req = msg.slice(37, msg.length);
|
||||
const uuid = msg.slice(1, 37).toString();
|
||||
if (opcode === 0x00) { // Job queued
|
||||
if (this.jobs[req]) {
|
||||
this.jobs[req].event.emit("uuid", uuid);
|
||||
}
|
||||
} else if (opcode === 0x01) { // Job completed successfully
|
||||
// the image API sends all job responses over the same socket; make sure this is ours
|
||||
if (this.jobs[uuid]) {
|
||||
const imageReq = await fetch(`http://${server}:8080/image?id=${uuid}`);
|
||||
const image = await imageReq.buffer();
|
||||
// The response data is given as the file extension/ImageMagick type of the image (e.g. "png"), followed
|
||||
// by a newline, followed by the image data.
|
||||
|
||||
this.jobs[uuid].event.emit("image", image, imageReq.headers.get("ext"));
|
||||
}
|
||||
} else if (opcode === 0x02) { // Job errored
|
||||
if (this.jobs[uuid]) {
|
||||
this.jobs[uuid].event.emit("error", new Error(req));
|
||||
}
|
||||
}
|
||||
});
|
||||
connection.on("error", (e) => {
|
||||
logger.error(e.toString());
|
||||
});
|
||||
connection.once("close", () => {
|
||||
for (const uuid of Object.keys(this.jobs)) {
|
||||
if (this.jobs[uuid].addr === server) {
|
||||
this.jobs[uuid].event.emit("error", "Job ended prematurely due to a closed connection; please run your image job again");
|
||||
delete this.jobs[uuid];
|
||||
}
|
||||
}
|
||||
//logger.log(`Lost connection to ${server}, attempting to reconnect...`);
|
||||
this.connections.delete(server);
|
||||
});
|
||||
this.connections.set(server, connection);
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
for (const connection of this.connections.values()) {
|
||||
connection.close();
|
||||
}
|
||||
for (const uuid of Object.keys(this.jobs)) {
|
||||
this.jobs[uuid].event.emit("error", "Job ended prematurely (not really an error; just run your image job again)");
|
||||
delete this.jobs[uuid];
|
||||
}
|
||||
this.connections.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
async start(object, num) {
|
||||
const currentServer = await this.getIdeal();
|
||||
const data = Buffer.concat([Buffer.from([0x01 /* queue job */]), Buffer.from(num.length.toString()), Buffer.from(num), Buffer.from(JSON.stringify(object))]);
|
||||
currentServer.sock.send(data);
|
||||
const event = new EventEmitter();
|
||||
this.jobs[num] = { event, addr: currentServer.addr };
|
||||
const uuid = await new Promise((resolve, reject) => {
|
||||
event.once("uuid", (uuid) => resolve(uuid));
|
||||
event.once("error", reject);
|
||||
});
|
||||
delete this.jobs[num];
|
||||
this.jobs[uuid] = { event: event, addr: currentServer.addr };
|
||||
return { uuid: uuid, event: event };
|
||||
}
|
||||
|
||||
run(object) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (process.env.API === "true") {
|
||||
// Connect to best image server
|
||||
const num = Math.floor(Math.random() * 100000).toString().slice(0, 5);
|
||||
const timeout = setTimeout(() => {
|
||||
if (this.jobs[num]) delete this.jobs[num];
|
||||
reject("the image request timed out after 25 seconds. Try uploading your image elsewhere.");
|
||||
}, 25000);
|
||||
this.start(object, num).catch(err => { // incredibly hacky code incoming
|
||||
clearTimeout(timeout);
|
||||
if (err instanceof Error) return reject(err);
|
||||
return err;
|
||||
}).then((data) => {
|
||||
clearTimeout(timeout);
|
||||
if (!data.event) reject("Not connected to image server");
|
||||
data.event.once("image", (image, type) => {
|
||||
delete this.jobs[data.uuid];
|
||||
const payload = {
|
||||
// Take just the image data
|
||||
buffer: image,
|
||||
type: type
|
||||
};
|
||||
resolve(payload);
|
||||
});
|
||||
data.event.once("error", (err) => {
|
||||
delete this.jobs[data.uuid];
|
||||
reject(err);
|
||||
});
|
||||
return;
|
||||
}).catch(err => reject(err));
|
||||
} else {
|
||||
// Called from command (not using image API)
|
||||
const worker = new Worker(path.join(__dirname, "../image-runner.js"), {
|
||||
workerData: object
|
||||
});
|
||||
worker.once("message", (data) => {
|
||||
resolve({
|
||||
buffer: Buffer.from([...data.buffer]),
|
||||
type: data.fileExtension
|
||||
});
|
||||
});
|
||||
worker.once("error", reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async handleCommand(data) {
|
||||
try {
|
||||
if (data.type === "run") {
|
||||
return await this.run(data.obj);
|
||||
} else if (data.type === "reload") {
|
||||
await this.disconnect();
|
||||
await this.repopulate();
|
||||
let amount = 0;
|
||||
for (const server of this.servers) {
|
||||
try {
|
||||
await this.connect(server);
|
||||
amount += 1;
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
return amount;
|
||||
} else if (data.type === "stats") {
|
||||
return await this.getRunning();
|
||||
}
|
||||
} catch (err) {
|
||||
return { err: err.message };
|
||||
}
|
||||
}
|
||||
|
||||
shutdown(done) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ImageWorker;
|
57
utils/services/prometheus.js
Normal file
57
utils/services/prometheus.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
const { BaseServiceWorker } = require("eris-fleet");
|
||||
const http = require("http");
|
||||
const logger = require("../logger.js");
|
||||
const database = require("../database.js");
|
||||
|
||||
class PrometheusWorker extends BaseServiceWorker {
|
||||
constructor(setup) {
|
||||
super(setup);
|
||||
|
||||
if (process.env.METRICS !== "" && process.env.METRICS !== undefined) {
|
||||
this.httpServer = http.createServer(async (req, res) => {
|
||||
if (req.method !== "GET") {
|
||||
res.statusCode = 405;
|
||||
return res.end("GET only");
|
||||
}
|
||||
res.write(`# HELP command_count Number of times a command has been run
|
||||
# TYPE command_count counter
|
||||
`);
|
||||
if (process.env.API === "true") {
|
||||
const servers = await this.ipc.command("image", { type: "stats" }, true);
|
||||
res.write(`# HELP connected_workers Number of workers connected
|
||||
# TYPE connected_workers gauge
|
||||
connected_workers ${servers.length}
|
||||
# HELP running_jobs Number of running jobs on this worker
|
||||
# TYPE running_jobs gauge
|
||||
# HELP queued_jobs Number of queued jobs on this worker
|
||||
# TYPE queued_jobs gauge
|
||||
# HELP max_jobs Number of max allowed jobs on this worker
|
||||
# TYPE max_jobs gauge
|
||||
`);
|
||||
for (const [i, w] of servers.entries()) {
|
||||
res.write(`running_jobs{worker="${i}"} ${w.runningJobs}\n`);
|
||||
res.write(`queued_jobs{worker="${i}"} ${w.queued}\n`);
|
||||
res.write(`max_jobs{worker="${i}"} ${w.max}\n`);
|
||||
}
|
||||
}
|
||||
const counts = await database.getCounts();
|
||||
for (const [i, w] of Object.entries(counts)) {
|
||||
res.write(`command_count{command="${i}"} ${w}\n`);
|
||||
}
|
||||
res.end();
|
||||
});
|
||||
this.httpServer.listen(process.env.METRICS, () => {
|
||||
logger.log("info", `Serving metrics at ${process.env.METRICS}`);
|
||||
});
|
||||
}
|
||||
|
||||
this.serviceReady();
|
||||
}
|
||||
|
||||
shutdown(done) {
|
||||
this.httpServer.close();
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PrometheusWorker;
|
|
@ -90,11 +90,15 @@ exports.play = async (client, sound, message, music = false) => {
|
|||
}
|
||||
};
|
||||
|
||||
exports.nextSong = async (client, message, connection, track, info, music, voiceChannel, loop = false, inQueue = false, lastTrack = null, oldPlaying = null) => {
|
||||
exports.nextSong = async (client, message, connection, track, info, music, voiceChannel, loop = false, inQueue = false, lastTrack = null) => {
|
||||
const parts = Math.floor((0 / info.length) * 10);
|
||||
let playingMessage;
|
||||
if (!music && this.players.get(voiceChannel.guild.id)) {
|
||||
const playMessage = this.players.get(voiceChannel.guild.id).playMessage;
|
||||
if (playMessage.channel.messages.get(playMessage.id)) playMessage.delete();
|
||||
}
|
||||
if (lastTrack === track) {
|
||||
playingMessage = oldPlaying;
|
||||
playingMessage = this.players.get(voiceChannel.guild.id).playMessage;
|
||||
} else {
|
||||
playingMessage = await client.createMessage(message.channel.id, !music ? "🔊 Playing sound..." : {
|
||||
"embed": {
|
||||
|
@ -123,10 +127,12 @@ exports.nextSong = async (client, message, connection, track, info, music, voice
|
|||
});
|
||||
}
|
||||
await connection.play(track);
|
||||
this.players.set(voiceChannel.guild.id, { player: connection, type: music ? "music" : "sound", host: message.author.id, voiceChannel: voiceChannel, originalChannel: message.channel, loop: loop });
|
||||
this.players.set(voiceChannel.guild.id, { player: connection, type: music ? "music" : "sound", host: message.author.id, voiceChannel: voiceChannel, originalChannel: message.channel, loop: loop, playMessage: playingMessage });
|
||||
if (inQueue && connection.listeners("error").length === 0) {
|
||||
connection.on("error", (error) => {
|
||||
if (playingMessage.channel.messages.get(playingMessage.id)) playingMessage.delete();
|
||||
const playMessage = this.players.get(voiceChannel.guild.id).playMessage;
|
||||
if (playMessage.channel.messages.get(playMessage.id)) playMessage.delete();
|
||||
this.manager.leave(voiceChannel.guild.id);
|
||||
connection.destroy();
|
||||
this.players.delete(voiceChannel.guild.id);
|
||||
|
@ -138,9 +144,9 @@ exports.nextSong = async (client, message, connection, track, info, music, voice
|
|||
connection.on("end", async (data) => {
|
||||
if (data.reason === "REPLACED") return;
|
||||
const queue = this.queues.get(voiceChannel.guild.id);
|
||||
const isLooping = this.players.get(voiceChannel.guild.id).loop;
|
||||
const player = this.players.get(voiceChannel.guild.id);
|
||||
let newQueue;
|
||||
if (isLooping) {
|
||||
if (player.loop) {
|
||||
queue.push(queue.shift());
|
||||
newQueue = queue;
|
||||
} else {
|
||||
|
@ -153,11 +159,21 @@ exports.nextSong = async (client, message, connection, track, info, music, voice
|
|||
this.players.delete(voiceChannel.guild.id);
|
||||
this.queues.delete(voiceChannel.guild.id);
|
||||
if (music) await client.createMessage(message.channel.id, "🔊 The current voice channel session has ended.");
|
||||
if (playingMessage.channel.messages.get(playingMessage.id)) await playingMessage.delete();
|
||||
try {
|
||||
if (playingMessage.channel.messages.get(playingMessage.id)) await playingMessage.delete();
|
||||
if (player.playMessage.channel.messages.get(player.playMessage.id)) await player.playMessage.delete();
|
||||
} catch {
|
||||
// no-op
|
||||
}
|
||||
} else {
|
||||
const newTrack = await fetch(`http://${connection.node.host}:${connection.node.port}/decodetrack?track=${encodeURIComponent(newQueue[0])}`, { headers: { Authorization: connection.node.password } }).then(res => res.json());
|
||||
this.nextSong(client, message, connection, newQueue[0], newTrack, music, voiceChannel, isLooping, true, track, playingMessage);
|
||||
if (newQueue[0] !== track && playingMessage.channel.messages.get(playingMessage.id)) await playingMessage.delete();
|
||||
this.nextSong(client, message, connection, newQueue[0], newTrack, music, voiceChannel, player.loop, true, track);
|
||||
try {
|
||||
if (newQueue[0] !== track && playingMessage.channel.messages.get(playingMessage.id)) await playingMessage.delete();
|
||||
if (newQueue[0] !== track && player.playMessage.channel.messages.get(player.playMessage.id)) await player.playMessage.delete();
|
||||
} catch {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue