d-bot
Version:
A quirky Discord bot made for single, small, private servers
108 lines (94 loc) • 4.47 kB
JavaScript
// Discord.io!
var util = require(__base+'core/util.js');
var config = require('./config.js');
const Eris = require('eris');
let bot = new Eris(config.token);
// TODO: Crawl back through message history, 100 messages every 20 seconds, to the beginning of time
// Track when the bot is online/offline to know when to look for gaps to fill in
module.exports = {
bot,
pmOwner: message => _sendMessages(config.owner, message),
sendMessage: _sendMessages,
sendMessages: _sendMessages,
editMessage: _editMessage,
uploadFile: _uploadFile,
fixMessage: _fixMessage,
getUsernameFromID: _getUsernameFromID,
getIDFromUsername: username => {
// TODO: Use fuzzy matching to get closest match (minimum 50% similarity)
username = username.toLowerCase();
if(!username || username.trim() === '') return false;
for(let [guildID, guild] of bot.guilds) {
for(let [memberID, member] of guild.members) {
if((member.nick || member.username).toLowerCase() === username) return memberID;
}
}
for(let aliasID of Object.keys(config.userAliases)) {
if(config.userAliases[aliasID].includes(username)) return aliasID;
}
return false;
},
getTimeFromID: _getTimeFromID
};
function _sendMessages(ID, messageArr, polite, callback) {
messageArr = Array.isArray(messageArr) ? messageArr : [messageArr];
let noMentions = polite === true || (polite && polite.noMentions);
let noEmbeds = polite === true || (polite && polite.noEmbeds);
Promise.all(messageArr.map(msg => {
if(noMentions) msg = suppressMentions(msg);
if(noEmbeds) msg = suppressLinks(msg);
if(msg.length > 2000) {
console.log((new Date()).toString().substr(0,24), 'Trimming message over 2000 chars');
msg = msg.substr(0, 2000);
}
return bot.createMessage(ID, msg);
})).then(callback).catch(err => console.log(new Date(), 'Error sending message(s)', err));
}
function _editMessage(channelID, messageID, content, polite, callback) {
if(polite === true || (polite && polite.noMentions)) content = suppressMentions(content);
if(polite === true || (polite && polite.noEmbeds)) content = suppressLinks(content);
bot.editMessage(channelID, messageID, content).then(callback);
}
function _uploadFile({ to, filename, file, message }, callback) {
bot.createMessage(to, message, { file, name: filename }).then(callback)
.catch(err => console.log(new Date(), 'Error uploading file', err));
}
function _fixMessage(message, serverID) { // Credit to discord.io
return message.replace(/<@&(\d*)>|<@!(\d*)>|<@(\d*)>|<#(\d*)>/g, function(match, RID, NID, UID, CID) {
var k, i;
if(UID || CID) {
if(bot.users.has(UID)) return '@' + bot.users.get(UID).username;
if(bot.channelGuildMap[CID]) return '#' + bot.guilds.get(bot.channelGuildMap[CID]).channels.get(CID).name;
}
if(RID || NID) {
if(NID && bot.guilds.has(serverID)) return '@' + bot.guilds.get(serverID).members.get(NID).nick;
for(let [guildID, guild] of bot.guilds) {
if(guild.roles.has(RID)) return '@' + guild.roles.get(RID).name;
if(guild.members.has(NID) && guild.members.get(NID).nick) return '@' + guild.members.get(NID).nick;
}
}
});
}
function _getUsernameFromID(id) {
return bot.users.has(id) ? bot.users.get(id).username :
config.userAliases[id] ? config.userAliases[id][0] : false;
}
function _getTimeFromID(id) { // Converts Discord snowflake ID to timestamp, thanks /u/Natsulus!
return new Date((id / 4194304) + 1420070400000);
}
function suppressMentions(message) {
return message.split('@everyone').join('(@)everyone').replace(/<@!?[0-9]+>/g, match => {
match = match.replace('!', '');
return "(@)" + _getUsernameFromID(match.substring(2, match.length - 1))
});
}
function suppressLinks(message) {
return message.replace(util.urlRX, match => (match[0] === ' ' ? ' ' : '') + '<' + match.trim() + '>');
}
bot.on('error', error => {
_sendMessages(config.owner, `An error has occurred: \`\`\`${error}\`\`\``);
console.log(new Date(), error);
});
bot.on('debug', debug => {
//console.log(debug) //Logs every event
});