Initial work on V2.0.0

Updated dependencies and corrected syntax errors caused by the newer deps.
This commit is contained in:
Ean Milligan (Bastion) 2021-11-21 22:14:57 -05:00
parent 73288073b1
commit 60188ca5d8
9 changed files with 827 additions and 809 deletions

View File

@ -1,6 +1,6 @@
export const config = { export const config = {
"name": "The Artificer", // Name of the bot "name": "The Artificer", // Name of the bot
"version": "1.4.3", // Version of the bot "version": "2.0.0", // Version of the bot
"token": "the_bot_token", // Discord API Token for this bot "token": "the_bot_token", // Discord API Token for this bot
"localtoken": "local_testing_token", // Discord API Token for a secondary OPTIONAL testing bot, THIS MUST BE DIFFERENT FROM "token" "localtoken": "local_testing_token", // Discord API Token for a secondary OPTIONAL testing bot, THIS MUST BE DIFFERENT FROM "token"
"prefix": "[[", // Prefix for all commands "prefix": "[[", // Prefix for all commands
@ -13,7 +13,7 @@ export const config = {
"rateLimitCnt": 10, // Amount of requests that can be made (successful or not) during above time range before getting rate limited "rateLimitCnt": 10, // Amount of requests that can be made (successful or not) during above time range before getting rate limited
"admin": 0n, // Discord user ID of the bot admin, this user will be the user that can ban/unban user/channel combos and API keys "admin": 0n, // Discord user ID of the bot admin, this user will be the user that can ban/unban user/channel combos and API keys
"adminKey": "your_25char_api_token", // API Key generated by nanoid that is 25 char long, this gets pre-populated into all_keys "adminKey": "your_25char_api_token", // API Key generated by nanoid that is 25 char long, this gets pre-populated into all_keys
"email": "" // Temporary set up for email, this will be adjusted to an actual email using deno-smtp in the future. "email": 0n // Temporary set up for email, this will be adjusted to an actual email using deno-smtp in the future.
}, },
"db": { // Settings for the MySQL database, this is required for use with the API, if you do not want to set this up, you will need to rip all code relating to the DB out of the bot "db": { // Settings for the MySQL database, this is required for use with the API, if you do not want to set this up, you will need to rip all code relating to the DB out of the bot
"host": "", // IP address for the db, usually localhost "host": "", // IP address for the db, usually localhost
@ -24,9 +24,9 @@ export const config = {
"name": "" // Name of the database Schema to use for the bot "name": "" // Name of the database Schema to use for the bot
}, },
"logRolls": false, // Enables logging of roll commands, this should be left disabled for privacy, but exists to allow verification of rolls before deployment, all API rolls will always be logged no matter what this is set to "logRolls": false, // Enables logging of roll commands, this should be left disabled for privacy, but exists to allow verification of rolls before deployment, all API rolls will always be logged no matter what this is set to
"logChannel": "the_log_channel", // Discord channel ID where the bot should put startup messages and other error messages needed "logChannel": 0n, // Discord channel ID where the bot should put startup messages and other error messages needed
"reportChannel": "the_report_channel", // Discord channel ID where reports will be sent when using the built-in report command "reportChannel": 0n, // Discord channel ID where reports will be sent when using the built-in report command
"devServer": "the_dev_server", // Discord guild ID where testing of indev features/commands will be handled, used in conjuction with the DEVMODE bool in mod.ts "devServer": 0n, // Discord guild ID where testing of indev features/commands will be handled, used in conjuction with the DEVMODE bool in mod.ts
"emojis": [ // Array of objects containing all emojis that the bot can send on your behalf, empty this array if you don't want any of them "emojis": [ // Array of objects containing all emojis that the bot can send on your behalf, empty this array if you don't want any of them
{ // Emoji object, duplicate for each emoji { // Emoji object, duplicate for each emoji
"name": "emoji_name", // Name of emoji in discord "name": "emoji_name", // Name of emoji in discord

19
deps.ts
View File

@ -1,19 +1,18 @@
// All external dependancies are to be loaded here to make updating dependancy versions much easier // All external dependancies are to be loaded here to make updating dependancy versions much easier
export { export {
startBot, editBotsStatus, startBot, editBotStatus, editBotNickname,
Intents, StatusTypes, ActivityType, Intents, DiscordActivityTypes,
sendMessage, sendDirectMessage, sendMessage, sendDirectMessage,
cache, botID, cache, cacheHandlers, botId,
memberIDHasPermission hasGuildPermissions
} from "https://deno.land/x/discordeno@10.3.0/mod.ts"; } from "https://deno.land/x/discordeno@12.0.1/mod.ts";
export type { export type {
CacheData, Message, Guild, MessageContent DiscordenoMessage, DiscordenoGuild, CreateMessage
} from "https://deno.land/x/discordeno@10.3.0/mod.ts"; } from "https://deno.land/x/discordeno@12.0.1/mod.ts";
export { Client } from "https://deno.land/x/mysql@v2.7.0/mod.ts"; export { Client } from "https://deno.land/x/mysql@v2.10.1/mod.ts";
export { serve } from "https://deno.land/std@0.83.0/http/server.ts"; export { Status, STATUS_TEXT } from "https://deno.land/std@0.115.1/http/http_status.ts";
export { Status, STATUS_TEXT } from "https://deno.land/std@0.83.0/http/http_status.ts";
export { nanoid } from "https://deno.land/x/nanoid@v3.0.0/mod.ts"; export { nanoid } from "https://deno.land/x/nanoid@v3.0.0/mod.ts";

View File

@ -3,4 +3,4 @@ export const DEVMODE = false;
// DEBUG is used to toggle the cmdPrompt // DEBUG is used to toggle the cmdPrompt
export const DEBUG = false; export const DEBUG = false;
// LOCALMODE is used to run a differnt bot token for local testing // LOCALMODE is used to run a differnt bot token for local testing
export const LOCALMODE = false; export const LOCALMODE = true;

164
mod.ts
View File

@ -6,12 +6,12 @@
import { import {
// Discordeno deps // Discordeno deps
startBot, editBotsStatus, startBot, editBotStatus, editBotNickname,
Intents, StatusTypes, ActivityType, Intents,
sendMessage, sendDirectMessage, sendMessage, sendDirectMessage,
cache, botID, cache, botId,
memberIDHasPermission, hasGuildPermissions,
Message, Guild, DiscordActivityTypes, DiscordenoGuild, DiscordenoMessage,
// MySQL Driver deps // MySQL Driver deps
Client Client
@ -44,18 +44,32 @@ utils.initLog("logs");
// Start up the Discord Bot // Start up the Discord Bot
startBot({ startBot({
token: LOCALMODE ? config.localtoken : config.token, token: LOCALMODE ? config.localtoken : config.token,
intents: [Intents.GUILD_MESSAGES, Intents.DIRECT_MESSAGES, Intents.GUILDS], intents: [Intents.GuildMessages, Intents.DirectMessages, Intents.Guilds],
eventHandlers: { eventHandlers: {
ready: () => { ready: () => {
utils.log(LT.INFO, `${config.name} Logged in!`); utils.log(LT.INFO, `${config.name} Logged in!`);
editBotsStatus(StatusTypes.Online, "Booting up . . .", ActivityType.Game); editBotStatus({
activities: [{
name: "Booting up . . .",
type: DiscordActivityTypes.Game,
createdAt: new Date().getTime()
}],
status: "online"
});
// Interval to rotate the status text every 30 seconds to show off more commands // Interval to rotate the status text every 30 seconds to show off more commands
setInterval(() => { setInterval(async () => {
utils.log(LT.LOG, "Changing bot status"); utils.log(LT.LOG, "Changing bot status");
try { try {
// Wrapped in try-catch due to hard crash possible // Wrapped in try-catch due to hard crash possible
editBotsStatus(StatusTypes.Online, intervals.getRandomStatus(cache), ActivityType.Game); editBotStatus({
activities: [{
name: await intervals.getRandomStatus(),
type: DiscordActivityTypes.Game,
createdAt: new Date().getTime()
}],
status: "online"
});
} catch (e) { } catch (e) {
utils.log(LT.ERROR, `Failed to update status: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to update status: ${JSON.stringify(e)}`);
} }
@ -64,34 +78,42 @@ startBot({
// Interval to update bot list stats every 24 hours // Interval to update bot list stats every 24 hours
LOCALMODE ? utils.log(LT.INFO, "updateListStatistics not running") : setInterval(() => { LOCALMODE ? utils.log(LT.INFO, "updateListStatistics not running") : setInterval(() => {
utils.log(LT.LOG, "Updating all bot lists statistics"); utils.log(LT.LOG, "Updating all bot lists statistics");
intervals.updateListStatistics(botID, cache.guilds.size); intervals.updateListStatistics(botId, cache.guilds.size);
}, 86400000); }, 86400000);
// setTimeout added to make sure the startup message does not error out // setTimeout added to make sure the startup message does not error out
setTimeout(() => { setTimeout(() => {
LOCALMODE ? utils.log(LT.INFO, "updateListStatistics not running") : intervals.updateListStatistics(botID, cache.guilds.size); LOCALMODE && editBotNickname(config.devServer, `LOCAL - ${config.name}`);
editBotsStatus(StatusTypes.Online, `Boot Complete`, ActivityType.Game); LOCALMODE ? utils.log(LT.INFO, "updateListStatistics not running") : intervals.updateListStatistics(botId, cache.guilds.size);
editBotStatus({
activities: [{
name: "Booting Complete",
type: DiscordActivityTypes.Game,
createdAt: new Date().getTime()
}],
status: "online"
});
sendMessage(config.logChannel, `${config.name} has started, running version ${config.version}.`).catch(e => { sendMessage(config.logChannel, `${config.name} has started, running version ${config.version}.`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`);
}); });
}, 1000); }, 1000);
}, },
guildCreate: (guild: Guild) => { guildCreate: (guild: DiscordenoGuild) => {
utils.log(LT.LOG, `Handling joining guild ${JSON.stringify(guild)}`); utils.log(LT.LOG, `Handling joining guild ${JSON.stringify(guild)}`);
sendMessage(config.logChannel, `New guild joined: ${guild.name} (id: ${guild.id}). This guild has ${guild.memberCount} members!`).catch(e => { sendMessage(config.logChannel, `New guild joined: ${guild.name} (id: ${guild.id}). This guild has ${guild.memberCount} members!`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`);
}); });
}, },
guildDelete: (guild: Guild) => { guildDelete: (guild: DiscordenoGuild) => {
utils.log(LT.LOG, `Handling leaving guild ${JSON.stringify(guild)}`); utils.log(LT.LOG, `Handling leaving guild ${JSON.stringify(guild)}`);
sendMessage(config.logChannel, `I have been removed from: ${guild.name} (id: ${guild.id}).`).catch(e => { sendMessage(config.logChannel, `I have been removed from: ${guild.name} (id: ${guild.id}).`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(e)}`);
}); });
}, },
debug: dmsg => utils.log(LT.LOG, `${JSON.stringify(dmsg)}`), debug: dmsg => utils.log(LT.LOG, `Debug Message | ${JSON.stringify(dmsg)}`),
messageCreate: async (message: Message) => { messageCreate: async (message: DiscordenoMessage) => {
// Ignore all other bots // Ignore all other bots
if (message.author.bot) return; if (message.isBot) return;
// Ignore all messages that are not commands // Ignore all messages that are not commands
if (message.content.indexOf(config.prefix) !== 0) return; if (message.content.indexOf(config.prefix) !== 0) return;
@ -114,7 +136,7 @@ startBot({
// Calculates ping between sending a message and editing it, giving a nice round-trip latency. // Calculates ping between sending a message and editing it, giving a nice round-trip latency.
try { try {
const m = await utils.sendIndirectMessage(message, "Ping?", sendMessage, sendDirectMessage); const m = await message.send("Ping?");
m.edit(`Pong! Latency is ${m.timestamp - message.timestamp}ms.`); m.edit(`Pong! Latency is ${m.timestamp - message.timestamp}ms.`);
} catch (e) { } catch (e) {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
@ -129,7 +151,7 @@ startBot({
utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`);
}); });
utils.sendIndirectMessage(message, "The Artificer was built in memory of my Grandmother, Babka\nWith much love, Ean\n\nDecember 21, 2020", sendMessage, sendDirectMessage).catch(e => { message.send("The Artificer was built in memory of my Grandmother, Babka\nWith much love, Ean\n\nDecember 21, 2020").catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -142,7 +164,7 @@ startBot({
utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`);
}); });
utils.sendIndirectMessage(message, longStrs.rollhelp.join("\n"), sendMessage, sendDirectMessage).catch(e => { message.send(longStrs.rollhelp.join("\n")).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -155,7 +177,7 @@ startBot({
utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`);
}); });
utils.sendIndirectMessage(message, longStrs.help.join("\n"), sendMessage, sendDirectMessage).catch(e => { message.send(longStrs.help.join("\n")).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -168,7 +190,7 @@ startBot({
utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`);
}); });
utils.sendIndirectMessage(message, longStrs.info.join("\n"), sendMessage, sendDirectMessage).catch(e => { message.send(longStrs.info.join("\n")).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -181,7 +203,7 @@ startBot({
utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`);
}); });
utils.sendIndirectMessage(message, longStrs.privacy.join("\n"), sendMessage, sendDirectMessage).catch(e => { message.send(longStrs.privacy.join("\n")).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -194,7 +216,7 @@ startBot({
utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`);
}); });
utils.sendIndirectMessage(message, `My current version is ${config.version}.`, sendMessage, sendDirectMessage).catch(e => { message.send(`My current version is ${config.version}.`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -207,10 +229,10 @@ startBot({
utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`);
}); });
sendMessage(config.reportChannel, ("USER REPORT:\n" + args.join(" "))).catch(e => { sendMessage(config.reportChannel, (`USER REPORT:\n${args.join(" ")}`)).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
utils.sendIndirectMessage(message, "Failed command has been reported to my developer.\n\nFor more in depth support, and information about planned maintenance, please join the support server here: https://discord.gg/peHASXMZYv", sendMessage, sendDirectMessage).catch(e => { message.send("Failed command has been reported to my developer.\n\nFor more in depth support, and information about planned maintenance, please join the support server here: https://discord.gg/peHASXMZYv").catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -233,7 +255,7 @@ startBot({
const rolls = BigInt(rollQuery[0].count); const rolls = BigInt(rollQuery[0].count);
const total = BigInt(totalQuery[0].count); const total = BigInt(totalQuery[0].count);
utils.sendIndirectMessage(message, `${config.name} is rolling dice for ${cache.members.size} active users, in ${cache.channels.size} channels of ${cache.guilds.size} servers.\n\nSo far, ${rolls} dice have been rolled and ${total - rolls} utility commands have been run.`, sendMessage, sendDirectMessage).catch(e => { message.send(`${config.name} is rolling dice for ${cache.members.size} active users, in ${cache.channels.size} channels of ${cache.guilds.size} servers.\n\nSo far, ${rolls} dice have been rolled and ${total - rolls} utility commands have been run.`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -250,19 +272,19 @@ startBot({
const apiArg = args[0].toLowerCase(); const apiArg = args[0].toLowerCase();
// Alert users who DM the bot that this command is for guilds only // Alert users who DM the bot that this command is for guilds only
if (message.guildID === "") { if (message.guildId === 0n) {
utils.sendIndirectMessage(message, `API commands are only available in guilds.`, sendMessage, sendDirectMessage).catch(e => { message.send(`API commands are only available in guilds.`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
return; return;
} }
// Makes sure the user is authenticated to run the API command // Makes sure the user is authenticated to run the API command
if (await memberIDHasPermission(message.author.id, message.guildID, ["ADMINISTRATOR"])) { if (await hasGuildPermissions(message.authorId, message.guildId, ["ADMINISTRATOR"])) {
// [[api help // [[api help
// Shows API help details // Shows API help details
if (apiArg === "help") { if (apiArg === "help") {
utils.sendIndirectMessage(message, longStrs.apihelp.join("\n"), sendMessage, sendDirectMessage).catch(e => { message.send(longStrs.apihelp.join("\n")).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -270,9 +292,9 @@ startBot({
// [[api allow/block // [[api allow/block
// Lets a guild admin allow or ban API rolls from happening in said guild // Lets a guild admin allow or ban API rolls from happening in said guild
else if (apiArg === "allow" || apiArg === "block" || apiArg === "enable" || apiArg === "disable") { else if (apiArg === "allow" || apiArg === "block" || apiArg === "enable" || apiArg === "disable") {
const guildQuery = await dbClient.query(`SELECT guildid FROM allowed_guilds WHERE guildid = ?`, [message.guildID]).catch(e0 => { const guildQuery = await dbClient.query(`SELECT guildid FROM allowed_guilds WHERE guildid = ?`, [message.guildId]).catch(e0 => {
utils.log(LT.ERROR, `Failed to query DB: ${JSON.stringify(e0)}`); utils.log(LT.ERROR, `Failed to query DB: ${JSON.stringify(e0)}`);
utils.sendIndirectMessage(message, `Failed to ${apiArg} API rolls for this guild. If this issue persists, please report this to the developers.`, sendMessage, sendDirectMessage).catch(e1 => { message.send(`Failed to ${apiArg} API rolls for this guild. If this issue persists, please report this to the developers.`).catch(e1 => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`);
}); });
return; return;
@ -280,25 +302,25 @@ startBot({
if (guildQuery.length === 0) { if (guildQuery.length === 0) {
// Since guild is not in our DB, add it in // Since guild is not in our DB, add it in
await dbClient.execute(`INSERT INTO allowed_guilds(guildid,active) values(?,?)`, [BigInt(message.guildID), ((apiArg === "allow" || apiArg === "enable") ? 1 : 0)]).catch(e0 => { await dbClient.execute(`INSERT INTO allowed_guilds(guildid,active) values(?,?)`, [BigInt(message.guildId), ((apiArg === "allow" || apiArg === "enable") ? 1 : 0)]).catch(e0 => {
utils.log(LT.ERROR, `Failed to insert into DB: ${JSON.stringify(e0)}`); utils.log(LT.ERROR, `Failed to insert into DB: ${JSON.stringify(e0)}`);
utils.sendIndirectMessage(message, `Failed to ${apiArg} API rolls for this guild. If this issue persists, please report this to the developers.`, sendMessage, sendDirectMessage).catch(e1 => { message.send(`Failed to ${apiArg} API rolls for this guild. If this issue persists, please report this to the developers.`).catch(e1 => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`);
}); });
return; return;
}); });
} else { } else {
// Since guild is in our DB, update it // Since guild is in our DB, update it
await dbClient.execute(`UPDATE allowed_guilds SET active = ? WHERE guildid = ?`, [((apiArg === "allow" || apiArg === "enable") ? 1 : 0), BigInt(message.guildID)]).catch(e0 => { await dbClient.execute(`UPDATE allowed_guilds SET active = ? WHERE guildid = ?`, [((apiArg === "allow" || apiArg === "enable") ? 1 : 0), BigInt(message.guildId)]).catch(e0 => {
utils.log(LT.ERROR, `Failed to update DB: ${JSON.stringify(e0)}`); utils.log(LT.ERROR, `Failed to update DB: ${JSON.stringify(e0)}`);
utils.sendIndirectMessage(message, `Failed to ${apiArg} API rolls for this guild. If this issue persists, please report this to the developers.`, sendMessage, sendDirectMessage).catch(e1 => { message.send(`Failed to ${apiArg} API rolls for this guild. If this issue persists, please report this to the developers.`).catch(e1 => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`);
}); });
return; return;
}); });
} }
// We won't get here if there's any errors, so we know it has bee successful, so report as such // We won't get here if there's any errors, so we know it has bee successful, so report as such
utils.sendIndirectMessage(message, `API rolls have successfully been ${apiArg}ed for this guild.`, sendMessage, sendDirectMessage).catch(e => { message.send(`API rolls have successfully been ${apiArg}ed for this guild.`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -306,16 +328,16 @@ startBot({
// [[api delete // [[api delete
// Lets a guild admin delete their server from the database // Lets a guild admin delete their server from the database
else if (apiArg === "delete") { else if (apiArg === "delete") {
await dbClient.execute(`DELETE FROM allowed_guilds WHERE guildid = ?`, [message.guildID]).catch(e0 => { await dbClient.execute(`DELETE FROM allowed_guilds WHERE guildid = ?`, [message.guildId]).catch(e0 => {
utils.log(LT.ERROR, `Failed to query DB: ${JSON.stringify(e0)}`); utils.log(LT.ERROR, `Failed to query DB: ${JSON.stringify(e0)}`);
utils.sendIndirectMessage(message, `Failed to delete this guild from the database. If this issue persists, please report this to the developers.`, sendMessage, sendDirectMessage).catch(e1 => { message.send(`Failed to delete this guild from the database. If this issue persists, please report this to the developers.`).catch(e1 => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`);
}); });
return; return;
}); });
// We won't get here if there's any errors, so we know it has bee successful, so report as such // We won't get here if there's any errors, so we know it has bee successful, so report as such
utils.sendIndirectMessage(message, `This guild's API setting has been removed from The Artifier's Database.`, sendMessage, sendDirectMessage).catch(e => { message.send(`This guild's API setting has been removed from The Artifier's Database.`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -324,9 +346,9 @@ startBot({
// Lets a guild admin check the status of API rolling in said guild // Lets a guild admin check the status of API rolling in said guild
else if (apiArg === "status") { else if (apiArg === "status") {
// Get status of guild from the db // Get status of guild from the db
const guildQuery = await dbClient.query(`SELECT active, banned FROM allowed_guilds WHERE guildid = ?`, [message.guildID]).catch(e0 => { const guildQuery = await dbClient.query(`SELECT active, banned FROM allowed_guilds WHERE guildid = ?`, [message.guildId]).catch(e0 => {
utils.log(LT.ERROR, `Failed to query DB: ${JSON.stringify(e0)}`); utils.log(LT.ERROR, `Failed to query DB: ${JSON.stringify(e0)}`);
utils.sendIndirectMessage(message, `Failed to check API rolls status for this guild. If this issue persists, please report this to the developers.`, sendMessage, sendDirectMessage).catch(e1 => { message.send(`Failed to check API rolls status for this guild. If this issue persists, please report this to the developers.`).catch(e1 => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e1)}`);
}); });
return; return;
@ -336,23 +358,23 @@ startBot({
if (guildQuery.length > 0) { if (guildQuery.length > 0) {
// Check if guild is banned from using API and return appropriate message // Check if guild is banned from using API and return appropriate message
if (guildQuery[0].banned) { if (guildQuery[0].banned) {
utils.sendIndirectMessage(message, `The Artificer's API is ${config.api.enable ? "currently enabled" : "currently disabled"}.\n\nAPI rolls are banned from being used in this guild. This will not be reversed.`, sendMessage, sendDirectMessage).catch(e => { message.send(`The Artificer's API is ${config.api.enable ? "currently enabled" : "currently disabled"}.\n\nAPI rolls are banned from being used in this guild. This will not be reversed.`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} else { } else {
utils.sendIndirectMessage(message, `The Artificer's API is ${config.api.enable ? "currently enabled" : "currently disabled"}.\n\nAPI rolls are ${guildQuery[0].active ? "allowed" : "blocked from being used"} in this guild.`, sendMessage, sendDirectMessage).catch(e => { message.send(`The Artificer's API is ${config.api.enable ? "currently enabled" : "currently disabled"}.\n\nAPI rolls are ${guildQuery[0].active ? "allowed" : "blocked from being used"} in this guild.`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
} else { } else {
// Guild is not in DB, therefore they are blocked // Guild is not in DB, therefore they are blocked
utils.sendIndirectMessage(message, `The Artificer's API is ${config.api.enable ? "currently enabled" : "currently disabled"}.\n\nAPI rolls are blocked from being used in this guild.`, sendMessage, sendDirectMessage).catch(e => { message.send(`The Artificer's API is ${config.api.enable ? "currently enabled" : "currently disabled"}.\n\nAPI rolls are blocked from being used in this guild.`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
} }
} else { } else {
utils.sendIndirectMessage(message, `API commands are powerful and can only be used by guild Owners and Admins.\n\nFor information on how to use the API, please check the GitHub README for more information: <https://github.com/Burn-E99/TheArtificer>`, sendMessage, sendDirectMessage).catch(e => { message.send(`API commands are powerful and can only be used by guild Owners and Admins.\n\nFor information on how to use the API, please check the GitHub README for more information: <https://github.com/Burn-E99/TheArtificer>`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
} }
@ -360,15 +382,15 @@ startBot({
// [[roll]] // [[roll]]
// Dice rolling commence! // Dice rolling commence!
else if ((command + args.join("")).indexOf(config.postfix) > -1) { else if ((`${command}${args.join("")}`).indexOf(config.postfix) > -1) {
// Light telemetry to see how many times a command is being run // Light telemetry to see how many times a command is being run
dbClient.execute(`CALL INC_CNT("roll");`).catch(e => { dbClient.execute(`CALL INC_CNT("roll");`).catch(e => {
utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`);
}); });
// If DEVMODE is on, only allow this command to be used in the devServer // If DEVMODE is on, only allow this command to be used in the devServer
if (DEVMODE && message.guildID !== config.devServer) { if (DEVMODE && message.guildId !== config.devServer) {
utils.sendIndirectMessage(message, "Command is in development, please try again later.", sendMessage, sendDirectMessage).catch(e => { message.send("Command is in development, please try again later.").catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
return; return;
@ -376,9 +398,9 @@ startBot({
// Rest of this command is in a try-catch to protect all sends/edits from erroring out // Rest of this command is in a try-catch to protect all sends/edits from erroring out
try { try {
const originalCommand = config.prefix + command + " " + args.join(" "); const originalCommand = `${config.prefix}${command} ${args.join(" ")}`;
const m = await utils.sendIndirectMessage(message, "Rolling...", sendMessage, sendDirectMessage); const m = await message.send("Rolling...");
const modifiers = { const modifiers = {
noDetails: false, noDetails: false,
@ -392,7 +414,7 @@ startBot({
// Check if any of the args are command flags and pull those out into the modifiers object // Check if any of the args are command flags and pull those out into the modifiers object
for (let i = 0; i < args.length; i++) { for (let i = 0; i < args.length; i++) {
utils.log(LT.LOG, `Checking ${command + args.join(" ")} for command modifiers ${i}`); utils.log(LT.LOG, `Checking ${command}${args.join(" ")} for command modifiers ${i}`);
switch (args[i].toLowerCase()) { switch (args[i].toLowerCase()) {
case "-nd": case "-nd":
modifiers.noDetails = true; modifiers.noDetails = true;
@ -484,7 +506,7 @@ startBot({
} }
// Rejoin all of the args and send it into the solver, if solver returns a falsy item, an error object will be substituded in // Rejoin all of the args and send it into the solver, if solver returns a falsy item, an error object will be substituded in
const rollCmd = command + " " + args.join(" "); const rollCmd = `${command} ${args.join(" ")}`;
const returnmsg = solver.parseRoll(rollCmd, config.prefix, config.postfix, modifiers.maxRoll, modifiers.nominalRoll, modifiers.order) || { error: true, errorCode: "EmptyMessage", errorMsg: "Error: Empty message", line1: "", line2: "", line3: "" }; const returnmsg = solver.parseRoll(rollCmd, config.prefix, config.postfix, modifiers.maxRoll, modifiers.nominalRoll, modifiers.order) || { error: true, errorCode: "EmptyMessage", errorMsg: "Error: Empty message", line1: "", line2: "", line3: "" };
let returnText = ""; let returnText = "";
@ -503,19 +525,19 @@ startBot({
return; return;
} else { } else {
// Else format the output using details from the solver // Else format the output using details from the solver
returnText = "<@" + message.author.id + ">" + returnmsg.line1 + "\n" + returnmsg.line2; returnText = `<@${message.authorId}>${returnmsg.line1}\n${returnmsg.line2}`;
if (modifiers.noDetails) { if (modifiers.noDetails) {
returnText += "\nDetails suppressed by -nd flag."; returnText += "\nDetails suppressed by -nd flag.";
} else { } else {
returnText += "\nDetails:\n" + modifiers.spoiler + returnmsg.line3 + modifiers.spoiler; returnText += `\nDetails:\n${modifiers.spoiler}${returnmsg.line3}${modifiers.spoiler}`;
} }
} }
// If the roll was a GM roll, send DMs to all the GMs // If the roll was a GM roll, send DMs to all the GMs
if (modifiers.gmRoll) { if (modifiers.gmRoll) {
// Make a new return line to be sent to the roller // Make a new return line to be sent to the roller
const normalText = "<@" + message.author.id + ">" + returnmsg.line1 + "\nResults have been messaged to the following GMs: " + modifiers.gms.join(" "); const normalText = `<@${message.authorId}>${returnmsg.line1}\nResults have been messaged to the following GMs: ${modifiers.gms.join(" ")}`;
// And message the full details to each of the GMs, alerting roller of every GM that could not be messaged // And message the full details to each of the GMs, alerting roller of every GM that could not be messaged
modifiers.gms.forEach(async e => { modifiers.gms.forEach(async e => {
@ -525,19 +547,19 @@ startBot({
if (b.size > 8388290) { if (b.size > 8388290) {
// Update return text // Update return text
returnText = "<@" + message.author.id + ">" + returnmsg.line1 + "\n" + returnmsg.line2 + "\nFull details could not be attached to this messaged as a `.txt` file as the file would be too large for Discord to handle. If you would like to see the details of rolls, please send the rolls in multiple messages instead of bundled into one."; returnText = `<@${message.authorId}>${returnmsg.line1}\n${returnmsg.line2}\nFull details could not be attached to this messaged as a \`.txt\` file as the file would be too large for Discord to handle. If you would like to see the details of rolls, please send the rolls in multiple messages instead of bundled into one.`;
// Attempt to DM the GMs and send a warning if it could not DM a GM // Attempt to DM the GMs and send a warning if it could not DM a GM
await sendDirectMessage(e.substr(2, (e.length - 3)), returnText).catch(() => { await sendDirectMessage(BigInt(e.substr(2, (e.length - 3))), returnText).catch(() => {
utils.sendIndirectMessage(message, "WARNING: " + e + " could not be messaged. If this issue persists, make sure direct messages are allowed from this server.", sendMessage, sendDirectMessage); message.send(`WARNING: ${e} could not be messaged. If this issue persists, make sure direct messages are allowed from this server.`);
}); });
} else { } else {
// Update return text // Update return text
returnText = "<@" + message.author.id + ">" + returnmsg.line1 + "\n" + returnmsg.line2 + "\nFull details have been attached to this messaged as a `.txt` file for verification purposes."; returnText = `<@${message.authorId}>${returnmsg.line1}\n${returnmsg.line2}\nFull details have been attached to this messaged as a \`.txt\` file for verification purposes.`;
// Attempt to DM the GMs and send a warning if it could not DM a GM // Attempt to DM the GMs and send a warning if it could not DM a GM
await sendDirectMessage(e.substr(2, (e.length - 3)), { "content": returnText, "file": { "blob": b, "name": "rollDetails.txt" } }).catch(() => { await sendDirectMessage(BigInt(e.substr(2, (e.length - 3))), { "content": returnText, "file": { "blob": b, "name": "rollDetails.txt" } }).catch(() => {
utils.sendIndirectMessage(message, "WARNING: " + e + " could not be messaged. If this issue persists, make sure direct messages are allowed from this server.", sendMessage, sendDirectMessage); message.send(`WARNING: ${e} could not be messaged. If this issue persists, make sure direct messages are allowed from this server.`);
}); });
} }
}); });
@ -559,18 +581,18 @@ startBot({
if (b.size > 8388290) { if (b.size > 8388290) {
// Update return text // Update return text
returnText = "<@" + message.author.id + ">" + returnmsg.line1 + "\n" + returnmsg.line2 + "\nDetails have been ommitted from this message for being over 2000 characters. Full details could not be attached to this messaged as a `.txt` file as the file would be too large for Discord to handle. If you would like to see the details of rolls, please send the rolls in multiple messages instead of bundled into one."; returnText = `<@${message.authorId}>${returnmsg.line1}\n${returnmsg.line2}\nDetails have been ommitted from this message for being over 2000 characters. Full details could not be attached to this messaged as a \`.txt\` file as the file would be too large for Discord to handle. If you would like to see the details of rolls, please send the rolls in multiple messages instead of bundled into one.`;
// Send the results // Send the results
m.edit(returnText); m.edit(returnText);
} else { } else {
// Update return text // Update return text
returnText = "<@" + message.author.id + ">" + returnmsg.line1 + "\n" + returnmsg.line2 + "\nDetails have been ommitted from this message for being over 2000 characters. Full details have been attached to this messaged as a `.txt` file for verification purposes."; returnText = `<@${message.authorId}>${returnmsg.line1}\n${returnmsg.line2}\nDetails have been ommitted from this message for being over 2000 characters. Full details have been attached to this messaged as a \`.txt\` file for verification purposes.`;
// Remove the original message to send new one with attachment // Remove the original message to send new one with attachment
m.delete(); m.delete();
await utils.sendIndirectMessage(message, { "content": returnText, "file": { "blob": b, "name": "rollDetails.txt" } }, sendMessage, sendDirectMessage); await message.send({ "content": returnText, "file": { "blob": b, "name": "rollDetails.txt" } });
} }
} else { } else {
// Finally send the text // Finally send the text
@ -594,16 +616,16 @@ startBot({
else { else {
// Start looping thru the possible emojis // Start looping thru the possible emojis
config.emojis.some((emoji: EmojiConf) => { config.emojis.some((emoji: EmojiConf) => {
utils.log(LT.LOG, `Checking if command was emoji ${emoji}`); utils.log(LT.LOG, `Checking if command was emoji ${JSON.stringify(emoji)}`);
// If a match gets found // If a match gets found
if (emoji.aliases.indexOf(command || "") > -1) { if (emoji.aliases.indexOf(command || "") > -1) {
// Light telemetry to see how many times a command is being run // Light telemetry to see how many times a command is being run
dbClient.execute(`CALL INC_CNT("emoji");`).catch(e => { dbClient.execute(`CALL INC_CNT("emojis");`).catch(e => {
utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${JSON.stringify(e)}`);
}); });
// Send the needed emoji1 // Send the needed emoji1
utils.sendIndirectMessage(message, `<${emoji.animated ? "a" : ""}:${emoji.name}:${emoji.id}>`, sendMessage, sendDirectMessage).catch(e => { message.send(`<${emoji.animated ? "a" : ""}:${emoji.name}:${emoji.id}>`).catch(e => {
utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`); utils.log(LT.ERROR, `Failed to send message: ${JSON.stringify(message)} | ${JSON.stringify(e)}`);
}); });
// And attempt to delete if needed // And attempt to delete if needed
@ -622,10 +644,10 @@ startBot({
// Start up the command prompt for debug usage // Start up the command prompt for debug usage
if (DEBUG) { if (DEBUG) {
utils.cmdPrompt(config.logChannel, config.name, sendMessage); utils.cmdPrompt(config.logChannel, config.name);
} }
// Start up the API for rolling from third party apps (like excel macros) // Start up the API for rolling from third party apps (like excel macros)
if (config.api.enable) { if (config.api.enable) {
api.start(dbClient, cache, sendMessage, sendDirectMessage); api.start(dbClient);
} }

1352
src/api.ts

File diff suppressed because it is too large Load Diff

View File

@ -6,16 +6,16 @@
import { import {
// Discordeno deps // Discordeno deps
CacheData cache, cacheHandlers
} from "../deps.ts"; } from "../deps.ts";
import { LogTypes as LT } from "./utils.enums.ts"; import { LogTypes as LT } from "./utils.enums.ts";
import utils from "./utils.ts"; import utils from "./utils.ts";
import config from "../config.ts"; import config from "../config.ts";
// getRandomStatus(bot cache) returns status as string // getRandomStatus() returns status as string
// Gets a new random status for the bot // Gets a new random status for the bot
const getRandomStatus = (cache: CacheData): string => { const getRandomStatus = async (): Promise<string> => {
let status = ""; let status = "";
switch (Math.floor((Math.random() * 4) + 1)) { switch (Math.floor((Math.random() * 4) + 1)) {
case 1: case 1:
@ -27,9 +27,11 @@ const getRandomStatus = (cache: CacheData): string => {
case 3: case 3:
status = `${config.prefix}info to learn more`; status = `${config.prefix}info to learn more`;
break; break;
default: default: {
status = `Rolling dice for ${cache.guilds.size} servers`; const cachedCount = await cacheHandlers.size("guilds")
status = `Rolling dice for ${cachedCount + cache.dispatchedGuildIds.size} servers`;
break; break;
}
} }
return status; return status;
@ -37,7 +39,7 @@ const getRandomStatus = (cache: CacheData): string => {
// updateListStatistics(bot ID, current guild count) returns nothing // updateListStatistics(bot ID, current guild count) returns nothing
// Sends the current server count to all bot list sites we are listed on // Sends the current server count to all bot list sites we are listed on
const updateListStatistics = (botID: string, serverCount: number): void => { const updateListStatistics = (botID: bigint, serverCount: number): void => {
config.botLists.forEach(async e => { config.botLists.forEach(async e => {
utils.log(LT.LOG, `Updating statistics for ${JSON.stringify(e)}`) utils.log(LT.LOG, `Updating statistics for ${JSON.stringify(e)}`)
if (e.enabled) { if (e.enabled) {
@ -45,7 +47,7 @@ const updateListStatistics = (botID: string, serverCount: number): void => {
tempHeaders.append(e.headers[0].header, e.headers[0].value); tempHeaders.append(e.headers[0].header, e.headers[0].value);
tempHeaders.append("Content-Type", "application/json"); tempHeaders.append("Content-Type", "application/json");
// ?{} is a template used in config, just need to replace it with the real value // ?{} is a template used in config, just need to replace it with the real value
const response = await fetch(e.apiUrl.replace("?{bot_id}", botID), { const response = await fetch(e.apiUrl.replace("?{bot_id}", botID.toString()), {
"method": 'POST', "method": 'POST',
"headers": tempHeaders, "headers": tempHeaders,
"body": JSON.stringify(e.body).replace('"?{server_count}"', serverCount.toString()) // ?{server_count} needs the "" removed from around it aswell to make sure its sent as a number "body": JSON.stringify(e.body).replace('"?{server_count}"', serverCount.toString()) // ?{server_count} needs the "" removed from around it aswell to make sure its sent as a number

View File

@ -64,7 +64,7 @@ const escapeCharacters = (str: string, esc: string): string => {
utils.log(LT.LOG, `Escaping character ${esc[i]} | ${str}, ${esc}`); utils.log(LT.LOG, `Escaping character ${esc[i]} | ${str}, ${esc}`);
// Create a new regex to look for that char that needs replaced and escape it // Create a new regex to look for that char that needs replaced and escape it
const temprgx = new RegExp(`[${esc[i]}]`, "g"); const temprgx = new RegExp(`[${esc[i]}]`, "g");
str = str.replace(temprgx, ("\\" + esc[i])); str = str.replace(temprgx, `\\${esc[i]}`);
} }
return str; return str;
}; };
@ -158,7 +158,7 @@ const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolean): Rol
if (remains.length > 0) { if (remains.length > 0) {
// Determine if the first item is a drop, and if it is, add the d back in // Determine if the first item is a drop, and if it is, add the d back in
if (remains.search(/\D/) !== 0 || remains.indexOf("l") === 0 || remains.indexOf("h") === 0) { if (remains.search(/\D/) !== 0 || remains.indexOf("l") === 0 || remains.indexOf("h") === 0) {
remains = "d" + remains; remains = `d${remains}`;
} }
// Loop until all remaining args are parsed // Loop until all remaining args are parsed
@ -260,7 +260,7 @@ const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolean): Rol
break; break;
default: default:
// Throw error immediately if unknown op is encountered // Throw error immediately if unknown op is encountered
throw new Error("UnknownOperation_" + tSep); throw new Error(`UnknownOperation_${tSep}`);
} }
// Finally slice off everything else parsed this loop // Finally slice off everything else parsed this loop
remains = remains.slice(afterNumIdx); remains = remains.slice(afterNumIdx);
@ -538,22 +538,22 @@ const formatRoll = (rollConf: string, maximiseRoll: boolean, nominalRoll: boolea
// If the roll was a crit hit or fail, or dropped/rerolled, add the formatting needed // If the roll was a crit hit or fail, or dropped/rerolled, add the formatting needed
if (e.critHit) { if (e.critHit) {
// Bold for crit success // Bold for crit success
preFormat = "**" + preFormat; preFormat = `**${preFormat}`;
postFormat = postFormat + "**"; postFormat = `${postFormat}**`;
} }
if (e.critFail) { if (e.critFail) {
// Underline for crit fail // Underline for crit fail
preFormat = "__" + preFormat; preFormat = `__${preFormat}`;
postFormat = postFormat + "__"; postFormat = `${postFormat}__`;
} }
if (e.dropped || e.rerolled) { if (e.dropped || e.rerolled) {
// Strikethrough for dropped/rerolled rolls // Strikethrough for dropped/rerolled rolls
preFormat = "~~" + preFormat; preFormat = `~~${preFormat}`;
postFormat = postFormat + "~~"; postFormat = `${postFormat}~~`;
} }
// Finally add this to the roll's details // Finally add this to the roll's details
tempDetails += preFormat + e.roll + postFormat + " + "; tempDetails += `${preFormat}${e.roll}${postFormat} + `;
}); });
// After the looping is done, remove the extra " + " from the details and cap it with the closing ] // After the looping is done, remove the extra " + " from the details and cap it with the closing ]
tempDetails = tempDetails.substr(0, (tempDetails.length - 3)); tempDetails = tempDetails.substr(0, (tempDetails.length - 3));
@ -660,13 +660,13 @@ const fullSolver = (conf: (string | number | SolvedStep)[], wrapDetails: boolean
// If operand1 is a SolvedStep, populate our subStepSolve with its details and crit/fail flags // If operand1 is a SolvedStep, populate our subStepSolve with its details and crit/fail flags
if (typeof operand1 === "object") { if (typeof operand1 === "object") {
oper1 = operand1.total; oper1 = operand1.total;
subStepSolve.details = operand1.details + "\\" + conf[i]; subStepSolve.details = `${operand1.details}\\${conf[i]}`;
subStepSolve.containsCrit = operand1.containsCrit; subStepSolve.containsCrit = operand1.containsCrit;
subStepSolve.containsFail = operand1.containsFail; subStepSolve.containsFail = operand1.containsFail;
} else { } else {
// else parse it as a number and add it to the subStep details // else parse it as a number and add it to the subStep details
oper1 = parseFloat(operand1.toString()); oper1 = parseFloat(operand1.toString());
subStepSolve.details = oper1.toString() + "\\" + conf[i]; subStepSolve.details = `${oper1.toString()}\\${conf[i]}`;
} }
// If operand2 is a SolvedStep, populate our subStepSolve with its details without overriding what operand1 filled in // If operand2 is a SolvedStep, populate our subStepSolve with its details without overriding what operand1 filled in
@ -740,7 +740,7 @@ const fullSolver = (conf: (string | number | SolvedStep)[], wrapDetails: boolean
// If this was a nested call, add on parens around the details to show what math we've done // If this was a nested call, add on parens around the details to show what math we've done
if (wrapDetails) { if (wrapDetails) {
stepSolve.details = "(" + stepSolve.details + ")"; stepSolve.details = `(${stepSolve.details})`;
} }
// If our total has reached undefined for some reason, error out now // If our total has reached undefined for some reason, error out now
@ -899,25 +899,25 @@ const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: string, m
// If the roll containted a crit success or fail, set the formatting around it // If the roll containted a crit success or fail, set the formatting around it
if (e.containsCrit) { if (e.containsCrit) {
preFormat = "**" + preFormat; preFormat = `**${preFormat}`;
postFormat = postFormat + "**"; postFormat = `${postFormat}**`;
} }
if (e.containsFail) { if (e.containsFail) {
preFormat = "__" + preFormat; preFormat = `__${preFormat}`;
postFormat = postFormat + "__"; postFormat = `${postFormat}__`;
} }
// Populate line2 (the results) and line3 (the details) with their data // Populate line2 (the results) and line3 (the details) with their data
if (order === "") { if (order === "") {
line2 += preFormat + e.rollTotal + postFormat + escapeCharacters(e.rollPostFormat, "|*_~`"); line2 += `${preFormat}${e.rollTotal}${postFormat}${escapeCharacters(e.rollPostFormat, "|*_~`")}`;
} else { } else {
// If order is on, turn rolls into csv without formatting // If order is on, turn rolls into csv without formatting
line2 += preFormat + e.rollTotal + postFormat + ", "; line2 += `${preFormat}${e.rollTotal}${postFormat}, `;
} }
line2 = line2.replace(/\*\*\*\*/g, "** **").replace(/____/g, "__ __").replace(/~~~~/g, "~~ ~~"); line2 = line2.replace(/\*\*\*\*/g, "** **").replace(/____/g, "__ __").replace(/~~~~/g, "~~ ~~");
line3 += "`" + e.initConfig + "` = " + e.rollDetails + " = " + preFormat + e.rollTotal + postFormat + "\n"; line3 += `\`${e.initConfig}\` = ${e.rollDetails} = ${preFormat}${e.rollTotal}${postFormat}\n`;
}); });
// If order is on, remove trailing ", " // If order is on, remove trailing ", "
@ -950,11 +950,11 @@ const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: string, m
errorMsg = "Formatting Error: CritScore range specified without a maximum, remove - or add maximum to correct"; errorMsg = "Formatting Error: CritScore range specified without a maximum, remove - or add maximum to correct";
break; break;
case "UnknownOperation": case "UnknownOperation":
errorMsg = "Error: Unknown Operation " + errorDetails; errorMsg = `Error: Unknown Operation ${errorDetails}`;
if (errorDetails === "-") { if (errorDetails === "-") {
errorMsg += "\nNote: Negative numbers are not supported"; errorMsg += "\nNote: Negative numbers are not supported";
} else if (errorDetails === " ") { } else if (errorDetails === " ") {
errorMsg += "\nNote: Every roll must be closed by " + localPostfix; errorMsg += `\nNote: Every roll must be closed by ${localPostfix}`;
} }
break; break;
case "NoZerosAllowed": case "NoZerosAllowed":
@ -982,7 +982,7 @@ const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: string, m
errorMsg += "Crit Score (cs)"; errorMsg += "Crit Score (cs)";
break; break;
default: default:
errorMsg += "Unhandled - " + errorDetails; errorMsg += `Unhandled - ${errorDetails}`;
break; break;
} }
errorMsg += " cannot be zero"; errorMsg += " cannot be zero";
@ -1013,7 +1013,7 @@ const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: string, m
break; break;
default: default:
utils.log(LT.ERROR, `Undangled Error: ${errorName}, ${errorDetails}`); utils.log(LT.ERROR, `Undangled Error: ${errorName}, ${errorDetails}`);
errorMsg = "Unhandled Error: " + solverError.message + "\nCheck input and try again, if issue persists, please use `[[report` to alert the devs of the issue"; errorMsg = `Unhandled Error: ${solverError.message}\nCheck input and try again, if issue persists, please use \`[[report\` to alert the devs of the issue`;
break; break;
} }

View File

@ -6,7 +6,7 @@
import { import {
// Discordeno deps // Discordeno deps
Message, MessageContent, sendMessage,
// nanoid deps // nanoid deps
nanoid nanoid
@ -35,9 +35,9 @@ const ask = async (question: string, stdin = Deno.stdin, stdout = Deno.stdout):
return answer.trim(); return answer.trim();
}; };
// cmdPrompt(logChannel, botName, sendMessage) returns nothing // cmdPrompt(logChannel, botName) returns nothing
// cmdPrompt creates an interactive CLI for the bot, commands can vary // cmdPrompt creates an interactive CLI for the bot, commands can vary
const cmdPrompt = async (logChannel: string, botName: string, sendMessage: (c: string, m: string) => Promise<Message>): Promise<void> => { const cmdPrompt = async (logChannel: bigint, botName: string): Promise<void> => {
let done = false; let done = false;
while (!done) { while (!done) {
@ -69,10 +69,10 @@ const cmdPrompt = async (logChannel: string, botName: string, sendMessage: (c: s
// Sends [message] to specified [channel] // Sends [message] to specified [channel]
else if (command === "m") { else if (command === "m") {
try { try {
const channelID = args.shift() || ""; const channelId = args.shift() || "";
const message = args.join(" "); const message = args.join(" ");
sendMessage(channelID, message).catch(reason => { sendMessage(BigInt(channelId), message).catch(reason => {
console.error(reason); console.error(reason);
}); });
} }
@ -104,18 +104,6 @@ const cmdPrompt = async (logChannel: string, botName: string, sendMessage: (c: s
} }
}; };
// sendIndirectMessage(originalMessage, messageContent, sendMessage, sendDirectMessage) returns Message
// sendIndirectMessage determines if the message needs to be sent as a direct message or as a normal message
const sendIndirectMessage = async (originalMessage: Message, messageContent: (string | MessageContent), sendMessage: (c: string, m: (string | MessageContent)) => Promise<Message>, sendDirectMessage: (c: string, m: (string | MessageContent)) => Promise<Message>): Promise<Message> => {
if (originalMessage.guildID === "") {
// guildID was empty, meaning the original message was sent as a DM
return await sendDirectMessage(originalMessage.author.id, messageContent);
} else {
// guildID was not empty, meaning the original message was sent in a server
return await sendMessage(originalMessage.channelID, messageContent);
}
};
// initLog() returns nothing // initLog() returns nothing
// Handles ensuring the required directory structure is created // Handles ensuring the required directory structure is created
const initLog = (name: string): void => { const initLog = (name: string): void => {
@ -161,4 +149,4 @@ const log = async (level: LogTypes, message: string, error = new Error()): Promi
} }
}; };
export default { cmdPrompt, sendIndirectMessage, initLog, log }; export default { cmdPrompt, initLog, log };

1
start.command Normal file
View File

@ -0,0 +1 @@
deno run --allow-write=./logs --allow-net .\mod.ts