update db structure to let init work correctly

This commit is contained in:
Ean Milligan 2025-04-26 13:22:45 -04:00
parent ef08cd779a
commit 76e007e2e4
44 changed files with 2543 additions and 2280 deletions

View File

@ -2,10 +2,11 @@
// DATA WILL BE LOST IF DB ALREADY EXISTS, RUN AT OWN RISK // DATA WILL BE LOST IF DB ALREADY EXISTS, RUN AT OWN RISK
import config from '../config.ts'; import config from '../config.ts';
import { dbClient } from '../src/db.ts'; import dbClient from '../src/db/client.ts';
console.log('Attempting to create DB'); console.log('Attempting to create DB');
await dbClient.execute(`CREATE SCHEMA IF NOT EXISTS ${config.db.name};`); await dbClient.execute(`CREATE SCHEMA IF NOT EXISTS ${config.db.name};`);
console.log('test');
await dbClient.execute(`USE ${config.db.name}`); await dbClient.execute(`USE ${config.db.name}`);
console.log('DB created'); console.log('DB created');

View File

@ -1,7 +1,7 @@
// This file will populate the tables with default values // This file will populate the tables with default values
import config from '../config.ts'; import config from '../config.ts';
import { dbClient } from '../src/db.ts'; import dbClient from '../src/db/client.ts';
console.log('Attempting to populate DB Admin API key'); console.log('Attempting to populate DB Admin API key');
await dbClient.execute('INSERT INTO all_keys(userid,apiKey) values(?,?)', [config.api.admin, config.api.adminKey]).catch((e) => { await dbClient.execute('INSERT INTO all_keys(userid,apiKey) values(?,?)', [config.api.admin, config.api.adminKey]).catch((e) => {
@ -10,7 +10,26 @@ await dbClient.execute('INSERT INTO all_keys(userid,apiKey) values(?,?)', [confi
console.log('Inesrtion done'); console.log('Inesrtion done');
console.log('Attempting to insert default commands into command_cnt'); console.log('Attempting to insert default commands into command_cnt');
const commands = ['ping', 'rip', 'rollhelp', 'help', 'info', 'version', 'report', 'stats', 'roll', 'emojis', 'api', 'privacy', 'mention', 'audit', 'heatmap', 'rollDecorators', 'opt-out', 'opt-in']; const commands = [
'ping',
'rip',
'rollhelp',
'help',
'info',
'version',
'report',
'stats',
'roll',
'emojis',
'api',
'privacy',
'mention',
'audit',
'heatmap',
'rollDecorators',
'opt-out',
'opt-in',
];
for (const command of commands) { for (const command of commands) {
await dbClient.execute('INSERT INTO command_cnt(command) values(?)', [command]).catch((e) => { await dbClient.execute('INSERT INTO command_cnt(command) values(?)', [command]).catch((e) => {
console.log(`Failed to insert ${command} into database`, e); console.log(`Failed to insert ${command} into database`, e);

54
mod.ts
View File

@ -25,7 +25,8 @@ import {
startBot, startBot,
} from './deps.ts'; } from './deps.ts';
import api from './src/api.ts'; import api from './src/api.ts';
import { dbClient, ignoreList } from './src/db.ts'; import dbClient from './src/db/client.ts';
import { ignoreList } from './src/db/common.ts';
import commands from './src/commands/_index.ts'; import commands from './src/commands/_index.ts';
import intervals from './src/intervals.ts'; import intervals from './src/intervals.ts';
import { successColor, warnColor } from './src/commandUtils.ts'; import { successColor, warnColor } from './src/commandUtils.ts';
@ -42,11 +43,13 @@ startBot({
ready: () => { ready: () => {
log(LT.INFO, `${config.name} Logged in!`); log(LT.INFO, `${config.name} Logged in!`);
editBotStatus({ editBotStatus({
activities: [{ activities: [
{
name: 'Booting up . . .', name: 'Booting up . . .',
type: DiscordActivityTypes.Game, type: DiscordActivityTypes.Game,
createdAt: new Date().getTime(), createdAt: new Date().getTime(),
}], },
],
status: 'online', status: 'online',
}); });
@ -56,11 +59,13 @@ startBot({
try { try {
// Wrapped in try-catch due to hard crash possible // Wrapped in try-catch due to hard crash possible
editBotStatus({ editBotStatus({
activities: [{ activities: [
{
name: await intervals.getRandomStatus(), name: await intervals.getRandomStatus(),
type: DiscordActivityTypes.Game, type: DiscordActivityTypes.Game,
createdAt: new Date().getTime(), createdAt: new Date().getTime(),
}], },
],
status: 'online', status: 'online',
}); });
} catch (e) { } catch (e) {
@ -69,7 +74,9 @@ startBot({
}, 30000); }, 30000);
// Interval to update bot list stats every 24 hours // Interval to update bot list stats every 24 hours
LOCALMODE ? log(LT.INFO, 'updateListStatistics not running') : setInterval(() => { LOCALMODE
? log(LT.INFO, 'updateListStatistics not running')
: setInterval(() => {
log(LT.LOG, 'Updating all bot lists statistics'); log(LT.LOG, 'Updating all bot lists statistics');
intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size); intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size);
}, 86400000); }, 86400000);
@ -93,15 +100,18 @@ startBot({
intervals.updateHourlyRates(); intervals.updateHourlyRates();
intervals.updateHeatmapPng(); intervals.updateHeatmapPng();
editBotStatus({ editBotStatus({
activities: [{ activities: [
{
name: 'Booting Complete', name: 'Booting Complete',
type: DiscordActivityTypes.Game, type: DiscordActivityTypes.Game,
createdAt: new Date().getTime(), createdAt: new Date().getTime(),
}], },
],
status: 'online', status: 'online',
}); });
sendMessage(config.logChannel, { sendMessage(config.logChannel, {
embeds: [{ embeds: [
{
title: `${config.name} is now Online`, title: `${config.name} is now Online`,
color: successColor, color: successColor,
fields: [ fields: [
@ -111,14 +121,16 @@ startBot({
inline: true, inline: true,
}, },
], ],
}], },
],
}).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:88', 'Startup', e)); }).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:88', 'Startup', e));
}, 1000); }, 1000);
}, },
guildCreate: (guild: DiscordenoGuild) => { guildCreate: (guild: DiscordenoGuild) => {
log(LT.LOG, `Handling joining guild ${JSON.stringify(guild)}`); log(LT.LOG, `Handling joining guild ${JSON.stringify(guild)}`);
sendMessage(config.logChannel, { sendMessage(config.logChannel, {
embeds: [{ embeds: [
{
title: 'New Guild Joined!', title: 'New Guild Joined!',
color: successColor, color: successColor,
fields: [ fields: [
@ -138,13 +150,15 @@ startBot({
inline: true, inline: true,
}, },
], ],
}], },
],
}).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:95', 'Join Guild', e)); }).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:95', 'Join Guild', e));
}, },
guildDelete: (guild: DiscordenoGuild) => { guildDelete: (guild: DiscordenoGuild) => {
log(LT.LOG, `Handling leaving guild ${JSON.stringify(guild)}`); log(LT.LOG, `Handling leaving guild ${JSON.stringify(guild)}`);
sendMessage(config.logChannel, { sendMessage(config.logChannel, {
embeds: [{ embeds: [
{
title: 'Removed from Guild', title: 'Removed from Guild',
color: warnColor, color: warnColor,
fields: [ fields: [
@ -164,9 +178,12 @@ startBot({
inline: true, inline: true,
}, },
], ],
}], },
],
}).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:99', 'Leave Guild', e)); }).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:99', 'Leave Guild', e));
dbClient.execute('DELETE FROM allowed_guilds WHERE guildid = ? AND banned = 0', [guild.id]).catch((e) => utils.commonLoggers.dbError('mod.ts:100', 'delete from', e)); dbClient
.execute('DELETE FROM allowed_guilds WHERE guildid = ? AND banned = 0', [guild.id])
.catch((e) => utils.commonLoggers.dbError('mod.ts:100', 'delete from', e));
}, },
debug: DEVMODE ? (dmsg) => log(LT.LOG, `Debug Message | ${JSON.stringify(dmsg)}`) : undefined, debug: DEVMODE ? (dmsg) => log(LT.LOG, `Debug Message | ${JSON.stringify(dmsg)}`) : undefined,
messageCreate: (message: DiscordenoMessage) => { messageCreate: (message: DiscordenoMessage) => {
@ -190,7 +207,10 @@ startBot({
log(LT.LOG, `Handling ${config.prefix}command message: ${JSON.stringify(message)}`); log(LT.LOG, `Handling ${config.prefix}command message: ${JSON.stringify(message)}`);
// Split into standard command + args format // Split into standard command + args format
const args = message.content.slice(config.prefix.length).trim().split(/[ \n]+/g); const args = message.content
.slice(config.prefix.length)
.trim()
.split(/[ \n]+/g);
const command = args.shift()?.toLowerCase(); const command = args.shift()?.toLowerCase();
// All commands below here // All commands below here
@ -292,7 +312,7 @@ startBot({
// [[xdydz (aka someone copy pasted the template as a roll) // [[xdydz (aka someone copy pasted the template as a roll)
// Help command specifically for the roll command // Help command specifically for the roll command
commands.rollHelp(message); commands.rollHelp(message);
} else if (command && (`${command}${args.join('')}`).indexOf(config.postfix) > -1) { } else if (command && `${command}${args.join('')}`.indexOf(config.postfix) > -1) {
// [[roll]] // [[roll]]
// Dice rolling commence! // Dice rolling commence!
commands.roll(message, args, command); commands.roll(message, args, command);

View File

@ -10,7 +10,7 @@ import {
log, log,
LT, LT,
} from '../deps.ts'; } from '../deps.ts';
import { dbClient } from './db.ts'; import dbClient from './db/client.ts';
import endpoints from './endpoints/_index.ts'; import endpoints from './endpoints/_index.ts';
import stdResp from './endpoints/stdResponses.ts'; import stdResp from './endpoints/stdResponses.ts';
@ -44,7 +44,9 @@ const start = async (): Promise<void> => {
// Check the requests API key // Check the requests API key
if (request.headers.has('X-Api-Key')) { if (request.headers.has('X-Api-Key')) {
// Get the userid and flags for the specific key // Get the userid and flags for the specific key
const dbApiQuery = await dbClient.query('SELECT userid, email, deleteCode FROM all_keys WHERE apiKey = ? AND active = 1 AND banned = 0', [request.headers.get('X-Api-Key')]); const dbApiQuery = await dbClient.query('SELECT userid, email, deleteCode FROM all_keys WHERE apiKey = ? AND active = 1 AND banned = 0', [
request.headers.get('X-Api-Key'),
]);
// If only one user returned, is not banned, and is currently active, mark as authenticated // If only one user returned, is not banned, and is currently active, mark as authenticated
if (dbApiQuery.length === 1) { if (dbApiQuery.length === 1) {
@ -58,7 +60,7 @@ const start = async (): Promise<void> => {
const apiTimeNow = new Date().getTime(); const apiTimeNow = new Date().getTime();
// Check if user has sent a request recently // Check if user has sent a request recently
if (rateLimitTime.has(apiUseridStr) && (((rateLimitTime.get(apiUseridStr) || 0) + config.api.rateLimitTime) > apiTimeNow)) { if (rateLimitTime.has(apiUseridStr) && (rateLimitTime.get(apiUseridStr) || 0) + config.api.rateLimitTime > apiTimeNow) {
// Get current count // Get current count
const currentCnt = rateLimitCnt.get(apiUseridStr) || 0; const currentCnt = rateLimitCnt.get(apiUseridStr) || 0;
if (currentCnt < config.api.rateLimitCnt) { if (currentCnt < config.api.rateLimitCnt) {

View File

@ -1,4 +1,5 @@
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -17,12 +18,16 @@ export const api = async (message: DiscordenoMessage, args: string[]) => {
// 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 === 0n) { if (message.guildId === 0n) {
message.send({ message
embeds: [{ .send({
embeds: [
{
color: failColor, color: failColor,
title: 'API commands are only available in guilds.', title: 'API commands are only available in guilds.',
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('apiCmd.ts:30', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('apiCmd.ts:30', message, e));
return; return;
} }
@ -63,12 +68,17 @@ export const api = async (message: DiscordenoMessage, args: string[]) => {
break; break;
} }
} else { } else {
message.send({ message
embeds: [{ .send({
embeds: [
{
color: failColor, color: failColor,
title: 'API commands are powerful and can only be used by guild Owners and Admins.', title: 'API commands are powerful and can only be used by guild Owners and Admins.',
description: 'For information on how to use the API, please check the GitHub README for more information [here](https://github.com/Burn-E99/TheArtificer).', description:
}], 'For information on how to use the API, please check the GitHub README for more information [here](https://github.com/Burn-E99/TheArtificer).',
}).catch((e: Error) => utils.commonLoggers.messageSendError('apiCmd.ts:77', message, e)); },
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('apiCmd.ts:77', message, e));
} }
}; };

View File

@ -1,4 +1,4 @@
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -8,7 +8,9 @@ import utils from '../../utils.ts';
export const allowBlock = async (message: DiscordenoMessage, apiArg: string) => { export const allowBlock = async (message: DiscordenoMessage, apiArg: string) => {
let errorOutInitial = false; let errorOutInitial = false;
const guildQuery = await dbClient.query(`SELECT guildid, channelid FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => { const guildQuery = await dbClient
.query(`SELECT guildid, channelid FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId])
.catch((e0) => {
utils.commonLoggers.dbError('allowBlock.ts:15', 'query', e0); utils.commonLoggers.dbError('allowBlock.ts:15', 'query', e0);
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:16', message, e)); message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:16', message, e));
errorOutInitial = true; errorOutInitial = true;
@ -18,22 +20,30 @@ export const allowBlock = async (message: DiscordenoMessage, apiArg: string) =>
let errorOut = false; let errorOut = false;
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,channelid,active) values(?,?,?)`, [message.guildId, message.channelId, (apiArg === 'allow' || apiArg === 'enable') ? 1 : 0]).catch( await dbClient
(e0) => { .execute(`INSERT INTO allowed_guilds(guildid,channelid,active) values(?,?,?)`, [
message.guildId,
message.channelId,
apiArg === 'allow' || apiArg === 'enable' ? 1 : 0,
])
.catch((e0) => {
utils.commonLoggers.dbError('allowBlock:26', 'insert into', e0); utils.commonLoggers.dbError('allowBlock:26', 'insert into', e0);
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:27', message, e)); message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:27', message, e));
errorOut = true; errorOut = true;
}, });
);
} 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 = ? AND channelid = ?`, [(apiArg === 'allow' || apiArg === 'enable') ? 1 : 0, message.guildId, message.channelId]).catch( await dbClient
(e0) => { .execute(`UPDATE allowed_guilds SET active = ? WHERE guildid = ? AND channelid = ?`, [
apiArg === 'allow' || apiArg === 'enable' ? 1 : 0,
message.guildId,
message.channelId,
])
.catch((e0) => {
utils.commonLoggers.dbError('allowBlock.ts:35', 'update', e0); utils.commonLoggers.dbError('allowBlock.ts:35', 'update', e0);
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:36', message, e)); message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:36', message, e));
errorOut = true; errorOut = true;
}, });
);
} }
if (errorOut) return; if (errorOut) return;

View File

@ -1,4 +1,4 @@
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -10,22 +10,30 @@ export const deleteGuild = async (message: DiscordenoMessage) => {
let errorOut = false; let errorOut = false;
await dbClient.execute(`DELETE FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => { await dbClient.execute(`DELETE FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => {
utils.commonLoggers.dbError('deleteGuild.ts:15', 'query', e0); utils.commonLoggers.dbError('deleteGuild.ts:15', 'query', e0);
message.send({ message
embeds: [{ .send({
embeds: [
{
color: failColor, color: failColor,
title: 'Failed to delete this guild from the database.', title: 'Failed to delete this guild from the database.',
description: 'If this issue persists, please report this to the developers.', description: 'If this issue persists, please report this to the developers.',
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('deleteGuild.ts:22', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('deleteGuild.ts:22', message, e));
errorOut = true; errorOut = true;
}); });
if (errorOut) return; if (errorOut) 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
message.send({ message
embeds: [{ .send({
embeds: [
{
color: successColor, color: successColor,
title: 'This guild\'s API setting has been removed from The Artifier\'s Database.', title: "This guild's API setting has been removed from The Artifier's Database.",
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('deleteGuild.ts:33', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('deleteGuild.ts:33', message, e));
}; };

View File

@ -1,4 +1,4 @@
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -8,7 +8,9 @@ import utils from '../../utils.ts';
export const showHideWarn = async (message: DiscordenoMessage, apiArg: string) => { export const showHideWarn = async (message: DiscordenoMessage, apiArg: string) => {
let errorOutInitial = false; let errorOutInitial = false;
const guildQuery = await dbClient.query(`SELECT guildid, channelid FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => { const guildQuery = await dbClient
.query(`SELECT guildid, channelid FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId])
.catch((e0) => {
utils.commonLoggers.dbError('showHideWarn.ts:15', 'query', e0); utils.commonLoggers.dbError('showHideWarn.ts:15', 'query', e0);
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:16', message, e)); message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:16', message, e));
errorOutInitial = true; errorOutInitial = true;
@ -18,14 +20,22 @@ export const showHideWarn = async (message: DiscordenoMessage, apiArg: string) =
let errorOut = false; let errorOut = false;
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,channelid,hidewarn) values(?,?,?)`, [message.guildId, message.channelId, (apiArg === 'hide-warn') ? 1 : 0]).catch((e0) => { await dbClient
.execute(`INSERT INTO allowed_guilds(guildid,channelid,hidewarn) values(?,?,?)`, [message.guildId, message.channelId, apiArg === 'hide-warn' ? 1 : 0])
.catch((e0) => {
utils.commonLoggers.dbError('showHideWarn.ts:25', 'insert inot', e0); utils.commonLoggers.dbError('showHideWarn.ts:25', 'insert inot', e0);
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:26', message, e)); message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:26', message, e));
errorOut = true; errorOut = true;
}); });
} 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 hidewarn = ? WHERE guildid = ? AND channelid = ?`, [(apiArg === 'hide-warn') ? 1 : 0, message.guildId, message.channelId]).catch((e0) => { await dbClient
.execute(`UPDATE allowed_guilds SET hidewarn = ? WHERE guildid = ? AND channelid = ?`, [
apiArg === 'hide-warn' ? 1 : 0,
message.guildId,
message.channelId,
])
.catch((e0) => {
utils.commonLoggers.dbError('showHideWarn.ts:32', 'update', e0); utils.commonLoggers.dbError('showHideWarn.ts:32', 'update', e0);
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:33', message, e)); message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:33', message, e));
errorOut = true; errorOut = true;

View File

@ -1,4 +1,4 @@
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -9,15 +9,21 @@ import utils from '../../utils.ts';
export const status = async (message: DiscordenoMessage) => { export const status = async (message: DiscordenoMessage) => {
// Get status of guild from the db // Get status of guild from the db
let errorOut = false; let errorOut = false;
const guildQuery = await dbClient.query(`SELECT active, banned FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => { const guildQuery = await dbClient
.query(`SELECT active, banned FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId])
.catch((e0) => {
utils.commonLoggers.dbError('status.ts:16', 'query', e0); utils.commonLoggers.dbError('status.ts:16', 'query', e0);
message.send({ message
embeds: [{ .send({
embeds: [
{
color: failColor, color: failColor,
title: 'Failed to check API rolls status for this guild.', title: 'Failed to check API rolls status for this guild.',
description: 'If this issue persists, please report this to the developers.', description: 'If this issue persists, please report this to the developers.',
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('status.ts:23', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('status.ts:23', message, e));
errorOut = true; errorOut = true;
}); });
if (errorOut) return; if (errorOut) return;

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -38,11 +39,15 @@ export const audit = async (message: DiscordenoMessage, args: string[]) => {
break; break;
} }
} else { } else {
message.send({ message
embeds: [{ .send({
embeds: [
{
color: failColor, color: failColor,
title: `Audit commands are powerful and can only be used by ${config.name}'s owner.`, title: `Audit commands are powerful and can only be used by ${config.name}'s owner.`,
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('audit.ts:51', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('audit.ts:51', message, e));
} }
}; };

View File

@ -1,4 +1,4 @@
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -28,13 +28,15 @@ export const auditDB = async (message: DiscordenoMessage) => {
// Send the results // Send the results
m.edit({ m.edit({
embeds: [{ embeds: [
{
color: infoColor2, color: infoColor2,
title: 'Database Audit', title: 'Database Audit',
description: 'Lists all tables with their current size and row count.', description: 'Lists all tables with their current size and row count.',
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
fields: embedFields, fields: embedFields,
}], },
],
}).catch((e: Error) => utils.commonLoggers.messageEditError('auditDB.ts:43', message, e)); }).catch((e: Error) => utils.commonLoggers.messageEditError('auditDB.ts:43', message, e));
} catch (e) { } catch (e) {
utils.commonLoggers.messageSendError('auditDB.ts:45', message, e); utils.commonLoggers.messageSendError('auditDB.ts:45', message, e);

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -28,7 +29,9 @@ export const emoji = (message: DiscordenoMessage, command: string) => {
dbClient.execute(queries.callIncCnt('emojis')).catch((e) => utils.commonLoggers.dbError('emojis.ts:28', 'call sproc INC_CNT on', e)); dbClient.execute(queries.callIncCnt('emojis')).catch((e) => utils.commonLoggers.dbError('emojis.ts:28', 'call sproc INC_CNT on', e));
// Send the needed emoji // Send the needed emoji
message.send(`<${emji.animated ? 'a' : ''}:${emji.name}:${emji.id}>`).catch((e: Error) => utils.commonLoggers.messageSendError('emoji.ts:33', message, e)); message
.send(`<${emji.animated ? 'a' : ''}:${emji.name}:${emji.id}>`)
.catch((e: Error) => utils.commonLoggers.messageSendError('emoji.ts:33', message, e));
// And attempt to delete if needed // And attempt to delete if needed
if (emji.deleteSender) { if (emji.deleteSender) {
message.delete().catch((e: Error) => utils.commonLoggers.messageDeleteError('emoji.ts:36', message, e)); message.delete().catch((e: Error) => utils.commonLoggers.messageDeleteError('emoji.ts:36', message, e));

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -16,16 +17,22 @@ export const handleMentions = (message: DiscordenoMessage) => {
// 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(queries.callIncCnt('mention')).catch((e) => utils.commonLoggers.dbError('handleMentions.ts:17', 'call sproc INC_CNT on', e)); dbClient.execute(queries.callIncCnt('mention')).catch((e) => utils.commonLoggers.dbError('handleMentions.ts:17', 'call sproc INC_CNT on', e));
message.send({ message
embeds: [{ .send({
embeds: [
{
color: infoColor1, color: infoColor1,
title: `Hello! I am ${config.name}!`, title: `Hello! I am ${config.name}!`,
fields: [{ fields: [
{
name: 'I am a bot that specializes in rolling dice and doing basic algebra.', name: 'I am a bot that specializes in rolling dice and doing basic algebra.',
value: `To learn about my available commands, please run \`${config.prefix}help\`. value: `To learn about my available commands, please run \`${config.prefix}help\`.
Want me to ignore you? Simply run \`${config.prefix}opt-out\` and ${config.name} will no longer read your messages or respond to you.`, Want me to ignore you? Simply run \`${config.prefix}opt-out\` and ${config.name} will no longer read your messages or respond to you.`,
}], },
}], ],
}).catch((e: Error) => utils.commonLoggers.messageSendError('handleMentions.ts:30', message, e)); },
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('handleMentions.ts:30', message, e));
}; };

View File

@ -1,4 +1,5 @@
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -13,8 +14,10 @@ export const heatmap = async (message: DiscordenoMessage) => {
dbClient.execute(queries.callIncCnt('heatmap')).catch((e) => utils.commonLoggers.dbError('heatmap.ts:14', 'call sproc INC_CNT on', e)); dbClient.execute(queries.callIncCnt('heatmap')).catch((e) => utils.commonLoggers.dbError('heatmap.ts:14', 'call sproc INC_CNT on', e));
if (config.api.enable) { if (config.api.enable) {
message.send({ message
embeds: [{ .send({
embeds: [
{
title: 'Roll Heatmap', title: 'Roll Heatmap',
description: `Over time, this image will show a nice pattern of when rolls are requested the most. description: `Over time, this image will show a nice pattern of when rolls are requested the most.
@ -27,15 +30,21 @@ Most Rolls: ${intervals.getMaxRollCnt()}`,
image: { image: {
url: `${config.api.publicDomain}api/heatmap.png`, url: `${config.api.publicDomain}api/heatmap.png`,
}, },
}], },
}).catch((e) => utils.commonLoggers.messageSendError('heatmap.ts:21', message, e)); ],
})
.catch((e) => utils.commonLoggers.messageSendError('heatmap.ts:21', message, e));
} else { } else {
message.send({ message
embeds: [{ .send({
embeds: [
{
title: 'Roll Heatmap Disabled', title: 'Roll Heatmap Disabled',
description: 'This command requires the bot\'s API to be enabled. If you are the host of this bot, check your `config.ts` file to enable it.', description: "This command requires the bot's API to be enabled. If you are the host of this bot, check your `config.ts` file to enable it.",
color: failColor, color: failColor,
}], },
}).catch((e) => utils.commonLoggers.messageSendError('heatmap.ts:21', message, e)); ],
})
.catch((e) => utils.commonLoggers.messageSendError('heatmap.ts:21', message, e));
} }
}; };

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -11,10 +12,12 @@ export const help = (message: DiscordenoMessage) => {
// 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(queries.callIncCnt('help')).catch((e) => utils.commonLoggers.dbError('htlp.ts:15', 'call sproc INC_CNT on', e)); dbClient.execute(queries.callIncCnt('help')).catch((e) => utils.commonLoggers.dbError('htlp.ts:15', 'call sproc INC_CNT on', e));
message.send({ message
embeds: [{ .send({
embeds: [
{
color: infoColor2, color: infoColor2,
title: 'The Artificer\'s Available Commands:', title: "The Artificer's Available Commands:",
fields: [ fields: [
{ {
name: `\`${config.prefix}?\``, name: `\`${config.prefix}?\``,
@ -88,11 +91,12 @@ export const help = (message: DiscordenoMessage) => {
}, },
{ {
name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`, name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`,
value: value: `Rolls all configs requested, you may repeat the command multiple times in the same message (just ensure you close each roll with \`${config.postfix}\`), run \`${config.prefix}??\` for more details`,
`Rolls all configs requested, you may repeat the command multiple times in the same message (just ensure you close each roll with \`${config.postfix}\`), run \`${config.prefix}??\` for more details`,
inline: true, inline: true,
}, },
], ],
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('help.ts:82', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('help.ts:82', message, e));
}; };

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -11,14 +12,18 @@ export const info = (message: DiscordenoMessage) => {
// 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(queries.callIncCnt('info')).catch((e) => utils.commonLoggers.dbError('info.ts:12', 'call sproc INC_CNT on', e)); dbClient.execute(queries.callIncCnt('info')).catch((e) => utils.commonLoggers.dbError('info.ts:12', 'call sproc INC_CNT on', e));
message.send({ message
embeds: [{ .send({
embeds: [
{
color: infoColor2, color: infoColor2,
title: `${config.name}, a Discord bot that specializing in rolling dice and calculating math`, title: `${config.name}, a Discord bot that specializing in rolling dice and calculating math`,
description: `${config.name} is developed by Ean AKA Burn_E99. description: `${config.name} is developed by Ean AKA Burn_E99.
Additional information can be found on my website [here](https://discord.burne99.com/TheArtificer/). Additional information can be found on my website [here](https://discord.burne99.com/TheArtificer/).
Want to check out my source code? Check it out [here](https://github.com/Burn-E99/TheArtificer). Want to check out my source code? Check it out [here](https://github.com/Burn-E99/TheArtificer).
Need help with this bot? Join my support server [here](https://discord.gg/peHASXMZYv).`, Need help with this bot? Join my support server [here](https://discord.gg/peHASXMZYv).`,
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('info.ts:23', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('info.ts:23', message, e));
}; };

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, ignoreList, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries, ignoreList } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -17,23 +18,31 @@ export const optIn = async (message: DiscordenoMessage) => {
ignoreList.splice(idIdx, 1); ignoreList.splice(idIdx, 1);
await dbClient.execute('DELETE FROM ignore_list WHERE userid = ?', [message.authorId]); await dbClient.execute('DELETE FROM ignore_list WHERE userid = ?', [message.authorId]);
message.reply({ message
embeds: [{ .reply({
embeds: [
{
color: successColor, color: successColor,
title: `${config.name} will now respond to you again.`, title: `${config.name} will now respond to you again.`,
description: `If you want ${config.name} to ignore to you again, please run the following command: description: `If you want ${config.name} to ignore to you again, please run the following command:
\`${config.prefix}opt-out\``, \`${config.prefix}opt-out\``,
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('optIn.ts:27', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('optIn.ts:27', message, e));
} catch (err) { } catch (err) {
message.reply({ message
embeds: [{ .reply({
embeds: [
{
color: failColor, color: failColor,
title: 'Opt-In failed', title: 'Opt-In failed',
description: 'Please try the command again. If the issue persists, please join the support server, linked in my About Me section.', description: 'Please try the command again. If the issue persists, please join the support server, linked in my About Me section.',
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('optIn.ts:27', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('optIn.ts:27', message, e));
} }
} }
}; };

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, ignoreList, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries, ignoreList } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -15,22 +16,30 @@ export const optOut = async (message: DiscordenoMessage) => {
ignoreList.push(message.authorId); ignoreList.push(message.authorId);
await dbClient.execute('INSERT INTO ignore_list(userid) values(?)', [message.authorId]); await dbClient.execute('INSERT INTO ignore_list(userid) values(?)', [message.authorId]);
message.reply({ message
embeds: [{ .reply({
embeds: [
{
color: successColor, color: successColor,
title: `${config.name} will no longer respond to you.`, title: `${config.name} will no longer respond to you.`,
description: `If you want ${config.name} to respond to you again, please DM ${config.name} the following command: description: `If you want ${config.name} to respond to you again, please DM ${config.name} the following command:
\`${config.prefix}opt-in\``, \`${config.prefix}opt-in\``,
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('optOut.ts:25', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('optOut.ts:25', message, e));
} catch (err) { } catch (err) {
message.reply({ message
embeds: [{ .reply({
embeds: [
{
color: failColor, color: failColor,
title: 'Opt-Out failed', title: 'Opt-Out failed',
description: `Please try the command again. If the issue persists, please report this using the \`${config.prefix}report opt-out failed\` command.`, description: `Please try the command again. If the issue persists, please report this using the \`${config.prefix}report opt-out failed\` command.`,
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('optOut.ts:33', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('optOut.ts:33', message, e));
} }
}; };

View File

@ -1,4 +1,5 @@
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -11,21 +12,26 @@ export const privacy = (message: DiscordenoMessage) => {
// 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(queries.callIncCnt('privacy')).catch((e) => utils.commonLoggers.dbError('privacy.ts:15', 'call sproc INC_CNT on', e)); dbClient.execute(queries.callIncCnt('privacy')).catch((e) => utils.commonLoggers.dbError('privacy.ts:15', 'call sproc INC_CNT on', e));
message.send({ message
embeds: [{ .send({
embeds: [
{
color: infoColor1, color: infoColor1,
title: 'Privacy Policy', title: 'Privacy Policy',
fields: [{ fields: [
{
name: 'The Artificer does not track or collect user information via Discord.', name: 'The Artificer does not track or collect user information via Discord.',
value: value: `The only user submitted information that is stored is submitted via the \`${config.prefix}report\` command. This information is only stored for a short period of time in a location that only the Developer of The Artificer can see.
`The only user submitted information that is stored is submitted via the \`${config.prefix}report\` command. This information is only stored for a short period of time in a location that only the Developer of The Artificer can see.
For more details, please check out the Privacy Policy on the GitHub [here](https://github.com/Burn-E99/TheArtificer/blob/master/PRIVACY.md). For more details, please check out the Privacy Policy on the GitHub [here](https://github.com/Burn-E99/TheArtificer/blob/master/PRIVACY.md).
Terms of Service can also be found on GitHub [here](https://github.com/Burn-E99/TheArtificer/blob/master/TERMS.md). Terms of Service can also be found on GitHub [here](https://github.com/Burn-E99/TheArtificer/blob/master/TERMS.md).
Want me to ignore you? Simply run \`${config.prefix}opt-out\` and ${config.name} will no longer read your messages or respond to you.`, Want me to ignore you? Simply run \`${config.prefix}opt-out\` and ${config.name} will no longer read your messages or respond to you.`,
}], },
}], ],
}).catch((e: Error) => utils.commonLoggers.messageSendError('privacy.ts:33', message, e)); },
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('privacy.ts:33', message, e));
}; };

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -15,20 +16,28 @@ export const report = (message: DiscordenoMessage, args: string[]) => {
if (args.join(' ')) { if (args.join(' ')) {
sendMessage(config.reportChannel, generateReport(args.join(' '))).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:22', message, e)); sendMessage(config.reportChannel, generateReport(args.join(' '))).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:22', message, e));
message.send({ message
embeds: [{ .send({
embeds: [
{
color: successColor, color: successColor,
title: 'Failed command has been reported to my developer.', title: 'Failed command has been reported to my developer.',
description: `For more in depth support, and information about planned maintenance, please join the support server [here](https://discord.gg/peHASXMZYv).`, description: `For more in depth support, and information about planned maintenance, please join the support server [here](https://discord.gg/peHASXMZYv).`,
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:29', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:29', message, e));
} else { } else {
message.send({ message
embeds: [{ .send({
embeds: [
{
color: failColor, color: failColor,
title: 'Please provide a short description of what failed', title: 'Please provide a short description of what failed',
description: 'Providing a short description helps my developer quickly diagnose what went wrong.', description: 'Providing a short description helps my developer quickly diagnose what went wrong.',
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:37', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:37', message, e));
} }
}; };

View File

@ -1,4 +1,5 @@
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -10,13 +11,17 @@ export const rip = (message: DiscordenoMessage) => {
// 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(queries.callIncCnt('rip')).catch((e) => utils.commonLoggers.dbError('rip.ts:14', 'call sproc INC_CNT on', e)); dbClient.execute(queries.callIncCnt('rip')).catch((e) => utils.commonLoggers.dbError('rip.ts:14', 'call sproc INC_CNT on', e));
message.send({ message
embeds: [{ .send({
embeds: [
{
color: infoColor2, color: infoColor2,
title: 'The Artificer was built in memory of my Grandmother, Babka', title: 'The Artificer was built in memory of my Grandmother, Babka',
description: `With much love, Ean description: `With much love, Ean
December 21, 2020`, December 21, 2020`,
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('rip.ts:26', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('rip.ts:26', message, e));
}; };

View File

@ -1,6 +1,7 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { DEVMODE } from '../../flags.ts'; import { DEVMODE } from '../../flags.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -22,12 +23,16 @@ export const roll = async (message: DiscordenoMessage, args: string[], command:
// 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) {
message.send({ message
embeds: [{ .send({
embeds: [
{
color: warnColor, color: warnColor,
title: 'Command is in development, please try again later.', title: 'Command is in development, please try again later.',
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('roll.ts:30', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('roll.ts:30', message, e));
return; return;
} }
@ -48,15 +53,13 @@ export const roll = async (message: DiscordenoMessage, args: string[], command:
// 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 = message.content.substring(2); const rollCmd = message.content.substring(2);
queueRoll( queueRoll(<QueuedRoll>{
<QueuedRoll> {
apiRoll: false, apiRoll: false,
dd: { m, message }, dd: { m, message },
rollCmd, rollCmd,
modifiers, modifiers,
originalCommand, originalCommand,
}, });
);
} catch (e) { } catch (e) {
log(LT.ERROR, `Undandled Error: ${JSON.stringify(e)}`); log(LT.ERROR, `Undandled Error: ${JSON.stringify(e)}`);
} }

View File

@ -1,6 +1,7 @@
import config from '../../../config.ts'; import config from '../../../config.ts';
import { DEVMODE } from '../../../flags.ts'; import { DEVMODE } from '../../../flags.ts';
import { dbClient, queries } from '../../db.ts'; import dbClient from '../../db/client.ts';
import { queries } from '../../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -55,7 +56,7 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
modifiers.gmRoll = true; modifiers.gmRoll = true;
// -gm is a little more complex, as we must get all of the GMs that need to be DMd // -gm is a little more complex, as we must get all of the GMs that need to be DMd
while (((i + 1) < args.length) && args[i + 1].startsWith('<@')) { while (i + 1 < args.length && args[i + 1].startsWith('<@')) {
log(LT.LOG, `Finding all GMs, checking args ${JSON.stringify(args)}`); log(LT.LOG, `Finding all GMs, checking args ${JSON.stringify(args)}`);
// Keep looping thru the rest of the args until one does not start with the discord mention code // Keep looping thru the rest of the args until one does not start with the discord mention code
modifiers.gms.push(args[i + 1].replace(/!/g, '')); modifiers.gms.push(args[i + 1].replace(/!/g, ''));
@ -63,11 +64,15 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
} }
if (modifiers.gms.length < 1) { if (modifiers.gms.length < 1) {
// If -gm is on and none were found, throw an error // If -gm is on and none were found, throw an error
m.edit(generateRollError(errorType, 'Must specifiy at least one GM by @mentioning them')).catch((e) => utils.commonLoggers.messageEditError('getModifiers.ts:66', m, e)); m.edit(generateRollError(errorType, 'Must specifiy at least one GM by @mentioning them')).catch((e) =>
utils.commonLoggers.messageEditError('getModifiers.ts:66', m, e)
);
if (DEVMODE && config.logRolls) { if (DEVMODE && config.logRolls) {
// If enabled, log rolls so we can verify the bots math // If enabled, log rolls so we can verify the bots math
dbClient.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'NoGMsFound', m.id]).catch((e) => utils.commonLoggers.dbError('getModifiers.ts:72', 'insert into', e)); dbClient
.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'NoGMsFound', m.id])
.catch((e) => utils.commonLoggers.dbError('getModifiers.ts:72', 'insert into', e));
} }
return modifiers; return modifiers;
} }
@ -76,13 +81,17 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
// Shift the -o out of the array so the next item is the direction // Shift the -o out of the array so the next item is the direction
args.splice(i, 1); args.splice(i, 1);
if (!args[i] || args[i].toLowerCase()[0] !== 'd' && args[i].toLowerCase()[0] !== 'a') { if (!args[i] || (args[i].toLowerCase()[0] !== 'd' && args[i].toLowerCase()[0] !== 'a')) {
// If -o is on and asc or desc was not specified, error out // If -o is on and asc or desc was not specified, error out
m.edit(generateRollError(errorType, 'Must specifiy `a` or `d` to order the rolls ascending or descending')).catch((e) => utils.commonLoggers.messageEditError('getModifiers.ts:81', m, e)); m.edit(generateRollError(errorType, 'Must specifiy `a` or `d` to order the rolls ascending or descending')).catch((e) =>
utils.commonLoggers.messageEditError('getModifiers.ts:81', m, e)
);
if (DEVMODE && config.logRolls) { if (DEVMODE && config.logRolls) {
// If enabled, log rolls so we can verify the bots math // If enabled, log rolls so we can verify the bots math
dbClient.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'NoOrderFound', m.id]).catch((e) => utils.commonLoggers.dbError('getModifiers.ts:89', 'insert into', e)); dbClient
.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'NoOrderFound', m.id])
.catch((e) => utils.commonLoggers.dbError('getModifiers.ts:89', 'insert into', e));
} }
return modifiers; return modifiers;
} }
@ -103,11 +112,15 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
// maxRoll and nominalRoll cannot both be on, throw an error // maxRoll and nominalRoll cannot both be on, throw an error
if (modifiers.maxRoll && modifiers.nominalRoll) { if (modifiers.maxRoll && modifiers.nominalRoll) {
m.edit(generateRollError(errorType, 'Cannot maximise and nominise the roll at the same time')).catch((e) => utils.commonLoggers.messageEditError('getModifiers.ts:106', m, e)); m.edit(generateRollError(errorType, 'Cannot maximise and nominise the roll at the same time')).catch((e) =>
utils.commonLoggers.messageEditError('getModifiers.ts:106', m, e)
);
if (DEVMODE && config.logRolls) { if (DEVMODE && config.logRolls) {
// If enabled, log rolls so we can verify the bots math // If enabled, log rolls so we can verify the bots math
dbClient.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'MaxAndNominal', m.id]).catch((e) => utils.commonLoggers.dbError('getModifiers.ts:120', 'insert into', e)); dbClient
.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'MaxAndNominal', m.id])
.catch((e) => utils.commonLoggers.dbError('getModifiers.ts:120', 'insert into', e));
} }
return modifiers; return modifiers;
} }

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -11,7 +12,8 @@ export const rollDecorators = (message: DiscordenoMessage) => {
// 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(queries.callIncCnt('rollDecorators')).catch((e) => utils.commonLoggers.dbError('rollHelp.ts:15', 'call sproc INC_CNT on', e)); dbClient.execute(queries.callIncCnt('rollDecorators')).catch((e) => utils.commonLoggers.dbError('rollHelp.ts:15', 'call sproc INC_CNT on', e));
message.send({ message
.send({
embeds: [ embeds: [
{ {
color: infoColor2, color: infoColor2,
@ -47,7 +49,8 @@ Examples: \`${config.prefix}d20${config.postfix} -nd\`, \`${config.prefix}d20${c
}, },
{ {
name: '`-gm @user1 @user2 @usern` - GM Roll', name: '`-gm @user1 @user2 @usern` - GM Roll',
value: 'Rolls the requested roll in GM mode, suppressing all publicly shown results and details and sending the results directly to the specified GMs', value:
'Rolls the requested roll in GM mode, suppressing all publicly shown results and details and sending the results directly to the specified GMs',
inline: true, inline: true,
}, },
{ {
@ -67,5 +70,6 @@ Available directions:
], ],
}, },
], ],
}).catch((e: Error) => utils.commonLoggers.messageSendError('rollHelp.ts:247', message, e)); })
.catch((e: Error) => utils.commonLoggers.messageSendError('rollHelp.ts:247', message, e));
}; };

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -11,11 +12,12 @@ export const rollHelp = (message: DiscordenoMessage) => {
// 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(queries.callIncCnt('rollhelp')).catch((e) => utils.commonLoggers.dbError('rollHelp.ts:15', 'call sproc INC_CNT on', e)); dbClient.execute(queries.callIncCnt('rollhelp')).catch((e) => utils.commonLoggers.dbError('rollHelp.ts:15', 'call sproc INC_CNT on', e));
message.send({ message
.send({
embeds: [ embeds: [
{ {
color: infoColor1, color: infoColor1,
title: 'The Artificer\'s Roll Command Details:', title: "The Artificer's Roll Command Details:",
description: `You can chain as many of these options as you want, as long as the option does not disallow it. description: `You can chain as many of these options as you want, as long as the option does not disallow it.
This command also can fully solve math equations with parenthesis. This command also can fully solve math equations with parenthesis.
@ -70,27 +72,32 @@ Additionally, replace \`x\` with \`F\` to roll Fate dice`,
}, },
{ {
name: '`r<q` [Optional]', name: '`r<q` [Optional]',
value: 'Rerolls any rolls that are less than or equal to `a`, `r3` will reroll every die that land on 3, 2, or 1, throwing out old rolls, cannot be used with `ro`', value:
'Rerolls any rolls that are less than or equal to `a`, `r3` will reroll every die that land on 3, 2, or 1, throwing out old rolls, cannot be used with `ro`',
inline: true, inline: true,
}, },
{ {
name: '`r>q` [Optional]', name: '`r>q` [Optional]',
value: 'Rerolls any rolls that are greater than or equal to `a`, `r3` will reroll every die that land on 3 or greater, throwing out old rolls, cannot be used with `ro`', value:
'Rerolls any rolls that are greater than or equal to `a`, `r3` will reroll every die that land on 3 or greater, throwing out old rolls, cannot be used with `ro`',
inline: true, inline: true,
}, },
{ {
name: '`roa` or `ro=q` [Optional]', name: '`roa` or `ro=q` [Optional]',
value: 'Rerolls any rolls that match `a`, `ro3` will reroll each die that lands on 3 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`', value:
'Rerolls any rolls that match `a`, `ro3` will reroll each die that lands on 3 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`',
inline: true, inline: true,
}, },
{ {
name: '`ro<q` [Optional]', name: '`ro<q` [Optional]',
value: 'Rerolls any rolls that are less than or equal to `a`, `ro3` will reroll each die that lands on 3, 2, or 1 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`', value:
'Rerolls any rolls that are less than or equal to `a`, `ro3` will reroll each die that lands on 3, 2, or 1 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`',
inline: true, inline: true,
}, },
{ {
name: '`ro>q` [Optional]', name: '`ro>q` [Optional]',
value: 'Rerolls any rolls that are greater than or equal to `a`, `ro3` will reroll each die that lands on 3 or greater ONLY ONE TIME, throwing out old rolls, cannot be used with `r`', value:
'Rerolls any rolls that are greater than or equal to `a`, `ro3` will reroll each die that lands on 3 or greater ONLY ONE TIME, throwing out old rolls, cannot be used with `r`',
inline: true, inline: true,
}, },
{ {
@ -185,27 +192,32 @@ Additionally, replace \`x\` with \`F\` to roll Fate dice`,
}, },
{ {
name: '`!p>u` [Optional]', name: '`!p>u` [Optional]',
value: 'Penetrating Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but subtracts one from each resulting explosion', value:
'Penetrating Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but subtracts one from each resulting explosion',
inline: true, inline: true,
}, },
{ {
name: '`!p<u` [Optional]', name: '`!p<u` [Optional]',
value: 'Penetrating Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but subtracts one from each resulting explosion', value:
'Penetrating Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but subtracts one from each resulting explosion',
inline: true, inline: true,
}, },
{ {
name: '`!!=u` [Optional]', name: '`!!=u` [Optional]',
value: 'Compounding Explosion on `u`, rolls one `dy` for each die that lands on `u`, but adds the resulting explosion to the die that caused this explosion', value:
'Compounding Explosion on `u`, rolls one `dy` for each die that lands on `u`, but adds the resulting explosion to the die that caused this explosion',
inline: true, inline: true,
}, },
{ {
name: '`!!>u` [Optional]', name: '`!!>u` [Optional]',
value: 'Compounding Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but adds the resulting explosion to the die that caused this explosion', value:
'Compounding Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but adds the resulting explosion to the die that caused this explosion',
inline: true, inline: true,
}, },
{ {
name: '`!!<u` [Optional]', name: '`!!<u` [Optional]',
value: 'Compounding Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but adds the resulting explosion to the die that caused this explosion', value:
'Compounding Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but adds the resulting explosion to the die that caused this explosion',
inline: true, inline: true,
}, },
], ],
@ -258,5 +270,6 @@ Additionally, replace \`x\` with \`F\` to roll Fate dice`,
], ],
}, },
], ],
}).catch((e: Error) => utils.commonLoggers.messageSendError('rollHelp.ts:247', message, e)); })
.catch((e: Error) => utils.commonLoggers.messageSendError('rollHelp.ts:247', message, e));
}; };

View File

@ -1,4 +1,5 @@
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
cache, cache,
@ -17,8 +18,12 @@ export const stats = async (message: DiscordenoMessage) => {
const m = await message.send(compilingStats); const m = await message.send(compilingStats);
// Calculate how many times commands have been run // Calculate how many times commands have been run
const rollQuery = await dbClient.query(`SELECT count, hourlyRate FROM command_cnt WHERE command = "roll";`).catch((e) => utils.commonLoggers.dbError('stats.ts:23', 'query', e)); const rollQuery = await dbClient
const totalQuery = await dbClient.query(`SELECT SUM(count) as count, SUM(hourlyRate) as hourlyRate FROM command_cnt;`).catch((e) => utils.commonLoggers.dbError('stats.ts:24', 'query', e)); .query(`SELECT count, hourlyRate FROM command_cnt WHERE command = "roll";`)
.catch((e) => utils.commonLoggers.dbError('stats.ts:23', 'query', e));
const totalQuery = await dbClient
.query(`SELECT SUM(count) as count, SUM(hourlyRate) as hourlyRate FROM command_cnt;`)
.catch((e) => utils.commonLoggers.dbError('stats.ts:24', 'query', e));
const rolls = BigInt(rollQuery[0].count); const rolls = BigInt(rollQuery[0].count);
const rollRate = parseFloat(rollQuery[0].hourlyRate); const rollRate = parseFloat(rollQuery[0].hourlyRate);
const total = BigInt(totalQuery[0].count); const total = BigInt(totalQuery[0].count);
@ -27,9 +32,17 @@ export const stats = async (message: DiscordenoMessage) => {
const cachedGuilds = await cacheHandlers.size('guilds'); const cachedGuilds = await cacheHandlers.size('guilds');
const cachedChannels = await cacheHandlers.size('channels'); const cachedChannels = await cacheHandlers.size('channels');
const cachedMembers = await cacheHandlers.size('members'); const cachedMembers = await cacheHandlers.size('members');
m.edit(generateStats(cachedGuilds + cache.dispatchedGuildIds.size, cachedChannels + cache.dispatchedChannelIds.size, cachedMembers, rolls, total - rolls, rollRate, totalRate - rollRate)).catch(( m.edit(
e: Error, generateStats(
) => utils.commonLoggers.messageEditError('stats.ts:38', m, e)); cachedGuilds + cache.dispatchedGuildIds.size,
cachedChannels + cache.dispatchedChannelIds.size,
cachedMembers,
rolls,
total - rolls,
rollRate,
totalRate - rollRate
)
).catch((e: Error) => utils.commonLoggers.messageEditError('stats.ts:38', m, e));
} catch (e) { } catch (e) {
utils.commonLoggers.messageSendError('stats.ts:41', message, e); utils.commonLoggers.messageSendError('stats.ts:41', message, e);
} }

View File

@ -1,5 +1,6 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -11,10 +12,14 @@ export const version = (message: DiscordenoMessage) => {
// 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(queries.callIncCnt('version')).catch((e) => utils.commonLoggers.dbError('version.ts:15', 'call sproc INC_CNT on', e)); dbClient.execute(queries.callIncCnt('version')).catch((e) => utils.commonLoggers.dbError('version.ts:15', 'call sproc INC_CNT on', e));
message.send({ message
embeds: [{ .send({
embeds: [
{
color: infoColor1, color: infoColor1,
title: `My current version is ${config.version}`, title: `My current version is ${config.version}`,
}], },
}).catch((e: Error) => utils.commonLoggers.messageSendError('version.ts:24', message, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('version.ts:24', message, e));
}; };

View File

@ -1,30 +0,0 @@
import config from '../config.ts';
import { Client } from '../deps.ts';
import { LOCALMODE } from '../flags.ts';
type UserIdObj = {
userid: bigint;
};
export const dbClient = await new Client().connect({
hostname: LOCALMODE ? config.db.localhost : config.db.host,
port: config.db.port,
db: config.db.name,
username: config.db.username,
password: config.db.password,
});
// List of userIds who have requested that the bot ignore them
export const ignoreList: Array<bigint> = [];
const dbIgnoreList = await dbClient.query('SELECT * FROM ignore_list');
dbIgnoreList.forEach((userIdObj: UserIdObj) => {
ignoreList.push(userIdObj.userid);
});
export const weekDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
export const queries = {
insertRollLogCmd: (api: number, error: number) => `INSERT INTO roll_log(input,result,resultid,api,error) values(?,?,?,${api},${error})`,
callIncCnt: (cmdName: string) => `CALL INC_CNT("${cmdName}");`,
callIncHeatmap: (dateObj: Date) => `CALL INC_HEATMAP("${weekDays[dateObj.getDay()]}", ${dateObj.getHours()});`,
};

14
src/db/client.ts Normal file
View File

@ -0,0 +1,14 @@
import config from '../../config.ts';
import { Client } from '../../deps.ts';
import { LOCALMODE } from '../../flags.ts';
const dbClient = await new Client().connect({
hostname: LOCALMODE ? config.db.localhost : config.db.host,
port: config.db.port,
db: config.db.name,
username: config.db.username,
password: config.db.password,
debug: true,
});
export default dbClient;

20
src/db/common.ts Normal file
View File

@ -0,0 +1,20 @@
import dbClient from './client.ts';
type UserIdObj = {
userid: bigint;
};
// List of userIds who have requested that the bot ignore them
export const ignoreList: Array<bigint> = [];
const dbIgnoreList = await dbClient.query('SELECT * FROM ignore_list');
dbIgnoreList.forEach((userIdObj: UserIdObj) => {
ignoreList.push(userIdObj.userid);
});
export const weekDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
export const queries = {
insertRollLogCmd: (api: number, error: number) => `INSERT INTO roll_log(input,result,resultid,api,error) values(?,?,?,${api},${error})`,
callIncCnt: (cmdName: string) => `CALL INC_CNT("${cmdName}");`,
callIncHeatmap: (dateObj: Date) => `CALL INC_HEATMAP("${weekDays[dateObj.getDay()]}", ${dateObj.getHours()});`,
};

View File

@ -1,5 +1,5 @@
import config from '../../../config.ts'; import config from '../../../config.ts';
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import { import {
// nanoid deps // nanoid deps
nanoid, nanoid,
@ -10,10 +10,16 @@ import { generateApiDeleteEmail } from '../../commandUtils.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
export const apiKeyDelete = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, apiUserEmail: string, apiUserDelCode: string) => { export const apiKeyDelete = async (
if (query.has('user') && ((query.get('user') || '').length > 0) && query.has('email') && ((query.get('email') || '').length > 0)) { requestEvent: Deno.RequestEvent,
query: Map<string, string>,
apiUserid: BigInt,
apiUserEmail: string,
apiUserDelCode: string
) => {
if (query.has('user') && (query.get('user') || '').length > 0 && query.has('email') && (query.get('email') || '').length > 0) {
if (apiUserid === BigInt(query.get('user') || '0') && apiUserEmail === query.get('email')) { if (apiUserid === BigInt(query.get('user') || '0') && apiUserEmail === query.get('email')) {
if (query.has('code') && ((query.get('code') || '').length > 0)) { if (query.has('code') && (query.get('code') || '').length > 0) {
if ((query.get('code') || '') === apiUserDelCode) { if ((query.get('code') || '') === apiUserDelCode) {
// User has recieved their delete code and we need to delete the account now // User has recieved their delete code and we need to delete the account now
let erroredOut = false; let erroredOut = false;

View File

@ -1,9 +1,9 @@
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiChannel = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => { export const apiChannel = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => {
if (query.has('user') && ((query.get('user') || '').length > 0)) { if (query.has('user') && (query.get('user') || '').length > 0) {
if (apiUserid === BigInt(query.get('user') || '0')) { if (apiUserid === BigInt(query.get('user') || '0')) {
// Flag to see if there is an error inside the catch // Flag to see if there is an error inside the catch
let erroredOut = false; let erroredOut = false;

View File

@ -1,5 +1,5 @@
import config from '../../../config.ts'; import config from '../../../config.ts';
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import { import {
// nanoid deps // nanoid deps
nanoid, nanoid,
@ -11,7 +11,7 @@ import utils from '../../utils.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
export const apiKey = async (requestEvent: Deno.RequestEvent, query: Map<string, string>) => { export const apiKey = async (requestEvent: Deno.RequestEvent, query: Map<string, string>) => {
if ((query.has('user') && ((query.get('user') || '').length > 0)) && (query.has('email') && ((query.get('email') || '').length > 0))) { if (query.has('user') && (query.get('user') || '').length > 0 && query.has('email') && (query.get('email') || '').length > 0) {
// Generate new secure key // Generate new secure key
const newKey = await nanoid(25); const newKey = await nanoid(25);
@ -19,13 +19,13 @@ export const apiKey = async (requestEvent: Deno.RequestEvent, query: Map<string,
let erroredOut = false; let erroredOut = false;
// Insert new key/user pair into the db // Insert new key/user pair into the db
await dbClient.execute('INSERT INTO all_keys(userid,apiKey,email) values(?,?,?)', [BigInt(query.get('user') || '0'), newKey, (query.get('email') || '').toLowerCase()]).catch( await dbClient
(e) => { .execute('INSERT INTO all_keys(userid,apiKey,email) values(?,?,?)', [BigInt(query.get('user') || '0'), newKey, (query.get('email') || '').toLowerCase()])
.catch((e) => {
utils.commonLoggers.dbError('apiKey.ts:27', 'insert into', e); utils.commonLoggers.dbError('apiKey.ts:27', 'insert into', e);
requestEvent.respondWith(stdResp.InternalServerError('Failed to store key.')); requestEvent.respondWith(stdResp.InternalServerError('Failed to store key.'));
erroredOut = true; erroredOut = true;
}, });
);
// Exit this case now if catch errored // Exit this case now if catch errored
if (erroredOut) { if (erroredOut) {

View File

@ -1,5 +1,5 @@
import config from '../../../config.ts'; import config from '../../../config.ts';
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import { import {
// nanoid deps // nanoid deps
nanoid, nanoid,
@ -8,7 +8,7 @@ import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiKeyAdmin = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => { export const apiKeyAdmin = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => {
if ((query.has('user') && ((query.get('user') || '').length > 0)) && (query.has('a') && ((query.get('a') || '').length > 0))) { if (query.has('user') && (query.get('user') || '').length > 0 && query.has('a') && (query.get('a') || '').length > 0) {
if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) { if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) {
// Generate new secure key // Generate new secure key
const newKey = await nanoid(25); const newKey = await nanoid(25);
@ -28,7 +28,7 @@ export const apiKeyAdmin = async (requestEvent: Deno.RequestEvent, query: Map<st
return; return;
} else { } else {
// Send API key as response // Send API key as response
requestEvent.respondWith(stdResp.OK(JSON.stringify({ 'key': newKey, 'userid': query.get('user') }))); requestEvent.respondWith(stdResp.OK(JSON.stringify({ key: newKey, userid: query.get('user') })));
return; return;
} }
} else { } else {

View File

@ -1,5 +1,5 @@
import config from '../../../config.ts'; import config from '../../../config.ts';
import { dbClient, queries } from '../../db.ts'; import dbClient from '../../db/client.ts';
import { import {
// Discordeno deps // Discordeno deps
cache, cache,
@ -17,12 +17,16 @@ const apiWarning = `The following roll was conducted using my built in API. If
export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => { export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => {
// Make sure query contains all the needed parts // Make sure query contains all the needed parts
if ( if (
(query.has('rollstr') && ((query.get('rollstr') || '').length > 0)) && (query.has('channel') && ((query.get('channel') || '').length > 0)) && query.has('rollstr') &&
(query.has('user') && ((query.get('user') || '').length > 0)) (query.get('rollstr') || '').length > 0 &&
query.has('channel') &&
(query.get('channel') || '').length > 0 &&
query.has('user') &&
(query.get('user') || '').length > 0
) { ) {
if (query.has('n') && query.has('m')) { if (query.has('n') && query.has('m')) {
// Alert API user that they shouldn't be doing this // Alert API user that they shouldn't be doing this
requestEvent.respondWith(stdResp.BadRequest('Cannot have both \'n\' and \'m\'.')); requestEvent.respondWith(stdResp.BadRequest("Cannot have both 'n' and 'm'."));
return; return;
} }
@ -31,8 +35,11 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
let hideWarn = false; let hideWarn = false;
// Check if the db has the requested userid/channelid combo, and that the requested userid matches the userid linked with the api key // Check if the db has the requested userid/channelid combo, and that the requested userid matches the userid linked with the api key
const dbChannelQuery = await dbClient.query('SELECT active, banned FROM allowed_channels WHERE userid = ? AND channelid = ?', [apiUserid, BigInt(query.get('channel') || '0')]); const dbChannelQuery = await dbClient.query('SELECT active, banned FROM allowed_channels WHERE userid = ? AND channelid = ?', [
if (dbChannelQuery.length === 1 && (apiUserid === BigInt(query.get('user') || '0')) && dbChannelQuery[0].active && !dbChannelQuery[0].banned) { apiUserid,
BigInt(query.get('channel') || '0'),
]);
if (dbChannelQuery.length === 1 && apiUserid === BigInt(query.get('user') || '0') && dbChannelQuery[0].active && !dbChannelQuery[0].banned) {
// Get the guild from the channel and make sure user is in said guild // Get the guild from the channel and make sure user is in said guild
const guild = cache.channels.get(BigInt(query.get('channel') || ''))?.guild; const guild = cache.channels.get(BigInt(query.get('channel') || ''))?.guild;
if (guild && guild.members.get(BigInt(query.get('user') || ''))?.id) { if (guild && guild.members.get(BigInt(query.get('user') || ''))?.id) {
@ -61,16 +68,20 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
requestEvent.respondWith(stdResp.BadRequest('rollCmd is required.')); requestEvent.respondWith(stdResp.BadRequest('rollCmd is required.'));
// Always log API rolls for abuse detection // Always log API rolls for abuse detection
dbClient.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'EmptyInput', null]).catch((e) => utils.commonLoggers.dbError('apiRoll.ts:65', 'insert', e)); dbClient
.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'EmptyInput', null])
.catch((e) => utils.commonLoggers.dbError('apiRoll.ts:65', 'insert', e));
return; return;
} }
if (query.has('o') && (query.get('o')?.toLowerCase() !== 'd' && query.get('o')?.toLowerCase() !== 'a')) { if (query.has('o') && query.get('o')?.toLowerCase() !== 'd' && query.get('o')?.toLowerCase() !== 'a') {
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.BadRequest('Order must be set to \'a\' or \'d\'.')); requestEvent.respondWith(stdResp.BadRequest("Order must be set to 'a' or 'd'."));
// Always log API rolls for abuse detection // Always log API rolls for abuse detection
dbClient.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'BadOrder', null]).catch((e) => utils.commonLoggers.dbError('apiRoll.ts:66', 'insert', e)); dbClient
.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'BadOrder', null])
.catch((e) => utils.commonLoggers.dbError('apiRoll.ts:66', 'insert', e));
return; return;
} }
@ -85,22 +96,20 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
nominalRoll: query.has('n'), nominalRoll: query.has('n'),
gmRoll: query.has('gms'), gmRoll: query.has('gms'),
gms: query.has('gms') ? (query.get('gms') || '').split(',') : [], gms: query.has('gms') ? (query.get('gms') || '').split(',') : [],
order: query.has('o') ? (query.get('o')?.toLowerCase() || '') : '', order: query.has('o') ? query.get('o')?.toLowerCase() || '' : '',
count: query.has('c'), count: query.has('c'),
valid: true, valid: true,
apiWarn: hideWarn ? '' : apiWarning, apiWarn: hideWarn ? '' : apiWarning,
}; };
// Parse the roll and get the return text // Parse the roll and get the return text
await queueRoll( await queueRoll(<QueuedRoll>{
<QueuedRoll> {
apiRoll: true, apiRoll: true,
api: { requestEvent, channelId: BigInt(query.get('channel') || '0'), userId: BigInt(query.get('user') || '') }, api: { requestEvent, channelId: BigInt(query.get('channel') || '0'), userId: BigInt(query.get('user') || '') },
rollCmd, rollCmd,
modifiers, modifiers,
originalCommand, originalCommand,
}, });
);
} catch (err) { } catch (err) {
// Handle any errors we missed // Handle any errors we missed
log(LT.ERROR, `Unhandled Error: ${JSON.stringify(err)}`); log(LT.ERROR, `Unhandled Error: ${JSON.stringify(err)}`);
@ -110,8 +119,8 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith( requestEvent.respondWith(
stdResp.Forbidden( stdResp.Forbidden(
`Verify you are a member of the guild you are sending this roll to. If you are, the ${config.name} may not have that registered, please send a message in the guild so ${config.name} can register this. This registration is temporary, so if you see this error again, just poke your server again.`, `Verify you are a member of the guild you are sending this roll to. If you are, the ${config.name} may not have that registered, please send a message in the guild so ${config.name} can register this. This registration is temporary, so if you see this error again, just poke your server again.`
), )
); );
} }
} else { } else {

View File

@ -1,6 +1,6 @@
import { import {
// httpd deps // httpd deps
Status, STATUS_CODE,
STATUS_TEXT, STATUS_TEXT,
} from '../../../deps.ts'; } from '../../../deps.ts';
@ -11,9 +11,9 @@ export const heatmapPng = async (requestEvent: Deno.RequestEvent) => {
// Send basic OK to indicate key has been sent // Send basic OK to indicate key has been sent
requestEvent.respondWith( requestEvent.respondWith(
new Response(file, { new Response(file, {
status: Status.OK, status: STATUS_CODE.OK,
statusText: STATUS_TEXT[Status.OK], statusText: STATUS_TEXT[STATUS_CODE.OK],
headers: imageHeaders, headers: imageHeaders,
}), })
); );
}; };

View File

@ -1,9 +1,9 @@
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiChannelAdd = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => { export const apiChannelAdd = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => {
if ((query.has('user') && ((query.get('user') || '').length > 0)) && (query.has('channel') && ((query.get('channel') || '').length > 0))) { if (query.has('user') && (query.get('user') || '').length > 0 && query.has('channel') && (query.get('channel') || '').length > 0) {
if (apiUserid === BigInt(query.get('user') || '0')) { if (apiUserid === BigInt(query.get('user') || '0')) {
// Flag to see if there is an error inside the catch // Flag to see if there is an error inside the catch
let erroredOut = false; let erroredOut = false;

View File

@ -1,12 +1,13 @@
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiChannelManageActive = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => { export const apiChannelManageActive = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => {
if ((query.has('channel') && ((query.get('channel') || '').length > 0)) && (query.has('user') && ((query.get('user') || '').length > 0))) { if (query.has('channel') && (query.get('channel') || '').length > 0 && query.has('user') && (query.get('user') || '').length > 0) {
if (apiUserid === BigInt(query.get('user') || '0')) { if (apiUserid === BigInt(query.get('user') || '0')) {
// Flag to see if there is an error inside the catch // Flag to see if there is an error inside the catch
let value, erroredOut = false; let value,
erroredOut = false;
// Determine value to set // Determine value to set
if (path.toLowerCase().indexOf('de') > 0) { if (path.toLowerCase().indexOf('de') > 0) {
@ -16,7 +17,9 @@ export const apiChannelManageActive = async (requestEvent: Deno.RequestEvent, qu
} }
// Update the requested entry // Update the requested entry
await dbClient.execute('UPDATE allowed_channels SET active = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')]).catch((e) => { await dbClient
.execute('UPDATE allowed_channels SET active = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')])
.catch((e) => {
utils.commonLoggers.dbError('apiChannelManageActive.ts:25', 'update', e); utils.commonLoggers.dbError('apiChannelManageActive.ts:25', 'update', e);
requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.')); requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.'));
erroredOut = true; erroredOut = true;

View File

@ -1,16 +1,21 @@
import config from '../../../config.ts'; import config from '../../../config.ts';
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiChannelManageBan = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => { export const apiChannelManageBan = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => {
if ( if (
(query.has('a') && ((query.get('a') || '').length > 0)) && (query.has('channel') && ((query.get('channel') || '').length > 0)) && query.has('a') &&
(query.has('user') && ((query.get('user') || '').length > 0)) (query.get('a') || '').length > 0 &&
query.has('channel') &&
(query.get('channel') || '').length > 0 &&
query.has('user') &&
(query.get('user') || '').length > 0
) { ) {
if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) { if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) {
// Flag to see if there is an error inside the catch // Flag to see if there is an error inside the catch
let value, erroredOut = false; let value,
erroredOut = false;
// Determine value to set // Determine value to set
if (path.toLowerCase().indexOf('un') > 0) { if (path.toLowerCase().indexOf('un') > 0) {
@ -20,7 +25,9 @@ export const apiChannelManageBan = async (requestEvent: Deno.RequestEvent, query
} }
// Execute the DB modification // Execute the DB modification
await dbClient.execute('UPDATE allowed_channels SET banned = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')]).catch((e) => { await dbClient
.execute('UPDATE allowed_channels SET banned = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')])
.catch((e) => {
utils.commonLoggers.dbError('apiChannelManageBan.ts:28', 'update', e); utils.commonLoggers.dbError('apiChannelManageBan.ts:28', 'update', e);
requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.')); requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.'));
erroredOut = true; erroredOut = true;

View File

@ -1,10 +1,10 @@
import config from '../../../config.ts'; import config from '../../../config.ts';
import { dbClient } from '../../db.ts'; import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiKeyManage = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => { export const apiKeyManage = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => {
if ((query.has('a') && ((query.get('a') || '').length > 0)) && (query.has('user') && ((query.get('user') || '').length > 0))) { if (query.has('a') && (query.get('a') || '').length > 0 && query.has('user') && (query.get('user') || '').length > 0) {
if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) { if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) {
// Flag to see if there is an error inside the catch // Flag to see if there is an error inside the catch
let key: string, let key: string,

View File

@ -1,21 +1,23 @@
import { import {
// httpd deps // httpd deps
Status, StatusCode,
STATUS_CODE,
STATUS_TEXT, STATUS_TEXT,
} from '../../deps.ts'; } from '../../deps.ts';
const genericResponse = (customText: string, status: Status) => new Response(customText || STATUS_TEXT[status], { status: status, statusText: STATUS_TEXT[status] }); const genericResponse = (customText: string, status: StatusCode) =>
new Response(customText || STATUS_TEXT[status], { status: status, statusText: STATUS_TEXT[status] });
export default { export default {
BadRequest: (customText: string) => genericResponse(customText, Status.BadRequest), BadRequest: (customText: string) => genericResponse(customText, STATUS_CODE.BadRequest),
FailedDependency: (customText: string) => genericResponse(customText, Status.FailedDependency), FailedDependency: (customText: string) => genericResponse(customText, STATUS_CODE.FailedDependency),
InternalServerError: (customText: string) => genericResponse(customText, Status.InternalServerError), InternalServerError: (customText: string) => genericResponse(customText, STATUS_CODE.InternalServerError),
Forbidden: (customText: string) => genericResponse(customText, Status.Forbidden), Forbidden: (customText: string) => genericResponse(customText, STATUS_CODE.Forbidden),
MethodNotAllowed: (customText: string) => genericResponse(customText, Status.MethodNotAllowed), MethodNotAllowed: (customText: string) => genericResponse(customText, STATUS_CODE.MethodNotAllowed),
NotFound: (customText: string) => genericResponse(customText, Status.NotFound), NotFound: (customText: string) => genericResponse(customText, STATUS_CODE.NotFound),
OK: (customText: string) => genericResponse(customText, Status.OK), OK: (customText: string) => genericResponse(customText, STATUS_CODE.OK),
RequestTimeout: (customText: string) => genericResponse(customText, Status.RequestTimeout), RequestTimeout: (customText: string) => genericResponse(customText, STATUS_CODE.RequestTimeout),
TooManyRequests: (customText: string) => genericResponse(customText, Status.TooManyRequests), TooManyRequests: (customText: string) => genericResponse(customText, STATUS_CODE.TooManyRequests),
Strings: { Strings: {
missingParams: 'Missing Parameters.', missingParams: 'Missing Parameters.',
restricted: 'This API is restricted.', restricted: 'This API is restricted.',

View File

@ -15,7 +15,8 @@ import {
LT, LT,
} from '../deps.ts'; } from '../deps.ts';
import { PastCommandCount } from './mod.d.ts'; import { PastCommandCount } from './mod.d.ts';
import { dbClient, weekDays } from './db.ts'; import dbClient from './db/client.ts';
import { weekDays } from './db/common.ts';
import utils from './utils.ts'; import utils from './utils.ts';
import config from '../config.ts'; import config from '../config.ts';
@ -23,7 +24,7 @@ import config from '../config.ts';
// Gets a new random status for the bot // Gets a new random status for the bot
const getRandomStatus = async (): Promise<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:
status = `${config.prefix}help for commands`; status = `${config.prefix}help for commands`;
break; break;
@ -55,14 +56,14 @@ const updateListStatistics = (botID: bigint, serverCount: number): void => {
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.toString()), { 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
}); });
log(LT.INFO, `Posted server count to ${e.name}. Results: ${JSON.stringify(response)}`); log(LT.INFO, `Posted server count to ${e.name}. Results: ${JSON.stringify(response)}`);
} }
} catch (err) { } catch (err) {
log(LT.ERROR, `Failed to update statistics for ${e.name} | Error: ${err.name} - ${err.message}`) log(LT.ERROR, `Failed to update statistics for ${e.name} | Error: ${err.name} - ${err.message}`);
} }
}); });
}; };
@ -74,7 +75,9 @@ const previousHours: Array<Array<PastCommandCount>> = [];
// Updates the hourlyRate for command usage // Updates the hourlyRate for command usage
const updateHourlyRates = async () => { const updateHourlyRates = async () => {
try { try {
const newestHour = await dbClient.query('SELECT command, count FROM command_cnt ORDER BY command;').catch((e) => utils.commonLoggers.dbError('intervals.ts:71', 'query', e)); const newestHour = await dbClient
.query('SELECT command, count FROM command_cnt ORDER BY command;')
.catch((e) => utils.commonLoggers.dbError('intervals.ts:71', 'query', e));
previousHours.push(newestHour); previousHours.push(newestHour);
if (previousHours.length > 1) { if (previousHours.length > 1) {
const oldestHour = previousHours[0]; const oldestHour = previousHours[0];
@ -83,7 +86,7 @@ const updateHourlyRates = async () => {
for (let i = 0; i < newestHour.length; i++) { for (let i = 0; i < newestHour.length; i++) {
computedDiff.push({ computedDiff.push({
command: newestHour[i].command, command: newestHour[i].command,
count: (newestHour[i].count - oldestHour[i].count), count: newestHour[i].count - oldestHour[i].count,
}); });
log(LT.LOG, `Updating hourlyRate | Computing diffs: ${JSON.stringify(computedDiff)}`); log(LT.LOG, `Updating hourlyRate | Computing diffs: ${JSON.stringify(computedDiff)}`);
} }
@ -91,9 +94,9 @@ const updateHourlyRates = async () => {
// Update DB // Update DB
computedDiff.forEach(async (cmd) => { computedDiff.forEach(async (cmd) => {
log(LT.LOG, `Updating hourlyRate | Storing to DB: ${JSON.stringify(cmd)}`); log(LT.LOG, `Updating hourlyRate | Storing to DB: ${JSON.stringify(cmd)}`);
await dbClient.execute(`UPDATE command_cnt SET hourlyRate = ? WHERE command = ?`, [cmd.count / previousHours.length, cmd.command]).catch((e) => await dbClient
utils.commonLoggers.dbError('intervals.ts:88', 'update', e) .execute(`UPDATE command_cnt SET hourlyRate = ? WHERE command = ?`, [cmd.count / previousHours.length, cmd.command])
); .catch((e) => utils.commonLoggers.dbError('intervals.ts:88', 'update', e));
}); });
} }
@ -163,7 +166,9 @@ const updateHeatmapPng = async () => {
return; return;
} }
// Get latest data from DB // Get latest data from DB
const heatmapData = await dbClient.query('SELECT * FROM roll_time_heatmap ORDER BY hour;').catch((e) => utils.commonLoggers.dbError('intervals.ts:148', 'query', e)); const heatmapData = await dbClient
.query('SELECT * FROM roll_time_heatmap ORDER BY hour;')
.catch((e) => utils.commonLoggers.dbError('intervals.ts:148', 'query', e));
minRollCnt = Infinity; minRollCnt = Infinity;
maxRollCnt = 0; maxRollCnt = 0;
@ -191,11 +196,7 @@ const updateHeatmapPng = async () => {
hourPixels[hour][0] + 1, hourPixels[hour][0] + 1,
dayPixels[day][1] - dayPixels[day][0] + 1, dayPixels[day][1] - dayPixels[day][0] + 1,
hourPixels[hour][1] - hourPixels[hour][0] + 1, hourPixels[hour][1] - hourPixels[hour][0] + 1,
is.Image.rgbToColor( is.Image.rgbToColor(255 * (1 - percent), 255 * percent, 0)
255 * (1 - percent),
255 * percent,
0,
),
); );
} }
} }

View File

@ -1,6 +1,7 @@
import config from '../../config.ts'; import config from '../../config.ts';
import { DEVMODE } from '../../flags.ts'; import { DEVMODE } from '../../flags.ts';
import { dbClient, queries } from '../db.ts'; import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
DiscordenoMessage, DiscordenoMessage,
@ -36,19 +37,23 @@ const handleRollWorker = async (rq: QueuedRoll) => {
if (rq.apiRoll) { if (rq.apiRoll) {
rq.api.requestEvent.respondWith(stdResp.RequestTimeout('Roll took too long to process, try breaking roll down into simpler parts')); rq.api.requestEvent.respondWith(stdResp.RequestTimeout('Roll took too long to process, try breaking roll down into simpler parts'));
} else { } else {
rq.dd.m.edit({ rq.dd.m
.edit({
embeds: [ embeds: [
(await generateRollEmbed( (
await generateRollEmbed(
rq.dd.message.authorId, rq.dd.message.authorId,
<SolvedRoll> { <SolvedRoll>{
error: true, error: true,
errorCode: 'TooComplex', errorCode: 'TooComplex',
errorMsg: 'Error: Roll took too long to process, try breaking roll down into simpler parts', errorMsg: 'Error: Roll took too long to process, try breaking roll down into simpler parts',
}, },
<RollModifiers> {}, <RollModifiers>{}
)).embed, )
).embed,
], ],
}).catch((e) => utils.commonLoggers.messageEditError('rollQueue.ts:51', rq.dd.m, e)); })
.catch((e) => utils.commonLoggers.messageEditError('rollQueue.ts:51', rq.dd.m, e));
} }
}, config.limits.workerTimeout); }, config.limits.workerTimeout);
@ -77,11 +82,11 @@ const handleRollWorker = async (rq: QueuedRoll) => {
rq.dd.m.edit({ embeds: [pubEmbedDetails.embed] }); rq.dd.m.edit({ embeds: [pubEmbedDetails.embed] });
} }
if (rq.apiRoll || DEVMODE && config.logRolls) { if (rq.apiRoll || (DEVMODE && config.logRolls)) {
// If enabled, log rolls so we can see what went wrong // If enabled, log rolls so we can see what went wrong
dbClient.execute(queries.insertRollLogCmd(rq.apiRoll ? 1 : 0, 1), [rq.originalCommand, returnmsg.errorCode, rq.apiRoll ? null : rq.dd.m.id]).catch((e) => dbClient
utils.commonLoggers.dbError('rollQueue.ts:82', 'insert into', e) .execute(queries.insertRollLogCmd(rq.apiRoll ? 1 : 0, 1), [rq.originalCommand, returnmsg.errorCode, rq.apiRoll ? null : rq.dd.m.id])
); .catch((e) => utils.commonLoggers.dbError('rollQueue.ts:82', 'insert into', e));
} }
} else { } else {
let n: DiscordenoMessage | void; let n: DiscordenoMessage | void;
@ -107,7 +112,8 @@ const handleRollWorker = async (rq: QueuedRoll) => {
// Attempt to DM the GM and send a warning if it could not DM a GM // Attempt to DM the GM and send a warning if it could not DM a GM
await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), { await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), {
embeds: rq.modifiers.count ? [gmEmbedDetails.embed, countEmbed] : [gmEmbedDetails.embed], embeds: rq.modifiers.count ? [gmEmbedDetails.embed, countEmbed] : [gmEmbedDetails.embed],
}).then(async () => { })
.then(async () => {
// Check if we need to attach a file and send it after the initial details sent // Check if we need to attach a file and send it after the initial details sent
if (gmEmbedDetails.hasAttachment) { if (gmEmbedDetails.hasAttachment) {
await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), { await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), {
@ -120,7 +126,8 @@ const handleRollWorker = async (rq: QueuedRoll) => {
} }
}); });
} }
}).catch(() => { })
.catch(() => {
if (rq.apiRoll && n) { if (rq.apiRoll && n) {
n.reply(generateDMFailed(gm)); n.reply(generateDMFailed(gm));
} else { } else {
@ -154,9 +161,13 @@ const handleRollWorker = async (rq: QueuedRoll) => {
} }
if (rq.apiRoll && !apiErroredOut) { if (rq.apiRoll && !apiErroredOut) {
dbClient.execute(queries.insertRollLogCmd(1, 0), [rq.originalCommand, returnmsg.errorCode, n ? n.id : null]).catch((e) => utils.commonLoggers.dbError('rollQueue.ts:155', 'insert into', e)); dbClient
.execute(queries.insertRollLogCmd(1, 0), [rq.originalCommand, returnmsg.errorCode, n ? n.id : null])
.catch((e) => utils.commonLoggers.dbError('rollQueue.ts:155', 'insert into', e));
rq.api.requestEvent.respondWith(stdResp.OK(JSON.stringify( rq.api.requestEvent.respondWith(
stdResp.OK(
JSON.stringify(
rq.modifiers.count rq.modifiers.count
? { ? {
counts: countEmbed, counts: countEmbed,
@ -164,8 +175,10 @@ const handleRollWorker = async (rq: QueuedRoll) => {
} }
: { : {
details: pubEmbedDetails, details: pubEmbedDetails,
}, }
))); )
)
);
} }
} }
} catch (e) { } catch (e) {
@ -184,22 +197,29 @@ export const queueRoll = async (rq: QueuedRoll) => {
} else if (!rollQueue.length && currentWorkers < config.limits.maxWorkers) { } else if (!rollQueue.length && currentWorkers < config.limits.maxWorkers) {
handleRollWorker(rq); handleRollWorker(rq);
} else { } else {
rq.dd.m.edit({ rq.dd.m
embeds: [{ .edit({
embeds: [
{
color: infoColor2, color: infoColor2,
title: `${config.name} currently has its hands full and has queued your roll.`, title: `${config.name} currently has its hands full and has queued your roll.`,
description: `There are currently ${currentWorkers + rollQueue.length} rolls ahead of this roll. description: `There are currently ${currentWorkers + rollQueue.length} rolls ahead of this roll.
The results for this roll will replace this message when it is done.`, The results for this roll will replace this message when it is done.`,
}], },
}).catch((e: Error) => utils.commonLoggers.messageEditError('rollQueue.ts:197', rq.dd.m, e)); ],
})
.catch((e: Error) => utils.commonLoggers.messageEditError('rollQueue.ts:197', rq.dd.m, e));
rollQueue.push(rq); rollQueue.push(rq);
} }
}; };
// Checks the queue constantly to make sure the queue stays empty // Checks the queue constantly to make sure the queue stays empty
setInterval(async () => { setInterval(async () => {
log(LT.LOG, `Checking rollQueue for items, rollQueue length: ${rollQueue.length}, currentWorkers: ${currentWorkers}, config.limits.maxWorkers: ${config.limits.maxWorkers}`); log(
LT.LOG,
`Checking rollQueue for items, rollQueue length: ${rollQueue.length}, currentWorkers: ${currentWorkers}, config.limits.maxWorkers: ${config.limits.maxWorkers}`
);
if (rollQueue.length && currentWorkers < config.limits.maxWorkers) { if (rollQueue.length && currentWorkers < config.limits.maxWorkers) {
const temp = rollQueue.shift(); const temp = rollQueue.shift();
if (temp) { if (temp) {