Compare commits

..

No commits in common. "master" and "V2.0.1" have entirely different histories.

21 changed files with 39 additions and 181 deletions

View File

@ -39,7 +39,7 @@ If you would like to remove all of your submitted data, this can easily be done
If you have been banned from using _The API_, your API Key, and registration information (Discord User ID, and Email Address) will not be deleted as this data is considered necessary. If you have been banned from using _The API_, your API Key, and registration information (Discord User ID, and Email Address) will not be deleted as this data is considered necessary.
If you would like your Discord Guild ID to be removed from _The Bot_'s database, a Guild Owner or Administrator needs to run `[[api delete`. This will remove your Discord Guild's ID from _The Bot_'s database, reverting it back to the default setting of blocking _The API_. Additionally, _The Bot_ will automatically remove any data related to your Discord Guild when _The Bot_ is removed from your guild. If you would like your Discord Guild ID to be removed from _The Bot_'s database, a Guild Owner or Administrator needs to run `[[api delete`. This will remove your Discord Guild's ID from _The Bot_'s database, reverting it back to the default setting of blocking _The API_.
If your guild has been banned from using _The API_, the Discord Guild ID will not be deleted as this data is considered necessary. If your guild has been banned from using _The API_, the Discord Guild ID will not be deleted as this data is considered necessary.

View File

@ -1,4 +1,4 @@
# The Artificer - A Dice Rolling Discord Bot | V2.1.2 - 2022/07/31 # The Artificer - A Dice Rolling Discord Bot | V2.0.1 - 2022/07/08
[![SonarCloud](https://sonarcloud.io/images/project_badges/sonarcloud-orange.svg)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![SonarCloud](https://sonarcloud.io/images/project_badges/sonarcloud-orange.svg)](https://sonarcloud.io/summary/new_code?id=TheArtificer)
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=bugs)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=ncloc)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=bugs)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=TheArtificer) [![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=TheArtificer&metric=ncloc)](https://sonarcloud.io/summary/new_code?id=TheArtificer)
@ -59,10 +59,6 @@ The Artificer comes with a few supplemental commands to the main rolling command
* If you encounter a command that errors out or returns something unexpected, please use this command to alert the developers of the problem. * If you encounter a command that errors out or returns something unexpected, please use this command to alert the developers of the problem.
* Example: * Example:
* `[[report [[2+2]] returned 5 when I expected it to return 4` will send the entire message after `[[report` to the devs via Discord. * `[[report [[2+2]] returned 5 when I expected it to return 4` will send the entire message after `[[report` to the devs via Discord.
* `[[opt-out` or `[[ignore-me`
* Adds you to an ignore list so the bot will never respond to you
* `[[opt-in` **Available via DM ONLY**
* Removes you from the ignore list
* `[[xdydzracsq!]]` * `[[xdydzracsq!]]`
* This is the command the bot was built specifically for. * This is the command the bot was built specifically for.
* It looks a little complicated at first, but if you are familiar with the [Roll20 formatting](https://artificer.eanm.dev/roll20), this will no different. * It looks a little complicated at first, but if you are familiar with the [Roll20 formatting](https://artificer.eanm.dev/roll20), this will no different.
@ -220,7 +216,7 @@ The Artificer is built on [Deno](https://deno.land/) `v1.22.0` using [Discordeno
You will also need to install and setup a MySQL database with a user for the bot to use to add/modify the database. This user must have the "DB Manager" admin rights and "REFERENCES" Global Privileges. Once the DB is installed and a user is setup, run the provided `db\initialize.ts` to create the schema and tables. After this, run `db\populateDefaults.ts` to insert some needed values into the tables. You will also need to install and setup a MySQL database with a user for the bot to use to add/modify the database. This user must have the "DB Manager" admin rights and "REFERENCES" Global Privileges. Once the DB is installed and a user is setup, run the provided `db\initialize.ts` to create the schema and tables. After this, run `db\populateDefaults.ts` to insert some needed values into the tables.
Once everything is set up, starting the bot can simply be done with the command in `start.command`. Once everything is set up, starting the bot can simply be done with `deno run --allow-net .\mod.ts`.
If you choose to run version `1.1.0` or newer, ensure you disable the API in `config.ts` or verify you have properly secured your instance of The Artificer. If you enable the API, you should manually generate a 25 char nanoid and place it in `config.api.adminKey` and copy your `userid` and place it in `config.api.admin` before running `db\populateDefaults.ts`. If you choose to run version `1.1.0` or newer, ensure you disable the API in `config.ts` or verify you have properly secured your instance of The Artificer. If you enable the API, you should manually generate a 25 char nanoid and place it in `config.api.adminKey` and copy your `userid` and place it in `config.api.admin` before running `db\populateDefaults.ts`.

View File

@ -10,12 +10,11 @@ pidfile="/var/dbots/TheArtificer/artificer.pid"
artificer_root="/var/dbots/TheArtificer" artificer_root="/var/dbots/TheArtificer"
artificer_write="./logs/,./src/endpoints/gets/heatmap.png" artificer_write="./logs/,./src/endpoints/gets/heatmap.png"
artificer_read="./src/solver/,./src/endpoints/gets/heatmap-base.png,./src/endpoints/gets/heatmap.png,./config.ts,./deps.ts,./src/mod.d.ts" artificer_read="./src/solver/,./src/endpoints/gets/heatmap-base.png,./src/endpoints/gets/heatmap.png"
artificer_log="/var/log/artificer.log"
artificer_chdir="${artificer_root}" artificer_chdir="${artificer_root}"
command="/usr/sbin/daemon" command="/usr/sbin/daemon"
command_args="-f -R 5 -P ${pidfile} -o ${artificer_log} /usr/local/bin/deno run --allow-write=${artificer_write} --allow-read=${artificer_read} --allow-net ${artificer_root}/mod.ts" command_args="-f -R 5 -P ${pidfile} /usr/local/bin/deno run --allow-write=${artificer_write} --allow-read=${artificer_read} --allow-net ${artificer_root}/mod.ts"
load_rc_config artificer load_rc_config artificer
run_rc_command "$1" run_rc_command "$1"

View File

@ -6,7 +6,7 @@ After=network.target
[Service] [Service]
Type=simple Type=simple
PIDFile=/run/deno.pid PIDFile=/run/deno.pid
ExecStart=/root/.deno/bin/deno run --allow-write=./logs/,./src/endpoints/gets/heatmap.png --allow-read=./src/solver/,./src/endpoints/gets/heatmap-base.png,./config.ts,./deps.ts,./src/mod.d.ts --allow-net .\mod.ts ExecStart=/root/.deno/bin/deno run --allow-write=./logs/,./src/endpoints/gets/heatmap.png --allow-read=./src/solver/,./src/endpoints/gets/heatmap-base.png --allow-net .\mod.ts
RestartSec=60 RestartSec=60
Restart=on-failure Restart=on-failure

View File

@ -1,6 +1,6 @@
export const config = { export const config = {
'name': 'The Artificer', // Name of the bot 'name': 'The Artificer', // Name of the bot
'version': '2.1.3', // Version of the bot 'version': '2.0.1', // Version of the bot
'token': 'the_bot_token', // Discord API Token for this bot 'token': 'the_bot_token', // Discord API Token for this bot
'localtoken': 'local_testing_token', // Discord API Token for a secondary OPTIONAL testing bot, THIS MUST BE DIFFERENT FROM "token" 'localtoken': 'local_testing_token', // Discord API Token for a secondary OPTIONAL testing bot, THIS MUST BE DIFFERENT FROM "token"
'prefix': '[[', // Prefix for all commands 'prefix': '[[', // Prefix for all commands

View File

@ -19,20 +19,8 @@ await dbClient.execute(`DROP PROCEDURE IF EXISTS INC_HEATMAP;`);
await dbClient.execute(`DROP TABLE IF EXISTS roll_time_heatmap;`); await dbClient.execute(`DROP TABLE IF EXISTS roll_time_heatmap;`);
await dbClient.execute(`DROP PROCEDURE IF EXISTS INC_CNT;`); await dbClient.execute(`DROP PROCEDURE IF EXISTS INC_CNT;`);
await dbClient.execute(`DROP TABLE IF EXISTS command_cnt;`); await dbClient.execute(`DROP TABLE IF EXISTS command_cnt;`);
await dbClient.execute(`DROP TABLE IF EXISTS ignore_list;`);
console.log('Tables dropped'); console.log('Tables dropped');
// Table to hold list of users who want to be ignored by the bot
console.log('Attempting to create table ignore_list');
await dbClient.execute(`
CREATE TABLE ignore_list (
userid bigint unsigned NOT NULL,
PRIMARY KEY (userid),
UNIQUE KEY ignore_list_userid_UNIQUE (userid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
`);
console.log('Table created');
// Light telemetry on how many commands have been run // Light telemetry on how many commands have been run
console.log('Attempting to create table command_cnt'); console.log('Attempting to create table command_cnt');
await dbClient.execute(` await dbClient.execute(`

View File

@ -10,7 +10,7 @@ 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'];
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);

20
mod.ts
View File

@ -25,7 +25,7 @@ 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.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';
@ -71,7 +71,7 @@ startBot({
// 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);
}, 86400000); }, 86400000);
// Interval to update hourlyRates every hour // Interval to update hourlyRates every hour
@ -89,7 +89,7 @@ startBot({
// setTimeout added to make sure the startup message does not error out // setTimeout added to make sure the startup message does not error out
setTimeout(() => { setTimeout(() => {
LOCALMODE && editBotNickname(config.devServer, `LOCAL - ${config.name}`); LOCALMODE && editBotNickname(config.devServer, `LOCAL - ${config.name}`);
LOCALMODE ? log(LT.INFO, 'updateListStatistics not running') : intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size); LOCALMODE ? log(LT.INFO, 'updateListStatistics not running') : intervals.updateListStatistics(botId, cache.guilds.size);
intervals.updateHourlyRates(); intervals.updateHourlyRates();
intervals.updateHeatmapPng(); intervals.updateHeatmapPng();
editBotStatus({ editBotStatus({
@ -173,9 +173,6 @@ startBot({
// Ignore all other bots // Ignore all other bots
if (message.isBot) return; if (message.isBot) return;
// Ignore users who requested to be ignored
if (ignoreList.includes(message.authorId) && (!message.content.startsWith(`${config.prefix}opt-in`) || message.guildId !== 0n)) return;
// Ignore all messages that are not commands // Ignore all messages that are not commands
if (message.content.indexOf(config.prefix) !== 0) { if (message.content.indexOf(config.prefix) !== 0) {
// Handle @bot messages // Handle @bot messages
@ -196,17 +193,6 @@ startBot({
// All commands below here // All commands below here
switch (command) { switch (command) {
case 'opt-out':
case 'ignore-me':
// [[opt-out or [[ignore-me
// Tells the bot to add you to the ignore list.
commands.optOut(message);
break;
case 'opt-in':
// [[opt-in
// Tells the bot to remove you from the ignore list.
commands.optIn(message);
break;
case 'ping': case 'ping':
// [[ping // [[ping
// Its a ping test, what else do you want. // Its a ping test, what else do you want.

View File

@ -14,8 +14,6 @@ import { roll } from './roll.ts';
import { handleMentions } from './handleMentions.ts'; import { handleMentions } from './handleMentions.ts';
import { audit } from './audit.ts'; import { audit } from './audit.ts';
import { heatmap } from './heatmap.ts'; import { heatmap } from './heatmap.ts';
import { optOut } from './optOut.ts';
import { optIn } from './optIn.ts';
export default { export default {
ping, ping,
@ -34,6 +32,4 @@ export default {
handleMentions, handleMentions,
audit, audit,
heatmap, heatmap,
optOut,
optIn,
}; };

View File

@ -21,10 +21,8 @@ export const handleMentions = (message: DiscordenoMessage) => {
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.`,
}], }],
}], }],
}).catch((e: Error) => utils.commonLoggers.messageSendError('handleMentions.ts:30', message, e)); }).catch((e: Error) => utils.commonLoggers.messageSendError('handleMentions.ts:30', message, e));

View File

@ -76,16 +76,6 @@ export const help = (message: DiscordenoMessage) => {
value: 'Heatmap of when the roll command is run the most', value: 'Heatmap of when the roll command is run the most',
inline: true, inline: true,
}, },
{
name: `\`${config.prefix}opt-out\` or \`${config.prefix}ignore-me\``,
value: 'Adds you to an ignore list so the bot will never respond to you',
inline: true,
},
{
name: `\`${config.prefix}opt-in\` **Available via DM ONLY**`,
value: 'Removes you from the ignore list',
inline: true,
},
{ {
name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`, name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`,
value: value:

View File

@ -1,4 +1,3 @@
import config from '../../config.ts';
import { dbClient, queries } from '../db.ts'; import { dbClient, queries } from '../db.ts';
import { import {
// Discordeno deps // Discordeno deps
@ -9,16 +8,16 @@ import utils from '../utils.ts';
export const info = (message: DiscordenoMessage) => { 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:14', 'call sproc INC_CNT on', e));
message.send({ message.send({
embeds: [{ embeds: [{
color: infoColor2, color: infoColor2,
title: `${config.name}, a Discord bot that specializing in rolling dice and calculating math`, title: 'The Artificer, a Discord bot that specializing in rolling dice and calculating math',
description: `${config.name} is developed by Ean AKA Burn_E99. description: `The Artificer 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:27', message, e));
}; };

View File

@ -1,39 +0,0 @@
import config from '../../config.ts';
import { dbClient, ignoreList, queries } from '../db.ts';
import {
// Discordeno deps
DiscordenoMessage,
} from '../../deps.ts';
import { failColor, successColor } from '../commandUtils.ts';
import utils from '../utils.ts';
export const optIn = async (message: DiscordenoMessage) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('opt-out')).catch((e) => utils.commonLoggers.dbError('optIn.ts:11', 'call sproc INC_CNT on', e));
const idIdx = ignoreList.indexOf(message.authorId);
if (idIdx !== -1) {
try {
ignoreList.splice(idIdx, 1);
await dbClient.execute('DELETE FROM ignore_list WHERE userid = ?', [message.authorId]);
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 (err) {
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));
}
}
};

View File

@ -1,36 +0,0 @@
import config from '../../config.ts';
import { dbClient, ignoreList, queries } from '../db.ts';
import {
// Discordeno deps
DiscordenoMessage,
} from '../../deps.ts';
import { failColor, successColor } from '../commandUtils.ts';
import utils from '../utils.ts';
export const optOut = async (message: DiscordenoMessage) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('opt-out')).catch((e) => utils.commonLoggers.dbError('optOut.ts:11', 'call sproc INC_CNT on', e));
try {
ignoreList.push(message.authorId);
await dbClient.execute('INSERT INTO ignore_list(userid) values(?)', [message.authorId]);
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 (err) {
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));
}
};

View File

@ -22,9 +22,7 @@ export const privacy = (message: DiscordenoMessage) => {
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.`,
}], }],
}], }],
}).catch((e: Error) => utils.commonLoggers.messageSendError('privacy.ts:33', message, e)); }).catch((e: Error) => utils.commonLoggers.messageSendError('privacy.ts:33', message, e));

View File

@ -46,7 +46,7 @@ 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 = `${command} ${args.join(' ')}`;
queueRoll( queueRoll(
<QueuedRoll> { <QueuedRoll> {

View File

@ -2,10 +2,6 @@ import config from '../config.ts';
import { Client } from '../deps.ts'; import { Client } from '../deps.ts';
import { LOCALMODE } from '../flags.ts'; import { LOCALMODE } from '../flags.ts';
type UserIdObj = {
userid: bigint;
};
export const dbClient = await new Client().connect({ export const dbClient = await new Client().connect({
hostname: LOCALMODE ? config.db.localhost : config.db.host, hostname: LOCALMODE ? config.db.localhost : config.db.host,
port: config.db.port, port: config.db.port,
@ -14,13 +10,6 @@ export const dbClient = await new Client().connect({
password: config.db.password, 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 weekDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
export const queries = { export const queries = {

View File

@ -47,22 +47,18 @@ const getRandomStatus = async (): Promise<string> => {
// Sends the current server count to all bot list sites we are listed on // Sends the current server count to all bot list sites we are listed on
const updateListStatistics = (botID: bigint, serverCount: number): void => { const updateListStatistics = (botID: bigint, serverCount: number): void => {
config.botLists.forEach(async (e) => { config.botLists.forEach(async (e) => {
try { log(LT.LOG, `Updating statistics for ${JSON.stringify(e)}`);
log(LT.LOG, `Updating statistics for ${JSON.stringify(e)}`); if (e.enabled) {
if (e.enabled) { const tempHeaders = new Headers();
const tempHeaders = new Headers(); tempHeaders.append(e.headers[0].header, e.headers[0].value);
tempHeaders.append(e.headers[0].header, e.headers[0].value); tempHeaders.append('Content-Type', 'application/json');
tempHeaders.append('Content-Type', 'application/json'); // ?{} is a template used in config, just need to replace it with the real value
// ?{} is a template used in config, just need to replace it with the real value const response = await fetch(e.apiUrl.replace('?{bot_id}', botID.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) {
log(LT.ERROR, `Failed to update statistics for ${e.name} | Error: ${err.name} - ${err.message}`)
} }
}); });
}; };

View File

@ -178,22 +178,22 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
// If maximiseRoll or nominalRoll are on, mark the output as such, else use default formatting // If maximiseRoll or nominalRoll are on, mark the output as such, else use default formatting
if (modifiers.maxRoll) { if (modifiers.maxRoll) {
line1 = ` requested the theoretical maximum of:\n\`${config.prefix}${fullCmd}\``; line1 = ` requested the theoretical maximum of: \`${config.prefix}${fullCmd}\``;
line2 = 'Theoretical Maximum Results: '; line2 = 'Theoretical Maximum Results: ';
} else if (modifiers.nominalRoll) { } else if (modifiers.nominalRoll) {
line1 = ` requested the theoretical nominal of:\n\`${config.prefix}${fullCmd}\``; line1 = ` requested the theoretical nominal of: \`${config.prefix}${fullCmd}\``;
line2 = 'Theoretical Nominal Results: '; line2 = 'Theoretical Nominal Results: ';
} else if (modifiers.order === 'a') { } else if (modifiers.order === 'a') {
line1 = ` requested the following rolls to be ordered from least to greatest:\n\`${config.prefix}${fullCmd}\``; line1 = ` requested the following rolls to be ordered from least to greatest: \`${config.prefix}${fullCmd}\``;
line2 = 'Results: '; line2 = 'Results: ';
tempReturnData.sort(compareTotalRolls); tempReturnData.sort(compareTotalRolls);
} else if (modifiers.order === 'd') { } else if (modifiers.order === 'd') {
line1 = ` requested the following rolls to be ordered from greatest to least:\n\`${config.prefix}${fullCmd}\``; line1 = ` requested the following rolls to be ordered from greatest to least: \`${config.prefix}${fullCmd}\``;
line2 = 'Results: '; line2 = 'Results: ';
tempReturnData.sort(compareTotalRolls); tempReturnData.sort(compareTotalRolls);
tempReturnData.reverse(); tempReturnData.reverse();
} else { } else {
line1 = ` rolled:\n\`${config.prefix}${fullCmd}\``; line1 = ` rolled: \`${config.prefix}${fullCmd}\``;
line2 = 'Results: '; line2 = 'Results: ';
} }

View File

@ -61,10 +61,8 @@ export const fullSolver = (conf: (string | number | SolvedStep)[], wrapDetails:
throw new Error('UnbalancedParens'); throw new Error('UnbalancedParens');
} }
// Call the solver on the items between openParen and closeParen (excluding the parens) // Replace the itemes between openParen and closeParen (including the parens) with its solved equilvalent by calling the solver on the items between openParen and closeParen (excluding the parens)
const parenSolve = fullSolver(conf.slice(openParen + 1, closeParen), true); conf.splice(openParen, closeParen + 1, fullSolver(conf.slice(openParen + 1, closeParen), true));
// Replace the itemes between openParen and closeParen (including the parens) with its solved equilvalent
conf.splice(openParen, closeParen - openParen + 1, parenSolve);
// Determing if we need to add in a multiplication sign to handle implicit multiplication (like "(4)2" = 8) // Determing if we need to add in a multiplication sign to handle implicit multiplication (like "(4)2" = 8)
// insertedMult flags if there was a multiplication sign inserted before the parens // insertedMult flags if there was a multiplication sign inserted before the parens

View File

@ -1 +1 @@
deno run --allow-write=./logs/,./src/endpoints/gets/heatmap.png --allow-read=./src/solver/,./src/endpoints/gets/heatmap-base.png,./config.ts,./deps.ts,./src/mod.d.ts --allow-net .\mod.ts deno run --allow-write=./logs/,./src/endpoints/gets/heatmap.png --allow-read=./src/solver/,./src/endpoints/gets/heatmap-base.png --allow-net .\mod.ts