Compare commits
13 Commits
Author | SHA1 | Date |
---|---|---|
|
65fbd115fb | |
|
783395e4a5 | |
|
23ca3a2665 | |
|
766dff179e | |
|
7bb6018bdf | |
|
f43cf0fa31 | |
|
38146a3c8f | |
|
539616679b | |
|
7b03f3140e | |
|
74b0e287fb | |
|
f4b0e04cec | |
|
c4c7098479 | |
|
9a8c718d57 |
|
@ -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_.
|
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 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.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# The Artificer - A Dice Rolling Discord Bot | V2.0.0 - 2022/07/05
|
# The Artificer - A Dice Rolling Discord Bot | V2.1.2 - 2022/07/31
|
||||||
[](https://sonarcloud.io/summary/new_code?id=TheArtificer)
|
[](https://sonarcloud.io/summary/new_code?id=TheArtificer)
|
||||||
[](https://sonarcloud.io/summary/new_code?id=TheArtificer) [](https://sonarcloud.io/summary/new_code?id=TheArtificer) [](https://sonarcloud.io/summary/new_code?id=TheArtificer) [](https://sonarcloud.io/summary/new_code?id=TheArtificer) [](https://sonarcloud.io/summary/new_code?id=TheArtificer) [](https://sonarcloud.io/summary/new_code?id=TheArtificer)
|
[](https://sonarcloud.io/summary/new_code?id=TheArtificer) [](https://sonarcloud.io/summary/new_code?id=TheArtificer) [](https://sonarcloud.io/summary/new_code?id=TheArtificer) [](https://sonarcloud.io/summary/new_code?id=TheArtificer) [](https://sonarcloud.io/summary/new_code?id=TheArtificer) [](https://sonarcloud.io/summary/new_code?id=TheArtificer)
|
||||||
|
|
||||||
|
@ -59,6 +59,10 @@ 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.
|
||||||
|
@ -216,7 +220,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 `deno run --allow-net .\mod.ts`.
|
Once everything is set up, starting the bot can simply be done with the command in `start.command`.
|
||||||
|
|
||||||
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`.
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,12 @@ 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"
|
artificer_read="./src/solver/,./src/endpoints/gets/heatmap-base.png,./src/endpoints/gets/heatmap.png,./config.ts,./deps.ts,./src/mod.d.ts"
|
||||||
|
artificer_log="/var/log/artificer.log"
|
||||||
|
|
||||||
artificer_chdir="${artificer_root}"
|
artificer_chdir="${artificer_root}"
|
||||||
command="/usr/sbin/daemon"
|
command="/usr/sbin/daemon"
|
||||||
command_args="-c -f -P ${pidfile} /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} -o ${artificer_log} /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"
|
||||||
|
|
|
@ -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 --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,./config.ts,./deps.ts,./src/mod.d.ts --allow-net .\mod.ts
|
||||||
RestartSec=60
|
RestartSec=60
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
export const config = {
|
export const config = {
|
||||||
'name': 'The Artificer', // Name of the bot
|
'name': 'The Artificer', // Name of the bot
|
||||||
'version': '2.0.0', // Version of the bot
|
'version': '2.1.3', // 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
|
||||||
'postfix': ']]', // Postfix for rolling command
|
'postfix': ']]', // Postfix for rolling command
|
||||||
'limits': { // Limits for the bot functions
|
'limits': { // Limits for the bot functions
|
||||||
'maxLoops': 10000000, // Determines how long the bot will attempt a roll, number of loops before it kills a roll. Increase this at your own risk, originally was set to 5 Million before rollWorkers were added, increased to 10 Million since multiple rolls can be handled concurrently
|
'maxLoops': 5000000, // Determines how long the bot will attempt a roll, number of loops before it kills a roll. Increase this at your own risk, originally was set to 5 Million before rollWorkers were added, increased to 10 Million since multiple rolls can be handled concurrently
|
||||||
'maxWorkers': 16, // Maximum number of worker threads to spawn at once (Set this to less than the number of threads your CPU has, Artificer will eat it all if too many rolls happen at once)
|
'maxWorkers': 16, // Maximum number of worker threads to spawn at once (Set this to less than the number of threads your CPU has, Artificer will eat it all if too many rolls happen at once)
|
||||||
'workerTimeout': 300000, // Maximum time before the bot kills a worker thread in ms
|
'workerTimeout': 300000, // Maximum time before the bot kills a worker thread in ms
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,8 +19,20 @@ 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(`
|
||||||
|
|
|
@ -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'];
|
const commands = ['ping', 'rip', 'rollhelp', 'help', 'info', 'version', 'report', 'stats', 'roll', 'emojis', 'api', 'privacy', 'mention', 'audit', 'heatmap', 'rollDecorators', 'opt-out', 'opt-in'];
|
||||||
for (const command of commands) {
|
for (const command of commands) {
|
||||||
await dbClient.execute('INSERT INTO command_cnt(command) values(?)', [command]).catch((e) => {
|
await dbClient.execute('INSERT INTO command_cnt(command) values(?)', [command]).catch((e) => {
|
||||||
console.log(`Failed to insert ${command} into database`, e);
|
console.log(`Failed to insert ${command} into database`, e);
|
||||||
|
|
20
mod.ts
20
mod.ts
|
@ -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 } from './src/db.ts';
|
import { dbClient, ignoreList } 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);
|
intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.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);
|
LOCALMODE ? log(LT.INFO, 'updateListStatistics not running') : intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size);
|
||||||
intervals.updateHourlyRates();
|
intervals.updateHourlyRates();
|
||||||
intervals.updateHeatmapPng();
|
intervals.updateHeatmapPng();
|
||||||
editBotStatus({
|
editBotStatus({
|
||||||
|
@ -173,6 +173,9 @@ 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
|
||||||
|
@ -193,6 +196,17 @@ 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.
|
||||||
|
|
|
@ -14,6 +14,8 @@ 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,
|
||||||
|
@ -32,4 +34,6 @@ export default {
|
||||||
handleMentions,
|
handleMentions,
|
||||||
audit,
|
audit,
|
||||||
heatmap,
|
heatmap,
|
||||||
|
optOut,
|
||||||
|
optIn,
|
||||||
};
|
};
|
||||||
|
|
|
@ -79,6 +79,11 @@ Please see attached file for audit details on cached guilds and members.`,
|
||||||
value: `${botsCount}`,
|
value: `${botsCount}`,
|
||||||
inline: true,
|
inline: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Average members per guild:',
|
||||||
|
value: `${(totalCount / cache.guilds.size).toFixed(2)}`,
|
||||||
|
inline: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
file: {
|
file: {
|
||||||
|
|
|
@ -21,8 +21,10 @@ 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));
|
||||||
|
|
|
@ -76,6 +76,16 @@ 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:
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import config from '../../config.ts';
|
||||||
import { dbClient, queries } from '../db.ts';
|
import { dbClient, queries } from '../db.ts';
|
||||||
import {
|
import {
|
||||||
// Discordeno deps
|
// Discordeno deps
|
||||||
|
@ -8,16 +9,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:14', 'call sproc INC_CNT on', e));
|
dbClient.execute(queries.callIncCnt('info')).catch((e) => utils.commonLoggers.dbError('info.ts:12', 'call sproc INC_CNT on', e));
|
||||||
|
|
||||||
message.send({
|
message.send({
|
||||||
embeds: [{
|
embeds: [{
|
||||||
color: infoColor2,
|
color: infoColor2,
|
||||||
title: 'The Artificer, a Discord bot that specializing in rolling dice and calculating math',
|
title: `${config.name}, a Discord bot that specializing in rolling dice and calculating math`,
|
||||||
description: `The Artificer is developed by Ean AKA Burn_E99.
|
description: `${config.name} is developed by Ean AKA Burn_E99.
|
||||||
Additional information can be found on my website [here](https://discord.burne99.com/TheArtificer/).
|
Additional information can be found on my website [here](https://discord.burne99.com/TheArtificer/).
|
||||||
Want to check out my source code? Check it out [here](https://github.com/Burn-E99/TheArtificer).
|
Want to check out my source code? Check it out [here](https://github.com/Burn-E99/TheArtificer).
|
||||||
Need help with this bot? Join my support server [here](https://discord.gg/peHASXMZYv).`,
|
Need help with this bot? Join my support server [here](https://discord.gg/peHASXMZYv).`,
|
||||||
}],
|
}],
|
||||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('info.ts:27', message, e));
|
}).catch((e: Error) => utils.commonLoggers.messageSendError('info.ts:23', message, e));
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,36 @@
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
};
|
|
@ -22,7 +22,9 @@ 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));
|
||||||
|
|
|
@ -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 = `${command} ${args.join(' ')}`;
|
const rollCmd = message.content.substring(2);
|
||||||
|
|
||||||
queueRoll(
|
queueRoll(
|
||||||
<QueuedRoll> {
|
<QueuedRoll> {
|
||||||
|
|
11
src/db.ts
11
src/db.ts
|
@ -2,6 +2,10 @@ 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,
|
||||||
|
@ -10,6 +14,13 @@ 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 = {
|
||||||
|
|
|
@ -47,18 +47,22 @@ 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) => {
|
||||||
log(LT.LOG, `Updating statistics for ${JSON.stringify(e)}`);
|
try {
|
||||||
if (e.enabled) {
|
log(LT.LOG, `Updating statistics for ${JSON.stringify(e)}`);
|
||||||
const tempHeaders = new Headers();
|
if (e.enabled) {
|
||||||
tempHeaders.append(e.headers[0].header, e.headers[0].value);
|
const tempHeaders = new Headers();
|
||||||
tempHeaders.append('Content-Type', 'application/json');
|
tempHeaders.append(e.headers[0].header, e.headers[0].value);
|
||||||
// ?{} is a template used in config, just need to replace it with the real value
|
tempHeaders.append('Content-Type', 'application/json');
|
||||||
const response = await fetch(e.apiUrl.replace('?{bot_id}', botID.toString()), {
|
// ?{} is a template used in config, just need to replace it with the real value
|
||||||
'method': 'POST',
|
const response = await fetch(e.apiUrl.replace('?{bot_id}', botID.toString()), {
|
||||||
'headers': tempHeaders,
|
'method': 'POST',
|
||||||
'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
|
'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)}`);
|
});
|
||||||
|
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}`)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { fullSolver } from './solver.ts';
|
||||||
// parseRoll(fullCmd, modifiers)
|
// parseRoll(fullCmd, modifiers)
|
||||||
// parseRoll handles converting fullCmd into a computer readable format for processing, and finally executes the solving
|
// parseRoll handles converting fullCmd into a computer readable format for processing, and finally executes the solving
|
||||||
export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll => {
|
export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll => {
|
||||||
const operators = ['^', '*', '/', '%', '+', '-'];
|
const operators = ['^', '*', '/', '%', '+', '-', '(', ')'];
|
||||||
const returnmsg = <SolvedRoll> {
|
const returnmsg = <SolvedRoll> {
|
||||||
error: false,
|
error: false,
|
||||||
errorCode: '',
|
errorCode: '',
|
||||||
|
@ -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: \`${config.prefix}${fullCmd}\``;
|
line1 = ` requested the theoretical maximum of:\n\`${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: \`${config.prefix}${fullCmd}\``;
|
line1 = ` requested the theoretical nominal of:\n\`${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: \`${config.prefix}${fullCmd}\``;
|
line1 = ` requested the following rolls to be ordered from least to greatest:\n\`${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: \`${config.prefix}${fullCmd}\``;
|
line1 = ` requested the following rolls to be ordered from greatest to least:\n\`${config.prefix}${fullCmd}\``;
|
||||||
line2 = 'Results: ';
|
line2 = 'Results: ';
|
||||||
tempReturnData.sort(compareTotalRolls);
|
tempReturnData.sort(compareTotalRolls);
|
||||||
tempReturnData.reverse();
|
tempReturnData.reverse();
|
||||||
} else {
|
} else {
|
||||||
line1 = ` rolled: \`${config.prefix}${fullCmd}\``;
|
line1 = ` rolled:\n\`${config.prefix}${fullCmd}\``;
|
||||||
line2 = 'Results: ';
|
line2 = 'Results: ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,10 @@ export const fullSolver = (conf: (string | number | SolvedStep)[], wrapDetails:
|
||||||
throw new Error('UnbalancedParens');
|
throw new Error('UnbalancedParens');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
// Call the solver on the items between openParen and closeParen (excluding the parens)
|
||||||
conf.splice(openParen, closeParen + 1, fullSolver(conf.slice(openParen + 1, closeParen), true));
|
const parenSolve = 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
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
deno run --allow-write=./logs/,./src/endpoints/gets/heatmap.png --allow-read=./src/solver/,./src/endpoints/gets/heatmap-base.png --allow-net .\mod.ts
|
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
|
Loading…
Reference in New Issue