Port to ESM modules (haha funny), removed cache request, many other changes that I forgot about

This commit is contained in:
Essem 2021-08-19 09:19:14 -05:00
parent 2fe45d842b
commit ae2ebe0337
No known key found for this signature in database
GPG key ID: 7D497397CC3A2A8C
157 changed files with 1661 additions and 897 deletions

View file

@ -1,5 +1,5 @@
// this is a method to wait for someone to rejoin a voice channel
const { EventEmitter } = require("events");
import { EventEmitter } from "events";
class AwaitRejoin extends EventEmitter {
constructor(channel, anyone, memberID) {
@ -37,4 +37,4 @@ class AwaitRejoin extends EventEmitter {
}
}
module.exports = AwaitRejoin;
export default AwaitRejoin;

View file

@ -1,7 +1,7 @@
exports.commands = new Map();
exports.paths = new Map();
exports.aliases = new Map();
exports.info = new Map();
export const commands = new Map();
export const paths = new Map();
export const aliases = new Map();
export const info = new Map();
class TimedMap extends Map {
set(key, value) {
@ -12,7 +12,7 @@ class TimedMap extends Map {
}
}
exports.runningCommands = new TimedMap();
export const runningCommands = new TimedMap();
/*class Cache extends Map {
constructor(values) {
@ -26,6 +26,6 @@ exports.runningCommands = new TimedMap();
}
}*/
exports.prefixCache = new Map();
exports.disabledCache = new Map();
exports.disabledCmdCache = new Map();
export const prefixCache = new Map();
export const disabledCache = new Map();
export const disabledCmdCache = new Map();

View file

@ -1,5 +1,6 @@
require("dotenv").config();
const { Pool } = require("pg");
import { config } from "dotenv";
config();
import { Pool } from "pg";
const pool = new Pool({
connectionString: process.env.DB
});

View file

@ -1,3 +1,3 @@
// wrapper for the database drivers in ./database/
module.exports = require(`./database/${process.env.DB ? process.env.DB.split("://")[0] : "dummy"}.js`);
export default await import(`./database/${process.env.DB ? process.env.DB.split("://")[0] : "dummy"}.js`);

View file

@ -1,33 +1,32 @@
// dummy (no-op) database handler
const misc = require("../misc.js");
const logger = require("../logger.js");
import { warn } from "../logger.js";
logger.warn("Using dummy database adapter. If this isn't what you wanted, check your DB variable.");
warn("Using dummy database adapter. If this isn't what you wanted, check your DB variable.");
exports.setup = async () => {};
exports.stop = async () => {};
exports.fixGuild = async () => {};
exports.addCount = async () => {};
exports.getCounts = async () => {
export async function setup() {}
export async function stop() {}
export async function fixGuild() {}
export async function addCount() {}
export async function getCounts() {
return {};
};
exports.disableCommand = async () => {};
exports.enableCommand = async () => {};
exports.disableChannel = async () => {};
exports.enableChannel = async () => {};
exports.getTags = async () => {};
exports.getTag = async () => {};
exports.setTag = async () => {};
exports.removeTag = async () => {};
exports.editTag = async () => {};
exports.setPrefix = async () => {};
exports.addGuild = async (guild) => {
}
export async function disableCommand() {}
export async function enableCommand() {}
export async function disableChannel() {}
export async function enableChannel() {}
export async function getTags() {}
export async function getTag() {}
export async function setTag() {}
export async function removeTag() {}
export async function editTag() {}
export async function setPrefix() {}
export async function addGuild(guild) {
return {
id: guild.id,
tags: misc.tagDefaults,
tags: {},
prefix: process.env.PREFIX,
disabled: [],
disabled_commands: []
};
};
exports.getGuild = exports.addGuild;
}
export const getGuild = addGuild;

View file

@ -1,74 +1,74 @@
const collections = require("../collections.js");
const logger = require("../logger.js");
import { prefixCache, disabledCmdCache, disabledCache, commands } from "../collections.js";
import { error, log } from "../logger.js";
const { Pool } = require("pg");
const connection = new Pool({
import Postgres from "pg";
const connection = new Postgres.Pool({
connectionString: process.env.DB,
statement_timeout: 10000
});
exports.getGuild = async (query) => {
export async function getGuild(query) {
return (await connection.query("SELECT * FROM guilds WHERE guild_id = $1", [query])).rows[0];
};
}
exports.setPrefix = async (prefix, guild) => {
export async function setPrefix(prefix, guild) {
await connection.query("UPDATE guilds SET prefix = $1 WHERE guild_id = $2", [prefix, guild.id]);
collections.prefixCache.set(guild.id, prefix);
};
prefixCache.set(guild.id, prefix);
}
exports.getTag = async (guild, tag) => {
export async function getTag(guild, tag) {
const tagResult = (await connection.query("SELECT * FROM tags WHERE guild_id = $1 AND name = $2", [guild, tag])).rows;
return tagResult[0] ? { content: tagResult[0].content, author: tagResult[0].author } : undefined;
};
}
exports.getTags = async (guild) => {
export async function getTags(guild) {
const tagArray = (await connection.query("SELECT * FROM tags WHERE guild_id = $1", [guild])).rows;
const tags = {};
for (const tag of tagArray) {
tags[tag.name] = { content: tag.content, author: tag.author };
}
return tags;
};
}
exports.setTag = async (name, content, guild) => {
export async function setTag(name, content, guild) {
await connection.query("INSERT INTO tags (guild_id, name, content, author) VALUES ($1, $2, $3, $4)", [guild.id, name, content.content, content.author]);
};
}
exports.editTag = async (name, content, guild) => {
export async function editTag(name, content, guild) {
await connection.query("UPDATE tags SET content = $1, author = $2 WHERE guild_id = $3 AND name = $4", [content.content, content.author, guild.id, name]);
};
}
exports.removeTag = async (name, guild) => {
export async function removeTag(name, guild) {
await connection.query("DELETE FROM tags WHERE guild_id = $1 AND name = $2", [guild.id, name]);
};
}
exports.disableCommand = async (guild, command) => {
export async function disableCommand(guild, command) {
const guildDB = await this.getGuild(guild);
await connection.query("UPDATE guilds SET disabled_commands = $1 WHERE guild_id = $2", [(guildDB.disabled_commands ? [...guildDB.disabled_commands, command] : [command]).filter((v) => v !== undefined), guild]);
collections.disabledCmdCache.set(guild, guildDB.disabled_commands ? [...guildDB.disabled_commands, command] : [command].filter((v) => v !== undefined));
};
disabledCmdCache.set(guild, guildDB.disabled_commands ? [...guildDB.disabled_commands, command] : [command].filter((v) => v !== undefined));
}
exports.enableCommand = async (guild, command) => {
export async function enableCommand(guild, command) {
const guildDB = await this.getGuild(guild);
const newDisabled = guildDB.disabled_commands ? guildDB.disabled_commands.filter(item => item !== command) : [];
await connection.query("UPDATE guilds SET disabled_commands = $1 WHERE guild_id = $2", [newDisabled, guild]);
collections.disabledCmdCache.set(guild, newDisabled);
};
disabledCmdCache.set(guild, newDisabled);
}
exports.disableChannel = async (channel) => {
export async function disableChannel(channel) {
const guildDB = await this.getGuild(channel.guild.id);
await connection.query("UPDATE guilds SET disabled = $1 WHERE guild_id = $2", [[...guildDB.disabled, channel.id], channel.guild.id]);
collections.disabledCache.set(channel.guild.id, [...guildDB.disabled, channel.id]);
};
disabledCache.set(channel.guild.id, [...guildDB.disabled, channel.id]);
}
exports.enableChannel = async (channel) => {
export async function enableChannel(channel) {
const guildDB = await this.getGuild(channel.guild.id);
const newDisabled = guildDB.disabled.filter(item => item !== channel.id);
await connection.query("UPDATE guilds SET disabled = $1 WHERE guild_id = $2", [newDisabled, channel.guild.id]);
collections.disabledCache.set(channel.guild.id, newDisabled);
};
disabledCache.set(channel.guild.id, newDisabled);
}
exports.getCounts = async () => {
export async function getCounts() {
const counts = await connection.query("SELECT * FROM counts");
//const countArray = [];
const countObject = {};
@ -76,37 +76,37 @@ exports.getCounts = async () => {
countObject[command] = count;
}
return countObject;
};
}
exports.addCount = async (command) => {
export async function addCount(command) {
let count = await connection.query("SELECT * FROM counts WHERE command = $1", [command]);
if (!count.rows[0]) {
await connection.query("INSERT INTO counts (command, count) VALUES ($1, $2)", [command, 0]);
count = await connection.query("SELECT * FROM counts WHERE command = $1", [command]);
}
await connection.query("UPDATE counts SET count = $1 WHERE command = $2", [count.rows[0].count ? count.rows[0].count + 1 : 1, command]);
};
}
exports.addGuild = async (guild) => {
export async function addGuild(guild) {
const query = await this.getGuild(guild);
if (query) return query;
try {
await connection.query("INSERT INTO guilds (guild_id, prefix, disabled, disabled_commands) VALUES ($1, $2, $3, $4)", [guild.id, process.env.PREFIX, [], []]);
} catch (e) {
logger.error(`Failed to register guild ${guild.id}: ${e}`);
error(`Failed to register guild ${guild.id}: ${e}`);
}
return await this.getGuild(guild.id);
};
}
exports.fixGuild = async (guild) => {
export async function fixGuild(guild) {
const guildDB = await connection.query("SELECT exists(SELECT 1 FROM guilds WHERE guild_id = $1)", [guild.id]);
if (!guildDB.rows[0].exists) {
logger.log(`Registering guild database entry for guild ${guild.id}...`);
log(`Registering guild database entry for guild ${guild.id}...`);
return await this.addGuild(guild);
}
};
}
exports.setup = async () => {
export async function setup() {
let counts;
try {
counts = await connection.query("SELECT * FROM counts");
@ -115,12 +115,12 @@ exports.setup = async () => {
}
if (!counts.rows[0]) {
for (const command of collections.commands.keys()) {
for (const command of commands.keys()) {
await connection.query("INSERT INTO counts (command, count) VALUES ($1, $2)", [command, 0]);
}
} else {
const exists = [];
for (const command of collections.commands.keys()) {
for (const command of commands.keys()) {
const count = await connection.query("SELECT * FROM counts WHERE command = $1", [command]);
if (!count.rows[0]) {
await connection.query("INSERT INTO counts (command, count) VALUES ($1, $2)", [command, 0]);
@ -134,8 +134,8 @@ exports.setup = async () => {
}
}
}
};
}
exports.stop = async () => {
export async function stop() {
await connection.end();
};
}

View file

@ -1,10 +1,10 @@
const collections = require("../collections.js");
const logger = require("../logger.js");
import collections from "../collections.js";
import logger from "../logger.js";
const sqlite3 = require("better-sqlite3");
import sqlite3 from "better-sqlite3";
const connection = sqlite3(process.env.DB.replace("sqlite://", ""));
exports.setup = async () => {
export async function setup() {
let counts;
try {
counts = connection.prepare("SELECT * FROM counts").all();
@ -39,13 +39,13 @@ exports.setup = async () => {
}
}
}
};
}
exports.stop = async () => {
export async function stop() {
connection.close();
};
}
exports.fixGuild = async (guild) => {
export async function fixGuild(guild) {
let guildDB;
try {
guildDB = connection.prepare("SELECT * FROM guilds WHERE guild_id = ?").get(guild.id);
@ -56,53 +56,53 @@ exports.fixGuild = async (guild) => {
logger.log(`Registering guild database entry for guild ${guild.id}...`);
return await this.addGuild(guild);
}
};
}
exports.addCount = async (command) => {
export async function addCount(command) {
connection.prepare("UPDATE counts SET count = count + 1 WHERE command = ?").run(command);
};
}
exports.getCounts = async () => {
export async function getCounts() {
const counts = connection.prepare("SELECT * FROM counts").all();
const countObject = {};
for (const { command, count } of counts) {
countObject[command] = count;
}
return countObject;
};
}
exports.disableCommand = async (guild, command) => {
export async function disableCommand(guild, command) {
const guildDB = await this.getGuild(guild);
connection.prepare("UPDATE guilds SET disabled_commands = ? WHERE guild_id = ?").run(JSON.stringify((guildDB.disabledCommands ? [...JSON.parse(guildDB.disabledCommands), command] : [command]).filter((v) => v !== undefined)), guild);
collections.disabledCmdCache.set(guild, guildDB.disabled_commands ? [...JSON.parse(guildDB.disabledCommands), command] : [command].filter((v) => v !== undefined));
};
}
exports.enableCommand = async (guild, command) => {
export async function enableCommand(guild, command) {
const guildDB = await this.getGuild(guild);
const newDisabled = guildDB.disabledCommands ? JSON.parse(guildDB.disabledCommands).filter(item => item !== command) : [];
connection.prepare("UPDATE guilds SET disabled_commands = ? WHERE guild_id = ?").run(JSON.stringify(newDisabled), guild);
collections.disabledCmdCache.set(guild, newDisabled);
};
}
exports.disableChannel = async (channel) => {
export async function disableChannel(channel) {
const guildDB = await this.getGuild(channel.guild.id);
connection.prepare("UPDATE guilds SET disabled = ? WHERE guild_id = ?").run(JSON.stringify([...JSON.parse(guildDB.disabled), channel.id]), channel.guild.id);
collections.disabledCache.set(channel.guild.id, [...JSON.parse(guildDB.disabled), channel.id]);
};
}
exports.enableChannel = async (channel) => {
export async function enableChannel(channel) {
const guildDB = await this.getGuild(channel.guild.id);
const newDisabled = JSON.parse(guildDB.disabled).filter(item => item !== channel.id);
connection.prepare("UPDATE guilds SET disabled = ? WHERE guild_id = ?").run(JSON.stringify(newDisabled), channel.guild.id);
collections.disabledCache.set(channel.guild.id, newDisabled);
};
}
exports.getTag = async (guild, tag) => {
export async function getTag(guild, tag) {
const tagResult = connection.prepare("SELECT * FROM tags WHERE guild_id = ? AND name = ?").get(guild, tag);
return tagResult ? { content: tagResult.content, author: tagResult.author } : undefined;
};
}
exports.getTags = async (guild) => {
export async function getTags(guild) {
const tagArray = connection.prepare("SELECT * FROM tags WHERE guild_id = ?").all(guild);
const tags = {};
if (!tagArray) return [];
@ -110,9 +110,9 @@ exports.getTags = async (guild) => {
tags[tag.name] = { content: tag.content, author: tag.author };
}
return tags;
};
}
exports.setTag = async (name, content, guild) => {
export async function setTag(name, content, guild) {
const tag = {
id: guild.id,
name: name,
@ -120,22 +120,22 @@ exports.setTag = async (name, content, guild) => {
author: content.author
};
connection.prepare("INSERT INTO tags (guild_id, name, content, author) VALUES (@id, @name, @content, @author)").run(tag);
};
}
exports.removeTag = async (name, guild) => {
export async function removeTag(name, guild) {
connection.prepare("DELETE FROM tags WHERE guild_id = ? AND name = ?").run(guild.id, name);
};
}
exports.editTag = async (name, content, guild) => {
export async function editTag(name, content, guild) {
connection.prepare("UPDATE tags SET content = ?, author = ? WHERE guild_id = ? AND name = ?").run(content.content, content.author, guild.id, name);
};
}
exports.setPrefix = async (prefix, guild) => {
export async function setPrefix(prefix, guild) {
connection.prepare("UPDATE guilds SET prefix = ? WHERE guild_id = ?").run(prefix, guild.id);
collections.prefixCache.set(guild.id, prefix);
};
}
exports.addGuild = async (guild) => {
export async function addGuild(guild) {
const query = await this.getGuild(guild);
if (query) return query;
const guildObject = {
@ -146,12 +146,12 @@ exports.addGuild = async (guild) => {
};
connection.prepare("INSERT INTO guilds (guild_id, prefix, disabled, disabled_commands) VALUES (@id, @prefix, @disabled, @disabledCommands)").run(guildObject);
return guildObject;
};
}
exports.getGuild = async (query) => {
export async function getGuild(query) {
try {
return connection.prepare("SELECT * FROM guilds WHERE guild_id = ?").get(query);
} catch {
return;
}
};
}

View file

@ -1,18 +1,36 @@
const collections = require("./collections.js");
const logger = require("./logger.js");
import { paths, commands, info, aliases as _aliases } from "./collections.js";
import { log } from "./logger.js";
//import { Worker, isMainThread, workerData, parentPort } from "worker_threads";
//import { join, dirname } from "path";
//import { fileURLToPath } from "url";
/*const importNoCache = (module) => {
return new Promise((resolve, reject) => {
const worker = new Worker(new URL("./handler.js", import.meta.url), {
workerData: { module: module }
});
worker.once("message", (result) => {
resolve(result);
});
worker.once("error", (result) => {
reject(result);
});
});
};*/
// load command into memory
exports.load = async (command, soundStatus) => {
const props = require(`../${command}`);
if (props.requires.includes("mashape") && process.env.MASHAPE === "") return logger.log("warn", `Mashape/RapidAPI info not provided in config, skipped loading command ${command}...`);
if (props.requires.includes("sound") && soundStatus) return logger.log("warn", `Failed to connect to some Lavalink nodes, skipped loading command ${command}...`);
export async function load(command, soundStatus) {
//const props = await importNoCache(`../${command}`);
const { default: props } = await import(`../${command}`);
if (props.requires.includes("mashape") && process.env.MASHAPE === "") return log("warn", `Mashape/RapidAPI info not provided in config, skipped loading command ${command}...`);
if (props.requires.includes("sound") && soundStatus) return log("warn", `Failed to connect to some Lavalink nodes, skipped loading command ${command}...`);
const commandArray = command.split("/");
const commandName = commandArray[commandArray.length - 1].split(".")[0];
collections.paths.set(commandName, command);
collections.commands.set(commandName, props);
paths.set(commandName, command);
commands.set(commandName, props);
collections.info.set(commandName, {
info.set(commandName, {
category: commandArray[2],
description: props.description,
aliases: props.aliases,
@ -22,23 +40,23 @@ exports.load = async (command, soundStatus) => {
if (props.aliases) {
for (const alias of props.aliases) {
collections.aliases.set(alias, commandName);
collections.paths.set(alias, command);
_aliases.set(alias, commandName);
paths.set(alias, command);
}
}
return false;
};
}
// unload command from memory
exports.unload = async (command) => {
/*export async function unload(command) {
let cmd;
if (collections.commands.has(command)) {
cmd = collections.commands.get(command);
} else if (collections.aliases.has(command)) {
cmd = collections.commands.get(collections.aliases.get(command));
if (commands.has(command)) {
cmd = commands.get(command);
} else if (_aliases.has(command)) {
cmd = commands.get(_aliases.get(command));
}
if (!cmd) return `The command \`${command}\` doesn't seem to exist, nor is it an alias.`;
const path = collections.paths.get(command);
const path = paths.get(command);
const mod = require.cache[require.resolve(`../${path}`)];
delete require.cache[require.resolve(`../${path}`)];
for (let i = 0; i < module.children.length; i++) {
@ -48,4 +66,15 @@ exports.unload = async (command) => {
}
}
return false;
};
}*/
/*if (!isMainThread) {
const getModule = async () => {
console.log("test");
const module = await import(workerData.module);
console.log("test 2");
parentPort.postMessage(module);
process.exit();
};
getModule();
}*/

View file

@ -1,32 +1,32 @@
const collections = require("./collections.js");
const fs = require("fs");
import { commands, info } from "./collections.js";
import { promises } from "fs";
const categoryTemplate = {
general: [],
tags: ["> **Every command in this category is a subcommand of the tag command.**\n"],
"image-editing": ["> **These commands support the PNG, JPEG, WEBP (static), and GIF (animated or static) formats.**\n"]
};
exports.categories = categoryTemplate;
export let categories = categoryTemplate;
exports.generateList = async () => {
this.categories = categoryTemplate;
for (const [command] of collections.commands) {
const category = collections.info.get(command).category;
const description = collections.info.get(command).description;
const params = collections.info.get(command).params;
export async function generateList() {
categories = categoryTemplate;
for (const [command] of commands) {
const category = info.get(command).category;
const description = info.get(command).description;
const params = info.get(command).params;
if (category === "tags") {
const subCommands = [...Object.keys(description)];
for (const subCommand of subCommands) {
this.categories.tags.push(`**tags${subCommand !== "default" ? ` ${subCommand}` : ""}**${params[subCommand] ? ` ${params[subCommand]}` : ""} - ${description[subCommand]}`);
categories.tags.push(`**tags${subCommand !== "default" ? ` ${subCommand}` : ""}**${params[subCommand] ? ` ${params[subCommand]}` : ""} - ${description[subCommand]}`);
}
} else {
if (!this.categories[category]) this.categories[category] = [];
this.categories[category].push(`**${command}**${params ? ` ${params}` : ""} - ${description}`);
if (!categories[category]) categories[category] = [];
categories[category].push(`**${command}**${params ? ` ${params}` : ""} - ${description}`);
}
}
};
}
exports.createPage = async (output) => {
export async function createPage(output) {
let template = `# <img src="https://raw.githubusercontent.com/esmBot/esmBot/master/esmbot.png" width="64"> esmBot${process.env.NODE_ENV === "development" ? " Dev" : ""} Command List
This page was last generated on \`${new Date().toString()}\`.
@ -41,7 +41,7 @@ Default prefix is \`&\`.
`;
template += "\n## Table of Contents\n";
for (const category of Object.keys(this.categories)) {
for (const category of Object.keys(categories)) {
const categoryStringArray = category.split("-");
for (const index of categoryStringArray.keys()) {
categoryStringArray[index] = categoryStringArray[index].charAt(0).toUpperCase() + categoryStringArray[index].slice(1);
@ -50,13 +50,13 @@ Default prefix is \`&\`.
}
// hell
for (const category of Object.keys(this.categories)) {
for (const category of Object.keys(categories)) {
const categoryStringArray = category.split("-");
for (const index of categoryStringArray.keys()) {
categoryStringArray[index] = categoryStringArray[index].charAt(0).toUpperCase() + categoryStringArray[index].slice(1);
}
template += `\n## ${categoryStringArray.join(" ")}\n`;
for (const command of this.categories[category]) {
for (const command of categories[category]) {
if (command.startsWith(">")) {
template += `${command}\n`;
} else {
@ -65,5 +65,5 @@ Default prefix is \`&\`.
}
}
await fs.promises.writeFile(output, template);
};
await promises.writeFile(output, template);
}

View file

@ -1,8 +1,12 @@
const magick = require(`../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/image.node`);
const { isMainThread, parentPort, workerData } = require("worker_threads");
const fetch = require("node-fetch");
import { createRequire } from "module";
import { isMainThread, parentPort, workerData } from "worker_threads";
import fetch from "node-fetch";
exports.run = object => {
const nodeRequire = createRequire(import.meta.url);
const magick = nodeRequire(`../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/image.node`);
function run(object) {
return new Promise((resolve, reject) => {
// If the image has a path, it must also have a type
let promise = new Promise((resolveTest) => { resolveTest(); }); // no-op
@ -32,10 +36,10 @@ exports.run = object => {
}
});
});
};
}
if (!isMainThread) {
this.run(workerData)
run(workerData)
.then(returnObject => {
parentPort.postMessage(returnObject);
process.exit();

View file

@ -1,16 +1,16 @@
const fetch = require("node-fetch");
const fs = require("fs");
const fileType = require("file-type");
import fetch from "node-fetch";
import fs from "fs";
import fileType from "file-type";
const formats = ["image/jpeg", "image/png", "image/webp", "image/gif", "video/mp4", "video/webm", "video/mov"];
exports.jobs = {};
export const jobs = {};
exports.connections = new Map();
export const connections = new Map();
exports.servers = JSON.parse(fs.readFileSync("./servers.json", { encoding: "utf8" })).image;
export const servers = JSON.parse(fs.readFileSync("./servers.json", { encoding: "utf8" })).image;
exports.getType = async (image, extraReturnTypes) => {
export async function getType(image, extraReturnTypes) {
if (!image.startsWith("http")) {
const imageType = await fileType.fromFile(image);
if (imageType && formats.includes(imageType.mime)) {
@ -50,4 +50,4 @@ exports.getType = async (image, extraReturnTypes) => {
clearTimeout(timeout);
}
return type;
};
}

View file

@ -1,6 +1,8 @@
const fetch = require("node-fetch");
const { getType } = require("./image.js");
const execPromise = require("util").promisify(require("child_process").exec);
import fetch from "node-fetch";
import { getType } from "./image.js";
import { exec } from "child_process";
import { promisify } from "util";
const execPromise = promisify(exec);
const tenorURLs = [
"tenor.com",
@ -119,7 +121,7 @@ const checkImages = async (message, extraReturnTypes, video) => {
};
// this checks for the latest message containing an image and returns the url of the image
module.exports = async (client, cmdMessage, extraReturnTypes = false, video = false) => {
export default async (client, cmdMessage, extraReturnTypes = false, video = false) => {
// we start by checking if the message is a reply to another message
if (cmdMessage.messageReference) {
const replyMessage = await client.getMessage(cmdMessage.messageReference.channelID, cmdMessage.messageReference.messageID).catch(() => undefined);

View file

@ -1,7 +1,7 @@
exports.log = (type, content) => content ? process.send({ op: type, msg: content }) : process.send({ op: "info", msg: type });
export function log(type, content) { return content ? process.send({ op: type, msg: content }) : process.send({ op: "info", msg: type }); }
exports.error = (...args) => this.log("error", ...args);
export function error(...args) { return log("error", ...args); }
exports.warn = (...args) => this.log("warn", ...args);
export function warn(...args) { return log("warn", ...args); }
exports.debug = (...args) => this.log("debug", ...args);
export function debug(...args) { return log("debug", ...args); }

View file

@ -1,18 +1,19 @@
const util = require("util");
const fs = require("fs");
import util from "util";
import fs from "fs";
import { config } from "dotenv";
// random(array) to select a random entry in array
exports.random = (array) => {
export function random(array) {
if (!array || array.length < 1) return null;
return array[Math.floor(Math.random() * array.length)];
};
}
const optionalReplace = (token) => {
return token === undefined || token === "" ? "" : (token === "true" || token === "false" ? token : "<redacted>");
};
// clean(text) to clean message of any private info or mentions
exports.clean = async (text) => {
export async function clean(text) {
if (text && text.constructor && text.constructor.name == "Promise")
text = await text;
if (typeof text !== "string")
@ -22,7 +23,7 @@ exports.clean = async (text) => {
.replaceAll("`", `\`${String.fromCharCode(8203)}`)
.replaceAll("@", `@${String.fromCharCode(8203)}`);
const { parsed } = require("dotenv").config();
const { parsed } = config();
const imageServers = JSON.parse(fs.readFileSync("./servers.json", { encoding: "utf8" })).image;
for (const { server, auth } of imageServers) {
@ -35,15 +36,15 @@ exports.clean = async (text) => {
}
return text;
};
}
// regexEscape(string) to escape characters in a string for use in a regex
exports.regexEscape = (string) => {
export function regexEscape(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
};
}
// decodeEntities(string)
exports.decodeEntities = (string) => {
export function decodeEntities(string) {
var translate_re = /&(nbsp|amp|quot|lt|gt);/g;
var translate = {
"nbsp": " ",
@ -58,15 +59,4 @@ exports.decodeEntities = (string) => {
var num = parseInt(numStr, 10);
return String.fromCharCode(num);
});
};
// define defaults for prefixes and tags
exports.defaults = {
prefix: process.env.PREFIX
};
exports.tagDefaults = {
help: {
content: "https://projectlounge.pw/esmBot/help.html",
author: "198198681982205953"
}
};
}

View file

@ -1,5 +1,5 @@
// eris doesn't come with a method to wait for interactions by default, so we make our own
const EventEmitter = require("events").EventEmitter;
import { EventEmitter } from "events";
class InteractionCollector extends EventEmitter {
constructor(client, message, options = {}) {
@ -30,4 +30,4 @@ class InteractionCollector extends EventEmitter {
}
}
module.exports = InteractionCollector;
export default InteractionCollector;

View file

@ -1,5 +1,5 @@
// eris doesn't come with an awaitMessages method by default, so we make our own
const EventEmitter = require("events").EventEmitter;
import { EventEmitter } from "events";
class MessageCollector extends EventEmitter {
constructor(client, channel, filter, options = {}) {
@ -34,4 +34,4 @@ class MessageCollector extends EventEmitter {
}
}
module.exports = MessageCollector;
export default MessageCollector;

View file

@ -1,8 +1,8 @@
const MessageCollector = require("./awaitmessages.js");
const InteractionCollector = require("./awaitinteractions.js");
const fetch = require("node-fetch");
import MessageCollector from "./awaitmessages.js";
import InteractionCollector from "./awaitinteractions.js";
import fetch from "node-fetch";
module.exports = async (client, message, pages, timeout = 120000) => {
export default async (client, message, pages, timeout = 120000) => {
const manageMessages = message.channel.guild && message.channel.permissionsOf(client.user.id).has("manageMessages") ? true : false;
const options = {
messageReference: {

View file

@ -1,4 +1,4 @@
module.exports = (input) => {
export default (input) => {
if (typeof input === "string") input = input.split(/\s+/g);
const args = { _: [] };
let curr = null;
@ -61,7 +61,7 @@ module.exports = (input) => {
// Format:
// [{name: "verbose", type: "bool"}, {name: "username", type: "string"}]
// */
// module.exports = (input, format) => {
// export default (input, format) => {
// let results = {};
// let text = input.split(' ').slice(1).join(' ');
// format.forEach(element => {

View file

@ -1,11 +1,12 @@
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");
import { BaseServiceWorker } from "eris-fleet";
import * as logger from "../logger.js";
import fetch from "node-fetch";
import WebSocket from "ws";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import { Worker } from "worker_threads";
import { EventEmitter } from "events";
class ImageWorker extends BaseServiceWorker {
constructor(setup) {
@ -255,7 +256,7 @@ class ImageWorker extends BaseServiceWorker {
}).catch(err => reject(err));
} else {
// Called from command (not using image API)
const worker = new Worker(path.join(__dirname, "../image-runner.js"), {
const worker = new Worker(path.join(path.dirname(fileURLToPath(import.meta.url)), "../image-runner.js"), {
workerData: object
});
worker.once("message", (data) => {
@ -300,4 +301,4 @@ class ImageWorker extends BaseServiceWorker {
}
}
module.exports = ImageWorker;
export default ImageWorker;

View file

@ -1,14 +1,14 @@
const { BaseServiceWorker } = require("eris-fleet");
const http = require("http");
const logger = require("../logger.js");
const database = require("../database.js");
import { BaseServiceWorker } from "eris-fleet";
import { createServer } from "http";
import { log } from "../logger.js";
import database from "../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) => {
this.httpServer = createServer(async (req, res) => {
if (req.method !== "GET") {
res.statusCode = 405;
return res.end("GET only");
@ -46,7 +46,7 @@ esmbot_connected_workers ${servers.length}
res.end();
});
this.httpServer.listen(process.env.METRICS, () => {
logger.log("info", `Serving metrics at ${process.env.METRICS}`);
log("info", `Serving metrics at ${process.env.METRICS}`);
});
}
@ -59,4 +59,4 @@ esmbot_connected_workers ${servers.length}
}
}
module.exports = PrometheusWorker;
export default PrometheusWorker;

View file

@ -1,20 +1,20 @@
const logger = require("./logger.js");
const fetch = require("node-fetch");
const fs = require("fs");
const format = require("format-duration");
const { Manager } = require("lavacord");
import * as logger from "./logger.js";
import fetch from "node-fetch";
import fs from "fs";
import format from "format-duration";
import { Manager } from "lavacord";
let nodes;
exports.players = new Map();
exports.queues = new Map();
exports.skipVotes = new Map();
export const players = new Map();
export const queues = new Map();
export const skipVotes = new Map();
exports.manager;
exports.status = false;
exports.connected = false;
export let manager;
export let status = false;
export let connected = false;
exports.checkStatus = async () => {
export async function checkStatus() {
const json = await fs.promises.readFile("./servers.json", { encoding: "utf8" });
nodes = JSON.parse(json).lava;
const newNodes = [];
@ -27,12 +27,12 @@ exports.checkStatus = async () => {
}
}
nodes = newNodes;
this.status = newNodes.length === 0 ? true : false;
return this.status;
};
status = newNodes.length === 0 ? true : false;
return status;
}
exports.connect = async (client) => {
this.manager = new Manager(nodes, {
export async function connect(client) {
manager = new Manager(nodes, {
user: client.user.id,
shards: client.shards.size || 1,
send: (packet) => {
@ -41,39 +41,39 @@ exports.connect = async (client) => {
return guild.shard.sendWS(packet.op, packet.d);
}
});
const { length } = await this.manager.connect();
const { length } = await manager.connect();
logger.log(`Successfully connected to ${length} Lavalink node(s).`);
exports.connected = true;
this.manager.on("error", (error, node) => {
connected = true;
manager.on("error", (error, node) => {
logger.error(`An error occurred on Lavalink node ${node}: ${error}`);
});
return length;
};
}
exports.play = async (client, sound, message, music = false) => {
if (!this.manager) return "The sound commands are still starting up!";
export async function play(client, sound, message, music = false) {
if (!manager) return "The sound commands are still starting up!";
if (!message.channel.guild) return "This command only works in servers!";
if (!message.member.voiceState.channelID) return "You need to be in a voice channel first!";
if (!message.channel.permissionsOf(client.user.id).has("voiceConnect")) return "I can't join this voice channel!";
const voiceChannel = message.channel.guild.channels.get(message.member.voiceState.channelID);
if (!voiceChannel.permissionsOf(client.user.id).has("voiceConnect")) return "I don't have permission to join this voice channel!";
const player = this.players.get(message.channel.guild.id);
if (!music && this.manager.voiceStates.has(message.channel.guild.id) && (player && player.type === "music")) return "I can't play a sound effect while playing music!";
const node = this.manager.idealNodes[0];
const player = players.get(message.channel.guild.id);
if (!music && manager.voiceStates.has(message.channel.guild.id) && (player && player.type === "music")) return "I can't play a sound effect while playing music!";
const node = manager.idealNodes[0];
if (!music && !nodes.filter(obj => obj.host === node.host)[0].local) {
sound = sound.replace(/\.\//, "https://raw.githubusercontent.com/esmBot/esmBot/master/");
}
const { tracks } = await fetch(`http://${node.host}:${node.port}/loadtracks?identifier=${sound}`, { headers: { Authorization: node.password } }).then(res => res.json());
const oldQueue = this.queues.get(voiceChannel.guild.id);
const oldQueue = queues.get(voiceChannel.guild.id);
if (!tracks || tracks.length === 0) return "I couldn't find that song!";
if (music) {
this.queues.set(voiceChannel.guild.id, oldQueue ? [...oldQueue, tracks[0].track] : [tracks[0].track]);
queues.set(voiceChannel.guild.id, oldQueue ? [...oldQueue, tracks[0].track] : [tracks[0].track]);
}
let connection;
if (player) {
connection = player.player;
} else {
connection = await this.manager.join({
connection = await manager.join({
guild: voiceChannel.guild.id,
channel: voiceChannel.id,
node: node.id
@ -83,17 +83,17 @@ exports.play = async (client, sound, message, music = false) => {
if (oldQueue && music) {
return `Your tune \`${tracks[0].info.title}\` has been added to the queue!`;
} else {
this.nextSong(client, message, connection, tracks[0].track, tracks[0].info, music, voiceChannel, player ? player.loop : false);
nextSong(client, message, connection, tracks[0].track, tracks[0].info, music, voiceChannel, player ? player.loop : false);
return;
}
};
}
exports.nextSong = async (client, message, connection, track, info, music, voiceChannel, loop = false, inQueue = false, lastTrack = null) => {
this.skipVotes.set(voiceChannel.guild.id, { count: 0, ids: [] });
export async function nextSong(client, message, connection, track, info, music, voiceChannel, loop = false, inQueue = false, lastTrack = null) {
skipVotes.set(voiceChannel.guild.id, { count: 0, ids: [] });
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 (!music && players.get(voiceChannel.guild.id)) {
const playMessage = players.get(voiceChannel.guild.id).playMessage;
try {
playMessage.delete();
} catch {
@ -101,7 +101,7 @@ exports.nextSong = async (client, message, connection, track, info, music, voice
}
}
if (lastTrack === track) {
playingMessage = this.players.get(voiceChannel.guild.id).playMessage;
playingMessage = players.get(voiceChannel.guild.id).playMessage;
} else {
playingMessage = await client.createMessage(message.channel.id, !music ? "🔊 Playing sound..." : {
"embed": {
@ -130,24 +130,24 @@ 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, playMessage: playingMessage });
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;
const playMessage = players.get(voiceChannel.guild.id).playMessage;
if (playMessage.channel.messages.get(playMessage.id)) playMessage.delete();
this.manager.leave(voiceChannel.guild.id);
manager.leave(voiceChannel.guild.id);
connection.destroy();
this.players.delete(voiceChannel.guild.id);
this.queues.delete(voiceChannel.guild.id);
players.delete(voiceChannel.guild.id);
queues.delete(voiceChannel.guild.id);
logger.error(error);
});
}
if (connection.listeners("end").length === 0) {
connection.on("end", async (data) => {
if (data.reason === "REPLACED") return;
const queue = this.queues.get(voiceChannel.guild.id);
const player = this.players.get(voiceChannel.guild.id);
const queue = queues.get(voiceChannel.guild.id);
const player = players.get(voiceChannel.guild.id);
let newQueue;
if (player.loop) {
queue.push(queue.shift());
@ -155,12 +155,12 @@ exports.nextSong = async (client, message, connection, track, info, music, voice
} else {
newQueue = queue ? queue.slice(1) : [];
}
this.queues.set(voiceChannel.guild.id, newQueue);
queues.set(voiceChannel.guild.id, newQueue);
if (newQueue.length === 0) {
this.manager.leave(voiceChannel.guild.id);
manager.leave(voiceChannel.guild.id);
connection.destroy();
this.players.delete(voiceChannel.guild.id);
this.queues.delete(voiceChannel.guild.id);
players.delete(voiceChannel.guild.id);
queues.delete(voiceChannel.guild.id);
if (music) await client.createMessage(message.channel.id, "🔊 The current voice channel session has ended.");
try {
if (playingMessage.channel.messages.get(playingMessage.id)) await playingMessage.delete();
@ -170,7 +170,7 @@ exports.nextSong = async (client, message, connection, track, info, music, voice
}
} 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, player.loop, true, track);
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();
@ -180,4 +180,4 @@ exports.nextSong = async (client, message, connection, track, info, music, voice
}
});
}
};
}

View file

@ -1,4 +1,4 @@
module.exports = (string) => {
export default (string) => {
const protocolAndDomainRE = /^(?:\w+:)?\/\/(\S+)$/;
const domainRE = /^[^\s.]+\.\S{2,}$/;
const match = string.match(protocolAndDomainRE);

View file

@ -1,4 +1,4 @@
module.exports = (str) => {
export default (str) => {
var regexString = ".{1,15}([\\s\u200B]+|$)|[^\\s\u200B]+?([\\s\u200B]+|$)";
var re = new RegExp(regexString, "g");
var lines = str.match(re) || [];