This repository was archived by the owner on Apr 17, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathbot.js
More file actions
343 lines (285 loc) · 11.8 KB
/
bot.js
File metadata and controls
343 lines (285 loc) · 11.8 KB
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
const { Client, Collection, GatewayIntentBits } = require('discord.js');
const bot = new Client({ intents: [GatewayIntentBits.Guilds] });
const { token } = require('./auth.json');
var parsefuncs = require('./parse.js');
var config = require('./config.js');
var commands = require('./handlers.js');
var CronJob = require('cron').CronJob;
var dbfuncs = require("./dbfuncs.js");
var lists = require('./lists.js');
let patchdb = require('./patchdb.js');
const fuzzysort = require('fuzzysort');
// setup access to commands
const fs = require('node:fs');
const path = require('node:path');
bot.commands = new Collection();
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
bot.commands.set(command.data.name, command);
}
bot.once('ready', () => {
console.log(`Logged in with id ${bot.user.id} as ${bot.user.tag}!`);
config.summonstrings.push(`<@${bot.user.id}> `);
config.summonstrings.push(`<@!${bot.user.id}> `);
if(process.env.NODE_ENV === 'devmode') {
config.summonstrings = ['!dev '];
console.log("devmode: !dev is the only command that can summon this bot instance");
}
//bot.user.setActivity('', { type: 'WATCHING'});
// setup cronjobs
if(process.env.NODE_ENV !== 'devmode') {
// ping poring.world every 6 minutes
new CronJob('0 0-59/6 * * * *', function() {
commands.handleSearch(undefined, undefined, bot);
}, null, true);
// makes additional pings every odd minute
new CronJob('0 1-59/2 * * * *', function() {
let qs = lists.schedule[new Date().getMinutes()];
if(config.schedulesearch && qs !== undefined){
commands.handleSearch(undefined, undefined, bot, qs);
}
}, null, true);
// makes backup at 06:06:06 AM
new CronJob('6 6 6 * * *', function() {
dbfuncs.backup(['sun','mon','tue','wed','thu','fri','sat'][new Date().getDay()]);
}, null, true);
}
});
// when kicked from guild or guild is deleted
bot.on('guildDelete', (guild) => {
console.log(`event guildDelete: ${guild.name} ${guild.id}`);
let changes = dbfuncs.deleteGuild(guild.id);
console.log('removed '+changes.discokids+' discokids from database');
console.log('removed '+changes.channels+' channels from database');
});
// when channel is deleted
bot.on('channelDelete', (channel) => {
if(dbfuncs.deleteChannel(channel.id))
console.log('event channelDelete: '+channel.id);
});
// when member leaves, remove any requests he has in the channel in this guild
bot.on('guildMemberRemove', (member) => {
if(dbfuncs.deleteMember(member.id, member.guild.id))
console.log(`event guildMemberRemove: ${member.tag} ${member.id} in ${member.guild.name} ${member.guild.id}`);
});
// when role is deleted, remove any requests assigned to the role
bot.on('roleDelete', (role) => {
if(dbfuncs.deleteMember('&'+role.id, role.guild.id))
console.log(`event roleDelete: ${role.name} ${role.id} in ${role.guild.name} ${role.guild.id}`);
});
bot.on('interactionCreate', async interaction => {
if(interaction.user.id === bot.user.id) return; // if from self, ignore
if(interaction.user.bot) return; // if from bot, ignore
if (interaction.isChatInputCommand()) {
const command = bot.commands.get(interaction.commandName);
if (!command) return;
console.log(`From ${interaction.user.tag} ${interaction.user.id} to #${interaction.channel.name} ${interaction.channel.id} in ${interaction.guild.name} ${interaction.guild.id}`);
console.log(` ${interaction.toString()}`);
try {
let pwbChannel = {}; // https://github.com/theBowja/PoringWorldBot/wiki/Developer-documentation
pwbChannel = dbfuncs.getChannel(interaction.channel.id); // may be undefined
await command.execute(interaction, { pwbChannel: pwbChannel });
} catch (error) {
console.error(error);
await interaction.reply({ content: 'There was an error while executing this command! Please contact the bot developer.', ephemeral: true });
}
} else if(interaction.isAutocomplete()) {
const command = bot.commands.get(interaction.commandName);
if (!command) return;
const option = interaction.options.getFocused(true);
if (!command.autocomplete || !command.autocomplete[option.name]) return;
let result;
if(option.value === "")
result = command.autocomplete[option.name].initial || command.autocomplete[option.name].all.slice(0, 25);
else
result = fuzzysort.go(option.value, command.autocomplete[option.name].all, { limit: 25 }).map(e => e.target);
await interaction.respond(result.map(e => ({ name: e, value: e })));
}
});
// NO LONGER USED
bot.on('message', message => {
let pwbContent, pwbUser, pwbChannel = {}; // https://github.com/theBowja/PoringWorldBot/wiki/Developer-documentation
function callCommandHandler(handler) { // so i don't have to type out the parameters every time
return handler(message, { pwbContent: pwbContent, pwbUser: pwbUser, pwbChannel: pwbChannel });
};
if(message.channel.type !== 'text') return; // if not from text channel, ignore
if(!message.guild) return; // only guild messages
if(message.author.id === bot.user.id) return; // if from self, ignore
if(message.author.bot) return; // if from bot, ignore
if(config.blacklistedguild.includes(message.guild.id)) return; // if from blacklisted guild
if(config.blacklisteduser.includes(message.author.id)) return; // if from blacklisted user
// attach contentObj to message
// contentObj is just message.content parsed into three properties: summon, command, body
pwbContent = parsefuncs.parseContent(message.content.toLowerCase().replace(/\s+/g, ' ')); // strip excess whitespaces
if(pwbContent.summon === undefined) return; // not summoned with summonstring
if(pwbContent.command === '') return; // no command provided
// retrieve user info of this guild if he exists in database
// attach userObj to message
// userObj
pwbUser = dbfuncs.getDiscokid(message.author.id, message.guild.id);
if(pwbUser === undefined)
pwbUser = { permission: 0, discordid: message.author.id };
if(pwbUser.permission < 0) return; // this member is banned from using this bot in this guild
if(message.author.id === message.guild.ownerID) pwbUser.permission = config.ownerperm;
if(message.member.hasPermission('ADMINISTRATOR')) pwbUser.permission = config.startperm;
console.log(`From ${message.author.tag} ${message.author.id} to #${message.channel.name} ${message.channel.id} in ${message.guild.name} ${message.guild.id}`);
console.log(` ${pwbContent.command} :: ${pwbContent.body}`);
// COMMANDS THAT DONT REQUIRE CHANNEL WATCH
switch(pwbContent.command) {
case 'help':
return callCommandHandler(commands.handleHelp);
case 'watch': // allow commands to be read on this channel
case 'listen':
return callCommandHandler(commands.handleWatch);
case 'status':
return message.channel.send('online');
case 'alive':
case 'awake':
return message.react('🙂');
case 'up':
return message.channel.send('dog');
case 'dead':
case 'ded':
return message.channel.send('rip');
case 'estimate':
case 'est':
case 'calculate':
case 'calc':
return callCommandHandler(commands.handleEstimate);
case 'joke':
return message.channel.send(lists.joke[Math.floor(Math.random() * lists.joke.length)]);
}
// retrieve channel info if exists in database
// attach channelObj to message
pwbChannel = dbfuncs.getChannel(message.channel.id);
if(pwbChannel === undefined) return; // channel isn't on watch
// COMMANDS THAT REQUIRE CHANNEL WATCH
// COMMANDS WITH NO PERMISSION LEVEL REQUIRED
switch(pwbContent.command) {
case 'invite':
case 'invitelink':
return message.channel.send('```https://discordapp.com/oauth2/authorize?client_id='+bot.user.id+'&scope=bot&permissions=2147634368```');
case 'request':
case 'req':
case 'subscribe':
case 'pingwhen':
case 'pingmewhen':
case 'pingme':
case 'tagwhen':
case 'tagmewhen':
case 'tagme':
return callCommandHandler(commands.handleTagMe);
case 'show':
case 'list':
case 'showme':
return callCommandHandler(commands.handleShowUser);
case 'delete':
case 'del':
case 'remove':
return callCommandHandler(commands.handleDelete);
case 'deleteall':
case 'delall':
case 'removeall':
return callCommandHandler(commands.handleDeleteAll);
case 'budget':
return callCommandHandler(commands.handleBudget);
case 'thanks':
case 'thank':
case 'ty':
return callCommandHandler(commands.handleThanks);
case 'pc': // quick price check for clean/unmodified equip
case 'pricecheck':
return callCommandHandler(commands.handlePriceCheck);
}
// no peasants allowed past here
if(pwbUser.permission === 0) return message.react('🔒');
// COMMANDS THAT REQUIRES HIGHER PERMISSION LEVEL
switch(pwbContent.command) {
case 'showhere':
// TODO: showhere for channel
// NOT IMPLEMENTED due to worries over message being too long and spammy
return;
case 'unwatch':
return callCommandHandler(commands.handleUnwatch); // remove this channel from channels table
case 'force':
case 'search':
case 'query':
return callCommandHandler(commands.handleSearch);
case 'permit':
case 'admin':
return callCommandHandler(commands.handlePermit);
case 'cleanupmember':
case 'cleanupmembers':
return callCommandHandler(commands.handleCleanupMembers);
return;
}
if(message.author.id !== config.owner) return;// message.react('🔒');
// FOLLOWING COMMANDS ARE RESTRICTED TO OWNER OVERLORD
switch(pwbContent.command) {
case 'clearsnaps':
let num = dbfuncs.deleteAllCurrentSnaps();
console.log(num + ' snap records deleted');
return message.channel.send(num + ' snap records deleted');
case 'debug':
return console.log(dbfuncs.listDiscokids()); // this is a debug function zzz
case 'logallchannels':
return console.log(dbfuncs.getAllChannels());
case 'showall':
return console.log(dbfuncs.listAllRequirements());
case 'showcurrent':
return console.log(dbfuncs.getSnaps());
case 'listguildsjoined':
let tmp = bot.guilds.cache.map(g => g.id+': '+g.name).join('\n');
return message.channel.send('```'+tmp+'```', { split: true });
case 'announce':
let chans = dbfuncs.getAllChannels();
for(let ch of chans) {
bot.channels.fetch(ch.discordchid).then((chan) => {
chan.send(pwbContent.body);
});
}
return message.react('✅');
case 'fixnames':
patchdb.fixnames(bot);
return;
case 'patch':
//let patchdb = require('./patchdb.js');
//return patchdb.doPatches();
return;
case 'backup':
if(pwbContent.body === '') return message.react('❎');
return dbfuncs.backup(pwbContent.body);
case 'cleanup':
patchdb.cleanupguilds(message);
patchdb.cleanupchannels(message);
patchdb.cleanupmembers(message);
return;
case 'cleanupguild':
case 'cleanupguilds':
patchdb.cleanupguilds(message);
return;
case 'cleanupchannel':
case 'cleanupchannels':
patchdb.cleanupchannels(message);
return;
case 'cleanupallmember':
case 'cleanupallmembers':
patchdb.cleanupmembers(message);
return;
}
});
// not sure if this is an actual event but whatever
bot.on("disconnect", function(event){
console.log(`${new Date().toLocaleString()}: The WebSocket has closed and will no longer attempt to reconnect`);
});
bot.on("error", (err) => {
console.log(err);
});
bot.on("rateLimit", (something) => {
console.log("ratelimit");
console.log(something);
});
bot.login(token);