· 5 years ago · Sep 16, 2020, 03:08 PM
1const Discord = require('discord.js')
2const FS = require('fs')
3const rp = require('request-promise')
4const $ = require('cheerio')
5const mysql = require('mysql')
6require('events').EventEmitter.prototype._maxListeners = 0
7
8// MySQL Connection Settings
9var pool = mysql.createPool({
10 connectionLimit: 500,
11 host: '',
12 user: '',
13 password: '',
14 database: '',
15})
16
17// Boolean variables used for state checking
18var emptyQueue = true
19var handlingQueue = false
20var updatingRanks = false
21var checkingHighest = false
22var checkingRoles = false
23var enabled = true
24
25const platforms = ['steam', 'psn', 'xbl']
26
27const modes = ['Standard', 'Doubles', 'Solo Duel']
28
29const ranks = ['Bronze', 'Silver', 'Gold', 'Platinum', 'Diamond', 'Champion']
30const rankColors = ['#d6680e', '#9aaab4', '#eec42c', '#00d5eb', '#4198d9', '#9a58b4']
31
32const ranks2 = ['Unranked', 'Bronze', 'Silver', 'Gold', 'Platinum', 'Diamond', 'Champion', 'Grand Champion']
33const rankColors2 = ['#627d8a', '#d6680e', '#9aaab4', '#eec42c', '#00d5eb', '#4198d9', '#9a58b4', '#703589']
34
35var rankValues = [] // is filled in by SetRankValues()
36
37const tiers = ['I', 'II', 'III']
38
39const URL = 'https://rocketleague.tracker.network/rocket-league/profile/'
40
41const TOKEN = '' // Fill with your discord app Token
42const ServerID = '' // ID of the server you want to use the bot in
43var bot = new Discord.Client()
44bot.login(TOKEN)
45
46var z = 0
47
48bot.on('ready', function () {
49 console.log('RL Stats Activated.')
50
51 // Verify log.txt exists or create it
52 VerifyLogFile()
53 UpdateLogFile('RL Stats Activated.')
54
55 SetRankValues()
56
57
58 // Production Intervals
59 /*setInterval(async function(){ emptyQueue = await CheckQueue() }, 60*1000)
60 setInterval(async function(){ if (!handlingQueue) { HandleQueue() } }, 2*60*1000)
61 setInterval(async function(){ if (!updatingRanks) { UpdateUsers() } }, 15*60*1000)
62 setInterval(async function(){ if (!checkingHighest) { CheckHighest() } }, 5*60*1000)
63 setInterval(async function(){ if (!checkingRoles) { CheckRoles() } }, 10*60*1000)*/
64
65 /*Testing with shorter times
66 setInterval(async function () { emptyQueue = await CheckQueue() }, 20 * 1000)
67 setInterval(async function () { if (!handlingQueue) { HandleQueue() } }, 60 * 1000)
68 setInterval(async function () { if (!updatingRanks) { UpdateUsers() } }, 3*60 * 1000)
69 setInterval(async function () { if (!checkingHighest) { CheckHighest() } }, 60 * 1000)
70 setInterval(async function () { if (!checkingRoles) { CheckRoles() } }, 90 * 1000)*/
71
72 setInterval(async function () { emptyQueue = await CheckQueue() }, 10 * 1000)
73 setInterval(async function () { if (!handlingQueue) { HandleQueue() } }, 30 * 1000)
74 setInterval(async function () { if (!updatingRanks) { UpdateUsers() } }, 1*60 * 1000)
75 setInterval(async function () { if (!checkingHighest) { CheckHighest() } }, 30 * 1000)
76 setInterval(async function () { if (!checkingRoles) { CheckRoles() } }, 45 * 1000)
77})
78
79bot.on('disconnect', function () {
80 UpdateLogFile('RL Stats Deactivated.')
81 enabled = false
82})
83
84bot.on('reconnecting', function () {
85 UpdateLogFile('RL Stats Reconnecting.')
86 enable = false
87})
88
89bot.on('resume', function () {
90 UpdateLogFile('RL Stats Resumed.')
91 enabled = false
92})
93
94bot.on('error', function (error) {
95 console.log(error.message)
96 UpdateLogFile(error.message)
97 enabled = false
98})
99
100bot.on('message', function (message) {
101
102 // Do nothing if the message is from the bot
103 if (message.author.equals(bot.user)) {
104 return
105 }
106
107 // Ignore all messages unless they start with '!rl'
108 if (message.content.toLowerCase().startsWith('!rl')) {
109
110 // Help command
111 if (message.content.toLowerCase() === '!rlhelp') {
112 var embed = new Discord.RichEmbed()
113 .setColor('#0291ED')
114 .addField('This is RL Stats!', "I will keep your Rocket League competitive ranks updated for you in this Discord server!")
115 .addField('Commands',
116 '!rlregister <Platform> <Account Name>')
117 .addField('Note',
118 '**Available Platforms**: `steam`, `psn`, `xbl`\n' +
119 'If you are on steam: Make sure to give your __Account Name__ and not your profile name.\n' +
120 'For a complete guide to setting up your Steam Account (if applicable) and Rocket League Tracker Network account to work with RL Stats, click the link below.\n' +
121 'https://docs.google.com/document/d/1wvKjSyu7Iig0qY9T4bFf7Z-EwM1KRrvZqbcbfqK7ssY/edit?usp=sharing')
122 message.channel.send(embed)
123 }
124
125 // Command for building all necessary roles
126 // Must have a role called 'Admin' to be able to use it
127 if (message.content.toLowerCase() == '!rlsetuproles') {
128 if (UserIsAdmin(message)) {
129 BuildRoleNames(message)
130 message.channel.send('All rank roles have been created.')
131 } else {
132 message.channel.send(message.member.toString() + ' You are not an admin user!')
133 }
134 }
135
136 // Command for deleting all roles created by the bot
137 // Must have a role called 'Admin' to be able to use it
138 if (message.content.toLowerCase() == '!rlcleanroles') {
139 if (UserIsAdmin(message)) {
140 DeleteRoles(message)
141 message.channel.send('All rank roles have been deleted.')
142 } else {
143 message.channel.send(message.member.toString() + ' You are not an admin user!')
144 }
145 }
146 if (message.content.toLowerCase() == '!rlenable') {
147 if (UserIsAdmin(message)) {
148 enabled = true;
149 message.channel.send('Der Bot wurde wieder Aktiviert.')
150 } else {
151 message.channel.send(message.member.toString() + ' You are not an admin user!')
152 }
153 }
154
155 // Command for registering users with the bot
156 if (message.content.toLowerCase().startsWith('!rlregister')) {
157 // Verify no users are mentioned in the message
158 if (UserMentioned(message)) {
159 message.channel.send('User mentions are not supported!')
160 } else {
161 var fullCommand = message.content.split(' ')
162 // Verify the correct amount of arguments were given
163 if (fullCommand.length != 3) {
164 message.channel.send('Incorrect amount of arguments!\nExpected: `2`\nGiven: `' + (fullCommand.length - 1) + '`')
165 } else {
166 // Command should look like "!rlregister steam jeremyd4500"
167 var Platform = fullCommand[1].toLowerCase() // steam
168 var AccountID = fullCommand[2].toLowerCase() // jeremyd4500
169 // Verify the platform is one of the available options
170 if (platforms.includes(Platform)) {
171 // Attempt to access a URL similar to 'https://rocketleague.tracker.network/profile/steam/jeremyd4500'
172 rp(URL + '/' + Platform + '/' + AccountID + '/overview')
173 .then(function (html) {
174 if (html.includes('We could not find your stats')) { // This page is shown with an invalid URL
175 message.channel.send("I'm sorry. I could not find **" + AccountID + "** in the tracker network.")
176 } else {
177 // Add new user to the queue table
178 AddUserToQueue(message.member.id, Platform, AccountID)
179 message.channel.send("Added stat request for **" + AccountID + "** under " + message.member.toString() + ' to the queue!')
180 }
181 })
182 .catch(function (error) {
183 UpdateLogFile(error)
184 })
185 } else {
186 message.channel.send('That is not a correct platform!\nPlatform Options: `steam`,`psn`,`xbl`')
187 }
188 }
189 }
190 }
191 }
192})
193
194// SQL Query
195// Updates the "Highest" column for the appropriate user
196function AddHighest(DiscordID, rank) {
197 UpdateLogFile('Function Call: AddHighest()')
198 return new Promise(resolve => {
199 pool.getConnection(async function (error, connection) {
200 if (error) { UpdateLogFile(error) } else {
201 var ID = await GetUserID(DiscordID)
202 connection.query("update ranks set Highest = '" + rank + "' where UserID = " + ID, function (error, results, fields) {
203 connection.release()
204 if (error) { UpdateLogFile(error) }
205 })
206 }
207 })
208 setTimeout(() => {
209 resolve(UpdateLogFile('SQL Query: Successfully updated Highest to value ' + rank + ' for user ' + DiscordID))
210 }, 5000)
211 })
212}
213
214// SQL Query
215// Inserts "Unranked" into all rank columns for a new user
216function AddRanksToUser(DiscordID) {
217 UpdateLogFile('Function Call: AddRanksToUser()')
218 return new Promise(resolve => {
219 pool.getConnection(async function (error, connection) {
220 if (error) { UpdateLogFile(error) } else {
221 var ID = await GetUserID(DiscordID)
222 connection.query("insert into ranks (UserID,Highest,Standard,Standard_rating,Doubles,Doubles_rating,SoloDuel,SoloDuel_rating,SoloStandard,SoloStandard_rating,Rumble,Rumble_rating,Dropshot,Dropshot_rating,Hoops,Hoops_rating,SnowDay,SnowDay_rating) values ('" + ID + "','Unranked','Unranked','800','Unranked','800','Unranked','800','Unranked','800','Unranked','800','Unranked','800','Unranked','800','Unranked','800')", function (error, results, fields) {
223 connection.release()
224 if (error) { UpdateLogFile(error) }
225 })
226 }
227 })
228 setTimeout(() => {
229 resolve(UpdateLogFile('SQL Query: Successfully added blank ranks for user ' + DiscordID))
230 }, 5000)
231 })
232}
233
234// Discord Process
235// Adds a new role to the server if it doesn't already exist
236function AddRole(message, RoleName, color) {
237 var role = message.guild.roles.find(role => role.name === RoleName)
238 if (role) {
239 UpdateLogFile("Role '" + RoleName + "' already exists!")
240 } else {
241 message.guild.createRole({
242 name: RoleName,
243 color: color
244 })
245 UpdateLogFile("Role '" + RoleName + "' has been created!")
246 }
247}
248
249// Discord Process
250// Adds a role to a user if it exists
251function AddRoleToUser(DiscordID, RoleName) {
252 UpdateLogFile('Function Call: AddRoleToUser()')
253 return new Promise(resolve => {
254 var success = false
255 let newRole = bot.guilds.get(ServerID).roles.find(role => role.name === RoleName).id
256 if (newRole) {
257 bot.guilds.get(ServerID).members.get(DiscordID).addRole(newRole)
258 success = true
259 } else {
260 UpdateLogFile('Role ' + RoleName + ' does not exist')
261 success = false
262 }
263 setTimeout(() => {
264 if (success) {
265 resolve(UpdateLogFile('Discord Process: Successfully added role ' + RoleName + ' to user ' + DiscordID))
266 } else {
267 resolve(UpdateLogFile('Discord Process: Failed to add role ' + RoleName + ' to user ' + DiscordID))
268 }
269 }, 2000)
270 })
271}
272
273// SQL Query
274// Adds a user from the queue table to the users table and then inserts blank ranks for them
275function AddUser(DiscordID, Platform, AccountID) {
276 UpdateLogFile('Function Call: AddUser()')
277 return new Promise(resolve => {
278 pool.getConnection(function (error, connection) {
279 if (error) { UpdateLogFile(error) } else {
280 connection.query("insert into users (DiscordID,Platform,AccountID) values ('" + DiscordID + "','" + Platform + "','" + AccountID + "')", async function (error, results, fields) {
281 connection.release()
282 if (error) { UpdateLogFile(error) } else {
283 await AddRanksToUser(DiscordID)
284 }
285 })
286 }
287 })
288 setTimeout(() => {
289 resolve(UpdateLogFile('SQL Query: Successfully added user ' + DiscordID + ' to the database'))
290 }, 5000)
291 })
292}
293
294// SQL Query
295// Updates any column for a user in the users table
296function AddUserDetail(ID, column, value) {
297 UpdateLogFile('Function Call: AddUserDetail()')
298 return new Promise(resolve => {
299 pool.getConnection(async function (error, connection) {
300 if (error) { UpdateLogFile(error) } else {
301 connection.query("update users set " + column + " = '" + value + "' where ID = " + ID, function (error, results, fields) {
302 connection.release()
303 if (error) { UpdateLogFile(error) }
304 })
305 }
306 })
307 setTimeout(() => {
308 resolve(UpdateLogFile('SQL Query: Successfully updated detail ' + column + ' with value ' + value + ' for user ' + ID))
309 }, 5000)
310 })
311}
312
313// SQL Query
314// Updates any column for a user in the ranks table
315function AddUserStat(UserID, column, value, rating) {
316 UpdateLogFile('Function Call: AddUserStat()')
317 return new Promise(resolve => {
318 pool.getConnection(async function (error, connection) {
319 if (error) { UpdateLogFile(error) } else {
320 connection.query("update ranks set " + column + " = '" + value + "', " + column + "_rating = '" + rating + "' where UserID = '" + UserID + "'", function (error, results, fields) {
321 connection.release()
322 if (error) { UpdateLogFile(error) }
323 })
324 }
325 })
326 setTimeout(() => {
327 resolve(UpdateLogFile('SQL Query: Successfully updated stat ' + column + ' with value ' + value + ' for user ' + UserID))
328 }, 5000)
329 })
330}
331
332// SQL Query
333// Adds a new user to the queue table
334function AddUserToQueue(DiscordID, Platform, AccountID) {
335 UpdateLogFile('Function Call: AddUserToQueue()')
336 return new Promise(resolve => {
337 pool.getConnection(async function (error, connection) {
338 if (error) { UpdateLogFile(error) } else {
339 connection.query("insert into queue (DiscordID,Platform,AccountID) values ('" + DiscordID + "','" + Platform + "','" + AccountID + "')", function (error, results, fields) {
340 connection.release()
341 if (error) { UpdateLogFile(error) }
342 })
343 }
344 })
345 setTimeout(() => {
346 resolve(UpdateLogFile('SQL Query: Successfully added queue entry for user ' + DiscordID))
347 }, 5000)
348 })
349}
350
351// Javascript
352// Creates all roles needed by the bot and calls AddRole() for each
353function BuildRoleNames(message) {
354 UpdateLogFile('Function Call: BuildRoleNames()')
355 // First add the "Highest" roles
356 for (let i = ranks2.length - 1; i >= 0; i--) {
357 AddRole(message, ranks2[i], rankColors2[i])
358 }
359 // Then add all the rank roles
360 for (let i = 0; i < modes.length; i++) {
361 var currentRole = modes[i] + ' Unranked'
362 AddRole(message, currentRole, '#627d8a')
363 for (let j = 0; j < ranks.length; j++) {
364 for (let k = 0; k < tiers.length; k++) {
365 currentRole = modes[i] + ' ' + ranks[j] + ' ' + tiers[k]
366 AddRole(message, currentRole, rankColors[j])
367 }
368 }
369 currentRole = modes[i] + ' Grand Champion'
370 AddRole(message, currentRole, '#703589')
371 }
372}
373
374// Javascript
375// Gets an array of Discord ID's from the users table and calls UpdateHighest() for each
376async function CheckHighest() {
377 checkingHighest = true
378 var users = await GetUsers()
379 for (let i = 0; i < users.length; i++) {
380 await UpdateHighest(users[i])
381 }
382 checkingHighest = false
383}
384
385// SQL Query
386// Checks if the queue table is empty
387function CheckQueue() {
388 UpdateLogFile('Function Call: CheckQueue()')
389 return new Promise(resolve => {
390 var isEmpty = true
391 pool.getConnection(function (error, connection) {
392 if (error) { UpdateLogFile(error) } else {
393 connection.query('select * from queue', function (error, results, fields) {
394 connection.release()
395 if (error) { UpdateLogFile(error) } else {
396 if (results.length > 0) {
397 isEmpty = false
398 }
399 UpdateLogFile('SQL Query: Successfully retrieved the queue')
400 }
401 })
402 }
403 })
404 setTimeout(() => {
405 resolve(isEmpty)
406 }, 5000)
407 })
408}
409
410// Javascript
411// Gets an array of Discord ID's from the users table and calls UpdateRankRoles() for each
412async function CheckRoles() {
413 z = z + 1
414 var CurrentTime = new Date()
415 var today = CurrentTime.getDate().toString() + '/' + (CurrentTime.getMonth() + 1).toString() + '/' + CurrentTime.getFullYear().toString()
416 var ClockTime = CurrentTime.getHours().toString() + ':' + CurrentTime.getMinutes().toString() + ':' + CurrentTime.getSeconds().toString()
417 var FullTime = today + ' ' + ClockTime + ' >>> '
418 console.log("Roles werden gecheckt (" + FullTime + z + ")")
419 checkingRoles = true
420 var users = await GetUsers()
421 for (let i = 0; i < users.length; i++) {
422 await UpdateRankRoles(users[i])
423 }
424 checkingRoles = false
425}
426
427// Discord Process
428// Deletes a role created by the bot if it exists
429function DeleteRole(message, roleName) {
430 var role = message.guild.roles.find(role => role.name === roleName)
431 if (role) {
432 role.delete()
433 UpdateLogFile("Role '" + roleName + "' has been deleted!")
434 } else {
435 UpdateLogFile("Role '" + roleName + "' does not exist!")
436 }
437}
438
439// Javascript
440// Creates the name of each role created by the bot and calls DeleteRole() for each
441function DeleteRoles(message) {
442 // First delete the "Highest" roles
443 for (let i = ranks2.length - 1; i >= 0; i--) {
444 DeleteRole(message, ranks2[i])
445 }
446 // Then delete the rank roles
447 for (let i = 0; i < modes.length; i++) {
448 var currentRole = modes[i] + ' Unranked'
449 DeleteRole(message, currentRole)
450 for (let j = 0; j < ranks.length; j++) {
451 for (let k = 0; k < tiers.length; k++) {
452 currentRole = modes[i] + ' ' + ranks[j] + ' ' + tiers[k]
453 DeleteRole(message, currentRole)
454 }
455 }
456 currentRole = modes[i] + ' Grand Champion'
457 DeleteRole(message, currentRole)
458 }
459}
460
461// Javascript
462// Updates the Platform and AccoundID for a user
463// Calls AddUserStat() to inserts "Unranked" for all ranks for a user
464async function EditUser(DiscordID, Platform, AccountID) {
465 UpdateLogFile('Function Call: EditUser()')
466 var ID = await GetUserID(DiscordID)
467 await AddUserDetail(ID, 'Platform', Platform)
468 await AddUserDetail(ID, 'AccountID', AccountID)
469 var SQLRanks = []
470 modes.forEach(function (item) {
471 SQLRanks.push(item)
472 })
473 SQLRanks.push('Highest')
474 SQLRanks.forEach(async function (item) {
475 item = item.replace(' ', '')
476 await AddUserStat(ID, item, 'Unranked', 0)
477 })
478}
479
480// SQL Query
481// Retrieves the value in the "Highest" column for a user in the ranks table
482function GetHighest(DiscordID) {
483 UpdateLogFile('Function Call: GetHighest()')
484 return new Promise(resolve => {
485 var highest = 'Unranked'
486 pool.getConnection(async function (error, connection) {
487 if (error) { UpdateLogFile(error) } else {
488 var ID = await GetUserID(DiscordID)
489 connection.query("select Highest from ranks where UserID = " + ID, function (error, results, fields) {
490 connection.release()
491 if (error) { UpdateLogFile(error) } else {
492 highest = results[0].Highest
493 UpdateLogFile('SQL Query: Successfully retrieved Highest rank for user ' + DiscordID)
494 }
495 })
496 }
497 })
498 setTimeout(() => {
499 resolve(highest)
500 }, 8000)
501 })
502}
503
504// SQL Query
505// Gets an array of all columns for each user in the queue table
506function GetQueue() {
507 UpdateLogFile('Function Call: GetQueue()')
508 return new Promise(resolve => {
509 var Queue = 0
510 pool.getConnection(function (error, connection) {
511 if (error) { UpdateLogFile(error) } else {
512 connection.query('select * from queue', function (error, results, fields) {
513 connection.release()
514 if (error) { UpdateLogFile(error) } else {
515 if (results.length > 0) {
516 Queue = []
517 results.forEach(function (item) {
518 Queue.push({
519 ID: item.ID,
520 DiscordID: item.DiscordID,
521 Platform: item.Platform,
522 AccountID: item.AccountID
523 })
524 })
525 }
526 UpdateLogFile('SQL Query: Successfully retrieved the queue')
527 }
528 })
529 }
530 })
531 setTimeout(() => {
532 resolve(Queue)
533 }, 5000)
534 })
535}
536
537// Javascript
538// Used to compare a numeric value tied each rank
539// Retrieves a rank based on a given value
540function GetRank(value) {
541 UpdateLogFile('Function Call: GetRank()')
542 var rank = 'Unranked'
543 rankValues.forEach(function (item) {
544 if (item.value === value) {
545 rank = item.rank
546 }
547 })
548 return rank
549}
550
551// Javascript
552// Used to compare a numeric value tied each rank
553// Retrieves a value based on a given rank
554function GetRankValue(rank) {
555 UpdateLogFile('Function Call: GetRankValue()')
556 var Value = 0
557 rankValues.forEach(function (item) {
558 if (item.rank === rank) {
559 Value = item.value
560 }
561 })
562 return Value
563}
564
565// SQL Query
566// Gets an array of all columns for each user in the users table
567function GetUserDetails(DiscordID) {
568 UpdateLogFile('Function Call: GetUserDetails()')
569 return new Promise(resolve => {
570 var details = []
571 pool.getConnection(async function (error, connection) {
572 if (error) { UpdateLogFile(error) } else {
573 var ID = await GetUserID(DiscordID)
574
575 connection.query("select * from users where ID = " + ID + " ORDER BY ID ASC", function (error, results, fields) {
576 connection.release()
577 try {
578 if (error) { UpdateLogFile(error) } else {
579 details.push(results[0].ID)
580 details.push(results[0].DiscordID)
581 details.push(results[0].Platform)
582 details.push(results[0].AccountID)
583 UpdateLogFile('SQL Query: Successfully retrieved all details for user ' + DiscordID)
584 }
585 }
586 catch (e) {
587 console.log("Fehler (" + ID + "):" + e);
588 UpdateLogFile("Fehler (" + ID + "):" + e);
589 }
590 })
591 }
592 })
593 setTimeout(() => {
594 resolve(details)
595 }, 10000)
596 })
597}
598
599// SQL Query
600// Gets the generated ID for a user in the users table
601function GetUserID(DiscordID) {
602 UpdateLogFile("Function Call: GetUserID()")
603 return new Promise(resolve => {
604 var ID = 0
605 pool.getConnection(function (error, connection) {
606 if (error) { UpdateLogFile(error) } else {
607 connection.query("select ID from users where DiscordID = '" + DiscordID + "' ORDER BY ID ASC", function (error, results, fields) {
608 connection.release()
609 if (error) { UpdateLogFile(error) } else {
610 ID = results[0].ID
611 UpdateLogFile('SQL Query: Successfully retrieved ID for user ' + DiscordID)
612 }
613 })
614 }
615 })
616 setTimeout(() => {
617 resolve(ID)
618 }, 5000)
619 })
620}
621
622// SQL Query
623// Gets an array of all ranks for a user in the ranks table
624function GetUserRanks(DiscordID) {
625 UpdateLogFile('Function Call: GetUserRanks()')
626 return new Promise(resolve => {
627 var ranks = []
628 pool.getConnection(async function (error, connection) {
629 if (error) { UpdateLogFile(error) } else {
630 var ID = await GetUserID(DiscordID)
631 connection.query("select * from ranks where UserID = " + ID, function (error, results, fields) {
632 connection.release()
633 if (error) { UpdateLogFile(error) } else {
634 ranks.push(results[0].Standard)
635 ranks.push(results[0].Doubles)
636 ranks.push(results[0].SoloDuel)
637 ranks.push(results[0].SoloStandard)
638 ranks.push(results[0].Rumble)
639 ranks.push(results[0].Dropshot)
640 ranks.push(results[0].Hoops)
641 ranks.push(results[0].SnowDay)
642 UpdateLogFile('SQL Query: Successfully retrieved all ranks for user ' + DiscordID)
643 }
644 })
645 }
646 })
647 setTimeout(() => {
648 resolve(ranks)
649 }, 10000)
650 })
651}
652
653// SQL Query
654// Gets an array of Discord ID's for all users in the users table
655function GetUsers() {
656 UpdateLogFile('Function Call: GetUsers()')
657 return new Promise(resolve => {
658 var users = []
659 pool.getConnection(function (error, connection) {
660 if (error) { UpdateLogFile(error) } else {
661 connection.query('select DiscordID from users', function (error, results, fields) {
662 connection.release()
663 if (error) { UpdateLogFile(error) } else {
664 for (let i = 0; i < results.length; i++) {
665 users.push(results[i].DiscordID)
666 }
667 UpdateLogFile('SQL Query: Successfully retrieved DiscordID for all users')
668 }
669 })
670 }
671 })
672 setTimeout(() => {
673 resolve(users)
674 }, 5000)
675 })
676}
677
678// Javascript
679// If the queue is not empty, either add or update a user to/in the users table
680async function HandleQueue() {
681 UpdateLogFile('Function Call: HandleQueue()')
682 if (!emptyQueue) {
683 handlingQueue = true
684 var queue = await GetQueue()
685 if (queue === 0) {
686 emptyQueue = true
687 handlingQueue = false
688 } else {
689 emptyQueue = false
690 for (let i = 0; i < queue.length; i++) {
691 if (await NewUser(queue[i].DiscordID)) {
692 await AddUser(queue[i].DiscordID, queue[i].Platform, queue[i].AccountID)
693 } else {
694 await EditUser(queue[i].DiscordID, queue[i].Platform, queue[i].AccountID)
695 }
696 await RemoveFromQueue(queue[i].ID)
697 }
698 handlingQueue = false
699 }
700
701 }
702}
703
704// SQL Query
705// Checks to see if a user already exists in the users table
706function NewUser(DiscordID) {
707 UpdateLogFile('Function Call: NewUser()')
708 return new Promise(resolve => {
709 var newUser = true
710 pool.getConnection(function (error, connection) {
711 if (error) { UpdateLogFile(error) } else {
712 connection.query("select * from users where DiscordID = '" + DiscordID + "'", function (error, results, fields) {
713 connection.release()
714 if (error) { UpdateLogFile(error) } else {
715 if (results.length > 0) {
716 newUser = false
717 UpdateLogFile('SQL Query: User ' + DiscordID + ' already exists')
718 } else {
719 UpdateLogFile('SQL Query: User ' + DiscordID + ' does not exist')
720 }
721 }
722 })
723 }
724 })
725 setTimeout(() => {
726 resolve(newUser)
727 }, 5000)
728 })
729}
730
731// SQL Query
732// Removes a user from the queue table
733function RemoveFromQueue(ID) {
734 UpdateLogFile('Function Call: RemoveFromQueue()')
735 return new Promise(resolve => {
736 pool.getConnection(function (error, connection) {
737 if (error) { UpdateLogFile(error) } else {
738 connection.query("delete from queue where ID = " + ID, function (error, results, fields) {
739 connection.release()
740 if (error) { UpdateLogFile(error) }
741 })
742 }
743 })
744 setTimeout(() => {
745 resolve(UpdateLogFile('SQL Query: Successfully removed a user from the queue'))
746 }, 5000)
747 })
748}
749
750// Discord Process
751// Removes a role from a user in the server
752function RemoveRoleFromUser(DiscordID, Role) {
753 UpdateLogFile('Function Call: RemoveRoleFromUser()')
754 return new Promise(resolve => {
755 setTimeout(() => {
756 bot.guilds.get(ServerID).members.get(DiscordID).removeRole(Role.ID)
757 UpdateLogFile('Discord Process: Successfully removed role ' + Role.Role + ' from user ' + DiscordID)
758 }, 2000)
759 })
760}
761
762// Javascript
763// Creates an array with values tied to each rank for use with the "Highest" role
764function SetRankValues() {
765 UpdateLogFile('Function Call: SetRankValues()')
766 for (let i = 0; i < ranks2.length; i++) {
767 rankValues.push({
768 rank: ranks2[i],
769 value: i
770 })
771 }
772}
773
774// Updates a user's "Highest" role in the server
775async function UpdateHighest(DiscordID) {
776 UpdateLogFile('Function Call: UpdateHighest()')
777 var highest = await GetHighest(DiscordID)
778 var highestValue = GetRankValue(highest) // The value of the old highest rank of the user
779 var userRanks = await GetUserRanks(DiscordID)
780 var currentHighest = 0
781 // Get the value of the new highest rank of the user
782 for (let i = 0; i < userRanks.length; i++) {
783 for (let j = rankValues.length - 1; j >= 0; j--) {
784 if (userRanks[i].startsWith(rankValues[j].rank)) {
785 if (rankValues[j].value > currentHighest) {
786 currentHighest = rankValues[j].value
787 }
788 }
789 }
790 }
791 // Get the rank of the new or old highest value
792 if (currentHighest != highestValue) {
793 highest = GetRank(currentHighest)
794 } else {
795 highest = GetRank(highestValue)
796 }
797 let currentRole;
798 try {
799 currentRole = bot.guilds.get(ServerID).roles.find(role => role.name === highest).id
800 let existingRole = bot.guilds.get(ServerID).members.get(DiscordID).roles.has(currentRole)
801
802
803
804 // If the current user does not have the role
805 if (!existingRole) {
806 // Remove all other "Highest" roles the user might have
807 for (let i = 0; i < ranks2.length; i++) {
808 let currentRole = bot.guilds.get(ServerID).roles.find(role => role.name === ranks2[i]).id
809 if (bot.guilds.get(ServerID).members.get(DiscordID).roles.has(currentRole)) {
810 setTimeout(() => {
811 bot.guilds.get(ServerID).members.get(DiscordID).removeRole(currentRole)
812 }, 1000);
813 }
814 }
815 // Add the new "Highest" role to the user
816 let currentRole = bot.guilds.get(ServerID).roles.find(role => role.name === highest).id
817 bot.guilds.get(ServerID).members.get(DiscordID).addRole(currentRole)
818 await AddHighest(DiscordID, highest)
819 }
820 } catch (e) {
821
822 }
823}
824
825// Javascript
826// Updates log.txt with a new value
827function UpdateLogFile(newValue) {
828 var CurrentTime = new Date()
829 var today = CurrentTime.getDate().toString() + '/' + (CurrentTime.getMonth() + 1).toString() + '/' + CurrentTime.getFullYear().toString()
830 var ClockTime = CurrentTime.getHours().toString() + ':' + CurrentTime.getMinutes().toString() + ':' + CurrentTime.getSeconds().toString()
831 var FullTime = today + ' ' + ClockTime + ' >>> '
832 FS.appendFile('log.txt', FullTime + newValue + '\r\n', function (error) {
833 if (error) { console.log(error) }
834 })
835}
836
837// Discord Process
838// Updates all rank roles for a user in the server
839async function UpdateRankRoles(DiscordID) {
840 var userRanks = await GetUserRanks(DiscordID)
841 // Get an array of roles that the user should have
842 var newRoles = []
843 for (let i = 0; i < modes.length; i++) {
844 newRoles.push(modes[i] + ' ' + userRanks[i])
845 }
846 var userRoles = [] // Used for the user's existing roles
847 var tempRanks = [] // Used as a list of roles to ignore
848 ranks2.forEach(function (item) {
849 tempRanks.push(item)
850 })
851 tempRanks.push('@everyone')
852 tempRanks.push('Owner')
853 tempRanks.push('Nadeko')
854 tempRanks.push('Birthday Bot')
855 tempRanks.push('Geburtstagskind ?')
856 tempRanks.push('Moderator')
857 tempRanks.push('VIP (Twitch)')
858 tempRanks.push('Twitch Subscriber')
859 tempRanks.push('Tier 3')
860 tempRanks.push('Tier 2')
861 tempRanks.push('Tier 1')
862 tempRanks.push('YAGPDB.xyz')
863 tempRanks.push('Rocket League')
864 tempRanks.push('Fortnite')
865 tempRanks.push('Osu!')
866 tempRanks.push('DE')
867 tempRanks.push('AT')
868 tempRanks.push('CH')
869 tempRanks.push('Bot')
870 tempRanks.push('CleanChat')
871 tempRanks.push('BotAleksS')
872 tempRanks.push('PatchBot')
873 tempRanks.push('RLTracker by RegiumNova.de')
874 tempRanks.push('BetterTTV')
875 tempRanks.push('Ark')
876 tempRanks.push('F1')
877 tempRanks.push('RL Itemshop')
878
879 // Add a statement like this for any pre-existing role in your server
880 // Get all roles from the user
881 try {
882 //console.log("'"+DiscordID+"' gerade in Benutzung")
883 bot.guilds.get(ServerID).members.get(DiscordID).roles.forEach(function (role, key, map) {
884 if (!tempRanks.includes(role.name)) {
885 userRoles.push({
886 Role: role.name,
887 ID: role.id
888 })
889 }
890 })
891 newRoles.forEach(function (item) {
892 var itemFound = false
893 // Check if user already has this role
894 for (let i = 0; i < userRoles.length; i++) {
895 if (item === userRoles[i].Role) {
896 itemFound = true
897 }
898 }
899 // If not, add the role to the user
900 if (!itemFound) {
901 setTimeout(async function () {
902 await AddRoleToUser(DiscordID, item)
903 }, 1000)
904 }
905 })
906 // Delay 5 seconds
907 setTimeout(function () {
908 userRoles = []
909 // Get all the users roles again since they have been updated
910 bot.guilds.get(ServerID).members.get(DiscordID).roles.forEach(function (role, key, map) {
911 if (!tempRanks.includes(role.name)) {
912 userRoles.push({
913 Role: role.name,
914 ID: role.id
915 })
916 }
917 })
918 userRoles.forEach(function (item) {
919 var itemFound = false
920 // Check if the user has a role he shouldn't have
921 for (let i = 0; i < newRoles.length; i++) {
922 if (item.Role === newRoles[i]) {
923 itemFound = true
924 }
925 }
926 // If he does, delete the role from the user
927 if (!itemFound) {
928 setTimeout(async function () {
929 await RemoveRoleFromUser(DiscordID, item)
930 }, 1000)
931 }
932 })
933 }, 5000)
934 } catch (e) {
935 console.log(e);
936 console.log("'"+DiscordID+"' nicht erkannt")
937 //if(enabled)
938 //delete_user(pool,DiscordID);
939 }
940}
941
942// Javascript
943// Parses the Rocket League Tracker Network to get each competitive rank for a user
944async function UpdateStats(DiscordID){
945 UpdateLogFile('Function Call: UpdateStats()')
946 // Get all columns from the users table for the user
947 var details = await GetUserDetails(DiscordID)
948 var UserID = details[0]
949 var Platform = details[2]
950 var AccountID = details[3]
951 var temp = []
952
953 var options = {
954 uri : "https://api.tracker.gg/api/v2/rocket-league/standard/profile/" + Platform + "/" + AccountID,
955 headers: {
956 'Referer': "https://rocketleague.tracker.network/rocket-league/profile/" + Platform + "/" + AccountID + "/overview",
957 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36"
958 },
959 json: true
960 }
961
962 rp(options)
963 .then(function(json){
964 let data = [[],[],[]];
965 for(let i in json['data']['segments']) {
966 const segment = json['data']['segments'][i];
967 if(segment['type'] === "playlist") {
968 data[0].push(segment['metadata']['name']);
969 data[1].push(segment['stats']['tier']['metadata']['name'])
970 data[2].push(segment['stats']['rating']['value'])
971 }
972 }
973 return Promise.all(
974 data.map(function(item){
975 temp.push(item)
976 }));
977 })
978 .then(function(){
979 var tempModes = temp[0]
980 var tempRanks = temp[1]
981 var tempRating = temp[2]
982 // remove the "Unranked" (Casual) category
983 tempModes.splice(0,1)
984 tempRanks.splice(0,1)
985 tempRating.splice(0,1)
986 for (let j = 0; j < tempRanks.length; j++){
987 // Format each one appropriately
988 tempModes[j] = tempModes[j].replace('Ranked ', '')
989 tempModes[j] = tempModes[j].replace(' 1v1', '')
990 tempModes[j] = tempModes[j].replace(' 2v2', '')
991 tempModes[j] = tempModes[j].replace(' 3v3', '')
992 tempModes[j] = tempModes[j].replace('Duel', 'Solo Duel')
993 tempModes[j] = tempModes[j].replace('Snowday', 'Snow Day')
994 tempModes[j] = tempModes[j].replace(' ', '')
995 // Add the new stat to ranks table for the user
996 AddUserStat(UserID, tempModes[j], tempRanks[j], tempRating[j])
997 }
998 })
999 .catch(function(error){
1000 UpdateLogFile(error)
1001 })
1002}
1003
1004// Javascript
1005// Gets an array of Discord ID's from the users table and calls UpdateStats() for each
1006async function UpdateUsers() {
1007 updatingRanks = true
1008 var users = await GetUsers()
1009 for (let i = 0; i < users.length; i++) {
1010 await UpdateStats(users[i])
1011 }
1012 updatingRanks = false
1013}
1014
1015// Discord Process
1016// Checks if a user has a role called "Admin"
1017function UserIsAdmin(message) {
1018 UpdateLogFile('Function Call: UserIsAdmin()')
1019 var AdminRole = message.guild.roles.find(role => role.name === 'Owner')
1020 if (AdminRole) {
1021 return message.member.roles.has(AdminRole.id)
1022 } else {
1023 return false
1024 }
1025}
1026
1027// Discord Process
1028// Checks if a user is mentioned in the command message
1029function UserMentioned(message) {
1030 UpdateLogFile('Function Call: UserMentioned()')
1031 return message.mentions.members.first()
1032}
1033
1034// Javascript
1035// Creates log.txt if it doesn't already exist
1036function VerifyLogFile() {
1037 FS.exists('log.txt', function (exists) {
1038 if (exists) {
1039 UpdateLogFile('log.txt already exists')
1040 } else {
1041 var log = FS.createWriteStream('log.txt')
1042 log.end()
1043 }
1044 })
1045}
1046
1047function delete_user(pool, DiscordID) {
1048 if (enabled) {
1049 pool.getConnection(function (error, connection) {
1050 if (error) { UpdateLogFile(error) } else {
1051 connection.query("SELECT * FROM users WHERE DiscordID = '" + DiscordID + "'", function (error, results, fields) {
1052 t = results[0].leavecheck;
1053 if (t != 3) {
1054 t++;
1055
1056 //DELETE FROM `tgfcptdk_tracker`.`users` WHERE `ID`=114;
1057 connection.query("UPDATE users SET leavecheck = '" + t + "' WHERE DiscordID =" + DiscordID, function (error, results, fields) {
1058 console.log("Discord ID: " + DiscordID + " wurde auf " + t + " gesetzt")
1059 UpdateLogFile("Discord ID: " + DiscordID + " wurde auf " + t + " gesetzt")
1060 connection.release()
1061 if (error) { UpdateLogFile(error) }
1062
1063 })
1064 } else {
1065 connection.query("DELETE FROM users WHERE DiscordID=" + DiscordID, function (error, results, fields) {
1066 connection.release()
1067 if (error) { UpdateLogFile(error) }
1068 console.log("Discord ID: " + DiscordID + " hat den Discord Verlassen und wurde Gelöscht")
1069 UpdateLogFile("Discord ID: " + DiscordID + " hat den Discord Verlassen und wurde Gelöscht")
1070
1071 })
1072 }
1073 })
1074 }
1075 })
1076 } else {
1077
1078 console.log("Bot deaktiviert: !rlenable nutzen um bot zu reaktivieren");
1079 UpdateLogFile("Bot deaktiviert: !rlenable nutzen um bot zu reaktivieren");
1080
1081 }
1082}