-
Notifications
You must be signed in to change notification settings - Fork 1
/
server.js
162 lines (145 loc) · 5.01 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
const Discord = require("discord.js");
const _ = require("lodash");
const utils = require("./utils");
const log = utils.getLogger('bot');
log.info(`booting up...`);
// basic server stuff, modules to load
const commandChar = process.env.COMMAND_CHAR || "!";
const spamTimeout = 3000; // milliseconds
const modules = [
'role',
'glossary',
'help'
];
// initialize the bot and all modules
const bot = new Discord.Client({
shards: 'auto',
messageCacheMaxSize: 100,
messageCacheLifetime: 60 * 10,
messageSweepInterval: 90,
ws: {
intents: [
'GUILDS',
'GUILD_MESSAGES',
'GUILD_MESSAGE_REACTIONS',
'DIRECT_MESSAGES',
'DIRECT_MESSAGE_REACTIONS'
]
},
disabledEvents: [
'GUILD_UPDATE',
'GUILD_MEMBER_ADD',
'GUILD_MEMBER_REMOVE',
'GUILD_MEMBER_UPDATE',
'GUILD_MEMBERS_CHUNK',
'GUILD_ROLE_CREATE',
'GUILD_ROLE_DELETE',
'GUILD_ROLE_UPDATE',
'GUILD_BAN_ADD',
'GUILD_BAN_REMOVE',
'GUILD_EMOJIS_UPDATE',
'GUILD_INTEGRATIONS_UPDATE',
'CHANNEL_DELETE',
'CHANNEL_UPDATE',
'CHANNEL_PINS_UPDATE',
'MESSAGE_DELETE',
'MESSAGE_UPDATE',
'MESSAGE_DELETE_BULK',
'USER_UPDATE',
'PRESENCE_UPDATE',
'TYPING_START',
'VOICE_STATE_UPDATE',
'VOICE_SERVER_UPDATE',
'WEBHOOKS_UPDATE',
]
});
const handlers = {};
const commands = {};
modules.forEach((module, index) => {
// eslint-disable-line global-require
const moduleObject = new (require("./modules/" + module + '.js'))(commandChar, modules);
if (moduleObject) {
log.info("Successfully initialized module", module);
modules[index] = moduleObject;
_.forEach(moduleObject.getCommands(), (commandObj, command) => {
handlers[command] = moduleObject;
commands[command] = commandObj;
// map aliases to handlers as well
if (commandObj.aliases) {
commandObj.aliases.forEach(alias => {
handlers[alias] = moduleObject;
commands[alias] = commandObj;
});
}
});
} else {
log.error("Couldn't initialize module", module);
}
});
// remember timestamps for last message per user
const userMessageTimes = {};
// generate RegExp pattern for message parsing
// Example: ((^|\s)!(card|price|mtr)|^!(hangman|standard|jar|help))( .*?)?(![^a-z0-9]|$)
const charPattern = _.escapeRegExp(commandChar);
// split inline and non-inline commands into 2 patterns
const commandPattern = '(^|\\s)' + charPattern + '(' +
Object.keys(commands).filter(cmd => commands[cmd].inline).map(_.escapeRegExp).join('|')
+ ')|^' + charPattern + '(' +
Object.keys(commands).filter(cmd => !commands[cmd].inline).map(_.escapeRegExp).join('|')
+ ')';
const regExpPattern = `(${commandPattern})( .*?)?(${charPattern}[^a-z0-9]|$)`;
const regExpObject = new RegExp(regExpPattern, 'ig');
/* Handle incoming messages */
bot.on("message", msg => {
const queries = msg.content.match(regExpObject);
const lastMessage = userMessageTimes[msg.author.id] || 0;
// if the message mentions us, log it
if (!msg.author.bot && // don't log if a bot mentions us
(msg.content.toLowerCase().indexOf(bot.user.username.toLowerCase()) > -1 ||
msg.mentions.users.has(bot.user.id))) {
log.info(utils.prettyLog(msg, 'mention', msg.content));
}
// check if the message...
if (queries && // ...contains at least one command
!msg.author.bot && // ...is not from a bot
// (!msg.guild || msg.guild.id !== '110373943822540800') && // ...is not from a blacklisted server
new Date().getTime() - lastMessage >= spamTimeout) // ...is outside the spam threshold
{
// store the time to prevent spamming from this user
userMessageTimes[msg.author.id] = new Date().getTime();
// only use the first 3 commands in a message, ignore the rest
queries.slice(0, 3).forEach(query => {
const command = query.trim().split(" ")[0].substr(commandChar.length).toLowerCase();
const parameter = query.trim().split(" ").slice(1).join(" ").replace(new RegExp(charPattern + '[^a-z0-9]?$', 'i'), '');
log.info(utils.prettyLog(msg, 'query', (command + ' ' + parameter).trim()));
const ret = handlers[command].handleMessage(command, parameter, msg);
// if ret is undefined or not a thenable this just returns a resolved promise and the callback won't be called
Promise.resolve(ret).catch(e => log.error('An error occured while handling', msg.content, ":", e.message));
});
}
});
/* Bot event listeners */
bot.on('ready', () => {
log.info('Bot is ready! Username:', bot.user.username, '/ Servers:', bot.guilds.cache.size);
utils.updateServerCount(bot);
});
bot.on('guildCreate', (guild) => {
log.info(utils.prettyLog({guild}, "joined"));
utils.updateServerCount(bot);
});
bot.on('guildDelete', (guild) => {
log.info(utils.prettyLog({guild}, "left"));
utils.updateServerCount(bot);
});
bot.on('error', (error) => {
log.error('client error received');
log.error(error);
console.log(error);
});
// bot.on("debug",console.debug);
// start the engines!
try {
bot.login(process.env.DISCORD_TOKEN);
} catch (err) {
log.error(err);
}