15 Commits

Author SHA1 Message Date
jcreek 4429e02b22 fix(*): Missed empty queue check for when a player leaves a queue they were the only one in 2020-11-19 23:36:13 +00:00
jcreek 49cd612f51 feat(*): Finish implementing start command 2020-11-19 23:24:59 +00:00
jcreek f6af7b4327 fix(*): Fix further missed lowercasing of channel names by Discord for text channels 2020-11-19 23:17:48 +00:00
Josh Creek 01768c5567 feat(*): Remove potential feature from readme as it has been implemented 2020-11-19 22:55:58 +00:00
Josh Creek 9700808773 feat(*): Add start command for voting to start the adventure before the queue is full 2020-11-19 22:53:45 +00:00
Josh Creek 857ee29e10 feat(*): Update help commands to use the correct command symbol from the config file rather than hard-coding one 2020-11-19 22:49:41 +00:00
jcreek d37b3f8225 fix(*): Fix bug where text channel names are automatically lowercased by Discord so couldn't be deleted if the username had capital letters 2020-11-18 19:15:57 +00:00
jcreek 6eb1bf5c8a fix(*): Fix broken channel deletion and add more helpful logs 2020-11-16 23:04:21 +00:00
jcreek f32441716f feat(*): Add a dev token for debugging and testing in the dev discord 2020-11-16 23:03:58 +00:00
jcreek 2d113f8a8b feat(*): Enable console logging even in production so Jord can see logs easily 2020-11-05 23:36:32 +00:00
jcreek 4bc416ec56 feat(*): Improve logging and error handling 2020-11-05 23:35:55 +00:00
jcreek e47ff9596b feat(*): Remove unused getCurrentDateAndTime function 2020-11-05 23:23:37 +00:00
jcreek 1dc17b49b9 fix(*): Further fixes to elasticsearch logging to get the stacktrace coming through correctly 2020-11-05 23:21:19 +00:00
jcreek 43778d360a fix(*): Make the elasticsearch logging render out log data correctly for filtering in kibana 2020-11-05 22:52:31 +00:00
jcreek 4e2c79614b feat(*): Implement winston-elasticsearch for logging to Elasticsearch 2020-11-05 16:55:16 +00:00
4 changed files with 71 additions and 126 deletions
+2 -18
View File
@@ -35,24 +35,12 @@ For a sanity check, you can run `docker images` and it should be displayed in th
## Running the Docker container
Running the bot with --detach runs the container in detatched mode (as in it runs in the background). If you want to see what is happening, remove that option.
Running the bot with -d runs the container in detatched mode (as in it runs in the background). If you want to see what is happening, remove that option.
`docker run --detach --name denbot denbot`
`docker run -d denbot`
You can use CTRL+C to exit out of this command window. If you're using Windows, Docker Desktop will now show your bot under 'Containers/Apps', from where you can easily stop and start it using the GUI.
## Updating
If doing it manually, in the folder with all the files run:
```
docker stop denbot
docker rm denbot
docker image rm denbot
docker build -t denbot .
docker run --detach --name denbot denbot
```
### More information
If you want more of a sanity check here are some following commands you can run the following commands:
@@ -63,7 +51,3 @@ If you want more of a sanity check here are some following commands you can run
To access the command line inside the docker container you can run:
`docker exec -it <container id> /bin/bash`
## Future feature suggestions
* If the party want to continue with the same people and the same link code they can do !again (only in the private chat) to run again and get the party for 30 more mins (denBot would also post the link code again so people can see it without scrolling) - using something like https://stackoverflow.com/questions/36563749/how-i-extend-settimeout-on-nodejs and an array of all the queues, removing those and their deletion functions each time an adventure channel is deleted
+3 -3
View File
@@ -3,10 +3,10 @@
"deletecommandstoggle": false,
"maxqueuesize": 4,
"elasticsearch" : {
"elasticsearch_address" : "http://YOUR-ELASTICSEARCH-ADDRESS-GOES-HERE:9200",
"elasticsearch_address" : "http://jcreek.ddns.net:9200",
"elasticsearch_index_pattern" : "[logs-denbot-]YYYY.MM.DD"
},
"prefix": "!",
"token-dev": "YOUR-DEV-TOKEN-GOES-HERE",
"token": "YOUR-TOKEN-GOES-HERE"
"token-dev": "Nzc4MDI2MTE1NDkwOTA2MTYz.X7L_SA.bNzC1kQUpBSwEsjp_cDGwR62Soo",
"token": "NzcwMDQyMDEzMjY5NDkxNzUy.X5Xzgg.kcr_51g95iUvEcYCfbQvG1Sx8ao"
}
-21
View File
@@ -1,21 +0,0 @@
const { loggers } = require("winston");
module.exports = {
sendEmbedMessage: function (logger, message, Discord, title, description, colour = '#F4B400') {
// For documentation see https://github.com/AnIdiotsGuide/discordjs-bot-guide/blob/master/first-bot/using-embeds-in-messages.md
try {
const embed = new Discord.MessageEmbed()
.setTitle(title)
.setColor(colour)
.setDescription(description)
.setFooter('This is a custom bot - if it goes down, tag Scruffy')
.setThumbnail('https://cdn.discordapp.com/icons/770039159506337802/a_510706276ebcf77e568900fa708e6c63.png?size=128')
.setTimestamp();
message.channel.send(embed);
} catch (error) {
logger.error('Failed to send embed message', error);
message.channel.send('There was a problem, sorry!');
}
},
};
+66 -84
View File
@@ -2,7 +2,6 @@ const Discord = require('discord.js');
const winston = require('winston');
const Elasticsearch = require('winston-elasticsearch');
const config = require('./config.json');
const {sendEmbedMessage} = require('./helpers.js');
const client = new Discord.Client();
const { format } = winston;
@@ -114,10 +113,10 @@ function generateRandomCode() {
function checkQueue(message) {
if (playerQueue.length === config.maxqueuesize || (playerQueue.length > 0 && playerQueue.length == playerVotes.length)) {
// Queue is full
logger.info('Queue is full');
logger.log('info', 'Queue is full');
// Post a message to say the queue is complete
sendEmbedMessage(logger, message, Discord, 'Queue full', `The adventure is beginning - players should check their DMs\n${playerQueue.map((player, index) => `${index + 1} - ${player.username}`).join('\n')}`)
message.channel.send(`The adventure is beginning - players should check their DMs\n${playerQueue.map((player, index) => `${index + 1} - ${player.username}`).join('\n')}`);
const randomCode = generateRandomCode();
const baseMessage = `@${playerQueue[0].username} is making the lobby. Here is your link code ${randomCode}`;
@@ -132,32 +131,27 @@ function checkQueue(message) {
});
} catch (error) {
logger.error('Tried to DM users: ', error);
sendEmbedMessage(logger, message, Discord, 'An error occurred', `There was an error, please let an admin know!\n${error}`, '#DB4437');
message.channel.send(`There was an error, please let an admin know!\n${error}`);
}
makeTempChannel(message, adventureMessage);
// Clear the queue and votes
// Clear the queue
playerQueue = [];
logger.info('Emptied queue');
playerVotes = [];
logger.info('Emptied votes');
pokemonName = '';
captainInGameName = '';
logger.info('Emptied pokemon name and captain name');
logger.log('info', 'Emptied queue');
}
else if (playerQueue.length === 0) {
sendEmbedMessage(logger, message, Discord, 'Queue empty', 'The queue is empty :(');
message.channel.send('The queue is empty :(');
pokemonName = '';
captainInGameName = '';
}
else {
// Show queue after adding
if (pokemonName === '' && captainInGameName === '') {
sendEmbedMessage(logger, message, Discord, generateQueueTitle(), `${playerQueue.map((player, index) => `${index + 1} - ${player.username}`).join('\n')}`);
message.channel.send(`${generateQueueTitle()}\n${playerQueue.map((player, index) => `${index + 1} - ${player.username}`).join('\n')}`);
}
else {
sendEmbedMessage(logger, message, Discord, generateQueueTitle(), `**Pokemon**: ${pokemonName}\n**Captain's IGN**: ${captainInGameName}\n${playerQueue.map((player, index) => `${index + 1} - ${player.username}`).join('\n')}`);
message.channel.send(`${generateQueueTitle()}\nPokemon: ${pokemonName}\nCaptain's IGN: ${captainInGameName}\n${playerQueue.map((player, index) => `${index + 1} - ${player.username}`).join('\n')}`);
}
}
}
@@ -181,7 +175,7 @@ function getUserFromMention(mention) {
}
function getChannelName(username) {
return `${username.toLowerCase().replace(' ', '-')}s-adventurers`;
return `${username.toLowerCase()}s-adventurers`;
}
function makeTempChannel(message, adventureMessage) {
@@ -211,16 +205,15 @@ function makeTempChannel(message, adventureMessage) {
// Post in the channel
createdChannel.send(adventureMessage);
createdChannel.send(`Please delete this channel when you're finished with it using the ${config.prefix}dc command`);
})
.catch(logger.error);
// try {
// // Delete the channel after the configured amount of minutes
// setTimeout(function(){ deleteChannel(message, channelName); }, (config.channeldeletetimeinminutes * 1000 * 60) );
// } catch (error) {
// logger.error(`Tried to delete channel ${channelName} after timeout: `, error);
// }
try {
// Delete the channel after the configured amount of minutes
setTimeout(function(){ deleteChannel(message, channelName); }, (config.channeldeletetimeinminutes * 1000 * 60) );
} catch (error) {
logger.error(`Tried to delete channel ${channelName} after timeout: `, error);
}
}
function deleteChannel(message, channelName) {
@@ -260,8 +253,8 @@ client.on('message', function (message) {
logger.info(`${message.author.username} used command q in ${message.channel.name}`);
logger.info(`${message.author.username} joined the queue.`);
sendEmbedMessage(logger, message, Discord, 'Queue in progress', `${message.author.username} joined the queue.`);
logger.log('info', `${message.author.username} joined the queue.`);
message.channel.send(`=====\n${message.author.username} joined the queue.`);
playerQueue.push(message.author);
@@ -307,8 +300,8 @@ client.on('message', function (message) {
}
}
logger.info(`${message.author.username} left the queue.`);
sendEmbedMessage(logger, message, Discord, 'Queue in progress', `${message.author.username} left the queue.`);
logger.log('info', `${message.author.username} left the queue.`);
message.channel.send(`${message.author.username} left the queue.`);
checkQueue(message);
}
@@ -335,17 +328,14 @@ client.on('message', function (message) {
if(playerQueue.length == 0) {
message.channel.send(`You can only vote to start an adventure early if there is a queue. You can start a queue by using the command ${config.prefix}help`);
}
else if (!playerQueue.includes(message.author)) {
message.channel.send(`You can only vote to start an adventure early if you are in the queue. You can join the queue by using the command ${config.prefix}q`);
}
else if(playerVotes.length == 0) {
// First player to vote
playerVotes.push(message.author);
sendEmbedMessage(logger, message, Discord, 'Voting to start early', `${message.author.username} voted to start the adventure.\nAll other players in the queue must also vote to start the adventure for it to begin without ${config.maxqueuesize} players.`);
message.channel.send(`=====\n${message.author.username} voted to start the adventure.\nAll other players in the queue must also vote to start the adventure for it to begin without ${config.maxqueuesize} players.`);
}
else if (playerVotes.includes(message.author.username)) {
sendEmbedMessage(logger, message, Discord, 'Voting to start early', `${message.author.username} has already voted to start the adventure.\nAll other players in the queue must also vote to start the adventure for it to begin without ${config.maxqueuesize} players.`);
message.channel.send(`=====\n${message.author.username} has already voted to start the adventure.\nAll other players in the queue must also vote to start the adventure for it to begin without ${config.maxqueuesize} players.`);
}
else if (playerVotes.length < config.maxqueuesize) {
// Not the first player to vote
@@ -353,7 +343,7 @@ client.on('message', function (message) {
if (playerVotes.length < playerQueue.length) {
// Still not all players voted
sendEmbedMessage(logger, message, Discord, 'Voting to start early', `${message.author.username} voted to start the adventure.\nAll other players in the queue must also vote to start the adventure for it to begin without ${config.maxqueuesize} players.`);
message.channel.send(`=====\n${message.author.username} voted to start the adventure.\nAll other players in the queue must also vote to start the adventure for it to begin without ${config.maxqueuesize} players.`);
}
else {
// All players have voted, we can start the adventure early
@@ -385,59 +375,51 @@ client.on('message', function (message) {
if (playerQueue.length === 0) {
message.channel.send(`The queue is already empty...`);
logger.info( `${message.author.username} attempted to clear the queue but it was already empty.`);
logger.log('info', `${message.author.username} attempted to clear the queue but it was already empty.`);
}
else {
else {
playerQueue = [];
playerVotes = [];
message.channel.send(`The queue has been cleared!`);
logger.info( `${message.author.username} cleared the queue and the votes.`);
pokemonName = '';
captainInGameName = '';
logger.info('Emptied pokemon name and captain name');
logger.log('info', `${message.author.username} cleared the queue.`);
}
}
// Remove a tagged user from the queue
if (command === 'ru' && args[0]) {
const user = getUserFromMention(args[0]);
// Delete the message with the bot command
if (config.deletecommandstoggle) {
message.delete();
}
if (config.deletecommandstoggle) {
message.delete();
}
logger.info(`${message.author.username} used command ru ${user} in ${message.channel.name}`);
logger.info(`${message.author.username} used command ru in ${message.channel.name}`);
try {
const user = getUserFromMention(args[0]);
if ((playerQueue.includes(user))) {
if ((playerQueue.includes(user))) {
// Search for the user
for(var i = 0; i < playerQueue.length; i++){
if ((playerQueue[i].username === user.username)){
playerQueue.splice(i, 1);
i--;
}
}
for( var i = 0; i < playerVotes.length; i++){
if ( playerVotes[i].username === user.username) {
playerVotes.splice(i, 1);
// Search for the user
for(var i = 0; i < playerQueue.length; i++){
if ((playerQueue[i].username === user.username)){
playerQueue.splice(i, 1);
i--;
}
}
message.channel.send(`${user.username} removed from queue.`);
logger.info( `${message.author.username} removed ${user.username} from queue.`);
for( var i = 0; i < playerVotes.length; i++){
if ( playerVotes[i].username === user.username) {
playerVotes.splice(i, 1);
i--;
}
}
checkQueue(message);
}
else if (!(playerQueue.includes(user))) {
message.channel.send(`${user.username} is not in the queue.`);
logger.info( `${message.author.username} attempted to remove ${user.username} from queue but they weren't in it.`);
}
} catch (error) {
logger.error(`Tried to remove user ${args[0]} from queue but got an error: ${error}`);
message.channel.send(`Failed to remove ${args[0]} from the queue.`);
message.channel.send(`${user.username} removed from queue.`);
logger.log('info', `${message.author.username} removed ${user.username} from queue.`);
checkQueue(message);
}
else if (!(playerQueue.includes(user))) {
message.channel.send(`${user.username} is not in the queue.`);
logger.log('info', `${message.author.username} attempted to remove ${user.username} from queue but they weren't in it.`);
}
}
@@ -447,23 +429,23 @@ client.on('message', function (message) {
// Determine if they can delete the channel (i.e. it's their temporary one) - compare the name
if (message.channel.name === getChannelName(message.author.username)) {
deleteChannel(message, message.channel.name)
logger.info( `${message.author.username} deleted their adventure channel.`);
logger.log('info', `${message.author.username} deleted their adventure channel.`);
}
else {
message.channel.send(`${message.author.username} is not allowed to delete this channel.`);
logger.info( `${message.author.username} attempted to delete channel ${message.channel.name} but it's not their adventure channel.`);
logger.log('info', `${message.author.username} attempted to delete channel ${message.channel.name} but it's not their adventure channel.`);
}
}
if (command === 'help') {
let msg = `
The commands available to you are:
- ${config.prefix}q - Join the queue
- ${config.prefix}q <pokemon> <ign> - Join the queue (first player can set the pokemon and their in-game name)
- ${config.prefix}lq - Leave the queue
- ${config.prefix}sq - Show the queue
- ${config.prefix}start - Vote to start the adventure early, without the full number of players (all players in the queue must use this to start early)
- ${config.prefix}dc - Delete an adventure channel (only the captain can use this)
- ${command}q - Join the queue
- ${command}q <pokemon> <ign> - Join the queue (first player can set the pokemon and their in-game name)
- ${command}lq - Leave the queue
- ${command}sq - Show the queue
- ${command}start - Vote to start the adventure early, without the full number of players (all players in the queue must use this to start early)
- ${command}dc - Delete an adventure channel (only the captain can use this)
`;
message.channel.send(msg);
@@ -472,14 +454,14 @@ The commands available to you are:
if (command === 'adminhelp') {
let msg = `
The commands available to you are:
- ${config.prefix}q - Join the queue
- ${config.prefix}q <pokemon> <ign> - Join the queue (first player can set the pokemon and their in-game name)
- ${config.prefix}lq - Leave the queue
- ${config.prefix}sq - Show the queue
- ${config.prefix}start - Vote to start the adventure early, without the full number of players (all players in the queue must use this to start early)
- ${config.prefix}cq - Clear the queue (admin-only, not to be shared with normal users)
- ${config.prefix}ru - Remove a tagged user from the queue (admin-only, not to be shared with normal users)
- ${config.prefix}dc - Delete an adventure channel (only the captain can use this)
- ${command}q - Join the queue
- ${command}q <pokemon> <ign> - Join the queue (first player can set the pokemon and their in-game name)
- ${command}lq - Leave the queue
- ${command}sq - Show the queue
- ${command}start - Vote to start the adventure early, without the full number of players (all players in the queue must use this to start early)
- ${command}cq - Clear the queue (admin-only, not to be shared with normal users)
- ${command}ru - Remove a tagged user from the queue (admin-only, not to be shared with normal users)
- ${command}dc - Delete an adventure channel (only the captain can use this)
`;
message.channel.send(msg);