Skip to content

Commit df33b9b

Browse files
authored
1.4.0 Release
Release 1.4.0 to main branch
2 parents 17ec97a + e37e564 commit df33b9b

31 files changed

+5521
-4113
lines changed

.dockerignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
node_modules
33
package-lock.json
44
yarn.lock
5+
pnpm-lock.yaml
56

67
## Github ##
78
*/.github/
89
*/workflows/
10+
.gitignore
911

1012
## Config ##
1113
config.yml
@@ -17,6 +19,7 @@ config.json
1719
Addons/
1820
Addon_Configs/
1921
EvoTickets
22+
Install/ # not supported in the Docker image
2023

2124
## Logs ##
2225
errors.txt
File renamed without changes.

.github/workflows/release.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@ jobs:
2323

2424
# Download the pterodactyl egg from Zorino's Discord link.
2525
- name: Receive Pterodactyl Egg
26-
run: wget -O pterodactyl-egg.json https://cdn.discordapp.com/attachments/940967061566398515/960130923771351110/egg-brayan-bot-v17.json
26+
run: wget -O pterodactyl-egg.json https://cdn.discordapp.com/attachments/940963220485718097/965499029763006474/egg-brayan-bot.json
2727

2828
# Generate checksums for all files and log them to the appropriate file
2929
- name: Generate Checksums
3030
run: |
31-
FILELIST=
3231
md5sum BrayanBot-v${{ steps.vars.outputs.version }}.zip pterodactyl-egg.json Dockerfile docker-compose.yml .dockerignore > md5-checksums.txt
3332
sha256sum BrayanBot-v${{ steps.vars.outputs.version }}.zip pterodactyl-egg.json Dockerfile docker-compose.yml .dockerignore > sha256-checksums.txt
3433
sha512sum BrayanBot-v${{ steps.vars.outputs.version }}.zip pterodactyl-egg.json Dockerfile docker-compose.yml .dockerignore > sha512-checksums.txt

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# IDE
22
.history/
33
.vscode/
4+
.idea/
45

56
# Logs
67
logs
@@ -34,3 +35,4 @@ disposal/
3435
.github/
3536
README.md
3637
egg-brayan-bot-v17.json
38+
pnpm-lock.yaml

Commands/General/serverinfo.js

Lines changed: 3 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,13 @@ module.exports = {
1818
* @param {Object} config
1919
*/
2020
module.exports.run = async (bot, message, args, config) => {
21-
let guildVariables = await module.exports.fetchGuildVariables(message.guild, "guild");
2221
message.channel.send(Utils.setupMessage({
2322
configPath: lang.General.ServerInfo,
2423
variables: [
2524
...Utils.userVariables(message.member),
2625
...Utils.userVariables(Utils.parseUser(message.guild.ownerId, message.guild), "guild-owner"),
2726
...Utils.botVariables(bot),
28-
...guildVariables,
27+
...Utils.guildVariables(message.guild, "guild"),
2928
],
3029
}));
3130
};
@@ -36,84 +35,13 @@ module.exports.run = async (bot, message, args, config) => {
3635
* @param {Discord.Interaction} interaction
3736
*/
3837
module.exports.runSlash = async (bot, interaction) => {
39-
let guildVariables = await module.exports.fetchGuildVariables(
40-
interaction.guild,
41-
"guild"
42-
);
4338
interaction.reply(Utils.setupMessage({
4439
configPath: lang.General.ServerInfo,
4540
variables: [
4641
...Utils.userVariables(interaction.member),
4742
...Utils.userVariables(Utils.parseUser(interaction.guild.ownerId, interaction.guild), "guild-owner"),
4843
...Utils.botVariables(bot),
49-
...guildVariables,
44+
...Utils.guildVariables(interaction.guild, "guild"),
5045
],
5146
}, true));
52-
};
53-
54-
module.exports.fetchGuildVariables = async (guild, prefix = "guild") => {
55-
let members = await guild.members.fetch();
56-
return [
57-
{ searchFor: new RegExp(`{${prefix}-id}`, "g"), replaceWith: guild.id },
58-
{
59-
searchFor: new RegExp(`{${prefix}-name}`, "g"), replaceWith: guild.name,
60-
},
61-
{
62-
searchFor: new RegExp(`{${prefix}-icon}`, "g"), replaceWith: guild.iconURL({ dynamic: true }),
63-
},
64-
{
65-
searchFor: new RegExp(`{${prefix}-boosts}`), replaceWith: guild.premiumSubscriptionCount == "NONE" ? 0 : guild.premiumSubscriptionCount,
66-
},
67-
{
68-
searchFor: new RegExp(`{${prefix}-level}`), replaceWith: guild.premiumTier,
69-
},
70-
{
71-
searchFor: new RegExp(`{${prefix}-max-members}`), replaceWith: guild.maximumMembers,
72-
},
73-
{
74-
searchFor: new RegExp(`{${prefix}-createdat}`), replaceWith: moment(guild.createdAt).format("MMMM Do YYYY, h:mm a"),
75-
},
76-
{
77-
searchFor: new RegExp(`{${prefix}-online-members}`), replaceWith: guild.members.cache.filter(
78-
(member) => member.presence && (member.presence.status !== "offline").size),
79-
},
80-
{
81-
searchFor: new RegExp(`{${prefix}-online-bots}`), replaceWith: guild.members.cache.filter((member) =>
82-
member.presence && member.presence.status !== "offline" && member.user.bot).size,
83-
},
84-
{
85-
searchFor: new RegExp(`{${prefix}-members}`), replaceWith: members.filter((m) => !m.user.bot).size,
86-
},
87-
{
88-
searchFor: new RegExp(`{${prefix}-bots}`), replaceWith: members.filter((m) => m.user.bot).size,
89-
},
90-
{
91-
searchFor: new RegExp(`{${prefix}-total-members}`), replaceWith: guild.memberCount,
92-
},
93-
{
94-
searchFor: new RegExp(`{${prefix}-total-roles}`), replaceWith: guild.roles.cache.size,
95-
},
96-
{
97-
searchFor: new RegExp(`{${prefix}-total-channels}`), replaceWith: guild.channels.cache.size,
98-
},
99-
{
100-
searchFor: new RegExp(`{${prefix}-total-emojis}`), replaceWith: guild.emojis.cache.size,
101-
},
102-
{
103-
searchFor: new RegExp(`{${prefix}-online-humans}`), replaceWith: guild.members.cache.filter((member) =>
104-
member.presence && member.presence.status == "online" && !member.user.bot).size,
105-
},
106-
{
107-
searchFor: new RegExp(`{${prefix}-idle-humans}`), replaceWith: guild.members.cache.filter((member) =>
108-
member.presence && member.presence.status == "idle" && !member.user.bot).size,
109-
},
110-
{
111-
searchFor: new RegExp(`{${prefix}-dnd-humans}`), replaceWith: guild.members.cache.filter((member) =>
112-
member.presence && member.presence.status == "dnd" && !member.user.bot).size,
113-
},
114-
{
115-
searchFor: new RegExp(`{${prefix}-offline-humans}`), replaceWith: guild.members.cache.filter((member) =>
116-
member.presence && member.presence.status == "offline" && !member.user.bot).size,
117-
},
118-
];
119-
};
47+
};

Commands/General/userinfo.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const Discord = require("discord.js"),
2+
Utils = require("../../Modules/Utils"),
3+
{ lang, config, commands } = require("../../index"),
4+
{ SlashCommandBuilder } = Utils.builder,
5+
moment = require("moment");
6+
7+
module.exports = {
8+
name: "userinfo",
9+
type: "general",
10+
commandData: commands.General.UserInfo,
11+
};
12+
13+
/**
14+
*
15+
* @param {Discord.Client} bot
16+
* @param {Discord.Message} message
17+
* @param {Array} args
18+
* @param {Object} config
19+
*/
20+
module.exports.run = async (bot, message, args, config) => {
21+
const user = Utils.parseUserFromMessage(message, args[0] ? args[0] : message.author.id, true);
22+
message.channel.send(Utils.setupMessage({
23+
configPath: lang.General.UserInfo,
24+
variables: [
25+
...Utils.userVariables(user),
26+
...Utils.memberVariables(user),
27+
...Utils.botVariables(bot),
28+
],
29+
}));
30+
};
31+
32+
/**
33+
*
34+
* @param {Discord.Client} bot
35+
* @param {Discord.Interaction} interaction
36+
*/
37+
module.exports.runSlash = async (bot, interaction) => {
38+
const user = interaction.options.getUser("target") ? Utils.parseUser(interaction.options.getUser("target").id, interaction.guild) : interaction.member;
39+
interaction.reply(Utils.setupMessage({
40+
configPath: lang.General.UserInfo,
41+
variables: [
42+
...Utils.userVariables(user),
43+
...Utils.memberVariables(user),
44+
...Utils.botVariables(bot),
45+
],
46+
}, true));
47+
};

Dockerfile

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,34 @@
1-
# BrayanBot Dockerfile v0.1.2
1+
# BrayanBot Dockerfile v0.1.3
22
# authors:
33
# - NotAShelf <[email protected]>
4-
# Node 17
4+
# Node 18.2.0
5+
# TODO: Switch to pnpm inside Docker
56

6-
FROM node:17.4.0
7+
# From Node 18 Alpine image
8+
FROM node:18-alpine
9+
LABEL MAINTAINER="NotAShelf <[email protected]>"
10+
11+
# update packages
12+
RUN apk update && apk add --no-cache git ca-certificates make gcc g++ bash
713

814
# Set working directory
915
WORKDIR /opt/brayanbot
10-
# and copy files into that directory (config.yml, modules etc.)
16+
17+
# And copy files into that directory (config.yml, modules etc.)
1118
COPY . ./
1219

13-
RUN npm install -g npm@8 && npm install --save-dev
20+
# Install dependencies
21+
RUN yarn
1422

1523
# Ensure these directories & files exist for compose volumes
16-
RUN touch /opt/brayanbot/config.yml && \
17-
touch /opt/brayanbot/lang.yml && \
18-
touch /opt/brayanbot/commands.yml
24+
RUN touch /opt/brayanbot/lang.yml && \
25+
touch /opt/brayanbot/commands.yml && \
26+
cp /opt/brayanbot/example.config.yml /opt/brayanbot/config.yml
27+
1928

20-
# Create a config.yml based on example config
21-
# and then start BrayanBot
29+
# Clean Yarn cache
30+
RUN yarn cache clean
2231

23-
CMD npm start
32+
# Start the bot
33+
CMD [ "yarn", "start" ]
2434

Events/interactionCreate.js

Lines changed: 97 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,58 @@
1-
const Discord = require("discord.js"),
2-
Utils = require("../Modules/Utils");
1+
const Utils = require("../Modules/Utils");
2+
const Discord = require("discord.js");
3+
const chalk = require("chalk");
4+
const ms = require("ms");
35

6+
let db;
7+
/**
8+
* @param {Discord.Client} bot
9+
* @param {Discord.Interaction} interaction
10+
*/
411
module.exports = async (bot, interaction) => {
12+
if(!db) db = await Utils.database.getDatabase();
513
const { config, lang, SlashCmds } = bot;
614
// Slash Command Executing
715
if (interaction.isCommand()) {
816
const command = SlashCmds.find((x) => x.commandData.SlashCommand.Data.Name.toLowerCase() == interaction.commandName.toLowerCase());
17+
let permissions = [], ignoreCooldown = false;
18+
919
if (command && typeof command.runSlash == "function") {
20+
// Command Cooldown Check
21+
if (command.commandData.Cooldown && !interaction.user.bot) {
22+
const ignoreUserCheck = bot.commands.IgnoredCooldown.Users ? bot.commands.IgnoredCooldown.Users.includes(x => x.id == interaction.user.id
23+
|| x.tag.toLowerCase() == interaction.user.tag.toLowerCase()
24+
|| x.username.toLowerCase() == interaction.user.username.toLowerCase()) : false;
25+
26+
const ignoreRoleCheck = bot.commands.IgnoredCooldown.Roles ? bot.commands.IgnoredCooldown.Roles.includes(x =>
27+
interaction.member.roles.cache.some(y => y.id == x
28+
|| y.name.toLowerCase() == x.toLowerCase())) : false;
29+
30+
if(ignoreUserCheck || ignoreRoleCheck) ignoreCooldown = true;
31+
32+
const cooldown = ms(command.commandData.Cooldown);
33+
const isOnCooldown = db.prepare(`SELECT * FROM cooldowns WHERE user=? AND command=?`).get(interaction.user.id, command.name);
34+
35+
36+
if (ignoreCooldown == false) {
37+
if(isOnCooldown && isOnCooldown.time - Date.now() < 0) {
38+
Utils.database.cooldowns.reset(command.name, interaction.user.id, cooldown)
39+
} else if(isOnCooldown) {
40+
return interaction.reply(Utils.setupMessage({
41+
configPath: lang.Presets.OnCooldown,
42+
variables: [
43+
...Utils.userVariables(interaction.member, 'user'),
44+
{ searchFor: /{cooldown}/g, replaceWith: ms(isOnCooldown.time - Date.now(), { long: true }) },
45+
{ searchFor: /{command}/g, replaceWith: command.name }
46+
]
47+
}))
48+
} else if(!isOnCooldown) {
49+
Utils.database.cooldowns.set(command.name, interaction.user.id, cooldown)
50+
db.prepare(`INSERT INTO cooldowns (user, command, time)VALUES(?,?,?)`).run(interaction.user.id, command.name, (Date.now() + cooldown));
51+
}
52+
}
53+
}
54+
55+
// Command Channel Check
1056
if (command.commandData.AllowedChannels) {
1157
if (typeof command.commandData.AllowedChannels == "string")
1258
command.commandData.AllowedChannels = [command.commandData.AllowedChannels];
@@ -28,18 +74,60 @@ module.exports = async (bot, interaction) => {
2874
],
2975
}, true))
3076
}
77+
};
78+
79+
// Command Permission Check
80+
if (command.commandData.Permission) {
81+
if (typeof command.commandData.Permission == "string")
82+
command.commandData.Permission = [command.commandData.Permission];
83+
else if (!command.commandData.Permission[0]) command.commandData.Permission = ["@everyone"];
84+
85+
if (command.commandData.Permission.includes("@everyone") || command.commandData.Permission.includes("everyone"))
86+
permissions.push(true);
87+
else command.commandData.Permission.forEach(permission => {
88+
const roleExists = Utils.findRole(permission, interaction.guild, false);
89+
const userExists = Utils.parseUser(permission, interaction.guild);
90+
91+
if (!roleExists && !userExists)
92+
Utils.logWarning(`${chalk.bold(permission)} is not a valid ${chalk.bold('role/user')} permission in command ${chalk.bold(command.name)}`)
93+
94+
if (userExists && userExists.id === interaction.user.id) permissions.push(true);
95+
else if(Utils.hasRole(interaction.member, permission, false)) permissions.push(true);
96+
})
97+
};
98+
99+
if (permissions.includes(true)) {
100+
let options = interaction.options && interaction.options._hoistedOptions ? Utils.parseSlashArgs(interaction.options._hoistedOptions) : {};
101+
await command.runSlash(bot, interaction, options, {
102+
commandUsed: interaction.commandName,
103+
commandData: command
104+
});
105+
} else {
106+
interaction.reply(Utils.setupMessage({
107+
configPath: lang.Presets.NoPermission,
108+
variables: [
109+
...Utils.userVariables(interaction.member),
110+
{
111+
searchFor: /{perms}/g, replaceWith: permissions[0] ? command.commandData.Permission.map((x) => {
112+
if (!!Utils.findRole(x, interaction.guild, false)) {
113+
let role = Utils.findRole(x, interaction.guild, true);
114+
if (role) return Utils.builder.roleMention(role.id);
115+
}
116+
if (!!Utils.parseUser(x, interaction.guild)) {
117+
let user = Utils.parseUser(x, interaction.guild, true);
118+
if (user) return Utils.builder.userMention(user.id);
119+
}
120+
}).join(", ") : "Invalid Permissions configured.",
121+
},
122+
],
123+
}));
31124
}
32-
let options = interaction.options && interaction.options._hoistedOptions ? Utils.parseSlashArgs(interaction.options._hoistedOptions) : {};
33-
let commandUsed = interaction.commandName, commandData = command;
34-
await command.runSlash(bot, interaction, options, { commandUsed, commandData });
125+
35126
} else {
36127
let cmd = interaction.guild.commands.cache.find((x) =>
37128
x.name.toLowerCase() == interaction.commandName.toLowerCase());
38129
if (cmd) cmd.delete();
39-
interaction.reply({
40-
content: "This command no longer exists.",
41-
ephemeral: true,
42-
});
130+
interaction.reply({ content: "This command no longer exists.", ephemeral: true });
43131
}
44132
} else if (interaction.isButton()) {
45133
bot.emit("interactionCreate-Button", interaction);

0 commit comments

Comments
 (0)