├── .gitignore ├── Lavalink.jar ├── README.md ├── api ├── app.js ├── database │ ├── database.js │ └── models │ │ ├── DiscordUser.js │ │ └── GuildMemberExperience.js ├── routes │ ├── auth.js │ └── user.js └── strategy │ └── discord.js ├── application.yml ├── database ├── db.js └── schema.sql ├── package-lock.json ├── package.json └── src ├── bot.js ├── commands ├── experience │ └── exp.js ├── miscellaneous │ └── info.js ├── moderation │ ├── ban.js │ └── changeprefix.js └── music │ ├── join.js │ ├── leave.js │ ├── play.js │ ├── search.js │ ├── shuffle.js │ ├── skip.js │ └── viewqueue.js ├── events ├── guilds │ └── guildCreate.js ├── messages │ └── message.js └── ready │ └── ready.js ├── musicevents ├── connect.js ├── end.js ├── error.js └── start.js └── utils ├── StateManager.js ├── database ├── random.js └── utils.js ├── register.js └── structures ├── BaseCommand.js └── BaseEvent.js /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | node_modules 3 | logs 4 | .jar 5 | .yml -------------------------------------------------------------------------------- /Lavalink.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stuyy/MultiGuild-Discord-Bot/657ac1177b983d476b114b0efcae8d17d9b277de/Lavalink.jar -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stuyy/MultiGuild-Discord-Bot/657ac1177b983d476b114b0efcae8d17d9b277de/README.md -------------------------------------------------------------------------------- /api/app.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const express = require('express'); 3 | const app = express(); 4 | const PORT = process.env.SERVER_PORT || 3001; 5 | const discordStrategy = require('./strategy/discord'); 6 | const passport = require('passport'); 7 | const session = require('express-session'); 8 | const SessionStore = require('express-session-sequelize')(session.Store); 9 | const cors = require('cors'); 10 | 11 | const database = require('./database/database'); 12 | 13 | const DiscordUser = require('./database/models/DiscordUser'); 14 | const GuildMember = require('./database/models/GuildMemberExperience'); 15 | 16 | const authRoute = require('./routes/auth'); 17 | const userRoute = require('./routes/user'); 18 | 19 | DiscordUser.init(database); 20 | DiscordUser.sync(); 21 | 22 | GuildMember.init(database); 23 | 24 | app.use(express.json()); 25 | app.use(express.urlencoded({ extended: false })); 26 | 27 | app.use(cors({ 28 | origin: ['http://localhost:8080'], 29 | credentials: true, 30 | })); 31 | 32 | app.use(session({ 33 | saveUninitialized: false, 34 | secret: 'some secret', 35 | resave: false, 36 | cookie: { 37 | maxAge: 60 * 10000 * 60 38 | }, 39 | store: new SessionStore({ db: database }), 40 | })); 41 | 42 | app.use(passport.initialize()); 43 | app.use(passport.session()); 44 | 45 | app.use('/auth', authRoute); 46 | app.use('/user', userRoute); 47 | 48 | app.listen(PORT, () => console.log(`Listening to Port ${PORT}`)); -------------------------------------------------------------------------------- /api/database/database.js: -------------------------------------------------------------------------------- 1 | const { Sequelize } = require('sequelize'); 2 | 3 | module.exports = new Sequelize({ 4 | username: process.env.DB_USER, 5 | password: process.env.DB_PASS, 6 | database: process.env.DB_NAME, 7 | dialect: 'mysql' 8 | }); -------------------------------------------------------------------------------- /api/database/models/DiscordUser.js: -------------------------------------------------------------------------------- 1 | const { Model, DataTypes } = require('sequelize'); 2 | 3 | module.exports = class User extends Model { 4 | static init(sequelize) { 5 | return super.init({ 6 | userId: { 7 | type: DataTypes.STRING, 8 | primaryKey: true 9 | }, 10 | username: { 11 | type: DataTypes.STRING, 12 | allowNull: false 13 | }, 14 | discriminator: { 15 | type: DataTypes.INTEGER, 16 | allowNull: false 17 | } 18 | }, { 19 | tableName: 'DiscordUsers', 20 | timestamps: true, 21 | sequelize, 22 | }); 23 | } 24 | } -------------------------------------------------------------------------------- /api/database/models/GuildMemberExperience.js: -------------------------------------------------------------------------------- 1 | const { Model, DataTypes } = require('sequelize'); 2 | 3 | module.exports = class GuildMemberExperience extends Model { 4 | static init(sequelize) { 5 | return super.init({ 6 | guildId: { 7 | type: DataTypes.STRING(100), 8 | allowNull: false, 9 | primaryKey: true 10 | }, 11 | memberId: { 12 | type: DataTypes.STRING(100), 13 | allowNull: false, 14 | primaryKey: true 15 | }, 16 | currentLevel: { 17 | type: DataTypes.SMALLINT, 18 | allowNull: false, 19 | defaultValue: 1 20 | }, 21 | experiencePoints: { 22 | type: DataTypes.INTEGER, 23 | defaultValue: 1, 24 | allowNull: false 25 | } 26 | }, { 27 | tableName: 'GuildMemberExperience', 28 | sequelize, 29 | timestamps: false, 30 | }); 31 | } 32 | } -------------------------------------------------------------------------------- /api/routes/auth.js: -------------------------------------------------------------------------------- 1 | const router = require('express').Router(); 2 | const passport = require('passport'); 3 | const GuildExperience = require('../database/models/GuildMemberExperience'); 4 | 5 | router.get('/', passport.authenticate('discord')); 6 | router.get('/redirect', passport.authenticate('discord'), async (req, res) => { 7 | try { 8 | const results = await GuildExperience.findAll({ 9 | where: { 10 | memberId: req.user.dataValues.userId 11 | } 12 | }); 13 | console.log(results); 14 | res.redirect('http://localhost:8080/'); 15 | } catch(err) { 16 | console.log(err); 17 | res.status(500).send({ msg: 'Error.' }); 18 | } 19 | }); 20 | 21 | router.get('/authorized', (req, res) => { 22 | if (req.user) res.status(200).json({ msg: 'Authorized' }); 23 | else res.status(403).json({ msg: 'Forbidden' }); 24 | }); 25 | 26 | module.exports = router; -------------------------------------------------------------------------------- /api/routes/user.js: -------------------------------------------------------------------------------- 1 | const router = require('express').Router(); 2 | const GuildExperience = require('../database/models/GuildMemberExperience'); 3 | 4 | function isAuthenticated(req, res, next) { 5 | if (req.user) next(); 6 | else { 7 | res.status(403).send({ msg: 'Not Authorized'}); 8 | } 9 | } 10 | 11 | router.get('/', isAuthenticated, async (req, res) => { 12 | const result = await GuildExperience.findAll({ 13 | where: { 14 | memberId: req.user.dataValues.userId, 15 | } 16 | }); 17 | if (result) { 18 | res.status(200).send(result); 19 | } else { 20 | res.status(500).send({ msg: 'Something went wrong' }); 21 | } 22 | }); 23 | 24 | module.exports = router; 25 | -------------------------------------------------------------------------------- /api/strategy/discord.js: -------------------------------------------------------------------------------- 1 | const DiscordStrategy = require('passport-discord'); 2 | const passport = require('passport'); 3 | const DiscordUser = require('../database/models/DiscordUser'); 4 | 5 | passport.serializeUser((user, done) => { 6 | done(null, user.dataValues.userId) 7 | }); 8 | 9 | passport.deserializeUser((id, done) => { 10 | console.log(id); 11 | console.log('Inside here.'); 12 | DiscordUser.findOne({ where: { userId: id }}) 13 | .then((user) => { 14 | done(null, user); 15 | }) 16 | .catch(err => done(err, null)); 17 | }); 18 | 19 | passport.use(new DiscordStrategy({ 20 | clientID: process.env.CLIENT_ID, 21 | clientSecret: process.env.CLIENT_SECRET, 22 | callbackURL: process.env.CLIENT_REDIRECT, 23 | scope: ['identify', 'guilds'] 24 | }, async (accessToken, refreshToken, profile, done) => { 25 | try { 26 | console.log('Hello?'); 27 | const user = await DiscordUser.findOne({ where: { userId: profile.id }}); 28 | if (user) { 29 | done(null, user); 30 | } else { 31 | const newUser = await DiscordUser.create({ 32 | userId: profile.id, 33 | username: profile.username, 34 | discriminator: profile.discriminator, 35 | }); 36 | await newUser.save(); 37 | done(null, newUser); 38 | } 39 | } catch(err) { 40 | done(null, false); 41 | } 42 | })); -------------------------------------------------------------------------------- /application.yml: -------------------------------------------------------------------------------- 1 | server: # REST and WS server 2 | port: 7000 3 | address: 0.0.0.0 4 | lavalink: 5 | server: 6 | password: "testing" 7 | sources: 8 | youtube: true 9 | bandcamp: true 10 | soundcloud: true 11 | twitch: true 12 | vimeo: true 13 | mixer: true 14 | http: true 15 | local: false 16 | bufferDurationMs: 400 17 | youtubePlaylistLoadLimit: 6 # Number of pages at 100 each 18 | youtubeSearchEnabled: true 19 | soundcloudSearchEnabled: true 20 | gc-warnings: true 21 | 22 | metrics: 23 | prometheus: 24 | enabled: false 25 | endpoint: /metrics 26 | 27 | sentry: 28 | dsn: "" 29 | logging: 30 | file: 31 | max-history: 30 32 | max-size: 1GB 33 | path: ./logs/ 34 | 35 | level: 36 | root: INFO 37 | lavalink: INFO -------------------------------------------------------------------------------- /database/db.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const mysql = require('mysql2/promise'); 3 | 4 | module.exports = mysql.createConnection({ 5 | user: process.env.DB_USER, 6 | password: process.env.DB_PASS, 7 | database: process.env.DB_NAME 8 | }); 9 | -------------------------------------------------------------------------------- /database/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE DiscordDb; 2 | 3 | CREATE TABLE Guilds ( 4 | guildId VARCHAR(100) NOT NULL PRIMARY KEY, 5 | guildOwnerId VARCHAR(100) NOT NULL 6 | ); 7 | 8 | CREATE TABLE GuildConfigurable ( 9 | guildId VARCHAR(100) NOT NULL PRIMARY KEY, 10 | cmdPrefix VARCHAR(10) DEFAULT '!', 11 | modLogId VARCHAR(100) 12 | ); 13 | 14 | CREATE TABLE GuildMemberExperience ( 15 | guildId VARCHAR(100) NOT NULL, 16 | memberId VARCHAR(100) NOT NULL, 17 | currentLevel SMALLINT NOT NULL DEFAULT 1, 18 | experiencePoints INT NOT NULL DEFAULT 1, 19 | PRIMARY KEY (guildId, memberId) 20 | ); 21 | 22 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "discordbot-mysql", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@discordjs/collection": { 8 | "version": "0.1.5", 9 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.5.tgz", 10 | "integrity": "sha512-CU1q0UXQUpFNzNB7gufgoisDHP7n+T3tkqTsp3MNUkVJ5+hS3BCvME8uCXAUFlz+6T2FbTCu75A+yQ7HMKqRKw==" 11 | }, 12 | "@types/node": { 13 | "version": "13.13.0", 14 | "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.0.tgz", 15 | "integrity": "sha512-WE4IOAC6r/yBZss1oQGM5zs2D7RuKR6Q+w+X2SouPofnWn+LbCqClRyhO3ZE7Ix8nmFgo/oVuuE01cJT2XB13A==" 16 | }, 17 | "abort-controller": { 18 | "version": "3.0.0", 19 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 20 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 21 | "requires": { 22 | "event-target-shim": "^5.0.0" 23 | } 24 | }, 25 | "accepts": { 26 | "version": "1.3.7", 27 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 28 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 29 | "requires": { 30 | "mime-types": "~2.1.24", 31 | "negotiator": "0.6.2" 32 | } 33 | }, 34 | "ansicolors": { 35 | "version": "0.3.2", 36 | "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", 37 | "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" 38 | }, 39 | "any-promise": { 40 | "version": "1.3.0", 41 | "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", 42 | "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" 43 | }, 44 | "array-flatten": { 45 | "version": "1.1.1", 46 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 47 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 48 | }, 49 | "asynckit": { 50 | "version": "0.4.0", 51 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 52 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 53 | }, 54 | "axios": { 55 | "version": "0.19.2", 56 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", 57 | "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", 58 | "requires": { 59 | "follow-redirects": "1.5.10" 60 | } 61 | }, 62 | "base64url": { 63 | "version": "3.0.1", 64 | "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", 65 | "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" 66 | }, 67 | "bluebird": { 68 | "version": "3.7.2", 69 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 70 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 71 | }, 72 | "body-parser": { 73 | "version": "1.19.0", 74 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 75 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 76 | "requires": { 77 | "bytes": "3.1.0", 78 | "content-type": "~1.0.4", 79 | "debug": "2.6.9", 80 | "depd": "~1.1.2", 81 | "http-errors": "1.7.2", 82 | "iconv-lite": "0.4.24", 83 | "on-finished": "~2.3.0", 84 | "qs": "6.7.0", 85 | "raw-body": "2.4.0", 86 | "type-is": "~1.6.17" 87 | }, 88 | "dependencies": { 89 | "debug": { 90 | "version": "2.6.9", 91 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 92 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 93 | "requires": { 94 | "ms": "2.0.0" 95 | } 96 | }, 97 | "iconv-lite": { 98 | "version": "0.4.24", 99 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 100 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 101 | "requires": { 102 | "safer-buffer": ">= 2.1.2 < 3" 103 | } 104 | } 105 | } 106 | }, 107 | "bytes": { 108 | "version": "3.1.0", 109 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 110 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 111 | }, 112 | "cardinal": { 113 | "version": "2.1.1", 114 | "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", 115 | "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", 116 | "requires": { 117 | "ansicolors": "~0.3.2", 118 | "redeyed": "~2.1.0" 119 | } 120 | }, 121 | "cls-bluebird": { 122 | "version": "2.1.0", 123 | "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", 124 | "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=", 125 | "requires": { 126 | "is-bluebird": "^1.0.2", 127 | "shimmer": "^1.1.0" 128 | } 129 | }, 130 | "combined-stream": { 131 | "version": "1.0.8", 132 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 133 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 134 | "requires": { 135 | "delayed-stream": "~1.0.0" 136 | } 137 | }, 138 | "content-disposition": { 139 | "version": "0.5.3", 140 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 141 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 142 | "requires": { 143 | "safe-buffer": "5.1.2" 144 | }, 145 | "dependencies": { 146 | "safe-buffer": { 147 | "version": "5.1.2", 148 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 149 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 150 | } 151 | } 152 | }, 153 | "content-type": { 154 | "version": "1.0.4", 155 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 156 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 157 | }, 158 | "cookie": { 159 | "version": "0.4.0", 160 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 161 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 162 | }, 163 | "cookie-signature": { 164 | "version": "1.0.6", 165 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 166 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 167 | }, 168 | "cors": { 169 | "version": "2.8.5", 170 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 171 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 172 | "requires": { 173 | "object-assign": "^4", 174 | "vary": "^1" 175 | } 176 | }, 177 | "debug": { 178 | "version": "3.1.0", 179 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 180 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 181 | "requires": { 182 | "ms": "2.0.0" 183 | } 184 | }, 185 | "delayed-stream": { 186 | "version": "1.0.0", 187 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 188 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 189 | }, 190 | "denque": { 191 | "version": "1.4.1", 192 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", 193 | "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" 194 | }, 195 | "depd": { 196 | "version": "1.1.2", 197 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 198 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 199 | }, 200 | "destroy": { 201 | "version": "1.0.4", 202 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 203 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 204 | }, 205 | "discord.js": { 206 | "version": "12.1.1", 207 | "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.1.1.tgz", 208 | "integrity": "sha512-Y6+QfAUZkb9cy27cfNqUigAgYVSKTw9jPF3mN4UDMih3Em3VQ0WjGBdX1UbE8CwFkLOu5XWQSNPdsoStTR8c2Q==", 209 | "requires": { 210 | "@discordjs/collection": "^0.1.5", 211 | "abort-controller": "^3.0.0", 212 | "form-data": "^3.0.0", 213 | "node-fetch": "^2.6.0", 214 | "prism-media": "^1.2.0", 215 | "setimmediate": "^1.0.5", 216 | "tweetnacl": "^1.0.3", 217 | "ws": "^7.2.1" 218 | } 219 | }, 220 | "dotenv": { 221 | "version": "8.2.0", 222 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", 223 | "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" 224 | }, 225 | "dottie": { 226 | "version": "2.0.2", 227 | "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", 228 | "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" 229 | }, 230 | "ee-first": { 231 | "version": "1.1.1", 232 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 233 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 234 | }, 235 | "encodeurl": { 236 | "version": "1.0.2", 237 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 238 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 239 | }, 240 | "erela.js": { 241 | "version": "1.1.7", 242 | "resolved": "https://registry.npmjs.org/erela.js/-/erela.js-1.1.7.tgz", 243 | "integrity": "sha512-SKxFaW5fH4h0Xq0jiD03AnhiyBEODsmBtPOusEjySxgDsFUiXdSFfl4FKDyjDggLG51o3lINf8hfpJvU+J7PLA==", 244 | "requires": { 245 | "axios": "^0.19.2", 246 | "events": "^3.1.0", 247 | "lodash": "^4.17.15", 248 | "util": "^0.12.1", 249 | "ws": "^7.2.1" 250 | } 251 | }, 252 | "escape-html": { 253 | "version": "1.0.3", 254 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 255 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 256 | }, 257 | "esprima": { 258 | "version": "4.0.1", 259 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 260 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 261 | }, 262 | "etag": { 263 | "version": "1.8.1", 264 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 265 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 266 | }, 267 | "event-target-shim": { 268 | "version": "5.0.1", 269 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 270 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" 271 | }, 272 | "events": { 273 | "version": "3.1.0", 274 | "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", 275 | "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==" 276 | }, 277 | "express": { 278 | "version": "4.17.1", 279 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 280 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 281 | "requires": { 282 | "accepts": "~1.3.7", 283 | "array-flatten": "1.1.1", 284 | "body-parser": "1.19.0", 285 | "content-disposition": "0.5.3", 286 | "content-type": "~1.0.4", 287 | "cookie": "0.4.0", 288 | "cookie-signature": "1.0.6", 289 | "debug": "2.6.9", 290 | "depd": "~1.1.2", 291 | "encodeurl": "~1.0.2", 292 | "escape-html": "~1.0.3", 293 | "etag": "~1.8.1", 294 | "finalhandler": "~1.1.2", 295 | "fresh": "0.5.2", 296 | "merge-descriptors": "1.0.1", 297 | "methods": "~1.1.2", 298 | "on-finished": "~2.3.0", 299 | "parseurl": "~1.3.3", 300 | "path-to-regexp": "0.1.7", 301 | "proxy-addr": "~2.0.5", 302 | "qs": "6.7.0", 303 | "range-parser": "~1.2.1", 304 | "safe-buffer": "5.1.2", 305 | "send": "0.17.1", 306 | "serve-static": "1.14.1", 307 | "setprototypeof": "1.1.1", 308 | "statuses": "~1.5.0", 309 | "type-is": "~1.6.18", 310 | "utils-merge": "1.0.1", 311 | "vary": "~1.1.2" 312 | }, 313 | "dependencies": { 314 | "debug": { 315 | "version": "2.6.9", 316 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 317 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 318 | "requires": { 319 | "ms": "2.0.0" 320 | } 321 | }, 322 | "safe-buffer": { 323 | "version": "5.1.2", 324 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 325 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 326 | } 327 | } 328 | }, 329 | "express-session": { 330 | "version": "1.17.1", 331 | "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz", 332 | "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==", 333 | "requires": { 334 | "cookie": "0.4.0", 335 | "cookie-signature": "1.0.6", 336 | "debug": "2.6.9", 337 | "depd": "~2.0.0", 338 | "on-headers": "~1.0.2", 339 | "parseurl": "~1.3.3", 340 | "safe-buffer": "5.2.0", 341 | "uid-safe": "~2.1.5" 342 | }, 343 | "dependencies": { 344 | "debug": { 345 | "version": "2.6.9", 346 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 347 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 348 | "requires": { 349 | "ms": "2.0.0" 350 | } 351 | }, 352 | "depd": { 353 | "version": "2.0.0", 354 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 355 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 356 | } 357 | } 358 | }, 359 | "express-session-sequelize": { 360 | "version": "2.2.0", 361 | "resolved": "https://registry.npmjs.org/express-session-sequelize/-/express-session-sequelize-2.2.0.tgz", 362 | "integrity": "sha512-8xpSTfLvpvLBqHxwEvYHV2gi9W+lG3+GsXSna6fZA5gCWmZTRvFbFfU4f0S1v7JHj6OXfiJVGWfe+aEDpzeAkw==" 363 | }, 364 | "finalhandler": { 365 | "version": "1.1.2", 366 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 367 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 368 | "requires": { 369 | "debug": "2.6.9", 370 | "encodeurl": "~1.0.2", 371 | "escape-html": "~1.0.3", 372 | "on-finished": "~2.3.0", 373 | "parseurl": "~1.3.3", 374 | "statuses": "~1.5.0", 375 | "unpipe": "~1.0.0" 376 | }, 377 | "dependencies": { 378 | "debug": { 379 | "version": "2.6.9", 380 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 381 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 382 | "requires": { 383 | "ms": "2.0.0" 384 | } 385 | } 386 | } 387 | }, 388 | "follow-redirects": { 389 | "version": "1.5.10", 390 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", 391 | "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", 392 | "requires": { 393 | "debug": "=3.1.0" 394 | } 395 | }, 396 | "form-data": { 397 | "version": "3.0.0", 398 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", 399 | "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", 400 | "requires": { 401 | "asynckit": "^0.4.0", 402 | "combined-stream": "^1.0.8", 403 | "mime-types": "^2.1.12" 404 | } 405 | }, 406 | "forwarded": { 407 | "version": "0.1.2", 408 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 409 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 410 | }, 411 | "fresh": { 412 | "version": "0.5.2", 413 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 414 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 415 | }, 416 | "generate-function": { 417 | "version": "2.3.1", 418 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", 419 | "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", 420 | "requires": { 421 | "is-property": "^1.0.2" 422 | } 423 | }, 424 | "http-errors": { 425 | "version": "1.7.2", 426 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 427 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 428 | "requires": { 429 | "depd": "~1.1.2", 430 | "inherits": "2.0.3", 431 | "setprototypeof": "1.1.1", 432 | "statuses": ">= 1.5.0 < 2", 433 | "toidentifier": "1.0.0" 434 | }, 435 | "dependencies": { 436 | "inherits": { 437 | "version": "2.0.3", 438 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 439 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 440 | } 441 | } 442 | }, 443 | "iconv-lite": { 444 | "version": "0.5.1", 445 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.1.tgz", 446 | "integrity": "sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q==", 447 | "requires": { 448 | "safer-buffer": ">= 2.1.2 < 3" 449 | } 450 | }, 451 | "inflection": { 452 | "version": "1.12.0", 453 | "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", 454 | "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" 455 | }, 456 | "inherits": { 457 | "version": "2.0.4", 458 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 459 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 460 | }, 461 | "ipaddr.js": { 462 | "version": "1.9.1", 463 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 464 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 465 | }, 466 | "is-arguments": { 467 | "version": "1.0.4", 468 | "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", 469 | "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" 470 | }, 471 | "is-bluebird": { 472 | "version": "1.0.2", 473 | "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", 474 | "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=" 475 | }, 476 | "is-generator-function": { 477 | "version": "1.0.7", 478 | "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", 479 | "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==" 480 | }, 481 | "is-property": { 482 | "version": "1.0.2", 483 | "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", 484 | "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" 485 | }, 486 | "lodash": { 487 | "version": "4.17.15", 488 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 489 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 490 | }, 491 | "long": { 492 | "version": "4.0.0", 493 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 494 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 495 | }, 496 | "lru-cache": { 497 | "version": "5.1.1", 498 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 499 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 500 | "requires": { 501 | "yallist": "^3.0.2" 502 | } 503 | }, 504 | "media-typer": { 505 | "version": "0.3.0", 506 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 507 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 508 | }, 509 | "merge-descriptors": { 510 | "version": "1.0.1", 511 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 512 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 513 | }, 514 | "methods": { 515 | "version": "1.1.2", 516 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 517 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 518 | }, 519 | "mime": { 520 | "version": "1.6.0", 521 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 522 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 523 | }, 524 | "mime-db": { 525 | "version": "1.43.0", 526 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 527 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 528 | }, 529 | "mime-types": { 530 | "version": "2.1.26", 531 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 532 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 533 | "requires": { 534 | "mime-db": "1.43.0" 535 | } 536 | }, 537 | "moment": { 538 | "version": "2.24.0", 539 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", 540 | "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" 541 | }, 542 | "moment-timezone": { 543 | "version": "0.5.28", 544 | "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.28.tgz", 545 | "integrity": "sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw==", 546 | "requires": { 547 | "moment": ">= 2.9.0" 548 | } 549 | }, 550 | "ms": { 551 | "version": "2.0.0", 552 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 553 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 554 | }, 555 | "mysql2": { 556 | "version": "2.1.0", 557 | "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.1.0.tgz", 558 | "integrity": "sha512-9kGVyi930rG2KaHrz3sHwtc6K+GY9d8wWk1XRSYxQiunvGcn4DwuZxOwmK11ftuhhwrYDwGx9Ta4VBwznJn36A==", 559 | "requires": { 560 | "cardinal": "^2.1.1", 561 | "denque": "^1.4.1", 562 | "generate-function": "^2.3.1", 563 | "iconv-lite": "^0.5.0", 564 | "long": "^4.0.0", 565 | "lru-cache": "^5.1.1", 566 | "named-placeholders": "^1.1.2", 567 | "seq-queue": "^0.0.5", 568 | "sqlstring": "^2.3.1" 569 | } 570 | }, 571 | "named-placeholders": { 572 | "version": "1.1.2", 573 | "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", 574 | "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", 575 | "requires": { 576 | "lru-cache": "^4.1.3" 577 | }, 578 | "dependencies": { 579 | "lru-cache": { 580 | "version": "4.1.5", 581 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 582 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 583 | "requires": { 584 | "pseudomap": "^1.0.2", 585 | "yallist": "^2.1.2" 586 | } 587 | }, 588 | "yallist": { 589 | "version": "2.1.2", 590 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 591 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" 592 | } 593 | } 594 | }, 595 | "negotiator": { 596 | "version": "0.6.2", 597 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 598 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 599 | }, 600 | "node-fetch": { 601 | "version": "2.6.0", 602 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", 603 | "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" 604 | }, 605 | "oauth": { 606 | "version": "0.9.15", 607 | "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", 608 | "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" 609 | }, 610 | "object-assign": { 611 | "version": "4.1.1", 612 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 613 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 614 | }, 615 | "on-finished": { 616 | "version": "2.3.0", 617 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 618 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 619 | "requires": { 620 | "ee-first": "1.1.1" 621 | } 622 | }, 623 | "on-headers": { 624 | "version": "1.0.2", 625 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 626 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" 627 | }, 628 | "parseurl": { 629 | "version": "1.3.3", 630 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 631 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 632 | }, 633 | "passport": { 634 | "version": "0.4.1", 635 | "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", 636 | "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", 637 | "requires": { 638 | "passport-strategy": "1.x.x", 639 | "pause": "0.0.1" 640 | } 641 | }, 642 | "passport-discord": { 643 | "version": "0.1.3", 644 | "resolved": "https://registry.npmjs.org/passport-discord/-/passport-discord-0.1.3.tgz", 645 | "integrity": "sha512-o8+KiQrV63DCJvYVceyVJgyFhHxqOPlcxaiB8Hlrrm0uq83KfQOMPUcXal0pao5Qx8ZeOH/RBJEbJV9aB0F/hw==", 646 | "requires": { 647 | "passport-oauth2": "^1.2.0" 648 | } 649 | }, 650 | "passport-oauth2": { 651 | "version": "1.5.0", 652 | "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.5.0.tgz", 653 | "integrity": "sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==", 654 | "requires": { 655 | "base64url": "3.x.x", 656 | "oauth": "0.9.x", 657 | "passport-strategy": "1.x.x", 658 | "uid2": "0.0.x", 659 | "utils-merge": "1.x.x" 660 | } 661 | }, 662 | "passport-strategy": { 663 | "version": "1.0.0", 664 | "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", 665 | "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" 666 | }, 667 | "path-to-regexp": { 668 | "version": "0.1.7", 669 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 670 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 671 | }, 672 | "pause": { 673 | "version": "0.0.1", 674 | "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", 675 | "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" 676 | }, 677 | "prism-media": { 678 | "version": "1.2.1", 679 | "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.1.tgz", 680 | "integrity": "sha512-R3EbKwJiYlTvGwcG1DpUt+06DsxOGS5W4AMEHT7oVOjG93MjpdhGX1whHyjnqknylLMupKAsKMEXcTNRbPe6Vw==" 681 | }, 682 | "proxy-addr": { 683 | "version": "2.0.6", 684 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 685 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 686 | "requires": { 687 | "forwarded": "~0.1.2", 688 | "ipaddr.js": "1.9.1" 689 | } 690 | }, 691 | "pseudomap": { 692 | "version": "1.0.2", 693 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 694 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" 695 | }, 696 | "qs": { 697 | "version": "6.7.0", 698 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 699 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 700 | }, 701 | "random-bytes": { 702 | "version": "1.0.0", 703 | "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 704 | "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" 705 | }, 706 | "range-parser": { 707 | "version": "1.2.1", 708 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 709 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 710 | }, 711 | "raw-body": { 712 | "version": "2.4.0", 713 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 714 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 715 | "requires": { 716 | "bytes": "3.1.0", 717 | "http-errors": "1.7.2", 718 | "iconv-lite": "0.4.24", 719 | "unpipe": "1.0.0" 720 | }, 721 | "dependencies": { 722 | "iconv-lite": { 723 | "version": "0.4.24", 724 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 725 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 726 | "requires": { 727 | "safer-buffer": ">= 2.1.2 < 3" 728 | } 729 | } 730 | } 731 | }, 732 | "redeyed": { 733 | "version": "2.1.1", 734 | "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", 735 | "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", 736 | "requires": { 737 | "esprima": "~4.0.0" 738 | } 739 | }, 740 | "retry-as-promised": { 741 | "version": "3.2.0", 742 | "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", 743 | "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", 744 | "requires": { 745 | "any-promise": "^1.3.0" 746 | } 747 | }, 748 | "safe-buffer": { 749 | "version": "5.2.0", 750 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 751 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" 752 | }, 753 | "safer-buffer": { 754 | "version": "2.1.2", 755 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 756 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 757 | }, 758 | "semver": { 759 | "version": "6.3.0", 760 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 761 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" 762 | }, 763 | "send": { 764 | "version": "0.17.1", 765 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 766 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 767 | "requires": { 768 | "debug": "2.6.9", 769 | "depd": "~1.1.2", 770 | "destroy": "~1.0.4", 771 | "encodeurl": "~1.0.2", 772 | "escape-html": "~1.0.3", 773 | "etag": "~1.8.1", 774 | "fresh": "0.5.2", 775 | "http-errors": "~1.7.2", 776 | "mime": "1.6.0", 777 | "ms": "2.1.1", 778 | "on-finished": "~2.3.0", 779 | "range-parser": "~1.2.1", 780 | "statuses": "~1.5.0" 781 | }, 782 | "dependencies": { 783 | "debug": { 784 | "version": "2.6.9", 785 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 786 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 787 | "requires": { 788 | "ms": "2.0.0" 789 | }, 790 | "dependencies": { 791 | "ms": { 792 | "version": "2.0.0", 793 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 794 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 795 | } 796 | } 797 | }, 798 | "ms": { 799 | "version": "2.1.1", 800 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 801 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 802 | } 803 | } 804 | }, 805 | "seq-queue": { 806 | "version": "0.0.5", 807 | "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", 808 | "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" 809 | }, 810 | "sequelize": { 811 | "version": "5.21.6", 812 | "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.21.6.tgz", 813 | "integrity": "sha512-RsgEpP2PP7txeoTWxoLLoe3xX8R2WYQAO7LNba2Ok3/pV5EFfKZry4fJXH56DUHJB909msMCHg0CJKDsQVbjcQ==", 814 | "requires": { 815 | "bluebird": "^3.5.0", 816 | "cls-bluebird": "^2.1.0", 817 | "debug": "^4.1.1", 818 | "dottie": "^2.0.0", 819 | "inflection": "1.12.0", 820 | "lodash": "^4.17.15", 821 | "moment": "^2.24.0", 822 | "moment-timezone": "^0.5.21", 823 | "retry-as-promised": "^3.2.0", 824 | "semver": "^6.3.0", 825 | "sequelize-pool": "^2.3.0", 826 | "toposort-class": "^1.0.1", 827 | "uuid": "^3.3.3", 828 | "validator": "^10.11.0", 829 | "wkx": "^0.4.8" 830 | }, 831 | "dependencies": { 832 | "debug": { 833 | "version": "4.1.1", 834 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 835 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 836 | "requires": { 837 | "ms": "^2.1.1" 838 | } 839 | }, 840 | "ms": { 841 | "version": "2.1.2", 842 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 843 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 844 | } 845 | } 846 | }, 847 | "sequelize-pool": { 848 | "version": "2.3.0", 849 | "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz", 850 | "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA==" 851 | }, 852 | "serve-static": { 853 | "version": "1.14.1", 854 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 855 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 856 | "requires": { 857 | "encodeurl": "~1.0.2", 858 | "escape-html": "~1.0.3", 859 | "parseurl": "~1.3.3", 860 | "send": "0.17.1" 861 | } 862 | }, 863 | "setimmediate": { 864 | "version": "1.0.5", 865 | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", 866 | "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" 867 | }, 868 | "setprototypeof": { 869 | "version": "1.1.1", 870 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 871 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 872 | }, 873 | "shimmer": { 874 | "version": "1.2.1", 875 | "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", 876 | "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" 877 | }, 878 | "sqlstring": { 879 | "version": "2.3.2", 880 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz", 881 | "integrity": "sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg==" 882 | }, 883 | "statuses": { 884 | "version": "1.5.0", 885 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 886 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 887 | }, 888 | "toidentifier": { 889 | "version": "1.0.0", 890 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 891 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 892 | }, 893 | "toposort-class": { 894 | "version": "1.0.1", 895 | "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", 896 | "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" 897 | }, 898 | "tweetnacl": { 899 | "version": "1.0.3", 900 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", 901 | "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" 902 | }, 903 | "type-is": { 904 | "version": "1.6.18", 905 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 906 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 907 | "requires": { 908 | "media-typer": "0.3.0", 909 | "mime-types": "~2.1.24" 910 | } 911 | }, 912 | "uid-safe": { 913 | "version": "2.1.5", 914 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 915 | "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 916 | "requires": { 917 | "random-bytes": "~1.0.0" 918 | } 919 | }, 920 | "uid2": { 921 | "version": "0.0.3", 922 | "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", 923 | "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" 924 | }, 925 | "unpipe": { 926 | "version": "1.0.0", 927 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 928 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 929 | }, 930 | "util": { 931 | "version": "0.12.2", 932 | "resolved": "https://registry.npmjs.org/util/-/util-0.12.2.tgz", 933 | "integrity": "sha512-XE+MkWQvglYa+IOfBt5UFG93EmncEMP23UqpgDvVZVFBPxwmkK10QRp6pgU4xICPnWRf/t0zPv4noYSUq9gqUQ==", 934 | "requires": { 935 | "inherits": "^2.0.3", 936 | "is-arguments": "^1.0.4", 937 | "is-generator-function": "^1.0.7", 938 | "safe-buffer": "^5.1.2" 939 | } 940 | }, 941 | "utils-merge": { 942 | "version": "1.0.1", 943 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 944 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 945 | }, 946 | "uuid": { 947 | "version": "3.4.0", 948 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 949 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" 950 | }, 951 | "validator": { 952 | "version": "10.11.0", 953 | "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", 954 | "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" 955 | }, 956 | "vary": { 957 | "version": "1.1.2", 958 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 959 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 960 | }, 961 | "wkx": { 962 | "version": "0.4.8", 963 | "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz", 964 | "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==", 965 | "requires": { 966 | "@types/node": "*" 967 | } 968 | }, 969 | "ws": { 970 | "version": "7.2.3", 971 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", 972 | "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==" 973 | }, 974 | "yallist": { 975 | "version": "3.1.1", 976 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 977 | "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" 978 | } 979 | } 980 | } 981 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "discordbot-mysql", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "nodemon ./src/bot.js", 9 | "lavalink": "java -jar Lavalink.jar", 10 | "start": "node ./src/bot.js", 11 | "dev:server": "nodemon ./api/app.js" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "dependencies": { 17 | "cors": "^2.8.5", 18 | "discord.js": "^12.1.1", 19 | "dotenv": "^8.2.0", 20 | "erela.js": "^1.1.7", 21 | "express": "^4.17.1", 22 | "express-session": "^1.17.1", 23 | "express-session-sequelize": "^2.2.0", 24 | "mysql2": "^2.1.0", 25 | "passport": "^0.4.1", 26 | "passport-discord": "^0.1.3", 27 | "sequelize": "^5.21.6" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/bot.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const { Client } = require('discord.js'); 3 | const { ErelaClient } = require('erela.js'); 4 | const client = new Client(); 5 | const StateManager = require('./utils/StateManager'); 6 | 7 | const { 8 | registerCommands, 9 | registerEvents, 10 | registerMusicEvents, 11 | } = require('./utils/register'); 12 | 13 | (async () => { 14 | await client.login(process.env.BOT_TOKEN); 15 | client.music = new ErelaClient(client, [ 16 | { 17 | host: process.env.HOST, 18 | port: process.env.PORT, 19 | password: process.env.PASSWORD 20 | } 21 | ]); 22 | client.commands = new Map(); 23 | await registerMusicEvents(client.music, '../musicevents'); 24 | await registerCommands(client, '../commands'); 25 | await registerEvents(client, '../events'); 26 | })(); -------------------------------------------------------------------------------- /src/commands/experience/exp.js: -------------------------------------------------------------------------------- 1 | const BaseCommand = require('../../utils/structures/BaseCommand'); 2 | 3 | module.exports = class ExperienceCommand extends BaseCommand { 4 | constructor () { 5 | super('info', 'moderation', []); 6 | } 7 | 8 | run (client, message, args) { 9 | console.log(this.name + ' was invoked'); 10 | } 11 | } -------------------------------------------------------------------------------- /src/commands/miscellaneous/info.js: -------------------------------------------------------------------------------- 1 | const BaseCommand = require('../../utils/structures/BaseCommand'); 2 | 3 | module.exports = class InfoCommand extends BaseCommand { 4 | constructor () { 5 | super('info', 'moderation', []); 6 | } 7 | 8 | run (client, message, args) { 9 | console.log(this.name + ' was invoked'); 10 | 11 | } 12 | } -------------------------------------------------------------------------------- /src/commands/moderation/ban.js: -------------------------------------------------------------------------------- 1 | const BaseCommand = require('../../utils/structures/BaseCommand'); 2 | 3 | module.exports = class BanCommand extends BaseCommand { 4 | constructor () { 5 | super('ban', 'moderation', []); 6 | } 7 | 8 | run (client, message, args) { 9 | console.log(this.name + ' was invoked'); 10 | } 11 | } -------------------------------------------------------------------------------- /src/commands/moderation/changeprefix.js: -------------------------------------------------------------------------------- 1 | const BaseCommand = require('../../utils/structures/BaseCommand'); 2 | const StateManager = require('../../utils/StateManager'); 3 | 4 | module.exports = class ChangePrefixCommand extends BaseCommand { 5 | constructor () { 6 | super('chprefix', 'owner', []); 7 | this.connection = StateManager.connection; 8 | } 9 | 10 | async run (client, message, args) { 11 | if (message.member.id === message.guild.ownerID) { 12 | const [ cmdName, newPrefix ] = message.content.split(" "); 13 | if (newPrefix) { 14 | try { 15 | await this.connection.query( 16 | `UPDATE GuildConfigurable SET cmdPrefix = '${newPrefix}' WHERE guildId = '${message.guild.id}'` 17 | ); 18 | message.channel.send(`Updated guild prefix to ${newPrefix}`); 19 | StateManager.emit('prefixUpdate', message.guild.id, newPrefix); 20 | } catch(err) { 21 | console.log(err); 22 | message.channel.send(`Failed to update guild prefix to ${newPrefix}`); 23 | } 24 | } else { 25 | message.channel.send('Incorrect amount of arguments'); 26 | } 27 | } else { 28 | message.channel.send('You do not have permission to use that command'); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/commands/music/join.js: -------------------------------------------------------------------------------- 1 | const BaseCommand = require('../../utils/structures/BaseCommand'); 2 | 3 | module.exports = class JoinCommand extends BaseCommand { 4 | constructor () { 5 | super('join', 'music', []); 6 | } 7 | 8 | async run (client, message, args) { 9 | const { channel } = message.member.voice; 10 | if (channel) { 11 | const player = client.music.players.spawn({ 12 | guild: message.guild, 13 | voiceChannel: channel, 14 | textChannel: message.channel, 15 | }); 16 | } else { 17 | message.channel.send('Please join a voice channel.'); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/commands/music/leave.js: -------------------------------------------------------------------------------- 1 | const BaseCommand = require('../../utils/structures/BaseCommand'); 2 | 3 | module.exports = class LeaveChannelCommand extends BaseCommand { 4 | constructor () { 5 | super('leave', 'music', []); 6 | } 7 | 8 | async run (client, message, args) { 9 | const { id } = message.guild; 10 | const player = client.music.players.get(id); 11 | const { channel } = message.member.voice; 12 | if (player && channel) { 13 | if (player.voiceChannel.id === channel.id) { 14 | client.music.players.destroy(id); 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/commands/music/play.js: -------------------------------------------------------------------------------- 1 | const BaseCommand = require('../../utils/structures/BaseCommand'); 2 | const { MessageEmbed } = require('discord.js'); 3 | 4 | module.exports = class PlayCommand extends BaseCommand { 5 | constructor () { 6 | super('play', 'music', []); 7 | } 8 | 9 | async run (client, message, args) { 10 | const query = args.join(' '); 11 | console.log(query); 12 | const { channel } = message.member.voice; 13 | if (channel) { 14 | let i = 0; 15 | const searchResults = await client.music.search(query, message.author); 16 | const tracks = searchResults.tracks.slice(0, 10); 17 | const tracksInfo = tracks.map(r => `${++i}) ${r.title} - ${r.uri}`).join('\n'); 18 | 19 | const embed = new MessageEmbed() 20 | .setAuthor(client.user.tag, client.user.displayAvatarURL()) 21 | .setDescription(tracksInfo) 22 | .setFooter('Music Results'); 23 | 24 | message.channel.send(embed); 25 | 26 | const filter = m => (message.author.id === m.author.id) && (m.content >= 1 && m.content <= tracks.length); 27 | 28 | try { 29 | const response = await message.channel 30 | .awaitMessages(filter, { max: 1, time: 10000, errors: ['time']}); 31 | 32 | if (response) { 33 | const entry = response.first().content; 34 | const player = client.music.players.get(message.guild.id); 35 | const track = tracks[entry-1]; 36 | player.queue.add(track); 37 | message.channel.send(`Enqueueing track ${track.title}`); 38 | if (!player.playing) player.play(); 39 | } 40 | } catch (err) { 41 | console.log(err); 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/commands/music/search.js: -------------------------------------------------------------------------------- 1 | const BaseCommand = require('../../utils/structures/BaseCommand'); 2 | const { MessageEmbed } = require('discord.js'); 3 | 4 | const selections = new Set(); 5 | const constants = ['queueall', 'stopselect']; 6 | 7 | module.exports = class SearchCommand extends BaseCommand { 8 | constructor () { 9 | super('search', 'music', []); 10 | } 11 | 12 | async run (client, message, args) { 13 | const query = args.join(' '); 14 | const { channel } = message.member.voice; 15 | const player = client.music.players.get(message.guild.id); 16 | if (channel && player) { 17 | if (channel.id === player.voiceChannel.id) { 18 | const searchResults = await client.music.search(query, message.author); 19 | const tracks = searchResults.tracks.slice(0, 10); 20 | let i = 0; 21 | const tracksInfo = tracks.map(track => `${++i}) [${track.title}](${track.uri})`); 22 | const embed = new MessageEmbed() 23 | .setAuthor(client.user.tag, client.user.displayAvatarURL()) 24 | .setDescription(tracksInfo) 25 | .setFooter('Music Results'); 26 | 27 | message.channel.send(embed); 28 | const filter = m => (m.author.id === message.author.id) 29 | && (channel.id === player.voiceChannel.id) 30 | && ((m.content >= 1 && m.content <= tracks.length) || constants.includes(m.content.toLowerCase())); 31 | 32 | const collector = message.channel.createMessageCollector(filter); 33 | const tracksToQueue = await handleCollector(collector, tracks); 34 | 35 | i = 0; 36 | const selectedTracksInfo = tracksToQueue.map(track => `${++i}) [${track.title}](${track.uri})`); 37 | const selectedTracksEmbed = new MessageEmbed() 38 | .setAuthor(client.user.tag, client.user.displayAvatarURL()) 39 | .setDescription(selectedTracksInfo); 40 | 41 | const msg = await message.channel.send('Confirm 👍 or Deny 👎', selectedTracksEmbed); 42 | await msg.react('👍'); 43 | await msg.react('👎'); 44 | 45 | try { 46 | const reactionFilter = (reaction, user) => ['👍', '👎'].includes(reaction.emoji.name) && (user.id === message.author.id); 47 | const reactions = await msg.awaitReactions(reactionFilter, { max: 1, time: 15000, errors: ['time'] }); 48 | const selectedReaction = reactions.get('👍') || reactions.get('👎'); 49 | if (selectedReaction.emoji.name === '👍') { 50 | for (const track of tracksToQueue) { 51 | player.queue.add(track); 52 | console.log(`${track.title} was queued.`) 53 | } 54 | if (!player.playing) player.play(); 55 | } else { 56 | message.channel.send('Cancelled. Did not queue any tracks.'); 57 | } 58 | } catch (err) { 59 | console.log(err); 60 | } 61 | } 62 | } else { 63 | message.channel.send('Not in voice channel or player does not exist.'); 64 | } 65 | } 66 | } 67 | 68 | function handleCollector(collector, tracks) { 69 | const tracksToQueue = []; 70 | return new Promise((resolve, reject) => { 71 | try { 72 | collector.on('collect', message => { 73 | if (message.content.toLowerCase() === 'queueall') { 74 | collector.stop(); 75 | selections.clear(); 76 | resolve(tracks); 77 | } else if (message.content.toLowerCase() === 'stopselect') { 78 | collector.stop(); 79 | selections.clear(); 80 | resolve(tracksToQueue); 81 | } else { 82 | const entry = message.content; 83 | console.log(selections); 84 | if (selections.has(entry)) { 85 | message.channel.send('You already selected that song!'); 86 | } else { 87 | message.channel.send(`You selected: ${tracks[entry-1].title}`); 88 | tracksToQueue.push(tracks[entry-1]); 89 | selections.add(entry); 90 | } 91 | } 92 | }); 93 | } catch (err) { 94 | reject(err); 95 | } 96 | }) 97 | } -------------------------------------------------------------------------------- /src/commands/music/shuffle.js: -------------------------------------------------------------------------------- 1 | const BaseCommand = require('../../utils/structures/BaseCommand'); 2 | 3 | module.exports = class ShuffleQueueCommand extends BaseCommand { 4 | constructor () { 5 | super('shuffle', 'music', []); 6 | } 7 | 8 | async run (client, message, args) { 9 | const { channel } = message.member.voice; 10 | const player = client.music.players.get(message.guild.id); 11 | 12 | if (channel && player) { 13 | if (channel.id === player.voiceChannel.id) { 14 | player.queue.shuffle(); 15 | message.channel.send('Shuffled the queue'); 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/commands/music/skip.js: -------------------------------------------------------------------------------- 1 | const BaseCommand = require('../../utils/structures/BaseCommand'); 2 | const { MessageEmbed } = require('discord.js'); 3 | 4 | let USED = false; 5 | 6 | module.exports = class SkipCommand extends BaseCommand { 7 | constructor () { 8 | super('skip', 'music', []); 9 | } 10 | 11 | async run (client, message, args) { 12 | 13 | const guildId = message.guild.id; 14 | const player = client.music.players.get(guildId); 15 | const { channel } = message.member.voice; 16 | if (player && channel) { 17 | if (player.voiceChannel.id === channel.id) { 18 | const members = channel.members.filter(m => !m.user.bot); 19 | if (members.size === 1) { 20 | player.stop(); 21 | message.channel.send(`Skipping... ${player.queue[0].title}`); 22 | } else { 23 | if (!USED) { 24 | USED = true; 25 | const votesRequired = Math.ceil(members.size * .6); 26 | const embed = new MessageEmbed() 27 | .setDescription(`Total votes required to skip: ${votesRequired}`); 28 | const msg = await message.channel.send(embed); 29 | await msg.react('👍'); 30 | await msg.react('👎'); 31 | 32 | const filter = (reaction, user) => { 33 | if (user.bot) return false; 34 | const { channel } = message.guild.members.cache.get(user.id).voice; 35 | if (channel) { 36 | if (channel.id === player.voiceChannel.id) { 37 | return ['👍'].includes(reaction.emoji.name); 38 | } 39 | return false; 40 | } else { 41 | return false; 42 | } 43 | } 44 | 45 | try { 46 | const reactions = await msg.awaitReactions(filter, { max: votesRequired, time: 10000, errors: ['time'] }); 47 | const totalVotes = reactions.get('👍').users.cache.filter(u => !u.bot); 48 | if (totalVotes.size >= votesRequired) { 49 | player.stop(); 50 | USED = false; 51 | } 52 | } catch (err) { 53 | console.log(err); 54 | USED = false; 55 | } 56 | } else { 57 | message.channel.send('Command cannot be used atm'); 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/commands/music/viewqueue.js: -------------------------------------------------------------------------------- 1 | const BaseCommand = require('../../utils/structures/BaseCommand'); 2 | const { MessageEmbed } = require('discord.js'); 3 | 4 | module.exports = class ViewQueueCommand extends BaseCommand { 5 | constructor () { 6 | super('viewqueue', 'music', []); 7 | } 8 | 9 | async run (client, message, args) { 10 | const player = client.music.players.get(message.guild.id); 11 | if (player) { 12 | 13 | let currentPage = 0; 14 | const embeds = generateQueueEmbed(player.queue); 15 | const queueEmbed = await message.channel.send(`Current Page: ${currentPage+1}/${embeds.length}`, embeds[currentPage]); 16 | await queueEmbed.react('⬅️'); 17 | await queueEmbed.react('➡️'); 18 | await queueEmbed.react('❌'); 19 | 20 | const filter = (reaction, user) => ['⬅️', '➡️', '❌'].includes(reaction.emoji.name) && (message.author.id === user.id); 21 | const collector = queueEmbed.createReactionCollector(filter); 22 | 23 | collector.on('collect', async (reaction, user) => { 24 | // If there are 2 embeds. 25 | if (reaction.emoji.name === '➡️') { 26 | if (currentPage < embeds.length-1) { 27 | currentPage++; 28 | queueEmbed.edit(`Current Page: ${currentPage+1}/${embeds.length}`, embeds[currentPage]); 29 | } 30 | } else if (reaction.emoji.name === '⬅️') { 31 | if (currentPage !== 0) { 32 | --currentPage; 33 | queueEmbed.edit(`Current Page ${currentPage+1}/${embeds.length}`, embeds[currentPage]); 34 | } 35 | } else { 36 | collector.stop(); 37 | console.log('Stopped collector..'); 38 | await queueEmbed.delete(); 39 | } 40 | }); 41 | } 42 | } 43 | } 44 | 45 | function generateQueueEmbed(queue) { 46 | const embeds = []; 47 | let k = 10; 48 | for(let i = 0; i < queue.length; i += 10) { 49 | const current = queue.slice(i, k); 50 | let j = i; 51 | k += 10; 52 | const info = current.map(track => `${++j}) [${track.title}](${track.uri})`).join('\n'); 53 | const embed = new MessageEmbed() 54 | .setDescription(`**[Current Song: ${queue[0].title}](${queue[0].uri})**\n${info}`); 55 | embeds.push(embed); 56 | } 57 | return embeds; 58 | } -------------------------------------------------------------------------------- /src/events/guilds/guildCreate.js: -------------------------------------------------------------------------------- 1 | const BaseEvent = require('../../utils/structures/BaseEvent'); 2 | const StateManager = require('../../utils/StateManager'); 3 | 4 | module.exports = class GuildCreateEvent extends BaseEvent { 5 | constructor () { 6 | super('guildCreate'); 7 | this.connection = StateManager.connection; 8 | } 9 | 10 | async run (client, guild) { 11 | try { 12 | await this.connection.query( 13 | `INSERT INTO Guilds VALUES('${guild.id}', '${guild.ownerID}')` 14 | ); 15 | await this.connection.query( 16 | `INSERT INTO GuildConfigurable (guildId) VALUES ('${guild.id}')` 17 | ); 18 | console.log(`Added to db.`) 19 | StateManager.emit('guildAdded', guild.id, '!'); 20 | } catch(err) { 21 | console.log(err); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/events/messages/message.js: -------------------------------------------------------------------------------- 1 | const BaseEvent = require('../../utils/structures/BaseEvent'); 2 | const StateManager = require('../../utils/StateManager'); 3 | const { MessageEmbed } = require('discord.js'); 4 | const { 5 | exists, 6 | insertGuildMember, 7 | updateGuildMemberExperience, 8 | } = require('../../utils/database/utils'); 9 | const { 10 | randomExperience, 11 | checkExperience, 12 | } = require('../../utils/database/random'); 13 | 14 | const guildCommandPrefixes = new Map(); 15 | 16 | module.exports = class MessageEvent extends BaseEvent { 17 | constructor () { 18 | super('message'); 19 | this.connection = StateManager.connection; 20 | } 21 | 22 | async run (client, message) { 23 | if (message.author.bot) return; 24 | const prefix = guildCommandPrefixes.get(message.guild.id); 25 | const usedPrefix = message.content.slice(0, prefix.length); 26 | 27 | if (prefix === usedPrefix) { 28 | const [cmdName, ...cmdArgs] = message.content.slice(prefix.length).split(/\s+/); 29 | const command = client.commands.get(cmdName); 30 | if (command) { 31 | command.run(client, message, cmdArgs); 32 | } 33 | } 34 | else { 35 | const guildId = message.guild.id; 36 | const memberId = message.member.id; 37 | const result = (await exists(guildId, memberId))[0]; 38 | if (result.length > 0) { 39 | const { experiencePoints, currentLevel } = result[0]; 40 | const xp = randomExperience(); 41 | const updatedXP = xp + experiencePoints; 42 | const newLevel = checkExperience(updatedXP, currentLevel); 43 | const update = await updateGuildMemberExperience(guildId, memberId, updatedXP, newLevel); 44 | } else { 45 | await insertGuildMember(guildId, memberId); 46 | console.log(`Updated XP for ${message.author.tag} in Guild (${guildId})`); 47 | } 48 | } 49 | } 50 | } 51 | 52 | StateManager.on('prefixFetched', (guildId, prefix) => { 53 | guildCommandPrefixes.set(guildId, prefix); 54 | }); 55 | 56 | StateManager.on('prefixUpdate', (guildId, prefix) => { 57 | guildCommandPrefixes.set(guildId, prefix); 58 | console.log('Guild prefix updated'); 59 | }); 60 | 61 | StateManager.on('guildAdded', (guildId, prefix) => { 62 | guildCommandPrefixes.set(guildId, prefix); 63 | console.log('Guild prefix Added'); 64 | }); -------------------------------------------------------------------------------- /src/events/ready/ready.js: -------------------------------------------------------------------------------- 1 | const BaseEvent = require('../../utils/structures/BaseEvent'); 2 | const StateManager = require('../../utils/StateManager'); 3 | 4 | const guildCommandPrefixes = new Map(); 5 | 6 | module.exports = class ReadyEvent extends BaseEvent { 7 | constructor () { 8 | super('ready'); 9 | this.connection = StateManager.connection; 10 | } 11 | async run (client) { 12 | console.log(client.user.tag + ' has logged in.'); 13 | client.guilds.cache.forEach(guild => { 14 | this.connection.query( 15 | `SELECT cmdPrefix FROM GuildConfigurable WHERE guildId = '${guild.id}'` 16 | ).then(result => { 17 | const guildId = guild.id; 18 | const prefix = result[0][0].cmdPrefix; 19 | guildCommandPrefixes.set(guildId, prefix); 20 | StateManager.emit('prefixFetched', guildId, prefix); 21 | }).catch(err => console.log(err)); 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/musicevents/connect.js: -------------------------------------------------------------------------------- 1 | const BaseEvent = require('../utils/structures/BaseEvent'); 2 | 3 | module.exports = class NodeConnectEvent extends BaseEvent { 4 | constructor () { 5 | super('nodeConnect'); 6 | } 7 | 8 | async run (client, node) { 9 | console.log('New Node Connected'); 10 | } 11 | } -------------------------------------------------------------------------------- /src/musicevents/end.js: -------------------------------------------------------------------------------- 1 | const BaseEvent = require('../utils/structures/BaseEvent'); 2 | 3 | module.exports = class TrackStartEvent extends BaseEvent { 4 | constructor () { 5 | super('queueEnd'); 6 | } 7 | 8 | async run (client, player) { 9 | player.textChannel.send("Queue has ended.") 10 | client.music.players.destroy(player.guild.id); 11 | } 12 | } -------------------------------------------------------------------------------- /src/musicevents/error.js: -------------------------------------------------------------------------------- 1 | const BaseEvent = require('../utils/structures/BaseEvent'); 2 | 3 | module.exports = class NodeErrorEvent extends BaseEvent { 4 | constructor () { 5 | super('nodeError'); 6 | } 7 | 8 | async run (client, node, error) { 9 | console.log('An error has occured'); 10 | console.log(error.message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/musicevents/start.js: -------------------------------------------------------------------------------- 1 | const BaseEvent = require('../utils/structures/BaseEvent'); 2 | 3 | module.exports = class TrackStartEvent extends BaseEvent { 4 | constructor () { 5 | super('trackStart'); 6 | } 7 | 8 | async run (client, player, track) { 9 | player.textChannel.send(`Now playing: ${track.title}`); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/utils/StateManager.js: -------------------------------------------------------------------------------- 1 | const { EventEmitter } = require('events'); 2 | const connection = require('../../database/db'); 3 | 4 | class StateManager extends EventEmitter { 5 | constructor (opts) { 6 | super(opts); 7 | connection 8 | .then((connection) => { 9 | this.connection = connection; 10 | }).catch(err => console.log(err)); 11 | } 12 | } 13 | 14 | module.exports = new StateManager(); -------------------------------------------------------------------------------- /src/utils/database/random.js: -------------------------------------------------------------------------------- 1 | const BASE = 10; 2 | 3 | function randomExperience() { 4 | return Math.ceil(Math.random() * 200); 5 | } 6 | 7 | /** 8 | * BASE = 10 9 | * LEVEL = 1 10 | * e^LEVEL 11 | */ 12 | function checkExperience(experience, level) { 13 | const y = (BASE*level) * (Math.pow(Math.E, level)); 14 | return experience >= y ? ++level : level; 15 | } 16 | module.exports = { 17 | randomExperience, 18 | checkExperience, 19 | } -------------------------------------------------------------------------------- /src/utils/database/utils.js: -------------------------------------------------------------------------------- 1 | const StateManager = require('../StateManager'); 2 | 3 | async function exists(guildId, memberId) { 4 | return await StateManager.connection.query( 5 | `SELECT * FROM GuildMemberExperience WHERE guildId = ${guildId} AND memberId = ${memberId}` 6 | ); 7 | } 8 | 9 | async function insertGuildMember(guildId, memberId) { 10 | return await StateManager.connection.query( 11 | `INSERT INTO GuildMemberExperience VALUES ( 12 | '${guildId}', '${memberId}', DEFAULT, DEFAULT 13 | )` 14 | ); 15 | } 16 | 17 | async function updateGuildMemberExperience(guildId, memberId, updatedXP, updatedLevel) { 18 | return await StateManager.connection.query( 19 | `UPDATE GuildMemberExperience SET experiencePoints = ${updatedXP}, currentLevel = ${updatedLevel} WHERE guildId = ${guildId} AND memberId = ${memberId}` 20 | ); 21 | } 22 | module.exports = { 23 | exists, 24 | insertGuildMember, 25 | updateGuildMemberExperience, 26 | }; -------------------------------------------------------------------------------- /src/utils/register.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs').promises; 3 | const BaseCommand = require('./structures/BaseCommand'); 4 | const BaseEvent = require('./structures/BaseEvent'); 5 | 6 | async function registerCommands(client, dir = '') { 7 | const filePath = path.join(__dirname, dir); 8 | const files = await fs.readdir(filePath); 9 | for (const file of files) { 10 | const stat = await fs.lstat(path.join(filePath, file)); 11 | if (stat.isDirectory()) registerCommands(client, path.join(dir, file)); 12 | if (file.endsWith('.js')) { 13 | const Command = require(path.join(filePath, file)); 14 | if (Command.prototype instanceof BaseCommand) { 15 | const cmd = new Command(); 16 | client.commands.set(cmd.name, cmd); 17 | } 18 | } 19 | } 20 | } 21 | 22 | async function registerEvents(client, dir = '') { 23 | const filePath = path.join(__dirname, dir); 24 | const files = await fs.readdir(filePath); 25 | for (const file of files) { 26 | const stat = await fs.lstat(path.join(filePath, file)); 27 | if (stat.isDirectory()) registerEvents(client, path.join(dir, file)); 28 | if (file.endsWith('.js')) { 29 | const Event = require(path.join(filePath, file)); 30 | if (Event.prototype instanceof BaseEvent) { 31 | const event = new Event(); 32 | client.on(event.name, event.run.bind(event, client)); 33 | } 34 | } 35 | } 36 | } 37 | 38 | async function registerMusicEvents(client, dir = '') { 39 | const filePath = path.join(__dirname, dir); 40 | const files = await fs.readdir(filePath); 41 | for (const file of files) { 42 | const stat = await fs.lstat(path.join(filePath, file)); 43 | if (stat.isDirectory()) registerMusicEvents(client, path.join(dir, file)); 44 | if (file.endsWith('.js')) { 45 | const Event = require(path.join(filePath, file)); 46 | if (Event.prototype instanceof BaseEvent) { 47 | const event = new Event(); 48 | client.on(event.name, event.run.bind(event, client)); 49 | } 50 | } 51 | } 52 | } 53 | 54 | module.exports = { 55 | registerCommands, 56 | registerEvents, 57 | registerMusicEvents 58 | }; -------------------------------------------------------------------------------- /src/utils/structures/BaseCommand.js: -------------------------------------------------------------------------------- 1 | module.exports = class BaseCommand { 2 | constructor (name, category, aliases) { 3 | this.name = name; 4 | this.category = category; 5 | this.aliases = aliases; 6 | } 7 | } -------------------------------------------------------------------------------- /src/utils/structures/BaseEvent.js: -------------------------------------------------------------------------------- 1 | module.exports = class BaseEvent { 2 | constructor (name) { 3 | this.name = name; 4 | } 5 | } --------------------------------------------------------------------------------