nice new update

This commit is contained in:
404invalid-user 2025-01-18 01:27:58 +00:00
parent e136522421
commit 666638c956
136 changed files with 4483 additions and 9190 deletions

View file

@ -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")
}
}
}
}

View file

@ -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)
}
}

View file

@ -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)
}
}
}
}

View file

@ -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');
});
}
}

View file

@ -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('&amp;', '&')
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);
}
}
}

View file

@ -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.")
}
})
}

View file

@ -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))
}
}

View file

@ -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**\nLets 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**\nLets 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))
}
}
}

View file

@ -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))
});
}
}

View 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;
}
}

View 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);
}
}

View 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],
});
});
}

View file

@ -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));
};
}
}

View file

@ -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));
};
}
}

View file

@ -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));
};
}
}

View file

@ -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));
};
}
}

View file

@ -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("⚙")
}
}
}

View file

@ -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")
}
}

View file

@ -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));
};
}
}

View file

@ -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));
};
}
}

View file

@ -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\"?")
}
}
}

View 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;
}
}

View 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.");
}
}

View 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.");
}
}

View 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.");
}
}

View file

@ -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)
}
}

View file

@ -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 })
}
}
}

View file

@ -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!');
};
};
}
}

View file

@ -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)
};
}
}

View file

@ -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)
};
}
}

View file

@ -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!");
}
}

View file

@ -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)
}
}
}

View 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);
}
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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);
}
}
}

View 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
}

View 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;
}

View 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;
}

View 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);
}

View 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;
}

View 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;
}

View 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
View 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);
}

View file

@ -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;
}
}
};

View file

@ -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;
}
}
});
};

View file

@ -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
View 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;
}

View 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;
}