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
import config from '../config.ts';
import { dbClient } from '../src/db.ts';
import dbClient from '../src/db/client.ts';
console.log('Attempting to create DB');
await dbClient.execute(`CREATE SCHEMA IF NOT EXISTS ${config.db.name};`);
console.log('test');
await dbClient.execute(`USE ${config.db.name}`);
console.log('DB created');

View File

@ -1,7 +1,7 @@
// This file will populate the tables with default values
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');
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('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) {
await dbClient.execute('INSERT INTO command_cnt(command) values(?)', [command]).catch((e) => {
console.log(`Failed to insert ${command} into database`, e);

54
mod.ts
View File

@ -25,7 +25,8 @@ import {
startBot,
} from './deps.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 intervals from './src/intervals.ts';
import { successColor, warnColor } from './src/commandUtils.ts';
@ -42,11 +43,13 @@ startBot({
ready: () => {
log(LT.INFO, `${config.name} Logged in!`);
editBotStatus({
activities: [{
activities: [
{
name: 'Booting up . . .',
type: DiscordActivityTypes.Game,
createdAt: new Date().getTime(),
}],
},
],
status: 'online',
});
@ -56,11 +59,13 @@ startBot({
try {
// Wrapped in try-catch due to hard crash possible
editBotStatus({
activities: [{
activities: [
{
name: await intervals.getRandomStatus(),
type: DiscordActivityTypes.Game,
createdAt: new Date().getTime(),
}],
},
],
status: 'online',
});
} catch (e) {
@ -69,7 +74,9 @@ startBot({
}, 30000);
// 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');
intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size);
}, 86400000);
@ -93,15 +100,18 @@ startBot({
intervals.updateHourlyRates();
intervals.updateHeatmapPng();
editBotStatus({
activities: [{
activities: [
{
name: 'Booting Complete',
type: DiscordActivityTypes.Game,
createdAt: new Date().getTime(),
}],
},
],
status: 'online',
});
sendMessage(config.logChannel, {
embeds: [{
embeds: [
{
title: `${config.name} is now Online`,
color: successColor,
fields: [
@ -111,14 +121,16 @@ startBot({
inline: true,
},
],
}],
},
],
}).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:88', 'Startup', e));
}, 1000);
},
guildCreate: (guild: DiscordenoGuild) => {
log(LT.LOG, `Handling joining guild ${JSON.stringify(guild)}`);
sendMessage(config.logChannel, {
embeds: [{
embeds: [
{
title: 'New Guild Joined!',
color: successColor,
fields: [
@ -138,13 +150,15 @@ startBot({
inline: true,
},
],
}],
},
],
}).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:95', 'Join Guild', e));
},
guildDelete: (guild: DiscordenoGuild) => {
log(LT.LOG, `Handling leaving guild ${JSON.stringify(guild)}`);
sendMessage(config.logChannel, {
embeds: [{
embeds: [
{
title: 'Removed from Guild',
color: warnColor,
fields: [
@ -164,9 +178,12 @@ startBot({
inline: true,
},
],
}],
},
],
}).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,
messageCreate: (message: DiscordenoMessage) => {
@ -190,7 +207,10 @@ startBot({
log(LT.LOG, `Handling ${config.prefix}command message: ${JSON.stringify(message)}`);
// 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();
// All commands below here
@ -292,7 +312,7 @@ startBot({
// [[xdydz (aka someone copy pasted the template as a roll)
// Help command specifically for the roll command
commands.rollHelp(message);
} else if (command && (`${command}${args.join('')}`).indexOf(config.postfix) > -1) {
} else if (command && `${command}${args.join('')}`.indexOf(config.postfix) > -1) {
// [[roll]]
// Dice rolling commence!
commands.roll(message, args, command);

View File

@ -10,7 +10,7 @@ import {
log,
LT,
} from '../deps.ts';
import { dbClient } from './db.ts';
import dbClient from './db/client.ts';
import endpoints from './endpoints/_index.ts';
import stdResp from './endpoints/stdResponses.ts';
@ -44,7 +44,9 @@ const start = async (): Promise<void> => {
// Check the requests API key
if (request.headers.has('X-Api-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 (dbApiQuery.length === 1) {
@ -58,7 +60,7 @@ const start = async (): Promise<void> => {
const apiTimeNow = new Date().getTime();
// 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
const currentCnt = rateLimitCnt.get(apiUseridStr) || 0;
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 {
// Discordeno deps
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
if (message.guildId === 0n) {
message.send({
embeds: [{
message
.send({
embeds: [
{
color: failColor,
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;
}
@ -63,12 +68,17 @@ export const api = async (message: DiscordenoMessage, args: string[]) => {
break;
}
} else {
message.send({
embeds: [{
message
.send({
embeds: [
{
color: failColor,
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).',
}],
}).catch((e: Error) => utils.commonLoggers.messageSendError('apiCmd.ts:77', message, e));
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));
}
};

View File

@ -1,4 +1,4 @@
import { dbClient } from '../../db.ts';
import dbClient from '../../db/client.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -8,7 +8,9 @@ import utils from '../../utils.ts';
export const allowBlock = async (message: DiscordenoMessage, apiArg: string) => {
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);
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:16', message, e));
errorOutInitial = true;
@ -18,22 +20,30 @@ export const allowBlock = async (message: DiscordenoMessage, apiArg: string) =>
let errorOut = false;
if (guildQuery.length === 0) {
// 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(
(e0) => {
await dbClient
.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);
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:27', message, e));
errorOut = true;
},
);
});
} else {
// 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(
(e0) => {
await dbClient
.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);
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:36', message, e));
errorOut = true;
},
);
});
}
if (errorOut) return;

View File

@ -1,4 +1,4 @@
import { dbClient } from '../../db.ts';
import dbClient from '../../db/client.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -10,22 +10,30 @@ export const deleteGuild = async (message: DiscordenoMessage) => {
let errorOut = false;
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);
message.send({
embeds: [{
message
.send({
embeds: [
{
color: failColor,
title: 'Failed to delete this guild from the database.',
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;
});
if (errorOut) return;
// We won't get here if there's any errors, so we know it has bee successful, so report as such
message.send({
embeds: [{
message
.send({
embeds: [
{
color: successColor,
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));
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));
};

View File

@ -1,4 +1,4 @@
import { dbClient } from '../../db.ts';
import dbClient from '../../db/client.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -8,7 +8,9 @@ import utils from '../../utils.ts';
export const showHideWarn = async (message: DiscordenoMessage, apiArg: string) => {
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);
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:16', message, e));
errorOutInitial = true;
@ -18,14 +20,22 @@ export const showHideWarn = async (message: DiscordenoMessage, apiArg: string) =
let errorOut = false;
if (guildQuery.length === 0) {
// 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);
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:26', message, e));
errorOut = true;
});
} else {
// 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);
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:33', message, e));
errorOut = true;

View File

@ -1,4 +1,4 @@
import { dbClient } from '../../db.ts';
import dbClient from '../../db/client.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -9,15 +9,21 @@ import utils from '../../utils.ts';
export const status = async (message: DiscordenoMessage) => {
// Get status of guild from the db
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);
message.send({
embeds: [{
message
.send({
embeds: [
{
color: failColor,
title: 'Failed to check API rolls status for this guild.',
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;
});
if (errorOut) return;

View File

@ -1,5 +1,6 @@
import config from '../../config.ts';
import { dbClient, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -38,11 +39,15 @@ export const audit = async (message: DiscordenoMessage, args: string[]) => {
break;
}
} else {
message.send({
embeds: [{
message
.send({
embeds: [
{
color: failColor,
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 {
// Discordeno deps
DiscordenoMessage,
@ -28,13 +28,15 @@ export const auditDB = async (message: DiscordenoMessage) => {
// Send the results
m.edit({
embeds: [{
embeds: [
{
color: infoColor2,
title: 'Database Audit',
description: 'Lists all tables with their current size and row count.',
timestamp: new Date().toISOString(),
fields: embedFields,
}],
},
],
}).catch((e: Error) => utils.commonLoggers.messageEditError('auditDB.ts:43', message, e));
} catch (e) {
utils.commonLoggers.messageSendError('auditDB.ts:45', message, e);

View File

@ -1,5 +1,6 @@
import config from '../../config.ts';
import { dbClient, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import {
// Discordeno deps
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));
// 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
if (emji.deleteSender) {
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 { dbClient, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -16,16 +17,22 @@ export const handleMentions = (message: DiscordenoMessage) => {
// 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));
message.send({
embeds: [{
message
.send({
embeds: [
{
color: infoColor1,
title: `Hello! I am ${config.name}!`,
fields: [{
fields: [
{
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\`.
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 {
// Discordeno deps
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));
if (config.api.enable) {
message.send({
embeds: [{
message
.send({
embeds: [
{
title: 'Roll Heatmap',
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: {
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 {
message.send({
embeds: [{
message
.send({
embeds: [
{
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,
}],
}).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 { dbClient, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -11,10 +12,12 @@ export const help = (message: DiscordenoMessage) => {
// 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));
message.send({
embeds: [{
message
.send({
embeds: [
{
color: infoColor2,
title: 'The Artificer\'s Available Commands:',
title: "The Artificer's Available Commands:",
fields: [
{
name: `\`${config.prefix}?\``,
@ -88,11 +91,12 @@ export const help = (message: DiscordenoMessage) => {
},
{
name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`,
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`,
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`,
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 { dbClient, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -11,14 +12,18 @@ export const info = (message: DiscordenoMessage) => {
// 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));
message.send({
embeds: [{
message
.send({
embeds: [
{
color: infoColor2,
title: `${config.name}, a Discord bot that specializing in rolling dice and calculating math`,
description: `${config.name} is developed by Ean AKA Burn_E99.
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).
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 { dbClient, ignoreList, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries, ignoreList } from '../db/common.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -17,23 +18,31 @@ export const optIn = async (message: DiscordenoMessage) => {
ignoreList.splice(idIdx, 1);
await dbClient.execute('DELETE FROM ignore_list WHERE userid = ?', [message.authorId]);
message.reply({
embeds: [{
message
.reply({
embeds: [
{
color: successColor,
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:
\`${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) {
message.reply({
embeds: [{
message
.reply({
embeds: [
{
color: failColor,
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.',
}],
}).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 { dbClient, ignoreList, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries, ignoreList } from '../db/common.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -15,22 +16,30 @@ export const optOut = async (message: DiscordenoMessage) => {
ignoreList.push(message.authorId);
await dbClient.execute('INSERT INTO ignore_list(userid) values(?)', [message.authorId]);
message.reply({
embeds: [{
message
.reply({
embeds: [
{
color: successColor,
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:
\`${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) {
message.reply({
embeds: [{
message
.reply({
embeds: [
{
color: failColor,
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.`,
}],
}).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 {
// Discordeno deps
DiscordenoMessage,

View File

@ -1,5 +1,6 @@
import config from '../../config.ts';
import { dbClient, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -11,21 +12,26 @@ export const privacy = (message: DiscordenoMessage) => {
// 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));
message.send({
embeds: [{
message
.send({
embeds: [
{
color: infoColor1,
title: 'Privacy Policy',
fields: [{
fields: [
{
name: 'The Artificer does not track or collect user information via Discord.',
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.
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.
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).
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 { dbClient, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -15,20 +16,28 @@ export const report = (message: DiscordenoMessage, args: string[]) => {
if (args.join(' ')) {
sendMessage(config.reportChannel, generateReport(args.join(' '))).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:22', message, e));
message.send({
embeds: [{
message
.send({
embeds: [
{
color: successColor,
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).`,
}],
}).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:29', message, e));
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:29', message, e));
} else {
message.send({
embeds: [{
message
.send({
embeds: [
{
color: failColor,
title: 'Please provide a short description of what failed',
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 {
// Discordeno deps
DiscordenoMessage,
@ -10,13 +11,17 @@ export const rip = (message: DiscordenoMessage) => {
// 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));
message.send({
embeds: [{
message
.send({
embeds: [
{
color: infoColor2,
title: 'The Artificer was built in memory of my Grandmother, Babka',
description: `With much love, Ean
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 { DEVMODE } from '../../flags.ts';
import { dbClient, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import {
// Discordeno deps
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 && message.guildId !== config.devServer) {
message.send({
embeds: [{
message
.send({
embeds: [
{
color: warnColor,
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;
}
@ -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
const rollCmd = message.content.substring(2);
queueRoll(
<QueuedRoll> {
queueRoll(<QueuedRoll>{
apiRoll: false,
dd: { m, message },
rollCmd,
modifiers,
originalCommand,
},
);
});
} catch (e) {
log(LT.ERROR, `Undandled Error: ${JSON.stringify(e)}`);
}

View File

@ -1,6 +1,7 @@
import config from '../../../config.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 {
// Discordeno deps
DiscordenoMessage,
@ -55,7 +56,7 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
modifiers.gmRoll = true;
// -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)}`);
// 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, ''));
@ -63,11 +64,15 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
}
if (modifiers.gms.length < 1) {
// 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 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;
}
@ -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
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
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 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;
}
@ -103,11 +112,15 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
// maxRoll and nominalRoll cannot both be on, throw an error
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 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;
}

View File

@ -1,5 +1,6 @@
import config from '../../config.ts';
import { dbClient, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -11,7 +12,8 @@ export const rollDecorators = (message: DiscordenoMessage) => {
// 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));
message.send({
message
.send({
embeds: [
{
color: infoColor2,
@ -47,7 +49,8 @@ Examples: \`${config.prefix}d20${config.postfix} -nd\`, \`${config.prefix}d20${c
},
{
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,
},
{
@ -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 { dbClient, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -11,11 +12,12 @@ export const rollHelp = (message: DiscordenoMessage) => {
// 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));
message.send({
message
.send({
embeds: [
{
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.
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]',
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,
},
{
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,
},
{
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,
},
{
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,
},
{
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,
},
{
@ -185,27 +192,32 @@ Additionally, replace \`x\` with \`F\` to roll Fate dice`,
},
{
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,
},
{
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,
},
{
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,
},
{
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,
},
{
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,
},
],
@ -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 {
// Discordeno deps
cache,
@ -17,8 +18,12 @@ export const stats = async (message: DiscordenoMessage) => {
const m = await message.send(compilingStats);
// 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 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 rollQuery = await dbClient
.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 rollRate = parseFloat(rollQuery[0].hourlyRate);
const total = BigInt(totalQuery[0].count);
@ -27,9 +32,17 @@ export const stats = async (message: DiscordenoMessage) => {
const cachedGuilds = await cacheHandlers.size('guilds');
const cachedChannels = await cacheHandlers.size('channels');
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((
e: Error,
) => utils.commonLoggers.messageEditError('stats.ts:38', m, e));
m.edit(
generateStats(
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) {
utils.commonLoggers.messageSendError('stats.ts:41', message, e);
}

View File

@ -1,5 +1,6 @@
import config from '../../config.ts';
import { dbClient, queries } from '../db.ts';
import dbClient from '../db/client.ts';
import { queries } from '../db/common.ts';
import {
// Discordeno deps
DiscordenoMessage,
@ -11,10 +12,14 @@ export const version = (message: DiscordenoMessage) => {
// 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));
message.send({
embeds: [{
message
.send({
embeds: [
{
color: infoColor1,
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 { dbClient } from '../../db.ts';
import dbClient from '../../db/client.ts';
import {
// nanoid deps
nanoid,
@ -10,10 +10,16 @@ import { generateApiDeleteEmail } from '../../commandUtils.ts';
import utils from '../../utils.ts';
import stdResp from '../stdResponses.ts';
export const apiKeyDelete = async (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)) {
export const apiKeyDelete = async (
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 (query.has('code') && ((query.get('code') || '').length > 0)) {
if (query.has('code') && (query.get('code') || '').length > 0) {
if ((query.get('code') || '') === apiUserDelCode) {
// User has recieved their delete code and we need to delete the account now
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 utils from '../../utils.ts';
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')) {
// Flag to see if there is an error inside the catch
let erroredOut = false;

View File

@ -1,5 +1,5 @@
import config from '../../../config.ts';
import { dbClient } from '../../db.ts';
import dbClient from '../../db/client.ts';
import {
// nanoid deps
nanoid,
@ -11,7 +11,7 @@ import utils from '../../utils.ts';
import stdResp from '../stdResponses.ts';
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
const newKey = await nanoid(25);
@ -19,13 +19,13 @@ export const apiKey = async (requestEvent: Deno.RequestEvent, query: Map<string,
let erroredOut = false;
// 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(
(e) => {
await dbClient
.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);
requestEvent.respondWith(stdResp.InternalServerError('Failed to store key.'));
erroredOut = true;
},
);
});
// Exit this case now if catch errored
if (erroredOut) {

View File

@ -1,5 +1,5 @@
import config from '../../../config.ts';
import { dbClient } from '../../db.ts';
import dbClient from '../../db/client.ts';
import {
// nanoid deps
nanoid,
@ -8,7 +8,7 @@ import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts';
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')) {
// Generate new secure key
const newKey = await nanoid(25);
@ -28,7 +28,7 @@ export const apiKeyAdmin = async (requestEvent: Deno.RequestEvent, query: Map<st
return;
} else {
// 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;
}
} else {

View File

@ -1,5 +1,5 @@
import config from '../../../config.ts';
import { dbClient, queries } from '../../db.ts';
import dbClient from '../../db/client.ts';
import {
// Discordeno deps
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) => {
// Make sure query contains all the needed parts
if (
(query.has('rollstr') && ((query.get('rollstr') || '').length > 0)) && (query.has('channel') && ((query.get('channel') || '').length > 0)) &&
(query.has('user') && ((query.get('user') || '').length > 0))
query.has('rollstr') &&
(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')) {
// 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;
}
@ -31,8 +35,11 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
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
const dbChannelQuery = await dbClient.query('SELECT active, banned FROM allowed_channels WHERE userid = ? AND channelid = ?', [apiUserid, BigInt(query.get('channel') || '0')]);
if (dbChannelQuery.length === 1 && (apiUserid === BigInt(query.get('user') || '0')) && dbChannelQuery[0].active && !dbChannelQuery[0].banned) {
const dbChannelQuery = await dbClient.query('SELECT active, banned FROM allowed_channels WHERE userid = ? AND channelid = ?', [
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
const guild = cache.channels.get(BigInt(query.get('channel') || ''))?.guild;
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.'));
// 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;
}
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
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
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;
}
@ -85,22 +96,20 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
nominalRoll: query.has('n'),
gmRoll: query.has('gms'),
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'),
valid: true,
apiWarn: hideWarn ? '' : apiWarning,
};
// Parse the roll and get the return text
await queueRoll(
<QueuedRoll> {
await queueRoll(<QueuedRoll>{
apiRoll: true,
api: { requestEvent, channelId: BigInt(query.get('channel') || '0'), userId: BigInt(query.get('user') || '') },
rollCmd,
modifiers,
originalCommand,
},
);
});
} catch (err) {
// Handle any errors we missed
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
requestEvent.respondWith(
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 {

View File

@ -1,6 +1,6 @@
import {
// httpd deps
Status,
STATUS_CODE,
STATUS_TEXT,
} from '../../../deps.ts';
@ -11,9 +11,9 @@ export const heatmapPng = async (requestEvent: Deno.RequestEvent) => {
// Send basic OK to indicate key has been sent
requestEvent.respondWith(
new Response(file, {
status: Status.OK,
statusText: STATUS_TEXT[Status.OK],
status: STATUS_CODE.OK,
statusText: STATUS_TEXT[STATUS_CODE.OK],
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 utils from '../../utils.ts';
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')) {
// Flag to see if there is an error inside the catch
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 utils from '../../utils.ts';
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')) {
// Flag to see if there is an error inside the catch
let value, erroredOut = false;
let value,
erroredOut = false;
// Determine value to set
if (path.toLowerCase().indexOf('de') > 0) {
@ -16,7 +17,9 @@ export const apiChannelManageActive = async (requestEvent: Deno.RequestEvent, qu
}
// 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);
requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.'));
erroredOut = true;

View File

@ -1,16 +1,21 @@
import config from '../../../config.ts';
import { dbClient } from '../../db.ts';
import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts';
export const apiChannelManageBan = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => {
if (
(query.has('a') && ((query.get('a') || '').length > 0)) && (query.has('channel') && ((query.get('channel') || '').length > 0)) &&
(query.has('user') && ((query.get('user') || '').length > 0))
query.has('a') &&
(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')) {
// Flag to see if there is an error inside the catch
let value, erroredOut = false;
let value,
erroredOut = false;
// Determine value to set
if (path.toLowerCase().indexOf('un') > 0) {
@ -20,7 +25,9 @@ export const apiChannelManageBan = async (requestEvent: Deno.RequestEvent, query
}
// 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);
requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.'));
erroredOut = true;

View File

@ -1,10 +1,10 @@
import config from '../../../config.ts';
import { dbClient } from '../../db.ts';
import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts';
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')) {
// Flag to see if there is an error inside the catch
let key: string,

View File

@ -1,21 +1,23 @@
import {
// httpd deps
Status,
StatusCode,
STATUS_CODE,
STATUS_TEXT,
} 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 {
BadRequest: (customText: string) => genericResponse(customText, Status.BadRequest),
FailedDependency: (customText: string) => genericResponse(customText, Status.FailedDependency),
InternalServerError: (customText: string) => genericResponse(customText, Status.InternalServerError),
Forbidden: (customText: string) => genericResponse(customText, Status.Forbidden),
MethodNotAllowed: (customText: string) => genericResponse(customText, Status.MethodNotAllowed),
NotFound: (customText: string) => genericResponse(customText, Status.NotFound),
OK: (customText: string) => genericResponse(customText, Status.OK),
RequestTimeout: (customText: string) => genericResponse(customText, Status.RequestTimeout),
TooManyRequests: (customText: string) => genericResponse(customText, Status.TooManyRequests),
BadRequest: (customText: string) => genericResponse(customText, STATUS_CODE.BadRequest),
FailedDependency: (customText: string) => genericResponse(customText, STATUS_CODE.FailedDependency),
InternalServerError: (customText: string) => genericResponse(customText, STATUS_CODE.InternalServerError),
Forbidden: (customText: string) => genericResponse(customText, STATUS_CODE.Forbidden),
MethodNotAllowed: (customText: string) => genericResponse(customText, STATUS_CODE.MethodNotAllowed),
NotFound: (customText: string) => genericResponse(customText, STATUS_CODE.NotFound),
OK: (customText: string) => genericResponse(customText, STATUS_CODE.OK),
RequestTimeout: (customText: string) => genericResponse(customText, STATUS_CODE.RequestTimeout),
TooManyRequests: (customText: string) => genericResponse(customText, STATUS_CODE.TooManyRequests),
Strings: {
missingParams: 'Missing Parameters.',
restricted: 'This API is restricted.',

View File

@ -15,7 +15,8 @@ import {
LT,
} from '../deps.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 config from '../config.ts';
@ -23,7 +24,7 @@ import config from '../config.ts';
// Gets a new random status for the bot
const getRandomStatus = async (): Promise<string> => {
let status = '';
switch (Math.floor((Math.random() * 4) + 1)) {
switch (Math.floor(Math.random() * 4 + 1)) {
case 1:
status = `${config.prefix}help for commands`;
break;
@ -55,14 +56,14 @@ const updateListStatistics = (botID: bigint, serverCount: number): void => {
tempHeaders.append('Content-Type', 'application/json');
// ?{} 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()), {
'method': 'POST',
'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
method: 'POST',
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
});
log(LT.INFO, `Posted server count to ${e.name}. Results: ${JSON.stringify(response)}`);
}
} 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
const updateHourlyRates = async () => {
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);
if (previousHours.length > 1) {
const oldestHour = previousHours[0];
@ -83,7 +86,7 @@ const updateHourlyRates = async () => {
for (let i = 0; i < newestHour.length; i++) {
computedDiff.push({
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)}`);
}
@ -91,9 +94,9 @@ const updateHourlyRates = async () => {
// Update DB
computedDiff.forEach(async (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) =>
utils.commonLoggers.dbError('intervals.ts:88', 'update', e)
);
await dbClient
.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;
}
// 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;
maxRollCnt = 0;
@ -191,11 +196,7 @@ const updateHeatmapPng = async () => {
hourPixels[hour][0] + 1,
dayPixels[day][1] - dayPixels[day][0] + 1,
hourPixels[hour][1] - hourPixels[hour][0] + 1,
is.Image.rgbToColor(
255 * (1 - percent),
255 * percent,
0,
),
is.Image.rgbToColor(255 * (1 - percent), 255 * percent, 0)
);
}
}

View File

@ -1,6 +1,7 @@
import config from '../../config.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 {
// Discordeno deps
DiscordenoMessage,
@ -36,19 +37,23 @@ const handleRollWorker = async (rq: QueuedRoll) => {
if (rq.apiRoll) {
rq.api.requestEvent.respondWith(stdResp.RequestTimeout('Roll took too long to process, try breaking roll down into simpler parts'));
} else {
rq.dd.m.edit({
rq.dd.m
.edit({
embeds: [
(await generateRollEmbed(
(
await generateRollEmbed(
rq.dd.message.authorId,
<SolvedRoll>{
error: true,
errorCode: 'TooComplex',
errorMsg: 'Error: Roll took too long to process, try breaking roll down into simpler parts',
},
<RollModifiers> {},
)).embed,
<RollModifiers>{}
)
).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);
@ -77,11 +82,11 @@ const handleRollWorker = async (rq: QueuedRoll) => {
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
dbClient.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)
);
dbClient
.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 {
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
await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), {
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
if (gmEmbedDetails.hasAttachment) {
await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), {
@ -120,7 +126,8 @@ const handleRollWorker = async (rq: QueuedRoll) => {
}
});
}
}).catch(() => {
})
.catch(() => {
if (rq.apiRoll && n) {
n.reply(generateDMFailed(gm));
} else {
@ -154,9 +161,13 @@ const handleRollWorker = async (rq: QueuedRoll) => {
}
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
? {
counts: countEmbed,
@ -164,8 +175,10 @@ const handleRollWorker = async (rq: QueuedRoll) => {
}
: {
details: pubEmbedDetails,
},
)));
}
)
)
);
}
}
} catch (e) {
@ -184,22 +197,29 @@ export const queueRoll = async (rq: QueuedRoll) => {
} else if (!rollQueue.length && currentWorkers < config.limits.maxWorkers) {
handleRollWorker(rq);
} else {
rq.dd.m.edit({
embeds: [{
rq.dd.m
.edit({
embeds: [
{
color: infoColor2,
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.
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);
}
};
// Checks the queue constantly to make sure the queue stays empty
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) {
const temp = rollQueue.shift();
if (temp) {