diff --git a/README.md b/README.md index 6b34f52..32c146c 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Version 1.4.2 - 2021/02/14 The Artificer is a Discord bot that specializes in rolling dice. The bot utilizes the compact [Roll20 formatting](https://roll20.zendesk.com/hc/en-us/articles/360037773133-Dice-Reference) for ease of use and will correctly perform any needed math on the roll (limited to basic algebra). -This bot was developed to replace the Sidekick discord bot after it went offline many times for extended periods. This was also developed to fix some annoyances that were found with Sidekick, specifically its vague error messages (such as `"Tarantallegra!"`, what is that supposed to mean) and its inability to handle implicit multiplication (such as `4(12 + 20)`). +This bot was developed to replace the Sidekick discord bot after it went offline many times for extended periods, and is now dead according to their GitHub. This was also developed to fix some annoyances that were found with Sidekick, specifically its vague error messages (such as `"Tarantallegra!"`, what is that supposed to mean) and its inability to handle implicit multiplication (such as `4(12 + 20)`). ## Using The Artificer I am hosting this bot for public use and you may find its invite link below. If you would like to host this bot yourself, details of how to do so are found at the end of this README, but I do not recommend this unless you are experienced with running Discord bots. @@ -12,6 +12,8 @@ After inviting the bot, if you would like it to remove the message requesting th [Bot Invite Link](https://discord.com/api/oauth2/authorize?client_id=789045930011656223&permissions=2048&scope=bot) +[Support Server Invite Link](https://discord.gg/peHASXMZYv) + --- ## Available Commands @@ -28,11 +30,11 @@ The Artificer comes with a few supplemental commands to the main rolling command * Provides a message similar to this subcommand description. * `[[api status` * Shows the current status of the API for this guild. - * `[[api allow or [[api enable` - * Allows API Rolls to be sent to this guild. - * `[[api block or [[api disable` - * Blocks API Rolls from being sent to this guild. - * `[[api delete` + * `[[api allow or [[api enable` + * Allows API Rolls to be sent to this guild. + * `[[api block or [[api disable` + * Blocks API Rolls from being sent to this guild. + * `[[api delete` * Deletes this guild from The Artificer's database. * `[[ping` * Tests the latency between you, Discord, and the bot. @@ -59,22 +61,22 @@ The Artificer comes with a few supplemental commands to the main rolling command * PI and e are available for use. * Parameters for rolling: - | Paramater | Required? | Repeatable? | Description | - |---------------|-------------|---------------|--------------------------------------------------------------------------------------------------| - | x | Optional | No | number of dice to roll, if omitted, 1 is used | - | dy | Required | No | size of dice to roll, d20 = 20 sided die | - | dz or dlz | Optional | No | drops the lowest z dice, cannot be used any other drop or keep options | - | kz or khz | Optional | No | keeps the highest z dice, cannot be used any other drop or keep options | - | dhz | Optional | No | drops the highest z dice, cannot be used any other drop or keep options | - | klz | Optional | No | keeps the lowest z dice, cannot be used any other drop or keep options | - | ra | Optional | Yes | rerolls any rolls that match a, r3 will reroll any dice that land on 3, throwing out old rolls | - | csq or cs=q | Optional | Yes | changes crit score to q | - | csq | Optional | Yes | changes crit score to be greater than or equal to q | - | cfq or cf=q | Optional | Yes | changes crit fail to q | - | cfq | Optional | Yes | changes crit fail to be greater than or equal to q | - | ! | Optional | No | exploding, rolls another dy for every crit roll | + | Paramater | Required? | Repeatable? | Description | + |---------------|-------------|---------------|--------------------------------------------------------------------------------------------------| + | x | Optional | No | number of dice to roll, if omitted, 1 is used | + | dy | Required | No | size of dice to roll, d20 = 20 sided die | + | dz or dlz | Optional | No | drops the lowest z dice, cannot be used any other drop or keep options | + | kz or khz | Optional | No | keeps the highest z dice, cannot be used any other drop or keep options | + | dhz | Optional | No | drops the highest z dice, cannot be used any other drop or keep options | + | klz | Optional | No | keeps the lowest z dice, cannot be used any other drop or keep options | + | ra | Optional | Yes | rerolls any rolls that match a, r3 will reroll any dice that land on 3, throwing out old rolls | + | csq or cs=q | Optional | Yes | changes crit score to q | + | csq | Optional | Yes | changes crit score to be greater than or equal to q | + | cfq or cf=q | Optional | Yes | changes crit fail to q | + | cfq | Optional | Yes | changes crit fail to be greater than or equal to q | + | ! | Optional | No | exploding, rolls another dy for every crit roll | * If the parameter is Required, it must be provided at all times. * If the parameter is Repeatable, it may occur multiple times in the roll configuration. @@ -170,7 +172,7 @@ If you run into any errors or problems with the bot, or think you have a good id --- ## Self Hosting The Artificer -The Artificer was built on Deno `v1.7.0` using Discodeno `v10.0.0`. If you choose to run this yourself, you will need to rename `config.example.ts` to `config.ts` and edit some values. You will need to create a new [Discord Application](https://discord.com/developers/applications) and copy the newly generated token into the `"token"` key. If you want to utilize some of the bots dev features, you will need to fill in the keys `"logChannel"` and `"reportChannel"` with text channel IDs and `"devServer"` with a guild ID. +The Artificer was built on [Deno](https://deno.land/) `v1.7.0` using [Discordeno](https://discordeno.mod.land/) `v10.3.0`. If you choose to run this yourself, you will need to rename `config.example.ts` to `config.ts` and edit some values. You will need to create a new [Discord Application](https://discord.com/developers/applications) and copy the newly generated token into the `"token"` key. If you want to utilize some of the bots dev features, you will need to fill in the keys `"logChannel"` and `"reportChannel"` with text channel IDs and `"devServer"` with a guild ID. 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. @@ -180,6 +182,11 @@ If you choose to run version `1.1.0` or newer, ensure you disable the API in `co --- +## Development Plans +Current and future plans are listed on [the Milestones page](https://github.com/Burn-E99/TheArtificer/milestones). + +--- + ### Built in memory of my Grandmother, Babka With much love, Ean diff --git a/config.example.ts b/config.example.ts index d4e1b96..bb70595 100644 --- a/config.example.ts +++ b/config.example.ts @@ -29,11 +29,27 @@ export const config = { "devServer": "the_dev_server", // Discord guild ID where testing of indev features/commands will be handled, used in conjuction with the DEVMODE bool in mod.ts "emojis": [ // Array of objects containing all emojis that the bot can send on your behalf, empty this array if you don't want any of them { // Emoji object, duplicate for each emoji - "name": "popcat", // Name of emoji in discord - "aliases": ["popcat", "pop", "p"], // Commands that will activate this emoji - "id": "796340018377523221", // Discord emoji ID for this emoji - "animated": true, // Tells the bot this emoji is animated so it sends correctly - "deleteSender": true // Tells the bot to attempt to delete the sender's message after sending the emoji + "name": "emoji_name", // Name of emoji in discord + "aliases": ["alias_1", "alias_2", "alias_n"], // Commands that will activate this emoji + "id": "the_emoji_id", // Discord emoji ID for this emoji + "animated": false, // Tells the bot this emoji is animated so it sends correctly + "deleteSender": false // Tells the bot to attempt to delete the sender's message after sending the emoji + } + ], + "botLists": [ // Array of objects containing all bot lists that stats should be posted to + { // Bot List object, duplicate for each bot list + "name": "Bot List Name", // Name of bot list, not used + "enabled": true, // Should statistics be posted to this list? + "apiUrl": "https://example.com/api/bots/?{bot_id}/stats", // API URL, use ?{bot_id} in place of the bot id so that it can be dynamically replaced + "headers": [ // Array of headers that need to be added to the request + { // Header Object, duplicate for every header needed + "header": "header_name", // Name of header needed, usually Authorization is needed + "value": "header_value" // Value for the header + } + ], + "body": { // Data payload to send to the bot list, will be turned into a string and any ?{} will be replaced with the required value, currently only has ?{server_count} + "param_name": "?{param_value}" // Add more params as needed + } } ] }; diff --git a/deps.ts b/deps.ts index 2755d74..31ff1c7 100644 --- a/deps.ts +++ b/deps.ts @@ -3,7 +3,7 @@ export { startBot, editBotsStatus, Intents, StatusTypes, ActivityType, sendMessage, sendDirectMessage, - cache, + cache, botID, memberIDHasPermission } from "https://deno.land/x/discordeno@10.3.0/mod.ts"; diff --git a/mod.ts b/mod.ts index 7f35eae..5ef0e74 100644 --- a/mod.ts +++ b/mod.ts @@ -8,9 +8,10 @@ import { // Discordeno deps startBot, editBotsStatus, Intents, StatusTypes, ActivityType, - Message, Guild, sendMessage, sendDirectMessage, - cache, + sendMessage, sendDirectMessage, + cache, botID, memberIDHasPermission, + Message, Guild, // MySQL Driver deps Client @@ -55,8 +56,12 @@ startBot({ } }, 30000); + // Interval to update bot list stats every 24 hours + LOCALMODE ? console.log("updateListStatistics not running") : setInterval(() => intervals.updateListStatistics(botID, cache.guilds.size), 86400000); + // setTimeout added to make sure the startup message does not error out setTimeout(() => { + LOCALMODE ? console.log("updateListStatistics not running") : intervals.updateListStatistics(botID, cache.guilds.size); editBotsStatus(StatusTypes.Online, `Boot Complete`, ActivityType.Game); sendMessage(config.logChannel, `${config.name} has started, running version ${config.version}.`).catch(() => { console.error("Failed to send message 00"); @@ -69,7 +74,7 @@ startBot({ }); }, guildDelete: (guild: Guild) => { - sendMessage(config.logChannel, `I have been removed from: ${guild.name} (id: ${guild.id})`).catch(() => { + sendMessage(config.logChannel, `I have been removed from: ${guild.name} (id: ${guild.id}).`).catch(() => { console.error("Failed to send message 02"); }); }, diff --git a/src/intervals.ts b/src/intervals.ts index 334ba18..e2e772b 100644 --- a/src/intervals.ts +++ b/src/intervals.ts @@ -33,4 +33,23 @@ const getRandomStatus = (cache: CacheData): string => { return status; }; -export default { getRandomStatus }; +// updateListStatistics(bot ID, current guild count) returns nothing +// Sends the current server count to all bot list sites we are listed on +const updateListStatistics = (botID: string, serverCount: number): void => { + config.botLists.forEach(async e => { + if (e.enabled) { + const tempHeaders = new Headers(); + tempHeaders.append(e.headers[0].header, e.headers[0].value); + 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), { + "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 + }); + console.log(response); + } + }); +}; + +export default { getRandomStatus, updateListStatistics };