nice new update
This commit is contained in:
parent
e136522421
commit
666638c956
136 changed files with 4483 additions and 9190 deletions
9
.env.example
Normal file
9
.env.example
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
CLIENT_ID=
|
||||
CLIENT_SECRET=
|
||||
BOT_TOKEN=
|
||||
|
||||
DB_URI=mariadb://knightrider:<password>@localhost:3306/knightrider
|
||||
|
||||
|
||||
WEBSITE_PORT=3000
|
24
.eslintrc.json
Normal file
24
.eslintrc.json
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
|
||||
],
|
||||
"overrides": [],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"no-console": "warn"
|
||||
}
|
||||
|
||||
}
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1 +1,6 @@
|
|||
node_modules
|
||||
.env
|
||||
/dist
|
||||
/logs
|
||||
/TODO
|
||||
/OLD_src
|
58
README.md
58
README.md
|
@ -1,44 +1,36 @@
|
|||
# knightrider
|
||||
|
||||
mfking discord bot with all that shit
|
||||
|
||||
### file structure
|
||||
this is the guide on what is where
|
||||
|
||||
```
|
||||
| - src - | - applications - \ - bot.js
|
||||
| | / - webserver.js
|
||||
| |
|
||||
| | - bot - | - addons
|
||||
| | | - commands
|
||||
| | | - events
|
||||
| | | - handlers
|
||||
| |
|
||||
| | - conf - \ conf.json
|
||||
| | / tokens.js
|
||||
| |
|
||||
| | - express
|
||||
| |
|
||||
| | - funcs
|
||||
| |
|
||||
| | - models
|
||||
```
|
||||
|
||||
# knightrider
|
||||
the all-purpose open source discord bot for CWH11's Hangout Crew.
|
||||
|
||||
|
||||
### set up
|
||||
- go to discord.com/developers and make a bot token
|
||||
- bot token goes in src/conf/tokens.js under { bot: {token: "here"} }
|
||||
- take note of the client id, client secret, snd then bot token
|
||||
|
||||
- make a mongo db with the schemas "servers" "users"
|
||||
- put the mongo db connect uri in src/conf/tokens.js under { db: {URI: "here"} }
|
||||
- make a mysql server with a db
|
||||
|
||||
- edit neccery information and details in src/conf/conf.json
|
||||
- copy the .env.example file to .env fill in the client id, client secret bot token and database uri
|
||||
|
||||
- npm install
|
||||
|
||||
- npm start
|
||||
- from the folder run `npm install --save-dev` then `npm run build` finally `npm run start`
|
||||
|
||||
yeah it will be more detailed with the next update.
|
||||
## Features
|
||||
|
||||
[ ] - reaction roles
|
||||
|
||||
[ ] - message macros
|
||||
|
||||
[ ] - custom reaction role embeds
|
||||
|
||||
[ ] - reaction ban
|
||||
|
||||
[ ] - reaction kick
|
||||
|
||||
[ ] - user info/strike system
|
||||
|
||||
[ ] - CAPS spam
|
||||
|
||||
~~[ ] - word filter~~ (use built in auto mod)
|
||||
|
||||
[ ] - simple web dashboard
|
||||
|
||||
~~[ ] - mc server status command~~ (use McStatus https://mcstauts.net/bot)
|
||||
|
|
20
TODO
20
TODO
|
@ -1,5 +1,15 @@
|
|||
better nav bar
|
||||
better main page
|
||||
batter server page
|
||||
better error checking for fivem cmd
|
||||
fix discord tag not showing up in fivem commands
|
||||
implement /reactionrole add /reactionrole remove commands--done
|
||||
implement add remove message macro cmd
|
||||
|
||||
|
||||
|
||||
implement event to listen for reactions and then role them
|
||||
|
||||
add onto rr event listner and add this
|
||||
add reaction remove listnere
|
||||
|
||||
implement /kickrole enable and /kickrole disable
|
||||
implement /banrole enable and /banrole disable
|
||||
|
||||
|
||||
|
||||
|
|
5
nodemon.json
Normal file
5
nodemon.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"watch": ["src"],
|
||||
"ext": "ts",
|
||||
"exec": "ts-node --files --project tsconfig.json src/index.ts"
|
||||
}
|
6789
package-lock.json
generated
6789
package-lock.json
generated
File diff suppressed because it is too large
Load diff
37
package.json
37
package.json
|
@ -2,11 +2,11 @@
|
|||
"name": "knightrider",
|
||||
"version": "4.8.434",
|
||||
"description": "a bot for a private discord server",
|
||||
"updatenote": "small update (untested): fixed non staff from accessing dashboard by doing to domain/server/:server-id",
|
||||
"main": "./src/knightrider.js",
|
||||
"main": "./dist/index.js",
|
||||
"scripts": {
|
||||
"start": "node ./src/knightrider.js",
|
||||
"help": "if you need help with this bot please look at http://knightrider.invalidlag.com/help/"
|
||||
"build": "tsc",
|
||||
"start": "node ./dist/index.js",
|
||||
"dev": "nodemon"
|
||||
},
|
||||
"author": "404invalid-user",
|
||||
"repository": {
|
||||
|
@ -15,22 +15,19 @@
|
|||
},
|
||||
"license": "Apache license 2.0",
|
||||
"dependencies": {
|
||||
"@discordjs/opus": "*",
|
||||
"body-parser": "*",
|
||||
"discord-bitfield-calculator": "^1.0.0",
|
||||
"discord.js": "^12.5.3",
|
||||
"ejs": "*",
|
||||
"express": "*",
|
||||
"express-rate-limit": "*",
|
||||
"ffmpeg-static": "*",
|
||||
"minecraft-server-util": "*",
|
||||
"mongoose": "*",
|
||||
"node-fetch": "*",
|
||||
"randomstring": "*",
|
||||
"request": "*",
|
||||
"url": "^*",
|
||||
"util": "*",
|
||||
"yt-search": "*",
|
||||
"ytdl-core": "*"
|
||||
"discord.js": "^14.16.3",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.21.1",
|
||||
"mariadb": "^3.4.0",
|
||||
"mcstatusbot-logger": "^1.0.5",
|
||||
"mysql2": "^3.12.0",
|
||||
"sequelize": "^6.37.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^5.0.0",
|
||||
"nodemon": "^3.1.9",
|
||||
"ts-node": "^10.9.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const chalk = require('chalk')
|
||||
const { readdirSync } = require('fs')
|
||||
const Discord = require('discord.js')
|
||||
module.exports = (client, webServer) => {
|
||||
|
||||
client.commands = new Discord.Collection();
|
||||
client.addons = [];
|
||||
const handlers = readdirSync(__dirname + '/../bot/handlers/').filter((file) => file.endsWith(".js"));
|
||||
for (let handler of handlers) {
|
||||
require(`../bot/handlers/${handler}`)(client);
|
||||
}
|
||||
|
||||
try {
|
||||
client.login(require('../conf/tokens').bot.token);
|
||||
} catch (error) {
|
||||
console.log(chalk.blue('[bot]: ') + chalk.red('(error): ') + "cant login error: " + error);
|
||||
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const chalk = require('chalk')
|
||||
const bodyParser = require('body-parser');
|
||||
const rateLimit = require("express-rate-limit");
|
||||
const express = require('express')
|
||||
const fs = require('fs')
|
||||
const conf = require('../conf/conf.json')
|
||||
|
||||
module.exports = (client, webServer) => {
|
||||
|
||||
webServer.use(bodyParser.json());
|
||||
webServer.use(bodyParser.urlencoded({ extended: true }));
|
||||
webServer.use(express.static(__dirname + '/../express/www/static'));
|
||||
webServer.set('view engine', 'ejs');
|
||||
webServer.set('views', __dirname + '/../express/www/views');
|
||||
webServer.use((req, res, next) => {
|
||||
const { headers: { cookie } } = req;
|
||||
if (cookie) {
|
||||
const values = cookie.split(';').reduce((res, item) => {
|
||||
const data = item.trim().split('=');
|
||||
return {...res, [data[0]]: data[1] };
|
||||
}, {});
|
||||
res.locals.cookie = values;
|
||||
} else res.locals.cookie = {};
|
||||
next();
|
||||
});
|
||||
//rate limit the api so we dont have spam
|
||||
const apiLimiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||
max: 400
|
||||
});
|
||||
|
||||
webServer.use("/api/", apiLimiter);
|
||||
|
||||
['get', 'post'].forEach(handler => {
|
||||
require(`../express/handlers/${handler}`)(client, webServer)
|
||||
})
|
||||
|
||||
try {
|
||||
webServer.listen(conf.port, () => {
|
||||
console.log(chalk.cyan('[webServer]: ') + 'running at ' + conf.domain + ' (port:' + conf.port + ')')
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(chalk.cyan('[webServer]: ') + chalk.cyan('(error): ') + 'could not start the web server error: ' + error)
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
const Server = require('../../models/server');
|
||||
const conf = require('../../conf/conf.json')
|
||||
module.exports = async(message, server, user, client) => {
|
||||
if (server.addons.caps == true) {
|
||||
if (!message.member.roles.cache.find(r => server.staffRoles.includes(r.name))) {
|
||||
const textRegex = new RegExp(/[^a-zA-Z0-9]/, 'g');
|
||||
const capsRegex = new RegExp(/[A-Z]/, 'g');
|
||||
|
||||
const capsText = message.content.replace(textRegex, '');
|
||||
const capsPerc = 1 - (capsText.replace(capsRegex, '').length / capsText.length);
|
||||
|
||||
if (capsText.length > 6 && capsPerc > 0.7) {
|
||||
message.channel.send("too many caps")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
const conf = require('../../conf/conf.json')
|
||||
module.exports = (message, server, user, client) => {
|
||||
//filter banned words at different levels
|
||||
try {
|
||||
if (server.addons.filter == true) {
|
||||
if (!message.member.roles.cache.find(r => server.staffRoles.includes(r.name))) {
|
||||
if (server.filter.level == 'safe') {
|
||||
server.filter.safe.forEach(async(word) => {
|
||||
let msgContent = message.content.toLowerCase();
|
||||
if (msgContent.includes(word)) {
|
||||
await message.delete().catch(error => {});
|
||||
addstrike(user);
|
||||
if (parseInt(server.channels.modLogs) !== 'NaW') {
|
||||
client.guilds.cache.get(server.id).channels.cache.get(server.channels.modLogs).send({ embed: { color: conf.colour.ok, title: 'filter has been triggered', url: conf.domain + '/server/' + user.guildID + '/user/' + user.id, author: { name: conf.bot.name, icon_url: conf.bot.logo, url: conf.bot.url, }, thumbnail: { url: message.author.displayAvatarURL() }, fields: [{ name: '__**Member**__', value: message.author.tag + '<@!' + message.author.id + '> (' + message.author.id + ')', inline: true, }, { name: '__**Channel**__', value: '<#' + message.channel.id + '>', inline: true }, { name: '__**Filter level**__', value: '`safe`' }, { name: '__**Mesage Content**__', value: '`"' + message.content + '"`', }, { name: '__**Filtered Word**__', value: '`"' + word + '"`' }], timestamp: new Date(), footer: { text: 'moderation log', } } });
|
||||
};
|
||||
message.reply(`please dont swear.\nwas this a miss trigger? fill in ${conf.domain}/server/${server.id}/er`).then(m => m.delete({ timeout: 30000 }));
|
||||
return;
|
||||
};
|
||||
});
|
||||
//filter normal mode
|
||||
} else if (server.filter.level == 'normal') {
|
||||
server.filter.normal.forEach(async(word) => {
|
||||
let msgContent = message.content.toLowerCase();
|
||||
if (msgContent.includes(word)) {
|
||||
await message.delete().catch(error => {});
|
||||
functions.addstrike(message);
|
||||
if (parseInt(server.channels.modLogs) !== 'NaW') {
|
||||
client.guilds.cache.get(conf.server.id).channels.cache.get(conf.server.channels.modLogs).send({ embed: { color: conf.colour.ok, title: 'filter has been triggered', url: conf.domain + '/server/' + user.guildID + '/user/' + user.id, author: { name: conf.bot.name, icon_url: conf.bot.logo, url: conf.bot.url, }, thumbnail: { url: message.author.displayAvatarURL() }, fields: [{ name: '__**Member**__', value: message.author.tag + '<@!' + message.author.id + '> (' + message.author.id + ')', inline: true, }, { name: '__**Channel**__', value: '<#' + message.channel.id + '>', inline: true }, { name: '__**Filter level**__', value: '`normal`' }, { name: '__**Mesage Content**__', value: '`"' + message.content + '"`', }, { name: '__**Filtered Word**__', value: '`"' + word + '"`' }], timestamp: new Date(), footer: { text: 'moderation log', } } });
|
||||
};
|
||||
message.reply(`please dont swear.\nwas this a miss trigger? fill in ${conf.domain}/server/${server.id}/er`).then(m => m.delete({ timeout: 30000 }));
|
||||
|
||||
return;
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
const http = require('http');
|
||||
const conf = require('../../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: 'fivem',
|
||||
description: "`.fivem` gets information for the fivem server. do `.fivem players` to see who is online",
|
||||
async execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
const url = "http://lxn4gvp-aries1.linuxnodes.net:3000"
|
||||
|
||||
if (!args[1]) {
|
||||
let serverEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor("fiveM info")
|
||||
.setColor(conf.colour.ok)
|
||||
.setDescription("some info about the server")
|
||||
try {
|
||||
await http.get(`${currentServer.configs.fivem.url}/dynamic.json`, (result) => {
|
||||
let body = ''
|
||||
result.on('data', (chunk) => {
|
||||
body += chunk
|
||||
})
|
||||
result.on('end', () => {
|
||||
let dynamicResponse = JSON.parse(body)
|
||||
serverEmbed.addField(`__**players:**__`, `${dynamicResponse.clients}/${dynamicResponse.sv_maxclients}`, true)
|
||||
|
||||
|
||||
}).on('error', function (error) {
|
||||
console.log('error: ' + error)
|
||||
})
|
||||
})
|
||||
|
||||
await http.get(`${currentServer.configs.fivem.url}/info.json`, (result) => {
|
||||
let body = ''
|
||||
result.on('data', (chunk) => {
|
||||
body += chunk
|
||||
})
|
||||
result.on('end', () => {
|
||||
let infoResponse = JSON.parse(body)
|
||||
|
||||
serverEmbed.addField(`__**server:**__`, `${infoResponse.server}`, true)
|
||||
|
||||
let oneEyncEnabled;
|
||||
let enhancedHostSupport;
|
||||
let scriptHookAllowed;
|
||||
if (infoResponse.vars.onesync_enabled == 'true') {
|
||||
oneEyncEnabled = ":white_check_mark:"
|
||||
} else {
|
||||
oneEyncEnabled = ":x:"
|
||||
}
|
||||
|
||||
if (infoResponse.vars.sv_enhancedHostSupport == 'true') {
|
||||
enhancedHostSupport = ":white_check_mark:"
|
||||
} else {
|
||||
enhancedHostSupport = ":x:"
|
||||
}
|
||||
|
||||
if (infoResponse.vars.sv_scriptHookAllowed == 'true') {
|
||||
scriptHookAllowed = ":white_check_mark:"
|
||||
} else {
|
||||
scriptHookAllowed = ":x:"
|
||||
}
|
||||
|
||||
serverEmbed.addField(`__**server Info:**__`, ` __onesync:__ ${infoResponse.vars.onesync} \n __onesync Enabled:__ ${oneEyncEnabled} \n __Enhanced Host Support:__ ${enhancedHostSupport} \n __Script Hook Allowed:__ ${scriptHookAllowed}`)
|
||||
serverEmbed.addField(`__**resources:**__`, `${infoResponse.resources}`)
|
||||
|
||||
message.channel.send(serverEmbed)
|
||||
})
|
||||
})
|
||||
} catch (error) {
|
||||
message.reply("__**there has been an error**__\nserver is down maybe.")
|
||||
console.log('error: ' + error)
|
||||
}
|
||||
|
||||
} else if (args[1] == 'ip') {
|
||||
let fivemIpEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor("fiveM ip")
|
||||
.setColor(conf.colour.ok)
|
||||
.setDescription("the fiveM server ip is: `" + currentServer.configs.fivem.ip + "`")
|
||||
message.channel.send(fivemIpEmbed)
|
||||
} else if (args[1] == 'players') {
|
||||
let playersEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor("fiveM players")
|
||||
.setColor(conf.colour.ok)
|
||||
|
||||
try {
|
||||
http.get(`${currentServer.configs.fivem.url}/players.json`, (result) => {
|
||||
let body = ''
|
||||
result.on('data', (chunk) => {
|
||||
body += chunk
|
||||
})
|
||||
|
||||
result.on('end', async () => {
|
||||
var response = JSON.parse(body)
|
||||
if (response.length == 0 || response.length < 0) {
|
||||
playersEmbed.addField("__info__", `no one is on the server`)
|
||||
}
|
||||
|
||||
let i;
|
||||
for (i = 0; i < response.length; i++) {
|
||||
let discordID = '';
|
||||
await response[i].identifiers.forEach(id => {
|
||||
if (id.includes('discord:')) {
|
||||
discordID = id.replace('discord:', '');
|
||||
}
|
||||
});
|
||||
playersEmbed.addField(`player ${i}:`, `__**name:**__ ${response[i].name} \n __**discord:**__ <@!${discordID}> \n __**fiveM id:**__ ${response[i].id} \n __**ping:**__ ${response[i].ping} \n`)
|
||||
}
|
||||
if (i == response.length) {
|
||||
try {
|
||||
message.channel.send(playersEmbed)
|
||||
} catch (error) {
|
||||
message.channel.send("i couldnt sent that maybe there are too many players online and i cant add them all to the embed.")
|
||||
console.log('error: ' + error)
|
||||
}
|
||||
}
|
||||
|
||||
}).on('error', function (error) {
|
||||
console.log('error: ' + error)
|
||||
})
|
||||
})
|
||||
} catch (error) {
|
||||
message.reply("__**there has been an error**__\nserver is down maybe.")
|
||||
console.log('error: ' + error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
const Discord = require('discord.js');
|
||||
const util = require('minecraft-server-util');
|
||||
|
||||
|
||||
module.exports = {
|
||||
name: 'mcstatus',
|
||||
description: "mcstat",
|
||||
execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
|
||||
|
||||
util.status('cwh11.mc.sparks.codes' || currentServer.conf.mc)
|
||||
.then((response) => {
|
||||
let minecraftEmbed = new Discord.MessageEmbed()
|
||||
.setColor(conf.colour.ok)
|
||||
.setAuthor(conf.bot.name, conf.bot.logo)
|
||||
.setTitle('Minecraft server status')
|
||||
.setURL('http://cwh11.mc.sparks.codes')
|
||||
.setThumbnail(`${message.guild.iconURL() || `${conf.domain}/logo.png`}`)
|
||||
.setDescription('its online!')
|
||||
.addField('Server IP:', `${response.host}`)
|
||||
.addField('Version:', `${response.version}`)
|
||||
.addField('MOTD:', `${response.description.descriptionText}`)
|
||||
.addFields({ name: 'Online Players', value: `${response.onlinePlayers}`, inline: true }, { name: 'Max Players', value: `${response.maxPlayers}`, inline: true }, )
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
|
||||
message.channel.send(minecraftEmbed).catch(error => console.log('error: ' + error));
|
||||
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('error: ' + error);
|
||||
message.channel.send('**there has been a error**\n this is probably because the server is down');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
const https = require('https');
|
||||
const conf = require('../../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: 'memes',
|
||||
description: " shrekbot meme command http://shrekbot.tk/github",
|
||||
execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
try {
|
||||
const url = `https://www.reddit.com/${currentServer.configs.memes || 'r/memes'}/.json?limit=200`
|
||||
|
||||
https.get(url, (result) => {
|
||||
var body = ''
|
||||
result.on('data', (chunk) => {
|
||||
body += chunk
|
||||
})
|
||||
|
||||
result.on('end', () => {
|
||||
var response = JSON.parse(body)
|
||||
var index = response.data.children[Math.floor(Math.random() * 129) + 1].data
|
||||
|
||||
if (index.post_hint !== 'image') {
|
||||
message.channel.send('there has been a shrekup retrying...')
|
||||
}
|
||||
|
||||
if (!index.preview) return message.channel.send('a big shrekup has hapened do that command agian');
|
||||
|
||||
var image = index.preview.images[0].source.url.replace('&', '&')
|
||||
var title = index.title
|
||||
var link = 'https://reddit.com' + index.permalink
|
||||
var subRedditName = index.subreddit_name_prefixed
|
||||
|
||||
if (index.post_hint !== 'image') {
|
||||
console.log("error no image")
|
||||
}
|
||||
|
||||
console.log(image);
|
||||
|
||||
const imageembed = new Discord.MessageEmbed()
|
||||
.setTitle('a meme provided by reddit')
|
||||
.setImage(image)
|
||||
.setColor(`${conf.colour.ok}`)
|
||||
.setDescription(`[${title}](${link})`)
|
||||
//.setURL(`https://reddit.com/${subRedditName}`)
|
||||
.setFooter('powered by ' + `${subRedditName}`)
|
||||
message.channel.send(imageembed).catch(error => console.log('error: ' + error))
|
||||
|
||||
}).on('error', function(error) {
|
||||
console.log('Got an error: ' + error);
|
||||
})
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('error: ' + error);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,203 +0,0 @@
|
|||
const ytdl = require('ytdl-core');
|
||||
const ytSearch = require('yt-search');
|
||||
const Discord = require('discord.js')
|
||||
const conf = require('../../../conf/conf.json')
|
||||
|
||||
const queue = new Map();
|
||||
|
||||
module.exports = {
|
||||
name: 'play',
|
||||
description: "the moosk command",
|
||||
aliases: ["p", "q", "skip", "stop", "remove", "queue"],
|
||||
async execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
|
||||
/*TODO
|
||||
*make these embeds better and objects
|
||||
*/
|
||||
const noContentErrorEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor('Music', `${conf.bot.logo}`)
|
||||
.setTitle('Error')
|
||||
.setURL(conf.domain)
|
||||
.setColor(conf.colour.okError)
|
||||
.setDescription("well what do you want to listen to?\ni know i am an amazing bot but i cant read minds ~~yet~~")
|
||||
.addField("possible fixes:", `You have two spaces between ${currentServer.prefix}play and the url/song name remove one of them`)
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
|
||||
const notVoiceErrorEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor('Music', `${conf.bot.logo}`)
|
||||
.setTitle('Error')
|
||||
.setURL(conf.domain)
|
||||
.setColor(conf.colour.okError)
|
||||
.setTitle("you need to be in a voice channel to execute this command im not exactly going to send you the cd")
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
|
||||
const noSongsErrorEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor('Music', `${conf.bot.logo}`)
|
||||
.setTitle('Error')
|
||||
.setURL(conf.domain)
|
||||
.setColor(conf.colour.okError)
|
||||
.setTitle("oof there are no songs left in queue")
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
|
||||
const errorEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor('Music', `${conf.bot.logo}`)
|
||||
.setTitle('Error')
|
||||
.setURL(conf.domain)
|
||||
.setColor(conf.colour.okError)
|
||||
.setTitle("There was some error ~~like there always is~~")
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
|
||||
const videoErrorEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor('Music', `${conf.bot.logo}`)
|
||||
.setTitle('Error')
|
||||
.setURL(conf.domain)
|
||||
.setColor(conf.colour.okError)
|
||||
.setTitle("I cant seem to find that video")
|
||||
.setDescription("try adding more key words or just use the song's url")
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
|
||||
|
||||
const voiceChannel = message.member.voice.channel;
|
||||
if (!voiceChannel) return message.channel.send(notVoiceErrorEmbed);
|
||||
const permissions = voiceChannel.permissionsFor(message.client.user);
|
||||
if (!permissions.has('connect')) return message.channel.send('i cant connect to this voice channel ask someone that can help me');
|
||||
if (!permissions.has('speak')) return message.channel.send('i cant talk in this voice channel aks someone that can help me');
|
||||
const serverQueue = queue.get(message.guild.id);
|
||||
|
||||
|
||||
if (args[0] === 'play' || args[0] === 'p') {
|
||||
if (!args[1]) return message.channel.send(noContentErrorEmbed).catch(e => console.log(e))
|
||||
let song = {};
|
||||
const videoFinder = async(query) => {
|
||||
const videoResult = await ytSearch(query).catch(e => console.log(e));
|
||||
try {
|
||||
return (videoResult.videos.length > 1) ? videoResult.videos[0] : null;
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
let songQuery = args.slice(1).join(' ').replace('http://', '').replace('https://', '').replace('www.', '').replace('youtube.com/', '').replace('/watch?v=', '').replace('&feature=share', '').replace('youtu.be', '')
|
||||
|
||||
const video = await videoFinder(songQuery);
|
||||
|
||||
if (video) {
|
||||
song = { title: video.title, url: video.url }
|
||||
} else {
|
||||
message.channel.send(videoErrorEmbed).catch(e => console.log(e))
|
||||
}
|
||||
if (!serverQueue) {
|
||||
const queueConstructor = {
|
||||
voiceChannel: voiceChannel,
|
||||
textChannel: message.channel,
|
||||
connection: null,
|
||||
songs: []
|
||||
}
|
||||
queue.set(message.guild.id, queueConstructor);
|
||||
queueConstructor.songs.push(song);
|
||||
try {
|
||||
const connection = await voiceChannel.join();
|
||||
queueConstructor.connection = connection;
|
||||
videoPlayer(message.guild, queueConstructor.songs[0], message);
|
||||
} catch (error) {
|
||||
queue.delete(message.guild.id);
|
||||
message.channel.send(errorEmbed).catch(e => console.log(e))
|
||||
console.log('error: ' + error)
|
||||
}
|
||||
} else {
|
||||
serverQueue.songs.push(song);
|
||||
let addSongEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor('Music', `${conf.bot.logo}`)
|
||||
.setColor(conf.colour.ok)
|
||||
.setTitle(`**${song.title}** added to the queue`)
|
||||
.setURL(`${song.url}`)
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
return message.channel.send(addSongEmbed).catch(e => console.log(e))
|
||||
}
|
||||
} else if (args[0] === 'queue' || args[0] === 'q') serverQueueGet(message, serverQueue, args);
|
||||
else if (args[0] === 'skip') skipSong(message, serverQueue);
|
||||
else if (args[0] === 'stop') stopSong(message, serverQueue);
|
||||
else if (args[0] === 'remove') removeSong(message, serverQueue, args);
|
||||
}
|
||||
}
|
||||
const videoPlayer = async(guild, song, message) => {
|
||||
const songQueue = queue.get(guild.id);
|
||||
if (!song) {
|
||||
songQueue.voiceChannel.leave();
|
||||
queue.delete(guild.id);
|
||||
return;
|
||||
}
|
||||
const stream = ytdl(song.url, { filter: 'audioonly' });
|
||||
try {
|
||||
songQueue.connection.play(stream, { seek: 0, volume: 0.5 })
|
||||
.on('finish', () => {
|
||||
songQueue.songs.shift();
|
||||
videoPlayer(guild, songQueue.songs[0], message);
|
||||
})
|
||||
} catch (err) {
|
||||
message.channel.send("i cant connect to the voice channel within the time frame i have high ping or some other error")
|
||||
}
|
||||
if (song.url) {
|
||||
let embedUrl = song.url
|
||||
if (!embedUrl.includes('http')) {
|
||||
embedUrl = conf.domain
|
||||
}
|
||||
let addSongEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor('Music', `${conf.bot.logo}`)
|
||||
.setColor(conf.colour.ok)
|
||||
.setTitle(`Now playing **${song.title}**`)
|
||||
.setURL(`${embedUrl}`)
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
await songQueue.textChannel.send(addSongEmbed)
|
||||
}
|
||||
}
|
||||
|
||||
const serverQueueGet = async(message, serverQueue, args) => {
|
||||
if (!message.member.voice.channel) return message.channel.send(notVoiceErrorEmbed);
|
||||
let serverQueueEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor('Music Queue', `${conf.bot.logo}`)
|
||||
.setColor(conf.colour.ok)
|
||||
.setTitle(`the server queue`)
|
||||
.setURL(`${conf.domain}`)
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`)
|
||||
await serverQueue.songs.forEach(theSong => {
|
||||
serverQueueEmbed.addField(`${serverQueue.songs.indexOf(theSong)}`, `__title:__ ${theSong.title}\n__url:__ ${theSong.url}`)
|
||||
})
|
||||
await message.channel.send(serverQueueEmbed)
|
||||
|
||||
}
|
||||
const skipSong = (message, serverQueue) => {
|
||||
if (!message.member.voice.channel) return message.channel.send(notVoiceErrorEmbed);
|
||||
if (!serverQueue) {
|
||||
return message.channel.send(noSongsErrorEmbed);
|
||||
}
|
||||
serverQueue.connection.dispatcher.end();
|
||||
}
|
||||
|
||||
const stopSong = (message, serverQueue) => {
|
||||
if (!message.member.voice.channel) return message.channel.send(notVoiceErrorEmbed);
|
||||
serverQueue.songs = [];
|
||||
serverQueue.connection.dispatcher.end();
|
||||
}
|
||||
|
||||
const removeSong = (message, serverQueue) => {
|
||||
serverQueue.songs.forEach(theSong => {
|
||||
if (args[1] == serverQueue.songs.indexOf(theSong)) {
|
||||
try {
|
||||
serverQueue.songs.indexOf(theSong) > -1 ? serverQueue.songs.splice(serverQueue.songs.indexOf(theSong), 1) : false
|
||||
} catch (err) {
|
||||
message.channel.send("there was an error removing that song")
|
||||
}
|
||||
} else {
|
||||
message.channel.send("That song isn't in the queue you can use the url insted.\nYou can find the url by clicking on the blue text in the embed i sent when you requested to play that song.")
|
||||
}
|
||||
})
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
const { version } = require('../../../../package.json');
|
||||
const conf = require('../../../conf/conf.json')
|
||||
|
||||
module.exports = {
|
||||
name: 'about',
|
||||
description: "about bot",
|
||||
async execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
message.channel.send(conf.domain + '/img/loading.gif').then(m => {
|
||||
|
||||
let totalSeconds = (client.uptime / 1000);
|
||||
let days = Math.floor(totalSeconds / 86400);
|
||||
totalSeconds %= 86400;
|
||||
let hours = Math.floor(totalSeconds / 3600);
|
||||
totalSeconds %= 3600;
|
||||
let minutes = Math.floor(totalSeconds / 60);
|
||||
let seconds = Math.floor(totalSeconds % 60);
|
||||
|
||||
let aboutEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor(conf.bot.name, `${conf.bot.logo}`, `${conf.domain}`)
|
||||
.setDescription('everything you need to know.')
|
||||
.setColor(conf.colour.ok)
|
||||
.setTitle('about')
|
||||
.setThumbnail(`${message.guild.iconURL() || `${conf.domain}/logo.png`}`)
|
||||
.addField('Website:', `${conf.domain}`)
|
||||
.addField('Coolness level', `epic bot for ${message.guild.name} server`)
|
||||
.addField('Developer(s)', '<@!522534458071449620>')
|
||||
.addField('Version', `${version}`)
|
||||
.addField('Libary', `discord.js v12`)
|
||||
.addField("commands sent:", `${currentServer.commandCount} commands`)
|
||||
.addField('Bot version:', `${version}`)
|
||||
.addField('Up Time', `${days} d, ${hours} h, ${minutes} m, ${seconds} s`)
|
||||
.addField("Memory usage:", `${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB / 1GB`)
|
||||
.addField('Ping', `ping: ${m.createdTimestamp - message.createdTimestamp} api ping: ${Math.round(client.ws.ping)}`)
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
m.edit(aboutEmbed).catch(error => console.log('error: ' + error));
|
||||
}).catch(error => console.log('error: ' + error))
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
const conf = require('../../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: 'help',
|
||||
description: "help command",
|
||||
execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
|
||||
|
||||
if (args[1] == 'embed') {
|
||||
let helpSomethingEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor(conf.bot.name, conf.bot.logo)
|
||||
.setColor('#10FF00')
|
||||
.setTitle('Help embed')
|
||||
.setDescription('**For mods and admins only**\nLet’s mods and admin make a custom embed.')
|
||||
.addField('Command structure', `${currentServer.prefix}embed [title] [description] [colour]`)
|
||||
.addField('Command example', `${currentServer.prefix}embed [bruv is awesome] [just joking you are] [#FF0000]`)
|
||||
.addField('Extra info', `To get the # colour code(s) [click here](https://htmlcolorcodes.com/)`)
|
||||
.setThumbnail(`${message.guild.iconURL() || `${conf.domain}/logo.png`}`)
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
message.channel.send(helpSomethingEmbed).catch(error => console.log('error: ' + error));
|
||||
} else if (args[1] == 'embed-img') {
|
||||
let helpSomethingEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor(conf.bot.name, conf.bot.logo)
|
||||
.setColor('#10FF00')
|
||||
.setTitle('Help embed-img')
|
||||
.setDescription('**For mods and admins only**\nLet’s mods and admin make a custom embed.')
|
||||
.addField('Command structure', `${currentServer.prefix}}embed [title] [description] [colour] [img-url]`)
|
||||
.addField('Command example', `${currentServer.prefix}embed [bruv is awesome] [just joking you are] [#FF0000] [http://imgsite.com/knightrider.png]`)
|
||||
.addField('Extra info', `To get the # colour code(s) [click here](https://htmlcolorcodes.com/)`)
|
||||
.setThumbnail(`${message.guild.iconURL() || `${conf.domain}/logo.png`}`)
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
message.channel.send(helpSomethingEmbed).catch(error => console.log('error: ' + error));
|
||||
} else {
|
||||
let helpEmbed = new Discord.MessageEmbed()
|
||||
.setColor(conf.colour.ok)
|
||||
.setTitle('Help!')
|
||||
.setURL(`${conf.domain}`)
|
||||
.setAuthor(conf.bot.name, conf.bot.logo)
|
||||
.addField("util commands:", `${currentServer.prefix}ping - shows ping\n${currentServer.prefix}about - gives general information about the bot`)
|
||||
.addField("general commands:", `${currentServer.prefix}mcstatus - shows minecraft server status\n${currentServer.prefix}memes - shows a random meme from redid mus be done in memes channel\n${currentServer.prefix}fivem - shows fiveM server status\n${currentServer.prefix}fivem players - shows online players on fiveM\n${currentServer.prefix}fivem ip - gives you the fiveM server ip\n${currentServer.prefix}play (song name) or (youtube-url) - plays selected music in a voice channel\n${currentServer.prefix}skip - skips the current song to the next one on the queue\n${currentServer.prefix}stop - bot stops playing music\n`)
|
||||
.addField("moderator commands:", `${currentServer.prefix}say #channel message - bot sends message in channel of choice\n${currentServer.prefix}filter <safe/normal/off> - sets the word filter level\n${currentServer.prefix}userinfo <@user> - gives how many strikes a user has and other basic info on the user like nots and join dates.\n${currentServer.prefix}noteset <@user> - sets a note for a user\n${currentServer.prefix}note <@user> - see a moderator note for a user\n${currentServer.prefix}embed [title] [description] [colour] - sends a embed\n${currentServer.prefix}embed-img [title] [description] [colour] [img-url]\n${currentServer.prefix}OTR11 - for <@!276156203770314755> announcment`)
|
||||
.setThumbnail(`${message.guild.iconURL() || `${conf.domain}/logo.png`}`)
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName}`, `${message.author.displayAvatarURL()}`);
|
||||
message.channel.send(helpEmbed).catch(error => console.log('error: ' + error))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
module.exports = {
|
||||
name: 'ping',
|
||||
description: "about bot",
|
||||
execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
message.channel.send("Pinging...").then(m => {
|
||||
var ping = m.createdTimestamp - message.createdTimestamp;
|
||||
var apiPing = Math.round(client.ws.ping)
|
||||
m.edit(`ping: ${ping}\napi ping: ${apiPing}`).catch(error => console.log('error: ' + error))
|
||||
});
|
||||
}
|
||||
}
|
79
src/bot/commands/messagemacro.ts
Normal file
79
src/bot/commands/messagemacro.ts
Normal file
|
@ -0,0 +1,79 @@
|
|||
import { Client, ChatInputCommandInteraction, PermissionFlagsBits, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
//@ts-expect-error
|
||||
import YALAS from 'mcstatusbot-logger';
|
||||
|
||||
import * as AddMessageMacro from './messagemacro/add';
|
||||
import * as ListMessageMacros from './messagemacro/list';
|
||||
import { GuildInstance } from "../../database/schemas/Guild";
|
||||
import { UserInstance } from "../../database/schemas/User";
|
||||
|
||||
const data = {
|
||||
serverOnly: false,
|
||||
guildId: null,
|
||||
allowSuspendedUserAccess: true,
|
||||
command: new SlashCommandBuilder()
|
||||
.setName('messagemacro')
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild)
|
||||
.setDescription("setup message macros for the server")
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('add')
|
||||
.setDescription("Add a message macro")
|
||||
.addStringOption(option =>
|
||||
option.setName('macro')
|
||||
.setDescription('The macro you send (without prefix)')
|
||||
.setRequired(true)
|
||||
.setMinLength(1)
|
||||
.setMaxLength(5)
|
||||
)
|
||||
.addStringOption(option =>
|
||||
option.setName('message')
|
||||
.setDescription('The content of the message the bot will send')
|
||||
.setRequired(true)
|
||||
.setMinLength(3)
|
||||
.setMaxLength(2000)
|
||||
)
|
||||
.addMentionableOption(option =>
|
||||
option.setName('trigger-role')
|
||||
.setDescription('The role that grants people permission to use this')
|
||||
.setRequired(true)
|
||||
)
|
||||
.addBooleanOption(o =>
|
||||
o.setName('deletecmd')
|
||||
.setDescription("should your macro message be deleted after you send it?")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addBooleanOption(o =>
|
||||
o.setName('impersonate')
|
||||
.setDescription("setting to true will use your name and photo")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addChannelOption(option =>
|
||||
option.setName('channel')
|
||||
.setDescription('The channel in which you want to it to be sent in (leave blank to send in same channel as command)')
|
||||
.setRequired(false)
|
||||
)
|
||||
|
||||
)
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('list')
|
||||
.setDescription("Lists all your message macros and allows you to edit/remove them")
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
export { data };
|
||||
|
||||
|
||||
export async function chatInputCommand(client: Client, interaction: ChatInputCommandInteraction, guild: GuildInstance, user: UserInstance) {
|
||||
switch (interaction.options.getSubcommand()) {
|
||||
case 'add':
|
||||
AddMessageMacro.chatInputCommand(client, interaction, guild, user)
|
||||
break;
|
||||
case 'list':
|
||||
ListMessageMacros.chatInputCommand(client, interaction, guild, user)
|
||||
break;
|
||||
}
|
||||
}
|
140
src/bot/commands/messagemacro/add.ts
Normal file
140
src/bot/commands/messagemacro/add.ts
Normal file
|
@ -0,0 +1,140 @@
|
|||
import { Client, ChatInputCommandInteraction, Role, GuildChannelResolvable, PermissionsBitField, ChannelType } from "discord.js";
|
||||
|
||||
import { schemas } from "../../../database";
|
||||
//@ts-expect-error
|
||||
import YALAS from 'mcstatusbot-logger';
|
||||
|
||||
import { GuildInstance } from "../../../database/schemas/Guild";
|
||||
import { UserInstance } from "../../../database/schemas/User";
|
||||
|
||||
|
||||
export async function chatInputCommand(client: Client, interaction: ChatInputCommandInteraction, guild: GuildInstance, user: UserInstance) {
|
||||
if (!interaction.guild) return interaction.reply("must be done in discord server");
|
||||
|
||||
const botMember = interaction.guild.members.me;
|
||||
if (!botMember) {
|
||||
YALAS.error("messagemacro add: bot in guild null");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//get macro
|
||||
let macroContent = interaction.options.getString('macro');
|
||||
if (!macroContent) return;
|
||||
macroContent = macroContent.replace(/\s+/g, '');
|
||||
|
||||
//get and validate message content
|
||||
const messageContent = interaction.options.getString('message');
|
||||
if (messageContent === null) return;
|
||||
if (messageContent.length < 3 || messageContent.length > 2000) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Invalid Message",
|
||||
description: "The set message must be between 3 and 2000 in length."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//get and validate role
|
||||
const role = interaction.options.getMentionable('trigger-role');
|
||||
if (!(role instanceof Role)) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Invalid Role",
|
||||
description: "The selected role is not a valid role"
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
const deleteMsg = interaction.options.getBoolean('deletecmd') ?? false;
|
||||
|
||||
const impersonate = interaction.options.getBoolean('impersonate') ?? false;
|
||||
|
||||
|
||||
|
||||
//get and validate channel
|
||||
let channel = interaction.options.getChannel('channel');
|
||||
console.log("balkkd cjrA")
|
||||
console.log(channel
|
||||
)
|
||||
if (channel === undefined) channel = null;
|
||||
if (channel !== null) {
|
||||
if (channel.type !== ChannelType.GuildText && channel.type !== ChannelType.GuildAnnouncement) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "That Will Not Work",
|
||||
description: "The selected channel is not a text channel please select a text channel."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
const botPermSM = botMember.permissionsIn((channel as GuildChannelResolvable)).toArray();
|
||||
if (botPermSM && !botPermSM.includes('SendMessages')) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Missing permission",
|
||||
description: "you need to give me the send message permission in the selected channel."
|
||||
}]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
await interaction.deferReply();
|
||||
//check msgMacro does net exist for reaction in channel
|
||||
try {
|
||||
const msgMacro = await schemas['MessageMacro'].findOne({
|
||||
where: {
|
||||
guild: guild.id,
|
||||
shortCode: macroContent,
|
||||
}
|
||||
});
|
||||
|
||||
if (msgMacro !== null) {
|
||||
return interaction.editReply({
|
||||
embeds: [{
|
||||
title: "Message Macro Exists",
|
||||
description: "The message macro `" + msgMacro.dataValues.shortCode + "` already exists please edit or remove it"
|
||||
}]
|
||||
});
|
||||
}
|
||||
} catch (err: any) {
|
||||
YALAS.error(err)
|
||||
YALAS.error(err.stack || err);
|
||||
return interaction.editReply("error when checking for existing message macro in database.");
|
||||
}
|
||||
|
||||
try {
|
||||
await schemas['MessageMacro'].create({
|
||||
guild: guild.id,
|
||||
channel: channel ? channel.id : null,
|
||||
shortCode: macroContent,
|
||||
message: messageContent,
|
||||
role: role.id,
|
||||
impersonate: impersonate,
|
||||
deleteShortCode: deleteMsg
|
||||
});
|
||||
} catch (err: any) {
|
||||
YALAS.error(err.stack || err);
|
||||
return interaction.editReply("error when saving reaction role to database.");
|
||||
}
|
||||
|
||||
|
||||
let prefixNote = '';
|
||||
if (macroContent.toLocaleLowerCase().startsWith(guild.prefix)) {
|
||||
prefixNote = "\nNote: it looks like your macro contains the prefix so to activate it you will need to type `" + guild.prefix + macroContent + "`";
|
||||
}
|
||||
try {
|
||||
return interaction.editReply({
|
||||
embeds: [{
|
||||
title: "Success",
|
||||
description: "The message Macro has been created."+macroContent
|
||||
}]
|
||||
});
|
||||
} catch (err: any) {
|
||||
YALAS.error(err.stack || err);
|
||||
}
|
||||
|
||||
}
|
183
src/bot/commands/messagemacro/list.ts
Normal file
183
src/bot/commands/messagemacro/list.ts
Normal file
|
@ -0,0 +1,183 @@
|
|||
import {
|
||||
Client,
|
||||
ChatInputCommandInteraction,
|
||||
EmbedBuilder,
|
||||
ButtonBuilder,
|
||||
ActionRowBuilder,
|
||||
ButtonStyle,
|
||||
} from "discord.js";
|
||||
|
||||
import { schemas } from "../../../database";
|
||||
//@ts-expect-error
|
||||
import YALAS from "mcstatusbot-logger";
|
||||
|
||||
import { GuildInstance } from "../../../database/schemas/Guild";
|
||||
import { UserInstance } from "../../../database/schemas/User";
|
||||
import { MessageMacroAttributes } from "../../../database/schemas/MessageMacro";
|
||||
|
||||
export async function chatInputCommand(client: Client, interaction: ChatInputCommandInteraction, guild: GuildInstance, user: UserInstance) {
|
||||
if (!interaction.guild) return interaction.reply("Must be done in a Discord server.");
|
||||
|
||||
const botMember = interaction.guild.members.me;
|
||||
if (!botMember) {
|
||||
YALAS.error("MessageMacro Add: Bot in guild is null");
|
||||
return;
|
||||
}
|
||||
|
||||
await interaction.deferReply();
|
||||
|
||||
let msgMacros = [];
|
||||
try {
|
||||
const msgMacroDocs = await schemas["MessageMacro"].findAll({
|
||||
where: {
|
||||
guild: guild.id,
|
||||
},
|
||||
});
|
||||
console.log("nuts")
|
||||
msgMacros = msgMacroDocs.map((item: any) => item.dataValues);
|
||||
} catch (err: any) {
|
||||
YALAS.error(err);
|
||||
YALAS.error(err.stack || err);
|
||||
return interaction.editReply("Error when checking for message macros in the database.");
|
||||
}
|
||||
|
||||
if (msgMacros.length === 0) {
|
||||
return interaction.editReply("No message macros found.");
|
||||
}
|
||||
console.log("balks")
|
||||
|
||||
|
||||
const updateEmbed = (index: number) => {
|
||||
const currentMacro: MessageMacroAttributes = msgMacros[index];
|
||||
const embed = new EmbedBuilder()
|
||||
.setAuthor({name: "Message Macro"})
|
||||
.setTitle(currentMacro.shortCode)
|
||||
.setDescription(currentMacro.message + `\n\n-# --\n-# Prefix: ${guild.prefix}\n-# role: <@&${currentMacro.role}>\n-# Channel: ${currentMacro.channel == null ? '' : '<#' + currentMacro.channel + '>'}`)
|
||||
|
||||
const buttons = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId("prev")
|
||||
.setLabel("<")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(index === 0),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("index")
|
||||
.setLabel(`${index + 1}/${msgMacros.length}`)
|
||||
.setStyle(ButtonStyle.Secondary)
|
||||
.setDisabled(true),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("next")
|
||||
.setLabel(">")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(index === msgMacros.length - 1)
|
||||
);
|
||||
|
||||
const actionButtons = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId("delete")
|
||||
.setLabel("Delete")
|
||||
.setStyle(ButtonStyle.Danger),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("edit")
|
||||
.setLabel("Edit")
|
||||
.setStyle(ButtonStyle.Success)
|
||||
);
|
||||
|
||||
return { embed, buttons, actionButtons };
|
||||
};
|
||||
|
||||
|
||||
// Pagination variables
|
||||
let currentIndex = 0;
|
||||
const { embed, buttons, actionButtons } = updateEmbed(currentIndex);
|
||||
|
||||
const message = await interaction.editReply({
|
||||
embeds: [embed],
|
||||
components: [buttons, actionButtons]
|
||||
});
|
||||
|
||||
const collector = message.createMessageComponentCollector({
|
||||
time: 60000, // 1 minute timeout
|
||||
});
|
||||
|
||||
collector.on("collect", async (i) => {
|
||||
if (i.user.id !== interaction.user.id) {
|
||||
return i.reply({ content: "This interaction isn't for you.", ephemeral: true });
|
||||
}
|
||||
|
||||
switch (i.customId) {
|
||||
case "prev":
|
||||
currentIndex = Math.max(0, currentIndex - 1);
|
||||
break;
|
||||
case "next":
|
||||
currentIndex = Math.min(msgMacros.length - 1, currentIndex + 1);
|
||||
break;
|
||||
case "delete":
|
||||
await schemas["MessageMacro"].destroy({
|
||||
where: { id: msgMacros[currentIndex].id },
|
||||
});
|
||||
msgMacros.splice(currentIndex, 1);
|
||||
currentIndex = Math.max(0, currentIndex - 1);
|
||||
break;
|
||||
case "edit":
|
||||
// Handle edit logic here
|
||||
await i.reply({
|
||||
content: "Edit functionality is not implemented yet.",
|
||||
ephemeral: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (msgMacros.length === 0) {
|
||||
collector.stop();
|
||||
return interaction.editReply({
|
||||
content: "All message macros have been deleted.",
|
||||
embeds: [],
|
||||
components: [],
|
||||
});
|
||||
}
|
||||
|
||||
const { embed, buttons, actionButtons } = updateEmbed(currentIndex);
|
||||
await i.update({ embeds: [embed], components: [buttons, actionButtons] });
|
||||
});
|
||||
|
||||
collector.on("end", () => {
|
||||
const buttons = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId("prev")
|
||||
.setLabel("<")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(true),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("index")
|
||||
.setLabel(`${currentIndex + 1}/${msgMacros.length}`)
|
||||
.setStyle(ButtonStyle.Secondary)
|
||||
.setDisabled(true),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("next")
|
||||
.setLabel(">")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(true)
|
||||
);
|
||||
const actionButtons = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId("delete")
|
||||
.setLabel("Delete")
|
||||
.setStyle(ButtonStyle.Danger)
|
||||
.setDisabled(true),
|
||||
new ButtonBuilder()
|
||||
.setCustomId("edit")
|
||||
.setLabel("Edit")
|
||||
.setStyle(ButtonStyle.Success)
|
||||
.setDisabled(true)
|
||||
);
|
||||
interaction.editReply({
|
||||
components: [buttons, actionButtons],
|
||||
});
|
||||
|
||||
});
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
const fs = require('fs')
|
||||
const conf = require('../../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: 'editfilter',
|
||||
description: "edit the filter array",
|
||||
execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
if (currentServer.staff.includes(message.author.id) || message.member.roles.cache.find(r => server.staffRoles.includes(r.name))) {
|
||||
|
||||
if (!args[1]) {
|
||||
message.channel.send("please specify an operation <add/remove/dash>");
|
||||
return;
|
||||
};
|
||||
if (!args[2]) {
|
||||
message.channel.send("please specify something to add to the filter");
|
||||
return;
|
||||
};
|
||||
if (message.content.toLowerCase().substring(currentServer.prefix.length).split(" ").slice(2).join(" ").includes('@everyone') || message.content.toLowerCase().substring(currentServer.prefix.length).split(" ").slice(2).join(" ").includes('@here')) {
|
||||
message.channel.send("please dont try and exploit me, if you would like to add that to the filter for a genuing reason please use the admin dashboard");
|
||||
return;
|
||||
};
|
||||
|
||||
if (args[1] == 'add') {
|
||||
currentServer.filter[currentServer.filter.level].push(message.content.toLowerCase().substring(currentServer.prefix.length).split(" ").slice(2).join(" "));
|
||||
currentServer.save();
|
||||
message.channel.send(message.content.toLowerCase().substring(currentServer.prefix.length).split(" ").slice(2).join(" ") + " has been added to the `" + currentServer.filter.level + "` filter");
|
||||
|
||||
} else if (args[1] == 'remove') {
|
||||
const index = currentServer.filter[currentServer.filter.level].indexOf(message.content.toLowerCase().substring(currentServer.prefix.length).split(" ").slice(2).join(" "));
|
||||
if (index > -1) {
|
||||
currentServer.filter[currentServer.filter.level].splice(index, 1);
|
||||
message.channel.send("`" + message.content.toLowerCase().substring(currentServer.prefix.length).split(" ").slice(2).join(" ") + "` has been removed from the `" + currentServer.filter.level + "` filter");
|
||||
} else {
|
||||
message.channel.send("you cant remove that as it dosnt exist in the `" + currentServer.filter.level + "` filter");
|
||||
};
|
||||
|
||||
} else if (args[1] == 'dash' || args[1] == 'dashboard') {
|
||||
message.channel.send(conf.domain + "/dashboard");
|
||||
};
|
||||
|
||||
|
||||
} else {
|
||||
return message.reply("you cant do that only staff can").catch(e => console.log(e));
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
module.exports = {
|
||||
name: 'embed-img',
|
||||
description: "embed with image command for mods and admins",
|
||||
execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
if (currentServer.staff.includes(message.author.id) || message.member.roles.cache.find(r => server.staffRoles.includes(r.name))) {
|
||||
if (!args[1]) return message.reply(`you at leas need to supply a title if you stuck do ${currentServer.prefix}help embed`);
|
||||
if (!message.content.includes('[')) return message.reply(`something is wrong with that if youre stuck do ${currentServer.prefix}help embed`);
|
||||
|
||||
let mcontent = message.content;
|
||||
let titleStart = mcontent.indexOf('[');
|
||||
let titleEnd = mcontent.indexOf(']');
|
||||
let title = mcontent.substr(titleStart + 1, titleEnd - titleStart - 1);
|
||||
|
||||
let descStart = mcontent.indexOf('[', titleStart + 1);
|
||||
let descEnd = mcontent.indexOf(']', titleEnd + 1);
|
||||
let description = mcontent.substr(descStart + 1, descEnd - descStart - 1);
|
||||
|
||||
let colorstart = mcontent.indexOf('[', descStart + 1);
|
||||
let colorend = mcontent.indexOf(']', descEnd + 1);
|
||||
let color = mcontent.substr(colorstart + 1, colorend - colorstart - 1);
|
||||
|
||||
let imgstart = mcontent.indexOf('[', colorstart + 1);
|
||||
let imgend = mcontent.indexOf(']', colorend + 1);
|
||||
let img = mcontent.substr(imgstart + 1, imgend - imgstart - 1);
|
||||
|
||||
let custome_embed = new Discord.MessageEmbed().setAuthor(`${message.member.displayName}`, `${message.author.displayAvatarURL()}`).setTitle(title).setDescription(description).setColor(color).setImage(`${img}`);
|
||||
message.channel.send(custome_embed);
|
||||
} else {
|
||||
return message.reply("you cant do that only staff can").catch(e => console.log(e));
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
module.exports = {
|
||||
name: 'embed',
|
||||
description: "embed command for mods and admins",
|
||||
execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
if (currentServer.staff.includes(message.author.id) || message.member.roles.cache.find(r => server.staffRoles.includes(r.name))) {
|
||||
if (!args[1]) return message.reply(`you at leas need to supply a title if you stuck do ${currentServer.prefix}help embed`);
|
||||
if (!message.content.includes('[')) return message.reply(`something is wrong with that if youre stuck do ${currentServer.prefix}help embed`);
|
||||
|
||||
|
||||
let mcontent = message.content;
|
||||
let titleStart = mcontent.indexOf('[');
|
||||
let titleEnd = mcontent.indexOf(']');
|
||||
let title = mcontent.substr(titleStart + 1, titleEnd - titleStart - 1);
|
||||
|
||||
let descStart = mcontent.indexOf('[', titleStart + 1);
|
||||
let descEnd = mcontent.indexOf(']', titleEnd + 1);
|
||||
let description = mcontent.substr(descStart + 1, descEnd - descStart - 1);
|
||||
|
||||
let colorstart = mcontent.indexOf('[', descStart + 1);
|
||||
let colorend = mcontent.indexOf(']', descEnd + 1);
|
||||
let color = mcontent.substr(colorstart + 1, colorend - colorstart - 1);
|
||||
|
||||
let custome_embed = new Discord.MessageEmbed().setAuthor(`${message.member.displayName}`, `${message.author.displayAvatarURL()}`).setTitle(title).setDescription(description).setColor(color);
|
||||
message.channel.send(custome_embed);
|
||||
|
||||
} else {
|
||||
return message.reply("you cant do that only staff can").catch(e => console.log(e));
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
module.exports = {
|
||||
name: 'filter',
|
||||
description: "sets filter",
|
||||
async execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
if (currentServer.staff.includes(message.author.id) || message.member.roles.cache.find(r => server.staffRoles.includes(r.name))) {
|
||||
if (args[1] == 'off') {
|
||||
currentServer.filter.level = 'off';
|
||||
currentServer.save();
|
||||
message.channel.send("filter has been set to " + currentServer.filter.level);
|
||||
} else if (args[1] == 'normal') {
|
||||
currentServer.filter.level = 'normal';
|
||||
currentServer.save();
|
||||
message.channel.send("filter has been set to " + currentServer.filter.level);
|
||||
} else if (args[1] == 'safe') {
|
||||
currentServer.filter.level = 'safe';
|
||||
currentServer.save();
|
||||
message.channel.send("filter has been set to " + currentServer.filter.level);
|
||||
} else {
|
||||
message.channel.send("that is not a valid filter setting you can chose from: 'normal' 'safe' and 'off'.");
|
||||
};
|
||||
|
||||
} else {
|
||||
return message.reply("you cant do that only staff can").catch(e => console.log(e));
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
const conf = require('../../../conf/conf.json');
|
||||
module.exports = {
|
||||
name: 'rulesrolesljoughuihoutfd8es5tryj/i.uliutygrjyhgjlkukbjhcfjklhgfhjouhbgrvycghujyiljknhbgvfhtgfhiuoihkjbnhbvgfgyuo',
|
||||
description: "say command for mods and admins",
|
||||
async execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
if (currentServer.staff.includes(message.author.id) || message.member.roles.cache.find(r => server.staffRoles.includes(r.name))) {
|
||||
|
||||
const exampleEmbed = new Discord.MessageEmbed()
|
||||
.setColor(conf.colour.ok)
|
||||
.setAuthor("Game Reaction Roles")
|
||||
.setTitle("react to get your roles")
|
||||
.setThumbnail('https://cdn.discordapp.com/icons/584484766997282836/94b16e813edb9a2f1df4a5bd16f98ad1.png')
|
||||
.setURL("http://knightRider.rf.gd/reaction-role-error.php")
|
||||
.setDescription("🚚 - <@&595087305212035084>\n🚜 - <@&595086913430355973>\n⛏️ - <@&595087098604683277>\n🗺️ - <@&604424840807710721>\n🚓 - <@&691635977889906849>\n🚗 - <@&752217267600621578>\n🏎️ - <@&752217137728192543>\n🔧 - <@&595767995998011392>\n⚙️ - <@&860942666195927050>")
|
||||
.setFooter('something wrong? go to http://knightRider.rf.gd/er.html');
|
||||
let msg = await message.channel.send(exampleEmbed);
|
||||
msg.react("🚚")
|
||||
msg.react("🚜")
|
||||
msg.react("⛏")
|
||||
msg.react("🗺")
|
||||
msg.react("🚓")
|
||||
msg.react("🚗")
|
||||
msg.react("🏎")
|
||||
msg.react("🔧")
|
||||
msg.react("⚙")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
module.exports = {
|
||||
name: 'note',
|
||||
description: "shows a users note",
|
||||
async execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
message.reply("* depricated *: do " + currentServer.prefix + "userinfo @someone")
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
module.exports = {
|
||||
name: 'say',
|
||||
description: "say command for mods and admins",
|
||||
execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
if (currentServer.staff.includes(message.author.id) || message.member.roles.cache.find(r => server.staffRoles.includes(r.name))) {
|
||||
|
||||
message.delete();
|
||||
let sayArgs = message.content.substring(prefix.length).split(" ");
|
||||
if (message.content.toLowerCase().includes('@everyone')) return message.reply(`Holup you can't @ every one`);
|
||||
if (message.content.toLowerCase().includes('@here')) return message.reply(`Holup you can't @ here`);
|
||||
message.channel.send(`${sayArgs.slice(2).join(" ")}`);
|
||||
} else {
|
||||
return message.reply("you cant do that only staff can").catch(e => console.log(e));
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
const conf = require('../../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: 'townhall',
|
||||
description: "say command for mods and admins",
|
||||
async execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
if (currentServer.staff.includes(message.author.id) || message.member.roles.cache.find(r => server.staffRoles.includes(r.name))) {
|
||||
|
||||
if (args[1] == 'end') {
|
||||
if (args[2] == 'confirm') {
|
||||
require('../../events/voicestateupdate').members[message.guild.id] = [];
|
||||
message.channel.send("townHall meeting members have been removed.")
|
||||
} else {
|
||||
message.channel.send("are you sure you want to end the townhall meeting? this will remove all members even ones that may still be currently in the voice channel.\nto confirm please do `" + currentServer.prefix + "townhall end confirm`.")
|
||||
}
|
||||
} else {
|
||||
let members = require('../../events/voicestateupdate').members[message.guild.id];
|
||||
let mpos = 0;
|
||||
let mEmbed = new Discord.MessageEmbed()
|
||||
.setColor(conf.colour.ok)
|
||||
.setTitle('Members that have Joined Townhall Vc')
|
||||
.setURL(conf.domain + '/server/' + message.guild.id + '/townhall')
|
||||
.setAuthor(conf.bot.name, conf.bot.logo, conf.bot.url)
|
||||
.setDescription('when the townhall meeting ends remember to do `' + currentServer.prefix + 'townhall end` otherwise users from the previous meeting will show up.')
|
||||
.setThumbnail(message.guild.iconURL() || conf.domain + '/logo.png')
|
||||
.setTimestamp()
|
||||
.setFooter('TownHall Meeting');
|
||||
|
||||
await members.forEach(async(member) => {
|
||||
let isStaff;
|
||||
if (client.guilds.cache.get(currentServer.id).members.cache.get(member).roles.cache.find(r => currentServer.staffRoles.includes(r.name))) {
|
||||
isStaff = 'yes';
|
||||
} else {
|
||||
isStaff = 'no';
|
||||
};
|
||||
mpos++;
|
||||
await mEmbed.addField(`__${client.users.cache.get(member).tag}:__`, `__**id:**__ ${member}\n__**@:**__ <@!${member}>\n__**isStaff:**__ ${isStaff}\n__**Join Position:**__ ${mpos}`);
|
||||
})
|
||||
message.channel.send({ embed: mEmbed });
|
||||
};
|
||||
} else {
|
||||
return message.reply("you cant do that only staff can").catch(e => console.log(e));
|
||||
};
|
||||
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
const conf = require('../../../conf/conf.json');
|
||||
const User = require('../../../models/user');
|
||||
module.exports = {
|
||||
name: 'userinfo',
|
||||
description: "get information about someone on the server",
|
||||
async execute(message, args, Discord, currentServer, messageUser, client) {
|
||||
try {
|
||||
if (currentServer.staff.includes(message.author.id) || message.member.roles.cache.find(r => server.staffRoles.includes(r.name))) {
|
||||
let theUser;
|
||||
if (message.mentions.users.first()) {
|
||||
theUser = message.mentions.users.first();
|
||||
} else {
|
||||
theUser = message.author;
|
||||
};
|
||||
let currentUser = await User.findOne({ userid: theUser, guildid: message.guild.id });
|
||||
if (currentUser == null) return message.channel.send("that user inst in the database");
|
||||
|
||||
const userInfoEmbed = new Discord.MessageEmbed()
|
||||
.setAuthor(`${conf.bot.name}`, `${conf.bot.logo}`)
|
||||
.setTitle('user info')
|
||||
.setURL(conf.domain)
|
||||
.setColor(conf.colour.ok)
|
||||
.setThumbnail(theUser.avatarURL())
|
||||
.addField("__**user:**__", "<@!" + currentUser.id + "> (" + currentUser.id + ")")
|
||||
.addField("__**strikes:**__", "`" + currentUser.strike.toString() + "`")
|
||||
.addField("__**note:**__", "`" + currentUser.note + "`")
|
||||
.setTimestamp()
|
||||
.setFooter(`Requested by ${message.member.displayName} | react with a ❌ to delete`, `${message.author.displayAvatarURL()}`);
|
||||
message.channel.send(userInfoEmbed).then(async sentMsg => {
|
||||
await sentMsg.react('❌');
|
||||
sentMsg.awaitReactions(async(reaction, user) => {
|
||||
if (reaction.emoji.name === '❌') await sentMsg.delete();
|
||||
});
|
||||
/*
|
||||
await sentMsg.react('❌');
|
||||
const filter = (reaction, user) => ['❌'].includes(reaction.emoji.name) && user.id === message.author.id;
|
||||
const [reaction] = await sentMsg.awaitReactions(filter, { maxMatches: 1 });
|
||||
if (reaction.emoji.name === '❌') await sentMsg.delete();
|
||||
*/
|
||||
});
|
||||
} else {
|
||||
return message.reply("you cant do that only staff can").catch(e => console.log(e));
|
||||
};
|
||||
} catch (err) {
|
||||
message.channel.send("an error happened. are they in the \"database\"?")
|
||||
}
|
||||
}
|
||||
}
|
86
src/bot/commands/reactionrole.ts
Normal file
86
src/bot/commands/reactionrole.ts
Normal file
|
@ -0,0 +1,86 @@
|
|||
import { Client, ChatInputCommandInteraction, PermissionFlagsBits, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
//@ts-expect-error
|
||||
import YALAS from 'mcstatusbot-logger';
|
||||
|
||||
import * as AddReactionRole from './reactionrole/add';
|
||||
import * as RemoveReactionRole from './reactionrole/remove';
|
||||
import { GuildInstance } from "../../database/schemas/Guild";
|
||||
import { UserInstance } from "../../database/schemas/User";
|
||||
|
||||
const data = {
|
||||
serverOnly: false,
|
||||
guildId: null,
|
||||
allowSuspendedUserAccess: true,
|
||||
command: new SlashCommandBuilder()
|
||||
.setName('reactionrole')
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageRoles)
|
||||
.setDescription("setup reaction roles for your server")
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('add')
|
||||
.setDescription("Add a reaction role to your channel")
|
||||
.addChannelOption(option =>
|
||||
option.setName('channel')
|
||||
.setDescription('The channel in which you want to add a reaction')
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption(option =>
|
||||
option.setName('emoji')
|
||||
.setDescription('The reaction emoji')
|
||||
.setRequired(true)
|
||||
)
|
||||
.addMentionableOption(option =>
|
||||
option.setName('role')
|
||||
.setDescription('The @ mention of the role you want to add')
|
||||
.setRequired(true)
|
||||
)
|
||||
.addBooleanOption(o =>
|
||||
o.setName('reaction-remove')
|
||||
.setDescription("allow users to remove the role by unreacting")
|
||||
.setRequired(true)
|
||||
)
|
||||
|
||||
)
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('remove')
|
||||
.setDescription("remove a reaction role")
|
||||
.addChannelOption(option =>
|
||||
option.setName('channel')
|
||||
.setDescription('The channel in which you want to remove a reaction')
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption(o =>
|
||||
o
|
||||
.setName('emoji')
|
||||
.setDescription("the reaction emoji")
|
||||
.setRequired(true)
|
||||
)
|
||||
|
||||
)
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('edit-embed')
|
||||
.setDescription("Edit the message embed sent with the list of reaction roles")
|
||||
.addChannelOption(option =>
|
||||
option.setName('channel')
|
||||
.setDescription('The channel in which you want to edit the embed for')
|
||||
.setRequired(true)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export { data };
|
||||
|
||||
|
||||
export async function chatInputCommand(client: Client, interaction: ChatInputCommandInteraction, guild: GuildInstance, user: UserInstance) {
|
||||
switch (interaction.options.getSubcommand()) {
|
||||
case 'add':
|
||||
AddReactionRole.chatInputCommand(client, interaction, guild, user)
|
||||
break;
|
||||
case 'remove':
|
||||
RemoveReactionRole.chatInputCommand(client, interaction, guild, user)
|
||||
break;
|
||||
}
|
||||
}
|
161
src/bot/commands/reactionrole/add.ts
Normal file
161
src/bot/commands/reactionrole/add.ts
Normal file
|
@ -0,0 +1,161 @@
|
|||
import { Client, ChatInputCommandInteraction, Role, GuildChannelResolvable, PermissionsBitField } from "discord.js";
|
||||
|
||||
import parseEmoji from "../../functions/parseEmoji";
|
||||
import { schemas } from "../../../database";
|
||||
//@ts-expect-error
|
||||
import YALAS from 'mcstatusbot-logger';
|
||||
|
||||
import SendReactionRoleEmbed from "../../functions/SendReactionRoleEmbed";
|
||||
import { GuildInstance } from "../../../database/schemas/Guild";
|
||||
import { UserInstance } from "../../../database/schemas/User";
|
||||
|
||||
|
||||
export async function chatInputCommand(client: Client, interaction: ChatInputCommandInteraction, guild: GuildInstance, user: UserInstance) {
|
||||
if (!interaction.guild) return interaction.reply("must be done in discord server");
|
||||
|
||||
const botMember = interaction.guild.members.me;
|
||||
if (!botMember) {
|
||||
YALAS.error("reactionrole add: bot in guild null");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//get and validate channel
|
||||
const channel = interaction.options.getChannel('channel');
|
||||
if (channel == undefined) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Channel Not Found",
|
||||
description: "The selected channel could not be found please try again."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
if (channel.type !== 0) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "That Will Not Work",
|
||||
description: "The selected channel is not a text channel please select a text channel."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
const botPermSM = botMember.permissionsIn((channel as GuildChannelResolvable)).toArray();
|
||||
if (botPermSM && !botPermSM.includes('SendMessages')) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Missing permission",
|
||||
description: "you need to give me the send message permission in the selected channel."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//check bot has manage roles perm
|
||||
const botPermMR = botMember.permissions.has(PermissionsBitField.Flags.ManageRoles);
|
||||
if (!botPermMR) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Missing permission",
|
||||
description: "you need to give me the Manage Roles permission in this server."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//get and validate emoji
|
||||
const emoji = interaction.options.getString('emoji');
|
||||
let cleanEmoji = parseEmoji(emoji);
|
||||
if (cleanEmoji == null) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Invalid Emoji",
|
||||
description: "The selected emoji is invalid please doublecheck it."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//get and validate role
|
||||
const role = interaction.options.getMentionable('role');
|
||||
if (!(role instanceof Role)) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Invalid Role",
|
||||
description: "The selected role is not a valid role"
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
//check bot can assign role
|
||||
const botHighestRole = botMember.roles.highest;
|
||||
if (role.position >= botHighestRole.position) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Missing permission",
|
||||
description: `The role <@&${role.id}> is higher than my role so I can't assign it to users.`
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
await interaction.deferReply();
|
||||
//check emoji does net exist for reaction in channel
|
||||
try {
|
||||
const reactionRole = await schemas['ReactionRole'].findOne({
|
||||
where: {
|
||||
guild: guild.id,
|
||||
channel: channel.id,
|
||||
role: role.id,
|
||||
reaction: cleanEmoji,
|
||||
}
|
||||
});
|
||||
|
||||
if (reactionRole !== null) {
|
||||
return interaction.editReply({
|
||||
embeds: [{
|
||||
title: "Reaction Role Exists",
|
||||
description: "This emoji is already setup to give selected role in selected channel."
|
||||
}]
|
||||
});
|
||||
}
|
||||
} catch (err: any) {
|
||||
YALAS.error(err)
|
||||
YALAS.error(err.stack || err);
|
||||
return interaction.editReply("error when checking for existing reaction role in database.");
|
||||
}
|
||||
|
||||
const allowReactionRemove: boolean = interaction.options.getBoolean('reaction-remove') || false;
|
||||
|
||||
try {
|
||||
await schemas['ReactionRole'].create({
|
||||
guild: guild.id,
|
||||
channel: channel.id,
|
||||
role: role.id,
|
||||
reaction: cleanEmoji,
|
||||
reactionRemove: allowReactionRemove
|
||||
});
|
||||
} catch (err: any) {
|
||||
YALAS.error(err.stack || err);
|
||||
return interaction.editReply("error when saving reaction role to database.");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const textChannel = interaction.guild?.channels.cache.get(channel.id);
|
||||
if (textChannel === undefined || textChannel.type !== 0) return;
|
||||
const embed = await SendReactionRoleEmbed(textChannel, guild.id, channel.id);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [{
|
||||
title: "Success",
|
||||
description: "The reaction role has been created and a new embed sent.\n-# Note you will need to delete the old embed"
|
||||
}]
|
||||
});
|
||||
} catch (err: any) {
|
||||
YALAS.error(err.stack || err);
|
||||
return interaction.editReply("error when making reaction role embed.");
|
||||
}
|
||||
|
||||
}
|
113
src/bot/commands/reactionrole/remove.ts
Normal file
113
src/bot/commands/reactionrole/remove.ts
Normal file
|
@ -0,0 +1,113 @@
|
|||
import { GuildInstance } from "../../../database/schemas/Guild";
|
||||
import { UserInstance } from "../../../database/schemas/User";
|
||||
|
||||
import { Client, ChatInputCommandInteraction, Role, GuildChannelResolvable, TextChannel } from "discord.js";
|
||||
|
||||
import parseEmoji from "../../functions/parseEmoji";
|
||||
import { schemas } from "../../../database";
|
||||
//@ts-expect-error
|
||||
import YALAS from 'mcstatusbot-logger';
|
||||
|
||||
import SendReactionRoleEmbed from "../../functions/SendReactionRoleEmbed";
|
||||
|
||||
|
||||
|
||||
export async function chatInputCommand(client: Client, interaction: ChatInputCommandInteraction, guild: GuildInstance, user: UserInstance) {
|
||||
if (!interaction.guild) return interaction.reply("must be done in discord server");
|
||||
|
||||
//get and validate channel
|
||||
const channel = interaction.options.getChannel('channel');
|
||||
if (channel == undefined) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Channel Not Found",
|
||||
description: "The selected channel could not be found please try again."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
if (channel.type !== 0) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "That Will Not Work",
|
||||
description: "The selected channel is not a text channel please select a text channel."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
const botPermissionsIn = interaction.guild.members.me?.permissionsIn((channel as GuildChannelResolvable)).toArray();
|
||||
if (botPermissionsIn && !botPermissionsIn.includes('SendMessages')) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Missing permission",
|
||||
description: "you need to give me the send message permission in the selected channel."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
//get and validate emoji
|
||||
const emoji = interaction.options.getString('emoji');
|
||||
|
||||
let cleanEmoji = parseEmoji(emoji);
|
||||
if (cleanEmoji == null) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "Invalid Emoji",
|
||||
description: "The selected emoji is invalid please doublecheck it."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
await interaction.deferReply();
|
||||
try {
|
||||
const reactionRoles = await schemas['ReactionRole'].findAll({
|
||||
where: {
|
||||
guild: guild.id,
|
||||
channel: channel.id,
|
||||
reaction: cleanEmoji,
|
||||
},
|
||||
raw: true
|
||||
});
|
||||
|
||||
if (reactionRoles.length <= 0) {
|
||||
return interaction.editReply({
|
||||
embeds: [{
|
||||
title: "Reaction Role(s) Doesn't Exists",
|
||||
description: "This reaction could not be found in the selected channel."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
for (const rr of reactionRoles) {
|
||||
try {
|
||||
await schemas['ReactionRole'].destroy({ where: { id: rr.id } });
|
||||
} catch (err: any) {
|
||||
YALAS.error(err.stack || err);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} catch (err: any) {
|
||||
YALAS.error(err)
|
||||
YALAS.error(err.stack || err);
|
||||
return interaction.editReply("error when getting and deleting reaction role in database.");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const textChannel = interaction.guild?.channels.cache.get(channel.id);
|
||||
if (textChannel === undefined || textChannel.type !== 0) return;
|
||||
const embed = await SendReactionRoleEmbed(textChannel, guild.id, channel.id);
|
||||
|
||||
return interaction.editReply({
|
||||
embeds: [{
|
||||
title: "Success",
|
||||
description: "The reaction role(s) have been removed and a new embed sent.\n-# Note you will need to delete the old embed"
|
||||
}]
|
||||
});
|
||||
} catch (err: any) {
|
||||
YALAS.error(err.stack || err);
|
||||
return interaction.editReply("error when making reaction role embed.");
|
||||
}
|
||||
|
||||
}
|
48
src/bot/commands/setprefix.ts
Normal file
48
src/bot/commands/setprefix.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
import { Client, ChatInputCommandInteraction, PermissionFlagsBits, SlashCommandBuilder } from "discord.js";
|
||||
|
||||
import { schemas } from "../../database/index";
|
||||
//@ts-expect-error
|
||||
import YALAS from 'mcstatusbot-logger';
|
||||
import { GuildInstance } from "../../database/schemas/Guild";
|
||||
import { UserInstance } from "../../database/schemas/User";
|
||||
|
||||
|
||||
const data = {
|
||||
serverOnly: false,
|
||||
guildId: null,
|
||||
allowSuspendedUserAccess: true,
|
||||
command: new SlashCommandBuilder()
|
||||
.setName('setprefix')
|
||||
.setDescription("sets the message prefix for your server")
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild)
|
||||
.addStringOption(o =>
|
||||
o.setName('prefix')
|
||||
.setDescription("the prefix eg . or !")
|
||||
.setRequired(true)
|
||||
)
|
||||
}
|
||||
|
||||
export { data };
|
||||
|
||||
|
||||
export async function chatInputCommand(client: Client, interaction: ChatInputCommandInteraction, guild: GuildInstance, user: UserInstance) {
|
||||
const prefix = interaction.options.getString('prefix');
|
||||
if (prefix == undefined) return;
|
||||
const prefixLower = prefix.toLowerCase();
|
||||
|
||||
if (prefix.length > 3) return interaction.reply("the is to long, limit is 3");
|
||||
if (guild.prefix === prefixLower) return interaction.reply("the prefix `" + guild.prefix + "` has been set");
|
||||
|
||||
|
||||
try {
|
||||
await schemas['Guild'].update({
|
||||
prefix: prefixLower
|
||||
}, {
|
||||
where: { id: guild.id }
|
||||
});
|
||||
return interaction.reply("the prefix `" + prefixLower + "` has been set");
|
||||
} catch (err: any) {
|
||||
YALAS.error(err.stack || err);
|
||||
return interaction.reply("failed to update prefix.");
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
const conf = require('../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: 'error',
|
||||
async exe(client, Discord, error) {
|
||||
//one day i will saves these to a file or something
|
||||
console.log(error)
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
const conf = require('../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: 'guildMemberAdd',
|
||||
async exe(client, Discord, member) {
|
||||
try {
|
||||
member.guild.fetchInvites().then(guildInvites => {
|
||||
const inviteGuild = invites;
|
||||
const invite = guildInvites.find(i => inviteGuild.get(i.code).uses < i.uses);
|
||||
const inviter = client.users.cache.get(invite.inviter.id);
|
||||
|
||||
const inviteLogEmbed = {
|
||||
color: `${conf.colour.ok}`,
|
||||
title: 'invite',
|
||||
url: `${conf.domain}`,
|
||||
author: {
|
||||
name: conf.bot.name
|
||||
},
|
||||
thumbnail: {
|
||||
url: `${conf.server.logo}`,
|
||||
},
|
||||
description: `${member.user.discriminator} (${member.user.id}) joined using invite code ${invite.code} from ${inviter.tag} (${inviter.id}). Invite was used ${invite.uses} times since its creation.`,
|
||||
fields: [{
|
||||
name: 'Member joined:',
|
||||
value: `${member.user.discriminator} (${member.user.id})`,
|
||||
},
|
||||
{
|
||||
name: 'Inviter:',
|
||||
value: `${inviter.tag} (${inviter.id})`,
|
||||
},
|
||||
{
|
||||
name: 'Invite Code:',
|
||||
value: `[https://discord.gg/${invite.code}](https://discord.gg/${invite.code})`,
|
||||
},
|
||||
{
|
||||
name: 'Invite Uses:',
|
||||
value: `${invite.uses}`,
|
||||
},
|
||||
{
|
||||
name: 'Time of Invite:',
|
||||
value: `${new Date()}`,
|
||||
}
|
||||
],
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
text: 'moderation logs'
|
||||
},
|
||||
};
|
||||
member.guild.channels.cache.get(conf.server.channels.modLogs).send({ embed: inviteLogEmbed });
|
||||
invites = guildInvites;
|
||||
});
|
||||
} catch (error) {
|
||||
require('../conf/functions.js').reportError(client, conf, "guildMemberAdd", error, { name: null, id: null })
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
const conf = require('../../conf/conf.json')
|
||||
|
||||
const getGuild = require('../../funcs/getserver');
|
||||
const getUser = require('../../funcs/getuser');
|
||||
|
||||
function addCmd(message) {
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
name: 'message',
|
||||
async exe(client, Discord, message) {
|
||||
if (message.author.bot || !message.guild) return;
|
||||
|
||||
let currentServer = await getGuild(message);
|
||||
let messageUser = await getUser(message);
|
||||
if (currentServer == null) return;
|
||||
|
||||
['caps', 'swearfilter'].forEach(addon => {
|
||||
require(`../addons/${addon}`)(message, currentServer, messageUser, client);
|
||||
})
|
||||
|
||||
//eval command
|
||||
if (message.content.toLowerCase().startsWith("--eval")) {
|
||||
const evalargs = message.content.split(" ").slice(1);
|
||||
|
||||
function clean(text) {
|
||||
if (typeof(text) === "string") {
|
||||
return text.replace(/`/g, "`" + String.fromCharCode(8203)).replace(/@/g, "@" + String.fromCharCode(8203));
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
if (message.author.id !== conf.owner) return message.channel.send("no you cant do that, only <@!522534458071449620> can.");
|
||||
if (message.author.id == conf.owner) {
|
||||
try {
|
||||
const code = evalargs.join(" ");
|
||||
let evaled = eval(code);
|
||||
if (typeof evaled !== "string") {
|
||||
evaled = require("util").inspect(evaled);
|
||||
}
|
||||
message.channel.send(clean(evaled), { code: "xl" });
|
||||
} catch (err) {
|
||||
message.channel.send(`\`ERROR\` \`\`\`xl\n${clean(err)}\n\`\`\``);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let args = message.content.toLowerCase().substring(currentServer.prefix.length).split(" ");
|
||||
if (!message.content.startsWith(currentServer.prefix)) return;
|
||||
|
||||
//otr commands
|
||||
if (message.author.id == conf.cwh11) {
|
||||
require('../../funcs/otr').otrCommand(message, args, Discord, currentServer, messageUser, client);
|
||||
};
|
||||
|
||||
//dynamic get command name or prefix
|
||||
if (client.commands.has(args[0])) {
|
||||
try {
|
||||
client.commands.get(args[0]).execute(message, args, Discord, currentServer, messageUser, client);
|
||||
addCmd(message);
|
||||
} catch (error) {
|
||||
message.reply('there was an error with that command!');
|
||||
};
|
||||
} else if (client.commands.find(command => command.aliases && command.aliases.includes(args[0]))) {
|
||||
try {
|
||||
client.commands.find(command => command.aliases && command.aliases.includes(args[0])).execute(message, args, Discord, currentServer, messageUser, client);
|
||||
addCmd(message);
|
||||
} catch (error) {
|
||||
message.reply('there was an error with that command!');
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
const Server = require('../../models/server');
|
||||
module.exports = {
|
||||
name: 'messageReactionAdd',
|
||||
async exe(client, Discord, reaction, user) {
|
||||
|
||||
let currentServer = await Server.findOne({ id: reaction.message.guild.id });
|
||||
if (currentServer == null) return;
|
||||
|
||||
if (!reaction.message.guild || user.bot) return;
|
||||
if (reaction.message.partial) await reaction.message.fetch();
|
||||
if (reaction.partial) await reaction.fetch();
|
||||
let member = await reaction.message.guild.members.fetch(user.id);
|
||||
try {
|
||||
currentServer.reactionRoles.forEach(role => {
|
||||
if (reaction.message.channel.id == role.channelID) {
|
||||
if (reaction.emoji.name == role.emoji) {
|
||||
let rr = client.guilds.cache.get(reaction.message.guild.id).roles.cache.get(role.roleID);
|
||||
member.roles.add(rr).catch(e => console.log(e));
|
||||
};
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
return console.log(error)
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
const Server = require('../../models/server');
|
||||
const conf = require('../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: 'messageReactionRemove',
|
||||
async exe(client, Discord, reaction, user) {
|
||||
|
||||
let currentServer = await Server.findOne({ id: reaction.message.guild.id });
|
||||
if (currentServer == null) return;
|
||||
|
||||
if (!reaction.message.guild || user.bot) return;
|
||||
if (reaction.message.partial) await reaction.message.fetch();
|
||||
if (reaction.partial) await reaction.fetch();
|
||||
let member = await reaction.message.guild.members.fetch(user.id);
|
||||
try {
|
||||
currentServer.reactionRoles.forEach(role => {
|
||||
if (reaction.message.channel.id == role.channelID) {
|
||||
if (reaction.emoji.name == role.emoji) {
|
||||
let rr = client.guilds.cache.get(reaction.message.guild.id).roles.cache.get(role.roleID);
|
||||
|
||||
member.roles.remove(rr).catch(e => console.log(e));
|
||||
|
||||
};
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
return console.log(error)
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
const { green } = require('chalk');
|
||||
const conf = require('../../conf/conf.json');
|
||||
module.exports = {
|
||||
name: 'ready',
|
||||
async exe(client) {
|
||||
console.log(green('[bot]: ') + `${client.user.tag}` + " is online");
|
||||
console.log("Ready!");
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
const Server = require("../../models/server");
|
||||
const conf = require('../../conf/conf.json')
|
||||
|
||||
var members = [];
|
||||
module.exports = {
|
||||
members: members,
|
||||
name: 'voiceStateUpdate',
|
||||
async exe(client, Discord, oldMember, newMember) {
|
||||
try {
|
||||
let newUserChannel = newMember.channelID;
|
||||
let oldUserChannel = oldMember.channelID;
|
||||
const currentServer = await Server.findOne({ id: newMember.guild.id });
|
||||
if (currentServer == null) return;
|
||||
if (currentServer.channels.townhall == ' ' || currentServer.channels.townhallLogs == ' ') return;
|
||||
if (newUserChannel == currentServer.channels.townhall) {
|
||||
let isStaff;
|
||||
if (client.guilds.cache.get(currentServer.id).members.cache.get(newMember.id).roles.cache.find(r => currentServer.staffRoles.includes(r.name))) {
|
||||
isStaff = 'yes';
|
||||
} else {
|
||||
isStaff = 'no';
|
||||
};
|
||||
if (!members[newMember.guild.id]) {
|
||||
members[newMember.guild.id] = [];
|
||||
};
|
||||
if (!members[newMember.guild.id].includes(newMember.id)) {
|
||||
members[newMember.guild.id].push(newMember.id)
|
||||
};
|
||||
const e6 = {
|
||||
color: conf.colour.ok,
|
||||
title: 'User joinded Town hall vc',
|
||||
author: {
|
||||
name: client.users.cache.get(newMember.id).tag,
|
||||
icon_url: client.users.cache.get(newMember.id).avatarURL()
|
||||
},
|
||||
description: "a new member has joined the town hall VC.\nto get all members that have joined during this session do `" + currentServer.prefix + "townhall`.",
|
||||
fields: [{
|
||||
name: '**__name:**__',
|
||||
value: client.users.cache.get(newMember.id).tag,
|
||||
},
|
||||
{
|
||||
name: '__**id:**__',
|
||||
value: newMember.id,
|
||||
},
|
||||
{
|
||||
name: '__**@ mention**__',
|
||||
value: '<@!' + newMember.id + '>'
|
||||
},
|
||||
{
|
||||
name: '__**is staff**__',
|
||||
value: isStaff
|
||||
},
|
||||
{
|
||||
name: '__**join position:**__',
|
||||
value: members.length
|
||||
},
|
||||
],
|
||||
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
text: 'TownHall Meeting Log'
|
||||
},
|
||||
};
|
||||
|
||||
client.guilds.cache.get(currentServer.id).channels.cache.get(currentServer.channels.townhallLogs).send({ embed: e6 });
|
||||
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
}
|
59
src/bot/functions/BanReactionRoleHandler.ts
Normal file
59
src/bot/functions/BanReactionRoleHandler.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
import { Client, MessageReaction, PartialMessageReaction, User, PartialUser, Guild, Role, GuildMember } from "discord.js";
|
||||
import { schemas } from "../../database";
|
||||
//@ts-expect-error
|
||||
import * as YALAS from 'mcstatusbot-logger';
|
||||
export default async function ReactionRoleAddHandler(reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser) {
|
||||
|
||||
const emoji: string | null = reaction.emoji.id ?? reaction.emoji.name;
|
||||
const guild: Guild | null = reaction.message.guild;
|
||||
const channelId: string = reaction.message.channelId;
|
||||
|
||||
if (guild === null || emoji === null) return YALAS.error("failed to find guild");
|
||||
|
||||
|
||||
async function getRole(roleId: string) {
|
||||
if (!guild) return null;
|
||||
let role: Role | null | undefined = guild.roles.cache.get(roleId);
|
||||
if (role) return role
|
||||
try {
|
||||
role = await guild.roles.fetch(roleId);
|
||||
} catch (error) {
|
||||
YALAS.error('Error fetching role:');
|
||||
YALAS.error(error);
|
||||
return null;
|
||||
}
|
||||
if (role) return role
|
||||
return null;
|
||||
}
|
||||
|
||||
const reactionRoles = await schemas['ReactionRole'].findAll({
|
||||
where: {
|
||||
guild: guild.id,
|
||||
channel: channelId,
|
||||
reaction: emoji,
|
||||
},
|
||||
raw: true
|
||||
});
|
||||
|
||||
for (const rRole of reactionRoles) {
|
||||
let role = await getRole(rRole.role);
|
||||
if (role == null) return YALAS.error("failed to find role '" + rRole.role + "' in guild '" + guild.id + "' ")
|
||||
|
||||
// Fetch role if not cached
|
||||
|
||||
|
||||
// Get the member from the user
|
||||
const member: GuildMember | null = guild.members.cache.get(user.id) || (await guild.members.fetch(user.id).catch(() => null));
|
||||
if (!member) return YALAS.error("Member not found in the guild '" + guild.id + "'");
|
||||
|
||||
|
||||
// Add the role to the member
|
||||
try {
|
||||
await member.roles.add(role);
|
||||
if (process.env.DEBUG === 'true') YALAS.info(`Added role "${role.name}" to user "${user.tag}".`);
|
||||
} catch (error) {
|
||||
YALAS.error("Error adding role '" + role.id + "' to user '" + user.id + "' for guild '" + guild.id + "'");
|
||||
YALAS.error(error);
|
||||
}
|
||||
}
|
||||
}
|
29
src/bot/functions/LookupGuild.ts
Normal file
29
src/bot/functions/LookupGuild.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { schemas } from "../../database";
|
||||
//@ts-expect-error
|
||||
import * as YALAS from 'mcstatusbot-logger';
|
||||
import { GuildAttributes } from "../../database/schemas/Guild";
|
||||
import { Guild } from "discord.js";
|
||||
|
||||
export default async function LookupGuild(guild: Guild | null): Promise<GuildAttributes | null> {
|
||||
if (guild == null) return null;
|
||||
try {
|
||||
let guildDoc = await schemas['Guild'].findOne({ where: { id: guild.id } });
|
||||
if (guildDoc !== null && guildDoc !== undefined) return guildDoc.dataValues;
|
||||
//TODO: implement a check to update guild name owner etc
|
||||
//TODO: make a webhook for defualt guild channel so can then be used and changed when needed for macro cmds
|
||||
|
||||
guildDoc = await schemas['Guild'].create({
|
||||
id: guild.id,
|
||||
name: guild.name,
|
||||
icon: guild.iconURL(),
|
||||
owner: guild.ownerId
|
||||
});
|
||||
|
||||
return guildDoc.dataValues;
|
||||
} catch (err: any) {
|
||||
|
||||
YALAS.error(err);
|
||||
YALAS.error(err.stack || err);
|
||||
return null;
|
||||
}
|
||||
}
|
25
src/bot/functions/LookupUser.ts
Normal file
25
src/bot/functions/LookupUser.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { User } from "discord.js";
|
||||
import { schemas } from "../../database";
|
||||
//@ts-expect-error
|
||||
import * as YALAS from 'mcstatusbot-logger';
|
||||
import { UserAttributes } from '../../database/schemas/User';
|
||||
export default async function LookupUser(user: User | null): Promise<UserAttributes | null> {
|
||||
if (user === null) return null
|
||||
let userDoc;
|
||||
try {
|
||||
userDoc = await schemas['User'].findOne({ where: { id: user.id } });
|
||||
if (userDoc !== null) return userDoc.dataValues;
|
||||
//TODO: implement check to update username avatar etc
|
||||
userDoc = await schemas['User'].create({
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
avatar: user.avatar,
|
||||
admin: false,
|
||||
});
|
||||
return userDoc.dataValues;
|
||||
} catch (err: any) {
|
||||
YALAS.error(err);
|
||||
YALAS.error(err.stack || err);
|
||||
return null;
|
||||
}
|
||||
}
|
33
src/bot/functions/PrefixCache.ts
Normal file
33
src/bot/functions/PrefixCache.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
export default class PrefixCache {
|
||||
private cache = new Map<string, string>();
|
||||
|
||||
// Add a value to the cache
|
||||
set(key: string, value: string): void {
|
||||
this.cache.set(key, value);
|
||||
}
|
||||
|
||||
// Retrieve a value from the cache
|
||||
get(key: string): string | null {
|
||||
return this.cache.get(key)??null;
|
||||
}
|
||||
|
||||
// Check if a key exists in the cache
|
||||
has(key: string): boolean {
|
||||
return this.cache.has(key);
|
||||
}
|
||||
|
||||
// Remove a key from the cache
|
||||
delete(key: string): void {
|
||||
this.cache.delete(key);
|
||||
}
|
||||
|
||||
// Clear the entire cache
|
||||
clear(): void {
|
||||
this.cache.clear();
|
||||
}
|
||||
|
||||
// Get the current size of the cache
|
||||
size(): number {
|
||||
return this.cache.size;
|
||||
}
|
||||
}
|
66
src/bot/functions/ReactionRoleAddHandler.ts
Normal file
66
src/bot/functions/ReactionRoleAddHandler.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
import { Client, MessageReaction, PartialMessageReaction, User, PartialUser, Guild, Role, GuildMember, TextChannel } from "discord.js";
|
||||
import { schemas } from "../../database";
|
||||
//@ts-expect-error
|
||||
import * as YALAS from 'mcstatusbot-logger';
|
||||
export default async function ReactionRoleAddHandler(reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser) {
|
||||
if (reaction.message.guild === undefined) return;
|
||||
const emoji: string | null = reaction.emoji.id ?? reaction.emoji.name;
|
||||
const guild: Guild | null = reaction.message.guild;
|
||||
const channel = reaction.message.channel;
|
||||
|
||||
if (guild === null || emoji === null) return YALAS.error("failed to find guild");
|
||||
|
||||
|
||||
async function getRole(roleId: string) {
|
||||
if (!guild) return null;
|
||||
let role: Role | null | undefined = guild.roles.cache.get(roleId);
|
||||
if (role) return role
|
||||
try {
|
||||
role = await guild.roles.fetch(roleId);
|
||||
} catch (error) {
|
||||
YALAS.error('Error fetching role:');
|
||||
YALAS.error(error);
|
||||
return null;
|
||||
}
|
||||
if (role) return role
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the member from the user
|
||||
const member: GuildMember | null = guild.members.cache.get(user.id) || (await guild.members.fetch(user.id).catch(() => null));
|
||||
if (!member) return YALAS.error("Member not found in the guild '" + guild.id + "'");
|
||||
|
||||
|
||||
const reactionRoles = await schemas['ReactionRole'].findAll({
|
||||
where: {
|
||||
guild: guild.id,
|
||||
channel: channel.id,
|
||||
reaction: emoji,
|
||||
},
|
||||
raw: true
|
||||
});
|
||||
|
||||
for (const rRole of reactionRoles) {
|
||||
let role = await getRole(rRole.role);
|
||||
if (role == null) return YALAS.error("failed to find role '" + rRole.role + "' in guild '" + guild.id + "' ")
|
||||
|
||||
//TODO: mod channel logs ad role error etc
|
||||
// Add the role to the member
|
||||
try {
|
||||
await member.roles.add(role);
|
||||
if (process.env.DEBUG === 'true') YALAS.info(`Added role "${role.name}" to user "${user.tag}".`);
|
||||
} catch (error) {
|
||||
|
||||
//TODO: implement ignore reaction reomve when using this
|
||||
//reaction.users.remove(user.id);
|
||||
//@ts-expect-error
|
||||
const errUsrMsg = await channel.send(`Sorry <@!${user.id}>, that did not work please try again later or ask a moderator.`);
|
||||
|
||||
setTimeout(() => {
|
||||
errUsrMsg.delete().catch((e: any) => null);
|
||||
}, 3500);
|
||||
YALAS.error("Error adding role '" + role.id + "' to user '" + user.id + "' for guild '" + guild.id + "'");
|
||||
YALAS.error(error);
|
||||
}
|
||||
}
|
||||
}
|
66
src/bot/functions/ReactionRoleRemoveHandler.ts
Normal file
66
src/bot/functions/ReactionRoleRemoveHandler.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
import { Client, MessageReaction, PartialMessageReaction, User, PartialUser, Guild, Role, GuildMember, TextChannel, flatten } from "discord.js";
|
||||
import { schemas } from "../../database";
|
||||
//@ts-expect-error
|
||||
import * as YALAS from 'mcstatusbot-logger';
|
||||
export default async function ReactionRoleRemoveHandler(reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser) {
|
||||
if (reaction.message.guild === undefined) return;
|
||||
const emoji: string | null = reaction.emoji.id ?? reaction.emoji.name;
|
||||
const guild: Guild | null = reaction.message.guild;
|
||||
const channel = reaction.message.channel;
|
||||
|
||||
if (guild === null || emoji === null) return YALAS.error("failed to find guild");
|
||||
|
||||
|
||||
async function getRole(roleId: string) {
|
||||
if (!guild) return null;
|
||||
let role: Role | null | undefined = guild.roles.cache.get(roleId);
|
||||
if (role) return role
|
||||
try {
|
||||
role = await guild.roles.fetch(roleId);
|
||||
} catch (error) {
|
||||
YALAS.error('Error fetching role:');
|
||||
YALAS.error(error);
|
||||
return null;
|
||||
}
|
||||
if (role) return role
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the member from the user
|
||||
const member: GuildMember | null = guild.members.cache.get(user.id) || (await guild.members.fetch(user.id).catch(() => null));
|
||||
if (!member) return YALAS.error("Member not found in the guild '" + guild.id + "'");
|
||||
|
||||
|
||||
const reactionRoles = await schemas['ReactionRole'].findAll({
|
||||
where: {
|
||||
guild: guild.id,
|
||||
channel: channel.id,
|
||||
reaction: emoji,
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
for (let rRole of reactionRoles) {
|
||||
let role = await getRole(rRole.dataValues.role);
|
||||
if (role == null) return YALAS.error("failed to find role '" + rRole.role + "' in guild '" + guild.id + "' ")
|
||||
|
||||
if (rRole.dataValues.reactionRemove === false) continue;
|
||||
|
||||
// Add the role to the member
|
||||
try {
|
||||
await member.roles.remove(role);
|
||||
if (process.env.DEBUG === 'true') YALAS.info(`Added role "${role.name}" to user "${user.tag}".`);
|
||||
} catch (error) {
|
||||
reaction.users.remove(user.id);
|
||||
//@ts-expect-error
|
||||
const errUsrMsg = await channel.send(`Sorry <@!${user.id}>, that did not work please try again later or ask a moderator.`);
|
||||
|
||||
setTimeout(() => {
|
||||
errUsrMsg.delete().catch((e: any) => null);
|
||||
}, 3500);
|
||||
YALAS.error("Error removingW role '" + role.id + "' to user '" + user.id + "' for guild '" + guild.id + "'");
|
||||
YALAS.error(error);
|
||||
}
|
||||
}
|
||||
//TODO: log roles added to user/errors
|
||||
}
|
71
src/bot/functions/SendReactionRoleEmbed.ts
Normal file
71
src/bot/functions/SendReactionRoleEmbed.ts
Normal file
|
@ -0,0 +1,71 @@
|
|||
import { EmbedBuilder, ColorResolvable, TextChannel } from 'discord.js';
|
||||
import { schemas } from '../../database';
|
||||
import { ReactionRoleInstance } from '../../database/schemas/ReactionRole';
|
||||
|
||||
|
||||
|
||||
function isOnlyNumbers(str: string): boolean {
|
||||
return /^\d+$/.test(str);
|
||||
}
|
||||
interface GroupedReactionRole {
|
||||
reaction: string;
|
||||
roles: string[]
|
||||
}
|
||||
function groupReactionRoles(reactionRoles: ReactionRoleInstance[]): GroupedReactionRole[] {
|
||||
return reactionRoles.reduce((acc, item) => {
|
||||
const { reaction, role } = item;
|
||||
|
||||
// Find if the reaction already exists in the accumulator
|
||||
let existing = acc.find(group => group.reaction === reaction);
|
||||
|
||||
if (existing) {
|
||||
existing.roles.push(role);
|
||||
} else {
|
||||
// Otherwise, create a new group for this reaction
|
||||
acc.push({
|
||||
reaction,
|
||||
roles: [role],
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, [] as GroupedReactionRole[]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default async function SendReactionRoleEmbed(roleChannel: TextChannel, guildId: string, channelId: string) {
|
||||
|
||||
let config = { where: { guild: guildId, channel: channelId }, raw: true };
|
||||
let reactionRoleEmbedConfig = await schemas['ReactionRoleEmbed'].findOne(config);
|
||||
if (reactionRoleEmbedConfig == null) {
|
||||
reactionRoleEmbedConfig = await schemas['ReactionRoleEmbed'].create({ guild: guildId, channel: channelId }, { raw: true });
|
||||
}
|
||||
|
||||
if (reactionRoleEmbedConfig === null) return { title: "error" };
|
||||
let reactionRoles = await schemas['ReactionRole'].findAll(config);
|
||||
let groupedReactionRoles = groupReactionRoles(reactionRoles);
|
||||
//[[icon]] [[role]]
|
||||
|
||||
let description: string = "";
|
||||
|
||||
for (const rr of groupedReactionRoles) {
|
||||
let roleRow = reactionRoleEmbedConfig.listItemTemplate.replace('[[icon]]', isOnlyNumbers(rr.reaction) ? `<:emoji:${rr.reaction}>` : rr.reaction).replace('[[roles]]', rr.roles.map(r => `<@&${r}>`).join(reactionRoleEmbedConfig.roleSeparator));
|
||||
description += roleRow + '\n';
|
||||
}
|
||||
|
||||
// inside a command, event listener, etc.
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor((reactionRoleEmbedConfig.color as ColorResolvable))
|
||||
.setTitle(reactionRoleEmbedConfig.title)
|
||||
.setURL(reactionRoleEmbedConfig.icon)
|
||||
//.setAuthor({ name: 'Some name', iconURL: 'https://i.imgur.com/AfFp7pu.png', url: 'https://discord.js.org' })
|
||||
.setDescription(description.substring(0, 4096))
|
||||
//.setFooter({ text: 'Some footer text here', iconURL: 'https://i.imgur.com/AfFp7pu.png' });
|
||||
|
||||
|
||||
const reactionRoleEmbedMsg = await roleChannel.send({ embeds: [embed] });
|
||||
for (const reactionRole of reactionRoles) {
|
||||
await reactionRoleEmbedMsg.react(reactionRole.reaction);
|
||||
}
|
||||
return reactionRoleEmbedMsg;
|
||||
}
|
11
src/bot/functions/parseEmoji.ts
Normal file
11
src/bot/functions/parseEmoji.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
export default function parseEmoji(input: string | null): string | null {
|
||||
|
||||
if (input === null || input == ' ' || input === ' ') return null;
|
||||
const customEmojiMatch = input.match(/^<:.*:(\d+)>$/);
|
||||
if (customEmojiMatch) return customEmojiMatch[1];
|
||||
|
||||
const unicodeEmojiRegex = /^[\p{Emoji_Presentation}\p{Emoji}\uFE0F]+$/u;
|
||||
if (unicodeEmojiRegex.test(input)) return input;
|
||||
|
||||
return null;
|
||||
}
|
60
src/bot/handlers/InteractionCreate.ts
Normal file
60
src/bot/handlers/InteractionCreate.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import { Client, Interaction, ChatInputCommandInteraction, User } from "discord.js";
|
||||
import { schemas } from '../../database/index';
|
||||
//@ts-expect-error
|
||||
import YALAS from 'mcstatusbot-logger';
|
||||
import LookupUser from "../functions/LookupUser";
|
||||
import LookupGuild from "../functions/LookupGuild";
|
||||
|
||||
|
||||
|
||||
async function chatInputCommand(client: Client, interaction: ChatInputCommandInteraction) {
|
||||
if (!client.commands.has(interaction.commandName)) return YALAS.warn("no command found for interaction: " + interaction.commandName);
|
||||
|
||||
if (interaction.guild===null) return interaction.reply("only works in discord servers sorry.");
|
||||
|
||||
//get user from db
|
||||
const user = await LookupUser(interaction.user)
|
||||
if (user == null) return interaction.reply({
|
||||
embeds: [{ title: "could not get your user info", description: "we could not get or create your user info to the bots database." }]
|
||||
});
|
||||
|
||||
|
||||
//get discord guild from db
|
||||
const guild = await LookupGuild(interaction.guild);
|
||||
if (guild == null) return interaction.reply({
|
||||
embeds: [{ title: "could not get discord server", description: "we could not get or create your discord server to the bots database." }]
|
||||
})
|
||||
|
||||
|
||||
const command = client.commands.get(interaction.commandName);
|
||||
|
||||
if (command.data.allowSuspendedUserAccess == false && user.suspended == true) {
|
||||
return interaction.reply({
|
||||
embeds: [{
|
||||
title: "You Are Suspended",
|
||||
description: "Your account has been suspended/blocked from using this bot."
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await command.chatInputCommand(client, interaction, guild, user);
|
||||
} catch (err: any) {
|
||||
YALAS.error("could not run command");
|
||||
YALAS.error(err.stack || err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export default async function InteractionCreate(client: Client, interaction: Interaction) {
|
||||
if (interaction.member && interaction.member.user.bot) return;
|
||||
|
||||
//slash command
|
||||
if (interaction.isChatInputCommand()) return chatInputCommand(client, interaction);
|
||||
//modal/form
|
||||
//if (interaction.isModalSubmit()) return modalSubmit(client, interaction, guild, user);
|
||||
|
||||
}
|
74
src/bot/handlers/MessageCreate.ts
Normal file
74
src/bot/handlers/MessageCreate.ts
Normal file
|
@ -0,0 +1,74 @@
|
|||
import { Client, Guild, Message } from "discord.js";
|
||||
import MessageMacro from "../messageHandler/plugins/MesageMacro";
|
||||
import { schemas } from "../../database";
|
||||
import LookupUser from "../functions/LookupUser";
|
||||
//@ts-expect-error
|
||||
import * as YALAS from 'mcstatusbot-logger';
|
||||
import { UserAttributes } from "../../database/schemas/User";
|
||||
import { GuildAttributes } from "../../database/schemas/Guild";
|
||||
import LookupGuild from "../functions/LookupGuild";
|
||||
import { MessageCreateOptions } from "../../../types/MessageCreate";
|
||||
|
||||
|
||||
import PrefixCache from "../functions/PrefixCache";
|
||||
|
||||
|
||||
function splitAndRemovePrefix(prefix: string, content: string): string[] {
|
||||
if (content.startsWith(prefix)) {
|
||||
content = content.slice(prefix.length).trim();
|
||||
}
|
||||
return content.split(/\s+/);
|
||||
}
|
||||
|
||||
|
||||
const guildPrefixs = new PrefixCache();
|
||||
|
||||
|
||||
async function getGuildPrefix(guild: Guild) {
|
||||
|
||||
let p = guildPrefixs.get(guild.id);
|
||||
console.log("p: "+p)
|
||||
if (p !== null) return p;
|
||||
|
||||
let guildDoc: GuildAttributes | null = await schemas['Guild'].findOne({
|
||||
where: { id: guild.id },
|
||||
attributes: ['prefix'],
|
||||
raw: true,
|
||||
});
|
||||
|
||||
if (guildDoc === null) {
|
||||
guildDoc = await LookupGuild(guild);
|
||||
if (guildDoc === null) {
|
||||
YALAS.error("MessageCreate: guild '" + guild.id + "' will not add to db");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
guildPrefixs.set(guild.id, guildDoc.prefix);
|
||||
p = guildDoc.prefix;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
async function GuildMsg(client: Client, msg: Message) {
|
||||
if (msg.guild === null) return;
|
||||
|
||||
const prefix: string | null = await getGuildPrefix(msg.guild);
|
||||
|
||||
//r
|
||||
if (prefix===null) return;
|
||||
if (!msg.content.toLowerCase().startsWith(prefix)) return;
|
||||
|
||||
const msgCmds: string[] = splitAndRemovePrefix(prefix, msg.content);
|
||||
try {
|
||||
await MessageMacro(client, msg, msgCmds);
|
||||
} catch (err: any) {
|
||||
YALAS.error("MessageCreate: failed to run message macro plugin");
|
||||
YALAS.error(err.stack || err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
export default async function MessageCreate(client: Client, msg: Message) {
|
||||
await GuildMsg(client, msg);
|
||||
return;
|
||||
}
|
36
src/bot/handlers/MessageReactionAdd.ts
Normal file
36
src/bot/handlers/MessageReactionAdd.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { Client, MessageReaction, PartialMessageReaction, User, PartialUser } from "discord.js";
|
||||
import ReactionRoleAddHandler from "../functions/ReactionRoleAddHandler";
|
||||
//@ts-expect-error
|
||||
import * as YALAS from 'mcstatusbot-logger';
|
||||
export default async function MessageReactionAdd(client: Client, reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser) {
|
||||
|
||||
if (reaction.partial) {
|
||||
console.log("reaction partial")
|
||||
try {
|
||||
await reaction.fetch();
|
||||
} catch (error) {
|
||||
YALAS.error('Something went wrong when fetching the message:', error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!reaction.message.guild) return;
|
||||
|
||||
|
||||
if (user.partial) {
|
||||
console.log("user partial")
|
||||
try {
|
||||
await user.fetch();
|
||||
} catch (error) {
|
||||
YALAS.error('Something went wrong when fetching the user:', error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (user.id===client.user?.id) return;
|
||||
|
||||
await ReactionRoleAddHandler(reaction, user);
|
||||
|
||||
//TODO: ban role hndler
|
||||
//TODO: kick role handler
|
||||
|
||||
return;
|
||||
}
|
31
src/bot/handlers/MessageReactionRemove.ts
Normal file
31
src/bot/handlers/MessageReactionRemove.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import { Client, MessageReaction, PartialMessageReaction, User, PartialUser } from "discord.js";
|
||||
import ReactionRoleRemoveHandler from "../functions/ReactionRoleRemoveHandler";
|
||||
//@ts-expect-error
|
||||
import * as YALAS from 'mcstatusbot-logger';
|
||||
export default async function MessageReactionRemove(client: Client, reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser) {
|
||||
if (!reaction.message.guild) return;
|
||||
// When a reaction is received, check if the structure is partial
|
||||
if (reaction.partial) {
|
||||
console.log("reaction partial")
|
||||
try {
|
||||
await reaction.fetch();
|
||||
} catch (error) {
|
||||
YALAS.error('Something went wrong when fetching the message:', error);
|
||||
// Return as `reaction.message.author` may be undefined/null
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (user.partial) {
|
||||
console.log("user partial")
|
||||
try {
|
||||
await user.fetch();
|
||||
} catch (error) {
|
||||
YALAS.error('Something went wrong when fetching the user:', error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (user.id === client.user?.id) return;
|
||||
await ReactionRoleRemoveHandler(reaction, user);
|
||||
return;
|
||||
}
|
19
src/bot/handlers/Ready.ts
Normal file
19
src/bot/handlers/Ready.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { Client, ActivityType } from 'discord.js';
|
||||
//@ts-expect-error
|
||||
import YALAS from 'mcstatusbot-logger';
|
||||
|
||||
export default function Ready(client: Client) {
|
||||
console.log("Ready!");
|
||||
YALAS.success("The bot is up and running!");
|
||||
YALAS.info(`logged in as ${client.user?.username}#${client.user?.tag}`);
|
||||
|
||||
//TODO: have list of messages in const folder and cycle them allow super admins (ids list in env file) to add from web ui
|
||||
// Update activity every hour so that it doesn't expire
|
||||
|
||||
if (client.user) client.user.setActivity("you", { type: ActivityType.Watching });
|
||||
setInterval(() => {
|
||||
if (client.user) client.user.setActivity("you", { type: ActivityType.Watching });
|
||||
}, 3600000);
|
||||
|
||||
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
const { readdirSync } = require("fs");
|
||||
const chalk = require('chalk');
|
||||
module.exports = (client) => {
|
||||
const addons = readdirSync(__dirname + '/../addons/').filter((file) => file.endsWith(".js"));
|
||||
for (let addonFile of addons) {
|
||||
try {
|
||||
console.log(chalk.green('[addon handler]: ') + " found '" + addonFile + "'");
|
||||
} catch (error) {
|
||||
console.log(chalk.green('[addon handler]: ') + chalk.red('(error): ') + "unhandled error: " + error);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
const { readdirSync } = require("fs");
|
||||
const chalk = require('chalk');
|
||||
let chalkColour;
|
||||
module.exports = (client) => {
|
||||
readdirSync(__dirname + "/../commands/").forEach((dir) => {
|
||||
const commands = readdirSync(__dirname + `/../commands/${dir}/`).filter((file) => file.endsWith(".js"));
|
||||
for (let file of commands) {
|
||||
let cmd = require(__dirname + `/../commands/${dir}/${file}`);
|
||||
if (cmd.name && cmd.description) {
|
||||
switch (dir) {
|
||||
case 'fun':
|
||||
chalkColour = 'green'
|
||||
break;
|
||||
case 'moderaton':
|
||||
chalkColour = 'blue'
|
||||
break;
|
||||
case 'info':
|
||||
chalkColour = 'cyan'
|
||||
break;
|
||||
default:
|
||||
chalkColour = 'green'
|
||||
}
|
||||
try {
|
||||
client.commands.set(cmd.name, cmd);
|
||||
console.log(chalk.yellow('[command handler]: ') + chalk[chalkColour]('(' + dir + '): ') + "name: " + cmd.name + " path: " + `./commands/${dir}/${file}`);
|
||||
} catch (error) {
|
||||
console.log(chalk.yellow('[command handler]: ') + chalk.red('(command error): ') + "adding command. path: " + `./commands/${dir}/${file}`);
|
||||
console.log("eeer: " + error)
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
console.log(chalk.yellow('[command handler]: ') + chalk.red('(command error): ') + "command dosnt contain a name or description. path: " + `./commands/${dir}/${file}`);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
const chalk = require('chalk');
|
||||
const { readdirSync } = require("fs");
|
||||
const Discord = require('discord.js');
|
||||
module.exports = (client) => {
|
||||
const eventFiles = readdirSync(__dirname + '/../events/').filter(file => file.endsWith('.js'));
|
||||
for (const file of eventFiles) {
|
||||
const event = require(__dirname + `/../events/${file}`);
|
||||
client.on(event.name, async(...args) => event.exe(client, Discord, ...args));
|
||||
};
|
||||
}
|
44
src/bot/index.ts
Normal file
44
src/bot/index.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { readdirSync } from 'fs';
|
||||
import { Client, Collection, GatewayIntentBits, Interaction, Events, Partials } from 'discord.js';
|
||||
import Ready from './handlers/Ready';
|
||||
import InteractionCreate from './handlers/InteractionCreate';
|
||||
import MessageCreate from './handlers/MessageCreate';
|
||||
import MessageReactionAdd from './handlers/MessageReactionAdd';
|
||||
import MessageReactionRemove from './handlers/MessageReactionRemove';
|
||||
|
||||
const client = new Client({
|
||||
intents: [
|
||||
GatewayIntentBits.Guilds,
|
||||
GatewayIntentBits.GuildMembers,
|
||||
GatewayIntentBits.GuildMessageReactions,
|
||||
GatewayIntentBits.GuildMessages,
|
||||
GatewayIntentBits.MessageContent,
|
||||
GatewayIntentBits.GuildPresences
|
||||
],
|
||||
partials: [Partials.Message, Partials.Channel, Partials.Reaction],
|
||||
});
|
||||
|
||||
|
||||
//load in slash commands
|
||||
client.commands = new Collection();
|
||||
const commands: string[] = readdirSync(__dirname + '/commands').filter((file: string) => file.endsWith('.js') || file.endsWith('.ts'));
|
||||
|
||||
for (const c of commands) {
|
||||
const command = require(__dirname + '/commands/' + c);
|
||||
if (!command.data.command) continue;
|
||||
if (!command.data.command.name) continue;
|
||||
client.commands.set(command.data.command.name, command);
|
||||
}
|
||||
|
||||
|
||||
client.once(Events.ClientReady, () => Ready(client));
|
||||
client.on(Events.InteractionCreate, (interaction: Interaction) => InteractionCreate(client, interaction));
|
||||
client.on(Events.MessageCreate, (msg) => MessageCreate(client, msg))
|
||||
|
||||
client.on(Events.MessageReactionAdd, (reaction, user) => MessageReactionAdd(client, reaction, user))
|
||||
client.on(Events.MessageReactionRemove, (reaction, user) => MessageReactionRemove(client, reaction, user))
|
||||
|
||||
export async function login(): Promise<boolean> {
|
||||
await client.login(process.env.BOT_TOKEN);
|
||||
return true;
|
||||
}
|
37
src/bot/messageHandler/plugins/MesageMacro.ts
Normal file
37
src/bot/messageHandler/plugins/MesageMacro.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
import { CategoryChannel, Client, DMChannel, GuildBasedChannel, Message, NewsChannel, TextChannel, ThreadChannel } from "discord.js";
|
||||
import { UserAttributes } from "../../../database/schemas/User";
|
||||
import { GuildAttributes, GuildInstance } from "../../../database/schemas/Guild";
|
||||
import { MessageCreateOptions } from "../../../../types/MessageCreate";
|
||||
import { schemas } from "../../../database";
|
||||
import LookupGuild from "../../functions/LookupGuild";
|
||||
//@ts-expect-error
|
||||
import * as YALAS from 'mcstatusbot-logger';
|
||||
|
||||
export default async function MessageMacro(client: Client, msg: Message, msgCmds: string[]) {
|
||||
if (msg.guild === null) return;
|
||||
if (msg.member === null) return;
|
||||
|
||||
const guild: GuildAttributes | null = await LookupGuild(msg.guild);
|
||||
if (guild == null) return YALAS.error("MessageCreate guild null")
|
||||
|
||||
|
||||
|
||||
const msgMacroDoc = await schemas['MessageMacro'].findOne({
|
||||
where: {
|
||||
guild: guild.id,
|
||||
shortCode: msgCmds[0]
|
||||
}
|
||||
});
|
||||
if (msgMacroDoc === null) return;
|
||||
const msgMacro = msgMacroDoc.dataValues;
|
||||
|
||||
if (!msg.member.roles.cache.has(msgMacro.role)) return;
|
||||
if (msgMacro.deleteShortCode === true) msg.deletable ?? msg.delete().catch((err: any) => null);
|
||||
|
||||
let channel = msgMacro.channel === null ? msg.channel : await msg.guild.channels.fetch(msgMacro.channel);
|
||||
if (channel === null || channel === undefined) return;
|
||||
if (!(channel instanceof TextChannel || channel instanceof DMChannel || channel instanceof NewsChannel || channel instanceof ThreadChannel)) return;
|
||||
|
||||
await channel.send(msgMacro.message);
|
||||
return;
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"prefix": ".",
|
||||
"owner": "522534458071449620",
|
||||
"domain": "http://localhost:4758",
|
||||
"port": "4758",
|
||||
"cwh11": "276156203770314755",
|
||||
"colour": {
|
||||
"ok": "#ff0000",
|
||||
"error": "#ff5733"
|
||||
},
|
||||
"mainServer": {
|
||||
"invite": "https://discord.gg/52AugmVzjt",
|
||||
"id": "here"
|
||||
},
|
||||
"bot": {
|
||||
"name": "knightrider",
|
||||
"logo": "https://cdn.discordapp.com/icons/584484766997282836/337d9f62b88bc8d343be2bb3bc90292f.png",
|
||||
"url": "http://knightrider.invalidlag.com/me"
|
||||
},
|
||||
"webServer": {
|
||||
"port": 4758,
|
||||
"oauthURI": "here"
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const { User } = require('discord.js');
|
||||
|
||||
const User = require('../models/user');
|
||||
const Server = require('../models/server');
|
||||
const getServer = require('../funcs/getserver');
|
||||
module.exports = {
|
||||
reportError: function(client, conf, task, error, user) {
|
||||
const errorEmbed = {
|
||||
color: `${conf.colour.okError}`,
|
||||
title: 'Error',
|
||||
url: `${conf.domain}`,
|
||||
author: {
|
||||
name: conf.bot.name
|
||||
},
|
||||
thumbnail: {
|
||||
url: `${conf.server.logo}`,
|
||||
},
|
||||
description: `there has been an error executing somthing this will be somthing from a automated script or a member using the bot\nthe infromation below can be sensative **do not share** this with anyone unless you know what to hide:`,
|
||||
fields: [{
|
||||
name: '__**task:**__',
|
||||
value: `\`${task}\``,
|
||||
},
|
||||
{
|
||||
name: '__**Error**__',
|
||||
value: `\`${error}\``,
|
||||
},
|
||||
{
|
||||
name: '__**user who triggered it**__',
|
||||
value: `__name:__ \`${currentUser.userName}\`\n__id:__ \`${user.id}\``,
|
||||
}
|
||||
],
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
text: 'Owner Error Log'
|
||||
},
|
||||
};
|
||||
client.users.cache.get(conf.owner).send({ embed: errorEmbed });
|
||||
|
||||
},
|
||||
addCmd: async function(message) {
|
||||
let currentServer = await Server.findOne({ id: message.guild.id });
|
||||
currentServer.commandCount++;
|
||||
currentServer.save();
|
||||
},
|
||||
addstrike: async function(message) {
|
||||
let currentUser = await User.findOne({ id: message.author.id })
|
||||
if (currentUser == null) {
|
||||
await User.create({
|
||||
id: message.author.id,
|
||||
avatar: message.author.avatarURL()
|
||||
})
|
||||
currentUser = await User.findOne({ id: message.author.id })
|
||||
}
|
||||
currentUser.strike++;
|
||||
currentUser.save()
|
||||
},
|
||||
|
||||
otrCommand: async function(message, args, Discord, client) {
|
||||
if (message.author.id == conf.cwh11) {
|
||||
let server = getServer(message);
|
||||
if (server == null) return message.channel.send("this server isnt in the db");
|
||||
const annoncmentsChannel = client.channels.cache.get(server.channels.annoncments);
|
||||
switch (args[0]) {
|
||||
case 'ito':
|
||||
await message.delete().catch(e => message.channel.send("i cant auto delete the messag you sent have i got permission to send messages in <#" + message.channel.id + ">?"));
|
||||
annoncmentsChannel.send("@here Hey guys! Charlie is in the office. Join him in voice if you want.").catch(e => message.channel.send("i cant do that have i got permission to send messages in <#" + channels.annoncments + ">?"));
|
||||
break;
|
||||
case 'otrf':
|
||||
await message.delete().catch(e => message.channel.send("i cant auto delete the messag you sent have i got permission to send messages in <#" + message.channel.id + ">?"));
|
||||
annoncmentsChannel.send("@here Hey guys! Charlie is on the road in the Ford. Join him in voice if you want.").catch(e => message.channel.send("i cant do that have i got permission to send messages in <#" + channels.annoncments + ">?"));
|
||||
break;
|
||||
case 'otrs':
|
||||
await message.delete().catch(e => message.channel.send("i cant auto delete the messag you sent have i got permission to send messages in <#" + message.channel.id + ">?"));
|
||||
annoncmentsChannel.send("@here Hey guys! Charlie is on the road in the Subaru. Join him in voice if you want.").catch(e => message.channel.send("i cant do that have i got permission to send messages in <#" + channels.annoncments + ">?"));
|
||||
break;
|
||||
case 'otr11':
|
||||
await message.delete().catch(e => message.channel.send("i cant auto delete the messag you sent have i got permission to send messages in <#" + message.channel.id + ">?"));
|
||||
annoncmentsChannel.send("@here Hey guys! Charlie is on the road in his car. Join him in voice if you want.").catch(e => message.channel.send("i cant do that have i got permission to send messages in <#" + channels.annoncments + ">?"));
|
||||
break;
|
||||
case 'otr':
|
||||
await message.delete().catch(e => message.channel.send("i cant auto delete the messag you sent have i got permission to send messages in <#" + message.channel.id + ">?"));
|
||||
annoncmentsChannel.send("@here Hey guys! Charlie is on the road. Join him in voice if you want.").catch(e => message.channel.send("i cant do that have i got permission to send messages in <#" + channels.annoncments + ">?"));
|
||||
break;
|
||||
case 'olb':
|
||||
await message.delete().catch(e => message.channel.send("i cant auto delete the messag you sent have i got permission to send messages in <#" + message.channel.id + ">?"));
|
||||
annoncmentsChannel.send("@here Hey guys! Charlie is on the road. Join him in voice if you want.").catch(e => message.channel.send("i cant do that have i got permission to send messages in <#" + channels.annoncments + ">?"));
|
||||
break;
|
||||
case 'yts':
|
||||
await message.delete().catch(e => message.channel.send("i cant auto delete the messag you sent have i got permission to send messages in <#" + message.channel.id + ">?"));
|
||||
annoncmentsChannel.send("@here Hey guys! Charlie is streaming on YouTube: https://www.youtube.com/channel/UC7uWWizg0tmQ2R1kBkuDJHg").catch(e => message.channel.send("i cant do that have i got permission to send messages in <#" + channels.annoncments + ">?"));
|
||||
break;
|
||||
case 'ts':
|
||||
await message.delete().catch(e => message.channel.send("i cant auto delete the messag you sent have i got permission to send messages in <#" + message.channel.id + ">?"));
|
||||
annoncmentsChannel.send("@here Hey guys! Charlie is streaming on Twitch: https://www.twitch.tv/therealcwh11").catch(e => message.channel.send("i cant do that have i got permission to send messages in <#" + channels.annoncments + ">?"));
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
};
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"584494185453977622": {
|
||||
"roles": {
|
||||
"✅": "584487354194984981"
|
||||
}
|
||||
},
|
||||
|
||||
"790737726332600360": {
|
||||
"roles": {
|
||||
"📑": "783031927753801770",
|
||||
"💻": "791376525475315742",
|
||||
"🎧": "791376529233674310",
|
||||
"🖥": "791376533057962095",
|
||||
"📱": "791376535138467900",
|
||||
"🎮": "791376535474536458",
|
||||
"🔌": "791376537211371560"
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
"791381305111347231": {
|
||||
"roles": {
|
||||
"🚚": "595087305212035084",
|
||||
"🚜": "595086913430355973",
|
||||
"⛏️": "595087098604683277",
|
||||
"🗺️": "604424840807710721",
|
||||
"🚓": "691635977889906849",
|
||||
"🚗": "752217267600621578",
|
||||
"🏎️": "752217137728192543",
|
||||
"🔧": "595767995998011392",
|
||||
"⚙️": "860942666195927050"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
module.exports = {
|
||||
bot: {
|
||||
token: "here"
|
||||
},
|
||||
oauth: {
|
||||
clientId: "here",
|
||||
clientSecret: "here",
|
||||
redirectUri: "http://localhost:4758/dashboard",
|
||||
scope: "identify email guilds"
|
||||
},
|
||||
db: {
|
||||
URI: "here"
|
||||
}
|
||||
|
||||
}
|
48
src/database/index.ts
Normal file
48
src/database/index.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
import { Sequelize, DataTypes } from 'sequelize';
|
||||
//@ts-ignore
|
||||
import YALAS from 'mcstatusbot-logger';
|
||||
|
||||
import BanReaction from './schemas/BanReaction';
|
||||
import Guild from './schemas/Guild';
|
||||
import KickReaction from './schemas/KickReaction';
|
||||
import MessageMacro from './schemas/MessageMacro';
|
||||
import ReactionRole from './schemas/ReactionRole';
|
||||
import ReactionRoleEmbed from './schemas/ReactionRoleEmbed';
|
||||
import User from './schemas/User';
|
||||
|
||||
|
||||
if (!process.env.DB_URI) {
|
||||
YALAS.crash("A database uri must be provided.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const sequelize = new Sequelize(process.env.DB_URI);
|
||||
|
||||
const schemas = {
|
||||
BanRole: BanReaction(sequelize),
|
||||
Guild: Guild(sequelize),
|
||||
KickRole: KickReaction(sequelize),
|
||||
MessageMacro: MessageMacro(sequelize),
|
||||
ReactionRole: ReactionRole(sequelize),
|
||||
ReactionRoleEmbed: ReactionRoleEmbed(sequelize),
|
||||
User: User(sequelize)
|
||||
};
|
||||
|
||||
|
||||
export async function connect() {
|
||||
|
||||
YALAS.info("attempting to connect to db");
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
YALAS.success("Connection has been established successfully.");
|
||||
} catch (error: any) {
|
||||
YALAS.crash(error.stack || error);
|
||||
YALAS.crash("Unable to connect to the database");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
export { schemas };
|
42
src/database/schemas/BanReaction.ts
Normal file
42
src/database/schemas/BanReaction.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { DataTypes, Sequelize, Model, Optional } from 'sequelize';
|
||||
|
||||
export interface BanReactionAttributes {
|
||||
id: number;
|
||||
guild: string;
|
||||
channel: string;
|
||||
reaction: string;
|
||||
}
|
||||
|
||||
export interface BanReactionCreationAttributes extends Optional<BanReactionAttributes, 'id'> { }
|
||||
|
||||
export interface BanReactionInstance
|
||||
extends Model<BanReactionAttributes, BanReactionCreationAttributes>,
|
||||
BanReactionAttributes { }
|
||||
|
||||
|
||||
export default function BanRole(sequelize: Sequelize) {
|
||||
const BanReaction = sequelize.define<BanReactionInstance>('BanReaction', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
},
|
||||
guild: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
channel: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
reaction: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
});
|
||||
|
||||
// Sync the model with the database
|
||||
BanReaction.sync({ alter: true });
|
||||
|
||||
return BanReaction;
|
||||
}
|
74
src/database/schemas/Guild.ts
Normal file
74
src/database/schemas/Guild.ts
Normal file
|
@ -0,0 +1,74 @@
|
|||
import { DataTypes, Sequelize, Model, Optional } from 'sequelize';
|
||||
|
||||
export interface GuildAttributes {
|
||||
id: string;
|
||||
name: string;
|
||||
icon: string | null;
|
||||
owner: string;
|
||||
prefix: string;
|
||||
modAddOnEnableCaps: boolean;
|
||||
modAddOnEnableFilter: boolean;
|
||||
modAddOnEnableEmojiSpam: boolean;
|
||||
logChannel: boolean | null;
|
||||
webhookURI: string
|
||||
}
|
||||
|
||||
export interface GuildCreationAttributes extends Optional<GuildAttributes, 'id' | 'icon' | 'prefix' | 'modAddOnEnableCaps' | 'modAddOnEnableFilter' | 'modAddOnEnableEmojiSpam' | 'logChannel' | 'webhookURI'> { }
|
||||
|
||||
export interface GuildInstance
|
||||
extends Model<GuildAttributes, GuildCreationAttributes>,
|
||||
GuildAttributes { }
|
||||
|
||||
export default function Guild(sequelize: Sequelize) {
|
||||
const Guild = sequelize.define<GuildInstance>('Guild', {
|
||||
id: {
|
||||
type: DataTypes.STRING,
|
||||
primaryKey: true,
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
icon: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
owner: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
prefix: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
defaultValue: '.',
|
||||
},
|
||||
modAddOnEnableCaps: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
modAddOnEnableFilter: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
modAddOnEnableEmojiSpam: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
logChannel: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
webhookURI: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
}
|
||||
});
|
||||
|
||||
// Sync the model with the database
|
||||
Guild.sync({ alter: true });
|
||||
|
||||
return Guild;
|
||||
}
|
41
src/database/schemas/KickReaction.ts
Normal file
41
src/database/schemas/KickReaction.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
import { DataTypes, Sequelize, Model, Optional } from 'sequelize';
|
||||
|
||||
export interface KickReactionAttributes {
|
||||
id: number;
|
||||
guild: string;
|
||||
channel: string;
|
||||
reaction: string;
|
||||
}
|
||||
|
||||
export interface KickReactionCreationAttributes extends Optional<KickReactionAttributes, 'id'> { }
|
||||
|
||||
export interface KickReactionInstance
|
||||
extends Model<KickReactionAttributes, KickReactionCreationAttributes>,
|
||||
KickReactionAttributes { }
|
||||
|
||||
export default function KickRole(sequelize: Sequelize) {
|
||||
const KickReaction = sequelize.define<KickReactionInstance>('KickReaction', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
},
|
||||
guild: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
channel: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
reaction: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
});
|
||||
|
||||
// Sync the model with the database
|
||||
KickReaction.sync({ alter: true });
|
||||
|
||||
return KickReaction;
|
||||
}
|
63
src/database/schemas/MessageMacro.ts
Normal file
63
src/database/schemas/MessageMacro.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
import { DataTypes, Sequelize, Model, Optional } from 'sequelize';
|
||||
|
||||
export interface MessageMacroAttributes {
|
||||
id: number;
|
||||
guild: string;
|
||||
channel: string | null;
|
||||
shortCode: string;
|
||||
message: string;
|
||||
role: string;
|
||||
impersonate: boolean;
|
||||
deleteShortCode: boolean;
|
||||
}
|
||||
|
||||
export interface MessageMacroCreationAttributes extends Optional<MessageMacroAttributes, 'id'> { }
|
||||
|
||||
export interface MessageMacroInstance
|
||||
extends Model<MessageMacroAttributes, MessageMacroCreationAttributes>,
|
||||
MessageMacroAttributes { }
|
||||
|
||||
export default function MessageMacro(sequelize: Sequelize) {
|
||||
const MessageMacro = sequelize.define<MessageMacroInstance>('MessageMacro', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
},
|
||||
guild: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
channel: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
shortCode: {
|
||||
type: DataTypes.STRING(5),
|
||||
allowNull: false,
|
||||
},
|
||||
message: {
|
||||
type: DataTypes.STRING(2000),
|
||||
allowNull: false,
|
||||
},
|
||||
role: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
impersonate: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
deleteShortCode: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false,
|
||||
}
|
||||
});
|
||||
|
||||
// Sync the model with the database
|
||||
MessageMacro.sync({ alter: true });
|
||||
|
||||
return MessageMacro;
|
||||
}
|
52
src/database/schemas/ReactionRole.ts
Normal file
52
src/database/schemas/ReactionRole.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { DataTypes, Sequelize, Model, Optional } from 'sequelize';
|
||||
|
||||
export interface ReactionRoleAttributes {
|
||||
id: number;
|
||||
guild: string;
|
||||
channel: string;
|
||||
role: string;
|
||||
reaction: string;
|
||||
reactionRemove: boolean;
|
||||
}
|
||||
|
||||
export interface ReactionRoleCreationAttributes extends Optional<ReactionRoleAttributes, 'id' | 'reactionRemove'> { }
|
||||
|
||||
export interface ReactionRoleInstance
|
||||
extends Model<ReactionRoleAttributes, ReactionRoleCreationAttributes>,
|
||||
ReactionRoleAttributes { }
|
||||
|
||||
export default function ReactionRole(sequelize: Sequelize) {
|
||||
const ReactionRole = sequelize.define<ReactionRoleInstance>('ReactionRole', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
},
|
||||
guild: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
channel: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
role: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
reaction: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
reactionRemove: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Sync the model with the database
|
||||
ReactionRole.sync({ alter: true });
|
||||
|
||||
return ReactionRole;
|
||||
}
|
66
src/database/schemas/ReactionRoleEmbed.ts
Normal file
66
src/database/schemas/ReactionRoleEmbed.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
import { flatten } from 'discord.js';
|
||||
import { DataTypes, Sequelize, Model, Optional } from 'sequelize';
|
||||
|
||||
export interface ReactionRoleEmbedAttributes {
|
||||
id: number;
|
||||
guild: string;
|
||||
channel: string;
|
||||
title: string;
|
||||
icon: string | null;
|
||||
color: string;
|
||||
roleSeparator: string;
|
||||
listItemTemplate: string;
|
||||
}
|
||||
|
||||
export interface ReactionRoleEmbedCreationAttributes extends Optional<ReactionRoleEmbedAttributes, 'id' | 'title' | 'icon' | 'color' | 'roleSeparator' | 'listItemTemplate'> { }
|
||||
|
||||
export interface ReactionRoleEmbedInstance
|
||||
extends Model<ReactionRoleEmbedAttributes, ReactionRoleEmbedCreationAttributes>,
|
||||
ReactionRoleEmbedAttributes { }
|
||||
|
||||
export default function ReactionRoleEmbed(sequelize: Sequelize) {
|
||||
const ReactionRoleEmbed = sequelize.define<ReactionRoleEmbedInstance>('ReactionRoleEmbed', {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
},
|
||||
guild: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
channel: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
title: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
defaultValue: "Reaction Roles",
|
||||
},
|
||||
icon: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
color: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
defaultValue: "#ff0000",
|
||||
},
|
||||
roleSeparator: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
defaultValue: ', '
|
||||
},
|
||||
listItemTemplate: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
defaultValue: "[[icon]] - [[roles]]",
|
||||
},
|
||||
});
|
||||
|
||||
// Synchronize the model with the database
|
||||
ReactionRoleEmbed.sync({ alter: true });
|
||||
|
||||
return ReactionRoleEmbed;
|
||||
}
|
45
src/database/schemas/User.ts
Normal file
45
src/database/schemas/User.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { DataTypes, Sequelize, Model, Optional } from 'sequelize';
|
||||
|
||||
export interface UserAttributes {
|
||||
id: string;
|
||||
username: string;
|
||||
avatar: string | null;
|
||||
admin: boolean;
|
||||
suspended: boolean;
|
||||
}
|
||||
|
||||
export interface UserCreationAttributes extends Optional<UserAttributes, 'id' | 'avatar' | 'suspended'> { }
|
||||
|
||||
export interface UserInstance extends Model<UserAttributes, UserCreationAttributes>, UserAttributes { }
|
||||
|
||||
export default function defineUser(sequelize: Sequelize) {
|
||||
const User = sequelize.define<UserInstance>('User', {
|
||||
id: {
|
||||
type: DataTypes.STRING,
|
||||
primaryKey: true,
|
||||
},
|
||||
username: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
avatar: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
admin: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
suspended: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
});
|
||||
|
||||
// Sync the model with the database (optional in production)
|
||||
User.sync({ alter: true });
|
||||
|
||||
return User;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
const { version, repository: { url } } = require('../../../../package.json');
|
||||
const { domain, prefix, mainServer: { invite } } = require('../../../conf/conf.json');
|
||||
module.exports = {
|
||||
name: '/api',
|
||||
dynamic: false,
|
||||
async exe(client, req, res) {
|
||||
try {
|
||||
res.status(200).json({ defaultPrefix: prefix, doamin: domain, version: version, mainGuild: invite, github: url.replace('.git', '') });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).json({ error: "500 - some error", message: "report it if it happens again" });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const fetch = require('node-fetch');
|
||||
const config = require('../../../conf/conf.json')
|
||||
const User = require('../../../models/userdashboard');
|
||||
const dbc = require('discord-bitfield-calculator')
|
||||
const token = require('../../../conf/tokens');
|
||||
const Server = require('../../../models/server');
|
||||
const randomString = require("randomstring").generate({
|
||||
length: 33,
|
||||
charset: 'alphabetic'
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
name: '/dashboard',
|
||||
dynamic: false,
|
||||
async exe(client, req, res) {
|
||||
// try {
|
||||
if (req.query.code) {
|
||||
let oath;
|
||||
let userInfo;
|
||||
let userGuilds = [];
|
||||
let guilds = [];
|
||||
let theAccessCode = randomString;
|
||||
|
||||
//access discord oauth2 and get nececry data
|
||||
await fetch('https://discord.com/api/oauth2/token', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams({
|
||||
client_id: token.oauth.clientId,
|
||||
client_secret: token.oauth.clientSecret,
|
||||
grant_type: 'authorization_code',
|
||||
redirect_uri: token.oauth.redirectUri,
|
||||
code: req.query.code,
|
||||
scope: token.oauth.scope,
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
}).then(discordRes => discordRes.json()).then(info => oath = info);
|
||||
|
||||
//fetch user info from OAuth2 token
|
||||
await fetch('https://discord.com/api/users/@me', {
|
||||
headers: {
|
||||
authorization: `${oath.token_type} ${oath.access_token}`,
|
||||
},
|
||||
}).then(async userRes => {
|
||||
userInfo = await userRes.json();
|
||||
});
|
||||
|
||||
//fetch guilds from OAuth2 token
|
||||
await fetch('https://discord.com/api/users/@me/guilds', {
|
||||
headers: {
|
||||
authorization: `${oath.token_type} ${oath.access_token}`,
|
||||
},
|
||||
})
|
||||
.then(async guildRes => {
|
||||
userGuilds = await guildRes.json()
|
||||
});
|
||||
|
||||
//if the access code was used/expired (from browser refresh) redirect without code and try use cookeis
|
||||
if (userInfo.message == '401: Unauthorized') return res.redirect('/dashboard');
|
||||
if (userGuilds.message == '401: Unauthorized') return res.redirect('/dashboard');
|
||||
|
||||
let botGuilds = await client.guilds.cache.map(guild => guild.id)
|
||||
//loop though oauth2 guilds and push guild info for matching guilds to 'guilds' array
|
||||
await userGuilds.forEach(async(userGuild) => {
|
||||
let currentServer = await Server.findOne({ id: userGuild.id })
|
||||
//handle servers only the user is in
|
||||
if (currentServer == null) {
|
||||
if (userGuild.owner == true) {
|
||||
guilds.push({ id: userGuild.id, name: userGuild.name, icon: `https://cdn.discordapp.com/icons/${userGuild.id}/${userGuild.icon}.webp`, mutual: false, userPermission: 'owner' });
|
||||
} else {
|
||||
if (dbc.permissions(userGuild.permissions_new).includes('MANAGE_GUILD')) {
|
||||
guilds.push({ id: userGuild.id, name: userGuild.name, icon: `https://cdn.discordapp.com/icons/${userGuild.id}/${userGuild.icon}.webp`, mutual: false, userPermission: 'MANAGE_GUILD' });
|
||||
};
|
||||
};
|
||||
//handle servers the bot and user are in
|
||||
} else {
|
||||
if (userGuild.owner == true) {
|
||||
guilds.push({ id: userGuild.id, name: userGuild.name, icon: `https://cdn.discordapp.com/icons/${userGuild.id}/${userGuild.icon}.webp`, mutual: true, userPermission: 'owner' });
|
||||
} else {
|
||||
if (client.guilds.cache.get(currentServer.id).members.cache.get(userInfo.id).roles.cache.find(r => currentServer.staffRoles.includes(r.name))) {
|
||||
guilds.push({ id: userGuild.id, name: userGuild.name, icon: `https://cdn.discordapp.com/icons/${userGuild.id}/${userGuild.icon}.webp`, mutual: true, userPermission: 'staffrole' });
|
||||
} else {
|
||||
currentServer.staff.forEach(userid => {
|
||||
if (userInfo.id == userid) {
|
||||
guilds.push({ id: userGuild.id, name: userGuild.name, icon: `https://cdn.discordapp.com/icons/${userGuild.id}/${userGuild.icon}.webp`, mutual: true, userPermission: 'staffid' });
|
||||
} else if (dbc.permissions(userGuild.permissions_new).includes('MANAGE_GUILD')) {
|
||||
guilds.push({ id: userGuild.id, name: userGuild.name, icon: `https://cdn.discordapp.com/icons/${userGuild.id}/${userGuild.icon}.webp`, mutual: true, userPermission: 'MANAGE_GUILD' });
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
delete botGuilds;
|
||||
|
||||
let currentUser = await User.findOne({ userId: userInfo.id });
|
||||
if (currentUser == null) {
|
||||
await User.create({
|
||||
userId: userInfo.id,
|
||||
userName: userInfo.username,
|
||||
discriminator: userInfo.discriminator || '0000',
|
||||
avatar: `https://cdn.discordapp.com/avatars/${userInfo.id}/${userInfo.avatar}.png`,
|
||||
accessCodes: [{ browser: req.headers['user-agent'], code: randomString }],
|
||||
guilds: guilds
|
||||
});
|
||||
currentUser = await User.findOne({ userId: userInfo.id });
|
||||
} else {
|
||||
let gotCorrectAccessCode = false;
|
||||
if (res.locals.cookie.accesscode) {
|
||||
await currentUser.accessCodes.forEach(async(accessCode) => {
|
||||
if (res.locals.cookie.accesscode == accessCode.code) {
|
||||
gotCorrectAccessCode = await true;
|
||||
theAccessCode = res.locals.cookie.accesscode;
|
||||
}
|
||||
});
|
||||
};
|
||||
if (gotCorrectAccessCode == false) {
|
||||
currentUser.accessCodes.push({ browser: req.headers['user-agent'], code: randomString });
|
||||
theAccessCode = randomString;
|
||||
};
|
||||
currentUser.userName = userInfo.username;
|
||||
currentUser.avatar = `https://cdn.discordapp.com/avatars/${userInfo.id}/${userInfo.avatar}.png`;
|
||||
currentUser.guilds = guilds;
|
||||
currentUser.save();
|
||||
};
|
||||
|
||||
res.cookie('id', currentUser.userId, { expires: new Date(253402300000000), httpOnly: true }).cookie('accesscode', theAccessCode, { expires: new Date(253402300000000), httpOnly: true }).status(200).render('dashboard/index.ejs', { currentUser: currentUser, guilds: currentUser.guilds });
|
||||
|
||||
} else if (req.query.error) {
|
||||
console.log("req query error: " + req.query.error)
|
||||
await res.status(500).render('500.ejs');
|
||||
|
||||
} else if (res.locals.cookie.id && res.locals.cookie.accesscode) {
|
||||
const currentUser = await User.findOne({ userId: res.locals.cookie.id });
|
||||
if (currentUser == null) return res.redirect('/login?nouser');
|
||||
|
||||
let hasAccess = false;
|
||||
await currentUser.accessCodes.forEach(async(userCode) => {
|
||||
if (res.locals.cookie.accesscode == userCode.code) {
|
||||
|
||||
hasAccess = true;
|
||||
return res.cookie('id', currentUser.userId, { expires: new Date(253402300000000), httpOnly: true }).cookie('accesscode', res.locals.cookie.accesscode, { expires: new Date(253402300000000), httpOnly: true }).render('dashboard/index.ejs', { user: { name: currentUser.userName, tag: currentUser.discriminator, avatar: currentUser.avatar }, currentUser: currentUser, guilds: currentUser.guilds });
|
||||
};
|
||||
});
|
||||
if (hasAccess == false) return res.redirect('/login?ninvalidcode');
|
||||
} else if (!res.locals.cookie.id || !res.locals.cookie.accesscode) return res.redirect('/login?nocookies');
|
||||
|
||||
/*
|
||||
} catch (error) {
|
||||
console.log(chalk.red('[express get]: ') + "there was an error with dashboard.js\nerror: " + error);
|
||||
return res.status(500).render('500.ejs');
|
||||
};
|
||||
*/
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const Server = require('../../../models/server')
|
||||
const Userdashboard = require('../../../models/userdashboard')
|
||||
const conf = require('../../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: '/server/:serverid/filter',
|
||||
dynamic: true,
|
||||
async exe(client, req, res) {
|
||||
try {
|
||||
if (!res.locals.cookie.id || !res.locals.cookie.accesscode) {
|
||||
return res.redirect(conf.domain + "/login")
|
||||
}
|
||||
let currentUser = await Userdashboard.findOne({ userId: res.locals.cookie.id })
|
||||
let currentServer = await Server.findOne({ id: req.params.serverid })
|
||||
if (currentServer == null) return res.render('404.ejs')
|
||||
let gAccess = false;
|
||||
await currentUser.guilds.forEach(async (guild) => {
|
||||
if (guild.id == currentServer.id) {
|
||||
gAccess = true;
|
||||
if (guild.userPermission == 'owner' || guild.userPermission == 'MANAGE_GUILD' || currentServer.staff.includes(currentUser.userId)) {
|
||||
let hasAccess = false;
|
||||
await currentUser.accessCodes.forEach(async(userCode) => {
|
||||
if (res.locals.cookie.accesscode == userCode.code) {
|
||||
|
||||
hasAccess = true;
|
||||
return res.cookie('id', currentUser.userId, { expires: new Date(253402300000000), httpOnly: true }).cookie('accesscode', res.locals.cookie.accesscode, { expires: new Date(253402300000000), httpOnly: true }).render('dashboard/filter.ejs', { domain: conf.domain, user: { id: currentUser.userId, accesscode: res.locals.cookie.accesscode }, currentUser: currentUser, currentServer: currentServer });
|
||||
};
|
||||
});
|
||||
if (hasAccess == false) return res.redirect('/login?ninvalidcode');
|
||||
};
|
||||
};
|
||||
});
|
||||
if (gAccess == false) {
|
||||
return res.status(401).render('error.ejs', { errorMessage: null, error: "you do not have access to the admin dashboard if you are a member of staff tell the bot owner" })
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
// require('../../../conf/functions.js').reportError(client, conf, "/api/reaction-error", error, { name: null, id: req.body.userid })
|
||||
res.status(500).render('error.ejs', { errorMessage: error, error: "there has been an issue with your request please try again, if this continuous report it at http://knightrider.rf.gd/er/admin.php" })
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
module.exports = {
|
||||
name: '/dash/message',
|
||||
async exe(client, req, res) {
|
||||
try {
|
||||
let usersDB = JSON.parse(fs.readFileSync('./././database/users.json', 'utf8'));
|
||||
if (!req.query.tmpPassWord) {
|
||||
res.redirect("http://idiotlanparty.com/oauth")
|
||||
}
|
||||
if (usersDB[req.query.userid].admin == true) {
|
||||
if (req.query.tmpPassWord == usersDB[req.query.userid].tmpPassWord) {
|
||||
res.render('admin-message.ejs', { userInfo: { id: req.query.userid, username: req.query.username, avatar: req.query.userAvatar }, tmpPassWord: req.query.tmpPassWord })
|
||||
} else {
|
||||
await res.status(401).render('error.ejs', { errorMessage: null, error: "you do not have access please login again to regenrate your temporary local oath key", userInfo: { id: req.query.userid, username: req.query.username, avatar: req.query.userAvatar } })
|
||||
}
|
||||
|
||||
} else if (usersDB[userInfo.id].admin == false) {
|
||||
await res.status(401).render('error.ejs', { errorMessage: null, error: "you do not have access to the admin dashboard if you are a member of staff fill out http://knightrider.rf.gd/er/admin.php", userInfo: { id: req.query.userid, username: req.query.userame, avatar: req.query.userAvatar } })
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
require('../../../conf/functions.js').reportError(client, conf, "/api/reaction-error", error, { name: null, id: req.body.userid })
|
||||
res.status(500).render('error.ejs', { errorMessage: error, error: "there has been an issue with your request please try again, if this continuous report it at http://knightrider.rf.gd/er/admin.php" })
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const Server = require('../../../models/server');
|
||||
const Userdashboard = require('../../../models/userdashboard');
|
||||
const conf = require('../../../conf/conf.json');
|
||||
module.exports = {
|
||||
name: '/server/:serverid/reactionroles',
|
||||
dynamic: true,
|
||||
async exe(client, req, res) {
|
||||
try {
|
||||
if (!res.locals.cookie.id || !res.locals.cookie.accesscode) {
|
||||
return res.redirect(conf.domain + "/login")
|
||||
}
|
||||
let currentUser = await Userdashboard.findOne({ userId: res.locals.cookie.id })
|
||||
if (currentUser == null) return res.render('404.ejs')
|
||||
let currentServer = await Server.findOne({ id: req.params.serverid })
|
||||
if (currentServer == null) return res.render('404.ejs')
|
||||
let gAccess = false;
|
||||
await currentUser.guilds.forEach(async (guild) => {
|
||||
if (guild.id == currentServer.id) {
|
||||
gAccess = true;
|
||||
if (guild.userPermission == 'owner' || guild.userPermission == 'MANAGE_GUILD' || currentServer.staff.includes(currentUser.userId)) {
|
||||
let hasAccess = false;
|
||||
let listedRoles = [];
|
||||
let listedChannels = [];
|
||||
let server = await client.guilds.cache.get(currentServer.id);
|
||||
let user = await server.members.fetch(currentUser.userId);
|
||||
//push server roles to array
|
||||
server.roles.cache.map((role) => listedRoles.push({ id: role.id, name: role.name }));
|
||||
//push only channels user can see to array
|
||||
server.channels.cache.filter(c => c.type == 'text').forEach(channel => {
|
||||
if (server.channels.cache.get(channel.id).permissionsFor(user).has(['SEND_MESSAGES', 'VIEW_CHANNEL'])) listedChannels.push({ name: channel.name, id: channel.id });
|
||||
});
|
||||
await currentUser.accessCodes.forEach(async(userCode) => {
|
||||
if (res.locals.cookie.accesscode == userCode.code) {
|
||||
hasAccess = true;
|
||||
return res.cookie('id', currentUser.userId, { expires: new Date(253402300000000), httpOnly: true }).cookie('accesscode', res.locals.cookie.accesscode, { expires: new Date(253402300000000), httpOnly: true }).render('dashboard/reactionroles.ejs', { domain: conf.domain, server: { channels: listedChannels, roles: listedRoles }, user: { id: currentUser.userId, accesscode: res.locals.cookie.accesscode }, currentUser: currentUser, currentServer: currentServer });
|
||||
};
|
||||
});
|
||||
if (hasAccess == false) return res.redirect('/login?ninvalidcode');
|
||||
};
|
||||
};
|
||||
});
|
||||
if (gAccess == false) {
|
||||
return res.status(401).render('error.ejs', { errorMessage: null, error: "you do not have access to the admin dashboard if you are a member of staff tell the bot owner" })
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
res.status(500).render('error.ejs', { errorMessage: error, error: "there has been an issue with your request please try again, if this continuous report it at http://knightrider.rf.gd/er/admin.php" })
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const Server = require('../../../models/server')
|
||||
const Userdashboard = require('../../../models/userdashboard')
|
||||
const conf = require('../../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: '/server/:serverid/filter',
|
||||
dynamic: true,
|
||||
async exe(client, req, res) {
|
||||
try {
|
||||
if (!res.locals.cookie.id || !res.locals.cookie.accesscode) {
|
||||
return res.redirect(conf.domain + "/login")
|
||||
}
|
||||
let currentUser = await Userdashboard.findOne({ userId: res.locals.cookie.id })
|
||||
if (currentUser == null) return res.redirect('/login');
|
||||
let currentServer = await Server.findOne({ id: req.params.serverid })
|
||||
if (currentServer == null) return res.render('404.ejs');
|
||||
let gAccess = false;
|
||||
let hasAccess = false;
|
||||
|
||||
await currentUser.guilds.forEach(async (guild) => {
|
||||
if (guild.id == currentServer.id) {
|
||||
gAccess = true;
|
||||
if (guild.userPermission == 'owner' || guild.userPermission == 'MANAGE_GUILD' || currentServer.staff.includes(currentUser.userId)) {
|
||||
await currentUser.accessCodes.forEach(async(userCode) => {
|
||||
if (res.locals.cookie.accesscode == userCode.code) {
|
||||
hasAccess = true;
|
||||
const memberCount = await client.guilds.cache.get(currentServer.id).memberCount;
|
||||
return res.cookie('id', currentUser.userId, { expires: new Date(253402300000000), httpOnly: true }).cookie('accesscode', res.locals.cookie.accesscode, { expires: new Date(253402300000000), httpOnly: true }).render('dashboard/server.ejs', { domain: conf.domain, user: { id: currentUser.userId, accesscode: res.locals.cookie.accesscode }, currentUser: currentUser, currentServer: currentServer, memberCount: memberCount });
|
||||
};
|
||||
});
|
||||
if (hasAccess == false) return res.redirect('/login?ninvalidcode');
|
||||
}
|
||||
};
|
||||
});
|
||||
if (gAccess == false) {
|
||||
return res.status(401).render('error.ejs', { errorMessage: null, error: "you do not have access to the admin dashboard if you are a member of staff tell the bot owner" })
|
||||
}
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
res.status(500).render('error.ejs', { errorMessage: error, error: "there has been an issue with your request please try again, if this continuous report it at http://knightrider.rf.gd/er/admin.php" })
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
module.exports = {
|
||||
name: '/er',
|
||||
exe(client, conf, req, res) {
|
||||
res.render('er/er.ejs')
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
const { webServer: { oauthURI } } = require('../../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: '/login',
|
||||
dynamic: false,
|
||||
exe(client, req, res) {
|
||||
res.redirect(oauthURI)
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const conf = require('../../../conf/conf.json')
|
||||
module.exports = {
|
||||
name: '/',
|
||||
dynamic: false,
|
||||
exe(client, req, res) {
|
||||
res.render('index.ejs', { bot: { name: conf.bot.name }, servers: client.guilds.cache.size, users: client.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0) });
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const chalk = require('chalk');
|
||||
const { readdirSync } = require("fs");
|
||||
module.exports = (client, webServer) => {
|
||||
|
||||
readdirSync(__dirname + '/../get/').forEach((dir) => {
|
||||
const getReqFiles = readdirSync(__dirname + `/../get/${dir}/`).filter((file) => file.endsWith(".js"));
|
||||
for (let file of getReqFiles) {
|
||||
let getReqFile = require(__dirname + `/../get/${dir}/${file}`);
|
||||
if (getReqFile.name) {
|
||||
try {
|
||||
if (getReqFile.dynamic == false) {
|
||||
webServer.get(getReqFile.name, async(...args) => getReqFile.exe(client, ...args));
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(chalk.cyan('[webserver get handler]: ') + chalk.red('(error): ') + "executing. path: " + `./get/${dir}/${file}`);
|
||||
continue;
|
||||
};
|
||||
} else {
|
||||
console.log(chalk.cyan('[webserver get handler]: ') + chalk.red('(error): ') + "get file dosnt contain a name or description. path: " + `./get/${dir}/${file}`);
|
||||
continue;
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
webServer.get('/server/:serverid', async(...args) => require('../get/dashboard/server').exe(client, ...args));
|
||||
webServer.get('/server/:serverid/filter', async(...args) => require('../get/dashboard/filter').exe(client, ...args));
|
||||
webServer.get('/server/:serverid/reactionroles', async(...args) => require('../get/dashboard/reactionroles').exe(client, ...args));
|
||||
|
||||
|
||||
webServer.get('*', (req, res) => {
|
||||
res.status(404).render('404.ejs');
|
||||
});
|
||||
console.log(chalk.cyan('[webserver]: ') + "loaded get request handler");
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const chalk = require('chalk');
|
||||
const { readdirSync } = require("fs");
|
||||
const conf = require('../../conf/conf.json');
|
||||
module.exports = (client, webServer) => {
|
||||
readdirSync(__dirname + '/../post/').forEach((dir) => {
|
||||
const postReqFiles = readdirSync(__dirname + `/../post/${dir}/`).filter((file) => file.endsWith(".js"));
|
||||
for (let file of postReqFiles) {
|
||||
let postReqFile = require(__dirname + `/../post/${dir}/${file}`);
|
||||
if (postReqFile.name) {
|
||||
try {
|
||||
webServer.post(postReqFile.name, async(...args) => postReqFile.exe(client, conf, ...args));
|
||||
} catch (error) {
|
||||
console.log(chalk.cyan('[webserver post handler]: ') + chalk.red('(error): ') + "executing. path: " + `./get/${dir}/${file}`);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
console.log(chalk.cyan('[webserver post handler]: ') + chalk.red('(error): ') + "post file dosnt contain a name or description. path: " + `./get/${dir}/${file}`);
|
||||
continue;
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
console.log(chalk.cyan('[webserver]: ') + "loaded post request handler");
|
||||
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const { version, repository: { url } } = require('../../../../package.json');
|
||||
const { domain, prefix, mainServer: { invite } } = require('../../../conf/conf.json');
|
||||
module.exports = {
|
||||
name: '/api',
|
||||
async exe(client, req, res) {
|
||||
try {
|
||||
res.status(200).json({ defaultPrefix: prefix, doamin: domain, version: version, mainGuild: invite, github: url.replace('.git', '') });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).json({ error: "500 - some error", message: "report it if it happens again" });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const Server = require('../../../models/server');
|
||||
const { domain } = require('../../../conf/conf.json');
|
||||
const Userdashboard = require('../../../models/userdashboard');
|
||||
module.exports = {
|
||||
name: '/api/updatefilter',
|
||||
async exe(client, conf, req, res) {
|
||||
try {
|
||||
if (!req.body.user || !req.body.server || !req.body.server.id || !req.body.normalFilter || !req.body.safeFilter) return res.status(401).JSON({ error: "000 - missing information", info: "please include all neccery information for this api endpoint for help on how to use this api more info in the docs " + conf.domain + '/docs' });
|
||||
let currentUser = await Userdashboard.findOne({ userId: req.body.user.id });
|
||||
if (currentUser == null) return res.status(404).json({ error: "404 - cant find you in the db" });
|
||||
let currentServer = await Server.findOne({ id: req.body.server.id });
|
||||
if (currentServer == null) return res.status(404).json({ error: "404 - cant find that server in the db" });
|
||||
let gAccess = false;
|
||||
await currentUser.guilds.forEach(async (guild) => {
|
||||
if (guild.id == currentServer.id) {
|
||||
gAccess = true;
|
||||
if (guild.userPermission == 'owner' || guild.userPermission == 'MANAGE_GUILD' || currentServer.staff.includes(currentUser.userId)) {
|
||||
|
||||
let hasAccess = false;
|
||||
await currentUser.accessCodes.forEach(async(userCode) => {
|
||||
if (req.body.user.accesscode == userCode.code) {
|
||||
hasAccess = true;
|
||||
currentServer.filter.normal = await req.body.normalFilter;
|
||||
currentServer.filter.safe = await req.body.safeFilter;
|
||||
currentServer.save();
|
||||
return res.status(200).json({ error: "no", message: "filters have been updates" });
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (hasAccess == false) return res.status(401).json({ error: "401 - unauthorised", info: "please include your accesscode and user id to use this api more info in the docs " + conf.domain + '/docs' });
|
||||
if (gAccess == false) {
|
||||
return res.status(401).render('error.ejs', { errorMessage: null, error: "you do not have access to the admin dashboard if you are a member of staff tell the bot owner" })
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).json({ error: "some error happened", info: "report this if it happenes again." + domain + '/er' });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const Userdashboard = require('../../../models/userdashboard');
|
||||
const Server = require('../../../models/server');
|
||||
const { prefix, domain } = require('../../../conf/conf.json');
|
||||
module.exports = {
|
||||
name: '/api/updateoverview',
|
||||
async exe(client, conf, req, res) {
|
||||
try {
|
||||
if (!req.body.user || !req.body.server || !req.body.server.id || !req.body.staffRoles || !req.body.staffids) return res.status(403).json({ error: "000 - missing information", message: "please include all neccery information for this api endpoint for help on how to use this api more info in the docs " + conf.domain + '/docs' })
|
||||
let currentUser = await Userdashboard.findOne({ userId: req.body.user.id })
|
||||
if (currentUser == null) return res.status(404).json({ error: "404 - cant find you in the db", message: "that user id cant be found" });
|
||||
let currentServer = await Server.findOne({ id: req.body.server.id });
|
||||
if (currentServer == null) return res.status(404).json({ error: "404 - cant find that server in the db", message: "that server id cant be found" });
|
||||
let gAccess = false;
|
||||
await currentUser.guilds.forEach(async (guild) => {
|
||||
if (guild.id == currentServer.id) {
|
||||
gAccess = true;
|
||||
if (guild.userPermission == 'owner' || guild.userPermission == 'MANAGE_GUILD' || currentServer.staff.includes(currentUser.userId)) {
|
||||
|
||||
let hasAccess = false;
|
||||
await currentUser.accessCodes.forEach(async(userCode) => {
|
||||
if (req.body.user.accesscode == userCode.code) {
|
||||
hasAccess = true;
|
||||
//apply all data from the req to the db (probabbly a better way to do this)
|
||||
currentServer.prefix = req.body.prefix || prefix;
|
||||
currentServer.staff = req.body.staffids || [];
|
||||
currentServer.staffRoles = req.body.staffRoles || [];
|
||||
currentServer.channels.modLogs = req.body.channels.modlogs || ' ';
|
||||
currentServer.channels.announcments = req.body.channels.announcments || ' ';
|
||||
currentServer.channels.townhall = req.body.channels.townhall || ' ';
|
||||
currentServer.channels.townhallLogs = req.body.channels.townhallLogs || ' ';
|
||||
currentServer.save();
|
||||
return res.status(200);
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (hasAccess == false) return res.status(401).json({ error: "401 - unauthorised", info: "please include your accesscode and user id to use this api more info in the docs " + conf.domain + '/docs' });
|
||||
if (gAccess == false) {
|
||||
return res.status(401).render('error.ejs', { errorMessage: null, error: "you do not have access to the admin dashboard if you are a member of staff tell the bot owner" })
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).JSON({ error: "some error happened", info: "report this if it happenes again. " + domain + '/er' });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
const Server = require('../../../models/server');
|
||||
const Userdashboard = require('../../../models/userdashboard');
|
||||
module.exports = {
|
||||
name: '/api/updatereactionroles',
|
||||
async exe(client, conf, req, res) {
|
||||
try {
|
||||
if (!req.body.user || !req.body.server || !req.body.server.id || !req.body.reactionRoles) return res.status(404).json({ error: "000 - missing information", info: "please include all neccery information for this api endpoint for help on how to use this api more info in the docs " + conf.domain + '/docs' });
|
||||
let currentUser = await Userdashboard.findOne({ userId: req.body.user.id });
|
||||
if (currentUser == null) return res.status(404).json({ error: "404 - cant find you in the db" });
|
||||
let currentServer = await Server.findOne({ id: req.body.server.id });
|
||||
if (currentServer == null) return res.status(404).json({ error: "404 - cant find that server in the db" });
|
||||
let gAccess = false;
|
||||
await currentUser.guilds.forEach(async (guild) => {
|
||||
if (guild.id == currentServer.id) {
|
||||
gAccess = true;
|
||||
if (guild.userPermission == 'owner' || guild.userPermission == 'MANAGE_GUILD' || currentServer.staff.includes(currentUser.userId)) {
|
||||
let hasAccess = false;
|
||||
await currentUser.accessCodes.forEach(async(userCode) => {
|
||||
if (req.body.user.accesscode == userCode.code) {
|
||||
hasAccess = true;
|
||||
currentServer.reactionRoles = await req.body.reactionRoles;
|
||||
currentServer.save();
|
||||
let eachChannelRoles = {};
|
||||
await currentServer.reactionRoles.forEach(role => {
|
||||
if (!eachChannelRoles[role.channelID]) {
|
||||
eachChannelRoles[role.channelID] = [{
|
||||
roleID: role.roleID,
|
||||
emoji: role.emoji
|
||||
}];
|
||||
} else {
|
||||
eachChannelRoles[role.channelID].push({
|
||||
roleID: role.roleID,
|
||||
emoji: role.emoji
|
||||
});
|
||||
};
|
||||
});
|
||||
for (let i in eachChannelRoles) {
|
||||
let rolesEmbed = {
|
||||
color: conf.colour.ok,
|
||||
title: 'ReactionRoles',
|
||||
url: conf.domain,
|
||||
author: {
|
||||
name: conf.bot.name,
|
||||
icon_url: conf.bot.logo,
|
||||
url: conf.bot.url,
|
||||
},
|
||||
description: 'react with the appropriate emoji to get your role',
|
||||
fields: [],
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
text: currentServer.name,
|
||||
},
|
||||
};
|
||||
|
||||
await eachChannelRoles[i].forEach(role => {
|
||||
rolesEmbed.fields.push({
|
||||
name: '\u200B',
|
||||
value: '<@&' + role.roleID + '> - ' + role.emoji,
|
||||
});
|
||||
});
|
||||
const channel = client.guilds.cache.get(currentServer.id).channels.cache.get(i)
|
||||
if (channel !== undefined) {
|
||||
const msg = await channel.send({ embed: rolesEmbed });
|
||||
eachChannelRoles[i].forEach(role => {
|
||||
msg.react(role.emoji);
|
||||
});
|
||||
};
|
||||
};
|
||||
return res.status(200).json({ error: "no", message: "reactionroles have been updates" });
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (hasAccess == false) return res.status(401).json({ error: "401 - unauthorised", info: "please include your accesscode and user id to use this api more info in the docs " + conf.domain + '/docs' });
|
||||
if (gAccess == false) {
|
||||
return res.status(401).render('error.ejs', { errorMessage: null, error: "you do not have access to the admin dashboard if you are a member of staff tell the bot owner" })
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).json({ error: "some error happened", info: "report this if it happenes again." + conf.domain + '/er' });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
module.exports = {
|
||||
name: '/api/userinfo/update',
|
||||
async exe(client, conf, req, res) {
|
||||
try {
|
||||
if (req.body.tmpPassWord == usersDB[req.body.userInfo.id].tmpPassWord) {
|
||||
|
||||
if (!usersDB[req.body.memberId]) {
|
||||
res.status(404).json({ error: "user id isnt in the database", info: "user id could be wrong or that user hasnt sent a message in the discord server since the bot has been setup" })
|
||||
} else {
|
||||
res.status(200).json({ userStrikes: usersDB[req.body.memberId].strike, userNote: usersDB[req.body.memberId].note, userAdmin: usersDB[req.body.memberId].admin })
|
||||
}
|
||||
} else {
|
||||
res.status(401).json({ error: "401 - unauthorised", info: "please include your tmp password and user id to use this api more info in the docs http://knightrider.rf.gd/docs/" })
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
res.status(500).JSON({ error: "some error happened", info: "report this if it happenes again." })
|
||||
require('./././conf/functions.js').reportError(client, conf, "/api/reaction-error", error, { name: null, id: req.body.userid })
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* licence https://github.com/404invalid-user/knightrider/blob/main/LICENCE
|
||||
*/
|
||||
module.exports = {
|
||||
name: '/api/userinfo',
|
||||
async exe(client, conf, req, res) {
|
||||
try {
|
||||
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
res.status(500).JSON({ error: "some error happened", info: "report this if it happenes again." })
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<link rel="shortcut icon" href="/logo.png">
|
||||
<title>404</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>404 - that page cant be found</h2>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,18 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<link rel="shortcut icon" href="/logo.png">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>500 - web server error </h2>
|
||||
<p>the owner has been informed of this error.</p>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,192 +0,0 @@
|
|||
@import url('https://fonts.googleapis.com/css2?family=Open+Sans&display=swap');
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
background-color: #2C2F33;
|
||||
color: rgb(255, 255, 255);
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
background-image: url('/assets/topggbackground.png');
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.user-information {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.useravatar {
|
||||
padding: auto;
|
||||
}
|
||||
|
||||
.username {
|
||||
padding: auto;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.servers-lists {
|
||||
width: 90%;
|
||||
padding: 15px 0 10px;
|
||||
background: #15528f69;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
|
||||
/* if screen big big make button marging right more so dosnt look weirds 3% and maybe makde button text 2em and width/height bigger*/
|
||||
|
||||
.server-list {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 40px;
|
||||
align-items: center;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.server-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
min-height: 10px;
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
flex-wrap: wrap;
|
||||
background-color: #000000;
|
||||
border-radius: 35px;
|
||||
}
|
||||
|
||||
.server {
|
||||
display: flex;
|
||||
min-width: 50%;
|
||||
flex-direction: row;
|
||||
min-height: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
margin: 0 0.5% 0 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.server-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
margin: 0.9% 0.6%;
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.server-icon {
|
||||
margin-top: 0.4%;
|
||||
margin-left: 0.4%;
|
||||
}
|
||||
|
||||
.server-icon-img {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.server-name {
|
||||
font-size: 1em;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.server-dash-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: rgb(240, 236, 236) 1px solid;
|
||||
color: rgb(255, 255, 255);
|
||||
width: 105px;
|
||||
height: 35px;
|
||||
border-radius: 100px;
|
||||
cursor: pointer;
|
||||
transition: all .2s ease;
|
||||
font-size: 1em;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
@media (max-width: 858px) {
|
||||
.container {
|
||||
width: 100% !important;
|
||||
}
|
||||
.servers-lists {
|
||||
width: 100% !important;
|
||||
margin: 0 !important;
|
||||
padding: 5px !important;
|
||||
}
|
||||
.server-container {
|
||||
flex-direction: column !important;
|
||||
padding: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
max-width: 40% !important;
|
||||
min-height: 150px;
|
||||
border-radius: 15% !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
.button-container {
|
||||
margin: 0 !important;
|
||||
width: 100%;
|
||||
min-height: 33px !important;
|
||||
background-color: aliceblue;
|
||||
color: black !important;
|
||||
}
|
||||
.server-info {
|
||||
margin-top: 8px !important;
|
||||
margin-bottom: 9px !important;
|
||||
margin-left: 4px !important;
|
||||
}
|
||||
.server-icon {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
align-content: center !important;
|
||||
width: 100%;
|
||||
height: 90%;
|
||||
flex-direction: column !important;
|
||||
margin: auto !important;
|
||||
}
|
||||
.server-icon-img {
|
||||
width: 100% !important;
|
||||
height: 90% !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 0 !important;
|
||||
color: rgb(0, 0, 0) !important;
|
||||
width: 100% !important;
|
||||
height: 35px;
|
||||
cursor: pointer;
|
||||
transition: all .2s ease;
|
||||
font-size: 1em;
|
||||
text-decoration: none !important;
|
||||
border-radius: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.manage {}
|
||||
|
||||
.invite {
|
||||
background-color: rgb(123, 255, 0);
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
margin: 0;
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 90px;
|
||||
padding-top: 169px;
|
||||
text-align: center;
|
||||
background: red;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: -ms-flexbox;
|
||||
/* IE10 */
|
||||
display: flex;
|
||||
-ms-flex-wrap: wrap;
|
||||
/* IE10 */
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.main {
|
||||
-ms-flex: 70%;
|
||||
/* IE10 */
|
||||
flex: 70%;
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#connection {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.dot {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
background-color: red;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat {
|
||||
background-color: rgb(233, 223, 223);
|
||||
padding: 5px;
|
||||
padding-right: 7px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
background: #ddd;
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
/* mobile navbar navbar */
|
||||
|
||||
.mobnav {
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 0;
|
||||
z-index: 1;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
transition: 0.5s;
|
||||
padding-top: 60px;
|
||||
overflow-x: hidden;
|
||||
background-color: #25282a;
|
||||
}
|
||||
|
||||
.mobnav a {
|
||||
display: block;
|
||||
font-size: 25px;
|
||||
color: #ffffff;
|
||||
transition: 0.3s;
|
||||
text-decoration: none;
|
||||
padding: 7px 8px 7px 32px;
|
||||
}
|
||||
|
||||
.mobnav a:hover {
|
||||
color: #888B8D;
|
||||
}
|
||||
|
||||
.mobnav .closebtn {
|
||||
top: 0;
|
||||
right: 25px;
|
||||
font-size: 36px;
|
||||
margin-left: 50px;
|
||||
position: absolute;
|
||||
}
|
||||
/* responsive */
|
||||
|
||||
@media screen and (max-height: 450px) {
|
||||
.mobnav {
|
||||
padding-top: 15px;
|
||||
}
|
||||
.mobnav a {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
.mobilenavbtn {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
/* desktop navbar */
|
||||
|
||||
.navbar {
|
||||
margin-top: 0;
|
||||
padding-top: 5px;
|
||||
background-color: #25282a;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.desktop-nav {
|
||||
left: 0;
|
||||
margin-top: 0;
|
||||
display: block;
|
||||
margin-bottom: 0;
|
||||
padding-top: 3px;
|
||||
margin-left: 5.5%;
|
||||
padding-bottom: 3px;
|
||||
transition: 143.9ms;
|
||||
}
|
||||
|
||||
.desktop-nav li {
|
||||
float: left;
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
transition: 0.5ms;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.desktop-nav li a {
|
||||
display: block;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
margin-top: 6px;
|
||||
padding-top: 8px;
|
||||
margin-bottom: 6px;
|
||||
padding-left: 14px;
|
||||
text-align: center;
|
||||
padding-bottom: 8px;
|
||||
padding-right: 14px;
|
||||
border-radius: 13px;
|
||||
text-decoration: none;
|
||||
font-family: "Zegoe UI Semi Bold - U";
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
.desktop-nav a:hover:not(.active) {
|
||||
color: #888B8D;
|
||||
}
|
||||
|
||||
.active a {
|
||||
color: #8C8B89;
|
||||
}
|
||||
/* responstive */
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
.desktop-nav {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
div.user {
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
float: left;
|
||||
margin: 5px;
|
||||
margin-right: 45%;
|
||||
}
|
||||
|
||||
.userimg {
|
||||
width: 50;
|
||||
height: 50;
|
||||
border-radius: 45%;
|
||||
background-color: grey;
|
||||
}
|
||||
|
||||
.usercaption {
|
||||
display: block;
|
||||
color: #ffffff;
|
||||
}
|
|
@ -1,232 +0,0 @@
|
|||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
background-color: #2C2F33;
|
||||
color: #ffffff;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.headding {
|
||||
margin-left: 3.4%;
|
||||
}
|
||||
|
||||
input[type=text],
|
||||
select,
|
||||
textarea {
|
||||
width: 30%;
|
||||
padding: 12px;
|
||||
border: 1px solid #2C2F33;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 16px;
|
||||
resize: vertical;
|
||||
background-color: #4c4e55;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.buttont {
|
||||
display: flex;
|
||||
background-color: #5865F2;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: rgb(240, 236, 236) 1px solid;
|
||||
width: 105px;
|
||||
height: 35px;
|
||||
color: white;
|
||||
padding: 12px 20px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all .2s ease;
|
||||
}
|
||||
|
||||
.buttonttt {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: rgb(240, 236, 236) 1px solid;
|
||||
color: rgb(255, 255, 255);
|
||||
min-width: 105px;
|
||||
min-height: 35px;
|
||||
max-width: 50%;
|
||||
border-radius: 100px;
|
||||
cursor: pointer;
|
||||
transition: all .2s ease;
|
||||
font-size: 1em;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background-color: #5460e7;
|
||||
}
|
||||
|
||||
.button#submit:hover {
|
||||
background-color: #EB459E;
|
||||
}
|
||||
|
||||
.container {
|
||||
border-radius: 5px;
|
||||
background-color: #40444B;
|
||||
padding: 20px;
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
.filterul {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.filterul li {
|
||||
list-style-type: none;
|
||||
float: left;
|
||||
padding: 5px;
|
||||
margin: 3px;
|
||||
border-radius: 5%;
|
||||
background-color: #33363a;
|
||||
}
|
||||
|
||||
.filters {
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex-containor {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
@media (max-width: 858px) {
|
||||
.flex-containor {
|
||||
flex-direction: column;
|
||||
}
|
||||
.server-name-text {
|
||||
margin-left: 1% !important;
|
||||
}
|
||||
.serverinfo {
|
||||
max-width: 45% !important;
|
||||
}
|
||||
.dropdown-content {
|
||||
width: 45% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
min-width: 15%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 0px;
|
||||
}
|
||||
|
||||
.menu div .button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: rgb(255, 255, 255);
|
||||
border-radius: 25px 25px 0 0;
|
||||
height: 50px;
|
||||
cursor: pointer;
|
||||
transition: all .2s ease;
|
||||
font-size: 1em;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.menu div .button:hover {
|
||||
background-color: #363a3f;
|
||||
}
|
||||
|
||||
.view {
|
||||
min-width: 70%;
|
||||
}
|
||||
|
||||
.view-btn-active {
|
||||
background-color: #404449;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.serverinfo {
|
||||
margin: 5px;
|
||||
margin-bottom: 0;
|
||||
padding: 5px;
|
||||
max-width: 80%;
|
||||
background-color: #575a5e;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.server-main-items {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
font-size: 1.5em;
|
||||
row-gap: 1.3%;
|
||||
}
|
||||
|
||||
.server-main-img,
|
||||
.dropdown-server-main-img {
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
vertical-align: middle
|
||||
}
|
||||
|
||||
.server-name-text {
|
||||
margin-left: 5.6%;
|
||||
}
|
||||
|
||||
.server-sub-items {
|
||||
margin-top: 6px;
|
||||
font-size: 0.5em;
|
||||
}
|
||||
|
||||
.dropbtn {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #6A6D70;
|
||||
width: 80%;
|
||||
margin: 5px;
|
||||
margin-top: 0;
|
||||
padding: 5px;
|
||||
font-size: 0.5em;
|
||||
box-shadow: 0px 8px 16px 0px rgb(0 0 0 / 20%);
|
||||
z-index: 1;
|
||||
border-radius: 0 0 8px 8px;
|
||||
}
|
||||
|
||||
.dropdown-content a {
|
||||
color: black;
|
||||
padding: 12px 16px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dropdown-content a:hover {
|
||||
background-color: #52565c;
|
||||
}
|
||||
|
||||
.dropdown:hover .dropdown-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 80%;
|
||||
}
|
||||
|
||||
.dropdown:hover .serverinfo {
|
||||
background-color: #6a6d70;
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
/* buttons */
|
||||
|
||||
.buttons {
|
||||
margin-top: 5px;
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
|
@ -1,11 +0,0 @@
|
|||
//for mobile navbar
|
||||
function openNav() {
|
||||
document.getElementById("mobilenavbar").style.width = "250px";
|
||||
}
|
||||
|
||||
function closeNav() {
|
||||
document.getElementById("mobilenavbar").style.width = "0";
|
||||
}
|
||||
if (window.innerWidth <= 280) {
|
||||
alert("please open your fold phone to use this page")
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue