mirror of
https://github.com/jcreek/denBot.git
synced 2026-07-12 18:33:45 +00:00
367 lines
11 KiB
JavaScript
367 lines
11 KiB
JavaScript
const Discord = require('discord.js');
|
|
const winston = require('winston');
|
|
const Elasticsearch = require('winston-elasticsearch');
|
|
const config = require('./config.json');
|
|
const client = new Discord.Client();
|
|
|
|
let env = 'dev';
|
|
if (process.env.NODE_ENV === 'production') {
|
|
env = 'prod';
|
|
}
|
|
|
|
const esTransportOpts = {
|
|
level: 'error',
|
|
clientOpts: {
|
|
host: config.elasticsearchhost,
|
|
log: 'error'
|
|
},
|
|
transformer: logData => {
|
|
return {
|
|
"@timestamp": (new Date()).getTime(),
|
|
severity: logData.level,
|
|
message: `${getCurrentDateAndTime()} - ${logData.message}`,
|
|
fields: {
|
|
app: 'denBot',
|
|
env: env
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
const logger = winston.createLogger({
|
|
level: 'info',
|
|
format: winston.format.combine(
|
|
winston.format.timestamp(),
|
|
winston.format.json()
|
|
),
|
|
defaultMeta: { service: 'user-service' },
|
|
transports: [
|
|
new winston.transports.File({ filename: 'error.log', level: 'error' }),
|
|
new winston.transports.File({ filename: 'combined.log' }),
|
|
new Elasticsearch(esTransportOpts)
|
|
],
|
|
});
|
|
|
|
//
|
|
// If we're not in production then log to the `console` with the format:
|
|
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
|
|
//
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
logger.add(new winston.transports.Console({
|
|
format: winston.format.simple(),
|
|
}));
|
|
}
|
|
let playerQueue = [];
|
|
let pokemonName = '';
|
|
let captainInGameName = '';
|
|
|
|
client.login(config.token);
|
|
client.once('ready', () =>{
|
|
logger.log('info', 'denBot logged in successfully!');
|
|
})
|
|
|
|
/*
|
|
* Commands:
|
|
* q - Join the queue
|
|
* q pokemon ign - Join the queue (first player can set the pokemon and their in-game name)
|
|
* lq - Leave the queue
|
|
* sq - Show the queue
|
|
* cq - Clear the queue
|
|
* ru - Remove a tagged user from the queue
|
|
* dc - Delete an adventure channel (only the captain can use this)
|
|
*/
|
|
|
|
function getCurrentDateAndTime() {
|
|
const today = new Date();
|
|
const date = `${today.getFullYear()}-${today.getMonth()+1}-${today.getDate()}`;
|
|
const time = `${today.getHours()}:${today.getMinutes()}:${today.getSeconds()}`;
|
|
const dateTime = `${date} ${time}`;
|
|
|
|
return dateTime;
|
|
}
|
|
|
|
function generateQueueTitle() {
|
|
return `\n===== ADVENTURE QUEUE (${playerQueue.length}/${config.maxqueuesize}) =====`;
|
|
}
|
|
|
|
function generateRandomCode() {
|
|
const num1 = Math.floor((Math.random() * 9999) + 1);
|
|
const num2 = Math.floor((Math.random() * 9999) + 1);
|
|
|
|
// Pad the start of the numbers so there's always four digits, including leading zeros
|
|
return `${num1.toString().padStart(4, '0')}-${num2.toString().padStart(4, '0')}`;
|
|
}
|
|
|
|
function checkQueue(message) {
|
|
if (playerQueue.length === config.maxqueuesize) {
|
|
// Queue is full
|
|
logger.log('info', 'Queue is full');
|
|
|
|
// Post a message to say the queue is complete
|
|
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}`;
|
|
const adventureMessage = (pokemonName === '' && captainInGameName === '')
|
|
? `${generateQueueTitle()}\n${baseMessage}`
|
|
: `${generateQueueTitle()}\nPokemon: ${pokemonName}\nCaptain's IGN: ${captainInGameName}\n${baseMessage}`;
|
|
|
|
try {
|
|
// DM users
|
|
playerQueue.forEach(player => {
|
|
client.users.cache.get(player.id).send(adventureMessage);
|
|
});
|
|
} catch (error) {
|
|
logger.log('error', error);
|
|
message.channel.send(`There was an error, please let an admin know!\n${error}`);
|
|
}
|
|
|
|
makeTempChannel(message, adventureMessage);
|
|
|
|
// Clear the queue
|
|
playerQueue = [];
|
|
logger.log('info', 'Emptied queue');
|
|
}
|
|
else if (playerQueue.length === 0) {
|
|
message.channel.send('The queue is empty :(');
|
|
pokemonName = '';
|
|
captainInGameName = '';
|
|
}
|
|
else {
|
|
// Show queue after adding
|
|
if (pokemonName === '' && captainInGameName === '') {
|
|
message.channel.send(`${generateQueueTitle()}\n${playerQueue.map((player, index) => `${index + 1} - ${player.username}`).join('\n')}`);
|
|
}
|
|
else {
|
|
message.channel.send(`${generateQueueTitle()}\nPokemon: ${pokemonName}\nCaptain's IGN: ${captainInGameName}\n${playerQueue.map((player, index) => `${index + 1} - ${player.username}`).join('\n')}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
function getUserFromMention(mention) {
|
|
if (!mention) return;
|
|
|
|
if (mention.startsWith('<@') && mention.endsWith('>')) {
|
|
mention = mention.slice(2, -1);
|
|
|
|
if (mention.startsWith('!')) {
|
|
mention = mention.slice(1);
|
|
}
|
|
|
|
return client.users.cache.get(mention);
|
|
}
|
|
}
|
|
|
|
function getChannelName(username) {
|
|
return `${username}s-adventurers`;
|
|
}
|
|
|
|
function makeTempChannel(message, adventureMessage) {
|
|
const channelName = getChannelName(playerQueue[0].username);
|
|
let createdChannelId = '';
|
|
let everyoneRole = message.guild.roles.cache.find(r => r.name === '@everyone');
|
|
|
|
let permissionOverwrites = [{
|
|
id: everyoneRole.id,
|
|
deny: ['VIEW_CHANNEL'],
|
|
},
|
|
];
|
|
|
|
playerQueue.forEach(player => {
|
|
permissionOverwrites.push({
|
|
id: player.id,
|
|
allow: ['VIEW_CHANNEL'],
|
|
});
|
|
});
|
|
|
|
logger.info(`Making temp channel ${channelName}`)
|
|
message.guild.channels.create(channelName, {
|
|
type: 'text',
|
|
permissionOverwrites: permissionOverwrites,
|
|
}).then(createdChannel => {
|
|
createdChannelId = createdChannel.id;
|
|
|
|
// Post in the channel
|
|
createdChannel.send(adventureMessage);
|
|
})
|
|
.catch(logger.error);
|
|
|
|
// Delete the channel after the configured amount of minutes
|
|
setTimeout(function(){ deleteChannel(message, channelName); }, (config.channeldeletetimeinminutes * 1000 * 60) );
|
|
}
|
|
|
|
function deleteChannel(message, channelName) {
|
|
try {
|
|
// Get a Channel by Name
|
|
const fetchedChannel = message.guild.channels.cache.find(channel => channel.name === channelName);
|
|
|
|
logger.info(`Deleting temp channel ${channelName}`)
|
|
fetchedChannel.delete();
|
|
} catch (error) {
|
|
logger.error(error);
|
|
}
|
|
}
|
|
|
|
client.on('message', function (message) {
|
|
// Ignore messages from the bot and that don't begin with the prefix, and do not run in DMs to bot
|
|
if (message.author.bot) return;
|
|
if (!message.content.startsWith(config.prefix)) return;
|
|
if (message.channel instanceof Discord.DMChannel) return;
|
|
|
|
const commandBody = message.content.slice(config.prefix.length);
|
|
const args = commandBody.split(' ');
|
|
const command = args.shift().toLowerCase();
|
|
|
|
// Join the queue
|
|
if (command === 'q' && !(playerQueue.includes(message.author))) {
|
|
// Delete the message with the bot command
|
|
if (config.deletecommandstoggle) {
|
|
message.delete();
|
|
}
|
|
|
|
logger.log('info', `${message.author.username} joined the queue.`);
|
|
message.channel.send(`=====\n${message.author.username} joined the queue.`);
|
|
|
|
playerQueue.push(message.author);
|
|
|
|
if (playerQueue.length === 1 && args[0] && args[1]) {
|
|
// First player can submit pokemon and in-game name
|
|
pokemonName = args[0];
|
|
captainInGameName = args[1];
|
|
}
|
|
|
|
checkQueue(message);
|
|
}
|
|
else if (command === 'q' && (playerQueue.includes(message.author))) {
|
|
// Delete the message with the bot command
|
|
if (config.deletecommandstoggle) {
|
|
message.delete();
|
|
}
|
|
message.channel.send(`${message.author.username} is too keen, you're already in the queue mate!`);
|
|
}
|
|
|
|
// Leave the queue
|
|
if(command === 'lq' && (playerQueue.includes(message.author))){
|
|
// Delete the message with the bot command
|
|
if (config.deletecommandstoggle) {
|
|
message.delete();
|
|
}
|
|
|
|
logger.log('info', `${message.author.username} left the queue.`);
|
|
message.channel.send(`${message.author.username} left the queue.`);
|
|
|
|
for( var i = 0; i < playerQueue.length; i++){
|
|
if ( playerQueue[i] === message.author) {
|
|
playerQueue.splice(i, 1);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
checkQueue(message);
|
|
}
|
|
else if (command === 'lq' && !(playerQueue.includes(message.author))) {
|
|
// Delete the message with the bot command
|
|
if (config.deletecommandstoggle) {
|
|
message.delete();
|
|
}
|
|
message.channel.send(`${message.author.username} you can't leave the queue before you've joined it!`);
|
|
}
|
|
|
|
// Show the queue
|
|
if(command === 'sq') {
|
|
// Delete the message with the bot command
|
|
if (config.deletecommandstoggle) {
|
|
message.delete();
|
|
}
|
|
checkQueue(message);
|
|
}
|
|
|
|
// Clear the queue
|
|
if(command === 'cq') {
|
|
// Delete the message with the bot command
|
|
if (config.deletecommandstoggle) {
|
|
message.delete();
|
|
}
|
|
|
|
if (playerQueue.length === 0) {
|
|
message.channel.send(`The queue is already empty...`);
|
|
logger.log('info', `${message.author.username} attempted to clear the queue but it was already empty.`);
|
|
}
|
|
else {
|
|
playerQueue = [];
|
|
message.channel.send(`The queue has been cleared!`);
|
|
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 ((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--;
|
|
}
|
|
}
|
|
|
|
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.`);
|
|
}
|
|
}
|
|
|
|
if (command === 'dc') {
|
|
// todo - add logic here to 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.log('info', `${message.author.username} deleted their adventure channel.`);
|
|
}
|
|
else {
|
|
message.channel.send(`${message.author.username} is not allowed to delete this channel.`);
|
|
logger.log('info', `${message.author.username} attempted to delete channel ${message.channel.id} but it's not their adventure channel.`);
|
|
}
|
|
}
|
|
|
|
if (command === 'help') {
|
|
let msg = `
|
|
The commands available to you are:
|
|
- !q - Join the queue
|
|
- !q <pokemon> <ign> - Join the queue (first player can set the pokemon and their in-game name)
|
|
- !lq - Leave the queue
|
|
- !sq - Show the queue
|
|
- !dc - Delete an adventure channel (only the captain can use this)
|
|
`;
|
|
|
|
message.channel.send(msg);
|
|
}
|
|
|
|
if (command === 'adminhelp') {
|
|
let msg = `
|
|
The commands available to you are:
|
|
- !q - Join the queue
|
|
- !q <pokemon> <ign> - Join the queue (first player can set the pokemon and their in-game name)
|
|
- !lq - Leave the queue
|
|
- !sq - Show the queue
|
|
- !cq - Clear the queue (admin-only, not to be shared with normal users)
|
|
- !ru - Remove a tagged user from the queue (admin-only, not to be shared with normal users)
|
|
- !dc - Delete an adventure channel (only the captain can use this)
|
|
`;
|
|
|
|
message.channel.send(msg);
|
|
}
|
|
});
|