-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathbot.js
More file actions
244 lines (222 loc) · 10.3 KB
/
bot.js
File metadata and controls
244 lines (222 loc) · 10.3 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
// Require the necessary discord.js classes
const { Client, Collection, REST, Routes, Events, GatewayIntentBits, SlashCommandBuilder, Partials, EmbedBuilder } = require('discord.js');
const config = require('./config.js');
const fs = require('node:fs');
const path = require('node:path');
const request = require('request');
const { MongoClient, RegExp } = require('mongodb');
const mongoClient = new MongoClient(config.mongo_uri);
const database = mongoClient.db('openatbp');
const players = database.collection('discord');
// Create a new client instance
const client = new Client({
partials: [
Partials.Message, // for message
Partials.Channel, // for text channel
Partials.GuildMember, // for guild member
Partials.Reaction, // for message reaction
Partials.GuildScheduledEvent, // for guild events
Partials.User, // for discord user
Partials.ThreadMember, // for thread member
],
intents: [
GatewayIntentBits.Guilds, // for guild related things
GatewayIntentBits.GuildMembers, // for guild members related things
GatewayIntentBits.GuildBans, // for manage guild bans
GatewayIntentBits.GuildEmojisAndStickers, // for manage emojis and stickers
GatewayIntentBits.GuildIntegrations, // for discord Integrations
GatewayIntentBits.GuildWebhooks, // for discord webhooks
GatewayIntentBits.GuildInvites, // for guild invite managing
GatewayIntentBits.GuildVoiceStates, // for voice related things
GatewayIntentBits.GuildPresences, // for user presence things
GatewayIntentBits.GuildMessages, // for guild messages things
GatewayIntentBits.GuildMessageReactions, // for message reactions things
GatewayIntentBits.GuildMessageTyping, // for message typing things
GatewayIntentBits.DirectMessages, // for dm messages
GatewayIntentBits.DirectMessageReactions, // for dm message reaction
GatewayIntentBits.DirectMessageTyping, // for dm message typinh
GatewayIntentBits.MessageContent, // enable if you need message content things
],
});
client.commands = new Collection();
const commands = [];
// Grab all the command files from the commands directory you created earlier
const foldersPath = path.join(__dirname, 'commands');
const commandFolders = fs.readdirSync(foldersPath);
// Grab all the command files from the commands directory you created earlier
const commandFiles = fs.readdirSync('./commands/').filter(file => file.endsWith('.js'));
// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
if ('data' in command && 'execute' in command) {
client.commands.set(command.data.name, command);
commands.push(command.data.toJSON());
} else {
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
}
}
// Construct and prepare an instance of the REST module
const rest = new REST().setToken(config.client_token);
// and deploy your commands!
(async () => {
try {
console.log(`Started refreshing ${commands.length} application (/) commands.`);
// The put method is used to fully refresh all commands in the guild with the current set
const data = await rest.put(
Routes.applicationCommands(config.client_id),
{ body: commands },
);
console.log(`Successfully reloaded ${data.length} application (/) commands.`);
} catch (error) {
// And of course, make sure you catch and log any errors!
console.error(error);
}
})();
var checkRoles = function(member){
return new Promise(function(resolve, reject) {
console.log(member.roles.resolve(SELECTABLE_ROLE_IDS));
member.roles.fetch().then((roles) => {
for(var role of roles){
for(var selectAbleRole of SELECTABLE_ROLE_IDS){
if(role[0] == selectAbleRole) resolve(role[0]);
}
}
}).catch((err) => {
reject(err);
});
});
};
var queueIds = [];
// When the client is ready, run this code (only once)
// We use 'c' for the event parameter to keep it separate from the already defined 'client'
client.once(Events.ClientReady, c => {
console.log(`Ready! Logged in as ${c.user.tag}`);
client.user.setActivity(`Online: 0 | LFG: 0`);
//createRoleSelector();
setInterval(() => {
request.get(config.game_url+"data/users",(err,res,body) => {
if (err) return;
try{
client.user.setActivity(`Online: ${JSON.parse(body).users} | LFG: ${queueIds.length}`);
}catch(e){
console.log(e);
}
});
},1000*60);
});
client.on(Events.InteractionCreate, (interaction) => {
if(interaction.isChatInputCommand()){
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}else{
command.execute(interaction);
}
}else{
if(interaction.customId == 'next' || interaction.customId == 'previous') return;
if(interaction.customId == 'queue'){
var removePlayer = false;
interaction.deferUpdate().then(() => {
players.findOne({id: interaction.user.id}).then((d) => {
if (d != null && !d.preQueue) removePlayer = true;
var currentEmbed = interaction.message.embeds[0];
var playerList = currentEmbed.fields[0].value;
if (playerList.includes('No one') && !playerList.includes(",") && !removePlayer){
playerList = interaction.member.displayName;
queueIds.push({'id':interaction.user.id,'start':Date.now()});
}
else{
if(playerList == interaction.member.displayName){
playerList = "No one";
queueIds = [];
}
else if(playerList.includes(interaction.member.displayName)){
var oldNames = playerList.split(", ");
var newNames = [];
for(var n of oldNames){
if (n != interaction.member.displayName) newNames.push(n);
}
playerList = newNames.join(", ");
queueIds = queueIds.filter(i => i.id != interaction.user.id);
}else if(!removePlayer){
playerList+= `, ${interaction.member.displayName}`;
queueIds.push({'id':interaction.user.id,'start':Date.now()});
}
}
if(queueIds.length > 0){
var ids = [];
for (var qId of queueIds){
ids.push(qId.id);
}
var timedOut = [];
for (var qId of queueIds){
if (Date.now() - (1000*60*60*3) > qId.start) timedOut.push(qId.id);
}
interaction.guild.members.fetch({user: ids, withPresences: true}).then((members) => {
// Build a map of current members (found on the guild)
const foundIds = [];
for (const [id, memberObj] of members) foundIds.push(id);
// Remove any queueIds that aren't on the guild
queueIds = queueIds.filter(q => foundIds.includes(q.id));
// Remove timed-out entries
const now = Date.now();
queueIds = queueIds.filter(q => now - (1000*60*60*3) <= q.start);
// Rebuild the playerList from the remaining IDs using current displayName
let playerList = "No one";
if (queueIds.length > 0) {
const displayNames = [];
for (const q of queueIds) {
const m = members.get(q.id);
if (m) displayNames.push(m.displayName);
}
playerList = displayNames.length ? displayNames.join(", ") : "No one";
}
// If full party, pop queue as before
if (queueIds.length >= 6) {
client.guilds.fetch(config.guild_id).then((g) => {
g.channels.fetch(config.queue_chat_channel).then((c) => {
const mentions = queueIds.map(i => `<@${i.id}> `).join("");
c.send({content: `${mentions}Your battle party awaits! There are enough players to queue for a 3v3!`}).then(() => {
playerList = '[QUEUE POPPED] No one';
queueIds = [];
const newEmbed = new EmbedBuilder().setTitle(currentEmbed.title).setDescription(currentEmbed.description).addFields({name: "In Queue", value: playerList});
interaction.editReply({embeds: [newEmbed], components: interaction.message.components});
}).catch(console.error);
}).catch(console.error);
}).catch(console.error);
} else {
const newEmbed = new EmbedBuilder().setTitle(currentEmbed.title).setDescription(currentEmbed.description).addFields({name: "In Queue", value: playerList});
interaction.editReply({embeds: [newEmbed], components: interaction.message.components});
}
}).catch(console.error);
}else{
var newEmbed = new EmbedBuilder().setTitle(currentEmbed.title).setDescription(currentEmbed.description).addFields({name: "In Queue", value: playerList});
interaction.editReply({embeds: [newEmbed], components: interaction.message.components});
}
}).catch(console.error);
}).catch(console.error);
return;
}
console.log(interaction.values[0]);
var roleId = interaction.values[0];
var member = interaction.member;
if(roleId != undefined){
const SELECTABLE_ROLE_IDS = ['947258999831658577', '947259030773051452', '947259059009093674', '947259110695534622', '947259138679910440',
'947259169206042676', '947259212210249830', '947259228601585694', '947259235459301416', '947259315796979723',
'947259365319143475', '947259395396468806', '947259450270572554', '947259510811144263', '947259545330266174',
'947259592235171911', '947259618244042802', '947259648837296159', '947284774706360383'];
member.roles.remove(SELECTABLE_ROLE_IDS).then(() => {
if(roleId != "NONE"){
member.roles.add(roleId).then(() => {
interaction.reply({content: 'Role added!', ephemeral: true}).catch(console.error);
}).catch(console.error);
}else{
interaction.reply({content: 'Role removed!', ephemeral: true}).catch(console.error);
}
}).catch(console.error);
}
}
});
// Log in to Discord with your client's token
client.login(config.client_token);