Merge pull request #21 from VermiumSifell/main

Release of 4.0.0
This commit is contained in:
Axel Olausson Holtenäs 2022-03-13 19:04:41 +01:00 committed by GitHub
commit 43633dfd60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 430 additions and 80 deletions

View file

@ -32,7 +32,15 @@
"ms-vscode.js-debug-companion",
"ms-vscode.references-view",
"ms-vscode.vscode-js-profile-table",
"pflannery.vscode-versionlens"
"pflannery.vscode-versionlens",
"adpyke.codesnap",
"Anan.devdocstab",
"axosoft.gitkraken-glo",
"Gruntfuggly.todo-tree",
"kiteco.kite",
"lkytal.pomodoro",
"wayou.vscode-todo-highlight",
"johnpapa.vscode-peacock"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": []

37
.vscode/settings.json vendored
View file

@ -1,26 +1,8 @@
{
"editor.wordWrapColumn": 100,
"editor.tabSize": 2,
// "workbench.colorCustomizations": {
// "titleBar.activeBackground": "#336699",
// "titleBar.inactiveBackground": "#33669999",
// "titleBar.activeForeground": "#e7e7e7",
// "titleBar.inactiveForeground": "#e7e7e799",
// "statusBarItem.hoverBackground": "#407fbf",
// "activityBar.activeBackground": "#407fbf",
// "activityBar.activeBorder": "#77284f",
// "activityBar.background": "#407fbf",
// "activityBar.foreground": "#e7e7e7",
// "activityBar.inactiveForeground": "#e7e7e799",
// "activityBarBadge.background": "#77284f",
// "activityBarBadge.foreground": "#e7e7e7",
// "sash.hoverBorder": "#407fbf",
// "statusBarItem.remoteBackground": "#336699",
// "statusBarItem.remoteForeground": "#e7e7e7"
// },
"editor.formatOnSave": true,
"javascript.format.enable": false,
"eslint.autoFixOnSave": true,
"files.eol": "\n",
"prettier.endOfLine": "lf",
"prettier.singleQuote": true,
@ -29,23 +11,6 @@
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#407fbf",
"activityBar.activeBorder": "#77284f",
"activityBar.background": "#407fbf",
"activityBar.foreground": "#e7e7e7",
"activityBar.inactiveForeground": "#e7e7e799",
"activityBarBadge.background": "#77284f",
"activityBarBadge.foreground": "#e7e7e7",
"sash.hoverBorder": "#407fbf",
"statusBarItem.hoverBackground": "#407fbf",
"statusBarItem.remoteBackground": "#336699",
"statusBarItem.remoteForeground": "#e7e7e7",
"titleBar.activeBackground": "#336699",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#33669999",
"titleBar.inactiveForeground": "#e7e7e799"
},
"cSpell.words": [
"Controlpanel",
"discordjs",
@ -55,5 +20,7 @@
"upsert",
"uuidv"
],
"editor.fontFamily": "Cascadia Code",
"editor.fontLigatures": true,
"git.enableCommitSigning": true
}

View file

@ -0,0 +1,89 @@
const { Permissions } = require('discord.js');
const config = require('../../../../../config.json');
const logger = require('../../../../handlers/logger');
// Database models
const { counters } = require('../../../../helpers/database/models');
module.exports = async (interaction) => {
// Destructure member
const { member } = interaction;
// Check permission
if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) {
// Create embed object
const embed = {
title: 'Admin',
color: config.colors.error,
description: 'You do not have permission to manage this!',
timestamp: new Date(),
footer: { iconURL: config.footer.icon, text: config.footer.text },
};
// Send interaction reply
return interaction.editReply({ embeds: [embed], ephemeral: true });
}
// Get options
const channel = await interaction.options.getChannel('channel');
const word = await interaction.options.getString('word');
const start = await interaction.options.getNumber('start');
if (channel.type !== 'GUILD_TEXT') {
// Create embed object
const embed = {
title: 'Admin - Counter',
description: `That channel is not supported, it needs to be a text channel.`,
timestamp: new Date(),
color: config.colors.error,
footer: { iconURL: config.footer.icon, text: config.footer.text },
};
// Send interaction reply
return await interaction.editReply({ embeds: [embed] });
}
const counterExist = await counters.findOne({
guildId: member.guild.id,
channelId: channel.id,
word,
});
if (!counterExist) {
await counters.create({
guildId: member.guild.id,
channelId: channel.id,
word,
counter: start || 0,
});
// Create embed object
const embed = {
title: 'Admin - Counter',
description: `${channel} is now counting when hearing word ${word} and it starts at number ${
start || 0
}.`,
timestamp: new Date(),
color: config.colors.success,
footer: { iconURL: config.footer.icon, text: config.footer.text },
};
// Send debug message
await logger.debug(
`Guild: ${member.guild.id} User: ${member.id} added ${channel.id} as a counter using word "${word}" for counting.`
);
// Send interaction reply
return await interaction.editReply({ embeds: [embed] });
}
// Create embed object
const embed = {
title: 'Admin - Counter',
description: `${channel} is already a counting channel.`,
timestamp: new Date(),
color: config.colors.error,
footer: { iconURL: config.footer.icon, text: config.footer.text },
};
// Send interaction reply
return await interaction.editReply({ embeds: [embed] });
};

View file

@ -0,0 +1,4 @@
const add = require('./add');
const remove = require('./remove');
module.exports = { add, remove };

View file

@ -0,0 +1,40 @@
const { Permissions } = require('discord.js');
const config = require('../../../../../config.json');
const logger = require('../../../../handlers/logger');
// Database models
const { counters } = require('../../../../helpers/database/models');
module.exports = async (interaction) => {
// Destructure member
const { member } = interaction;
// Check permission
if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) {
// Create embed object
const embed = {
title: 'Admin',
color: config.colors.error,
description: 'You do not have permission to manage this!',
timestamp: new Date(),
footer: { iconURL: config.footer.icon, text: config.footer.text },
};
// Send interaction reply
return interaction.editReply({ embeds: [embed], ephemeral: true });
}
// Get options
const channel = await interaction.options.getChannel('channel');
await counters
.deleteOne({ guildId: member.guild.id, channelId: channel.id })
.then(async () => {
interaction.editReply({ content: 'Removed' });
});
// Send debug message
await logger.debug(
`Guild: ${member.guild.id} User: ${member.id} executed remove counter.`
);
};

View file

@ -0,0 +1,44 @@
const { Permissions } = require('discord.js');
const config = require('../../../../config.json');
const logger = require('../../../handlers/logger');
const { add, remove } = require('./addons');
module.exports = async (interaction) => {
// Destructure member
const { member } = interaction;
// Check permission
if (!member.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) {
// Create embed object
const embed = {
title: 'Admin',
color: config.colors.error,
description: 'You do not have permission to manage this!',
timestamp: new Date(),
footer: { iconURL: config.footer.icon, text: config.footer.text },
};
// Send interaction reply
await interaction.editReply({ embeds: [embed], ephemeral: true });
}
// If subcommand is give
if (interaction.options.getSubcommand() === 'add') {
// Execute give addon
await add(interaction);
}
// If subcommand is take
else if (interaction.options.getSubcommand() === 'remove') {
// Execute take addon
await remove(interaction);
}
// Send debug message
await logger.debug(
`Guild: ${member.guild.id} User: ${member.id} executed /${
interaction.commandName
} ${interaction.options.getSubcommandGroup()} ${interaction.options.getSubcommand()}`
);
};

View file

@ -1,6 +1,7 @@
const { SlashCommandBuilder } = require('@discordjs/builders');
const credits = require('./credits');
const counter = require('./counter');
module.exports = {
data: new SlashCommandBuilder()
@ -84,6 +85,42 @@ module.exports = {
.setRequired(true)
)
)
)
.addSubcommandGroup((group) =>
group
.setName('counter')
.setDescription('Manage counters.')
.addSubcommand((command) =>
command
.setName('add')
.setDescription('Add a counter')
.addChannelOption((option) =>
option
.setName('channel')
.setDescription('The counter channel.')
.setRequired(true)
)
.addStringOption((option) =>
option
.setName('word')
.setDescription('The counter word.')
.setRequired(true)
)
.addNumberOption((option) =>
option.setName('start').setDescription('Start at number X.')
)
)
.addSubcommand((command) =>
command
.setName('remove')
.setDescription('Remove a counter')
.addChannelOption((option) =>
option
.setName('channel')
.setDescription('The counter channel.')
.setRequired(true)
)
)
),
async execute(interaction) {
// If subcommand group is credits
@ -91,5 +128,11 @@ module.exports = {
// Execute credits group
await credits(interaction);
}
// If subcommand group is credits
else if (interaction.options.getSubcommandGroup() === 'counter') {
// Execute credits group
await counter(interaction);
}
},
};

View file

@ -0,0 +1,48 @@
const config = require('../../../../config.json');
const logger = require('../../../handlers/logger');
const { counters } = require('../../../helpers/database/models');
module.exports = async (interaction) => {
try {
// Destructure member
const { member } = await interaction;
// Get options
const channel = await interaction.options.getChannel('channel');
const counter = await counters.findOne({
guildId: member.guild.id,
channelId: channel.id,
});
if (!counter) {
// Create embed object
const embed = {
title: 'Counter - View',
description: `${channel} is not a counting channel.`,
timestamp: new Date(),
color: config.colors.error,
footer: { iconURL: config.footer.icon, text: config.footer.text },
};
// Send interaction reply
return await interaction.editReply({ embeds: [embed] });
}
// Create embed object
const embed = {
title: 'Counter - View',
color: config.colors.success,
description: `${channel} is currently at number ${counter.counter}.`,
timestamp: new Date(),
footer: { iconURL: config.footer.icon, text: config.footer.text },
};
// Send interaction reply
return await interaction.editReply({ embeds: [embed], ephemeral: true });
} catch (e) {
// Send debug message
await logger.error(e);
}
};

View file

@ -0,0 +1,26 @@
const { SlashCommandBuilder } = require('@discordjs/builders');
const view = require('./addons/view');
module.exports = {
data: new SlashCommandBuilder()
.setName('counter')
.setDescription('Manage counters.')
.addSubcommand((subcommand) =>
subcommand
.setName('view')
.setDescription('View a counter.')
.addChannelOption((option) =>
option
.setName('channel')
.setDescription('The counter channel you want to view')
)
),
async execute(interaction) {
// If subcommand is view
if (interaction.options.getSubcommand() === 'view') {
// Execute view addon
await view(interaction);
}
},
};

View file

@ -5,6 +5,7 @@ const {
guilds,
experiences,
credits,
counters,
timeouts,
} = require('../helpers/database/models');
@ -17,6 +18,30 @@ module.exports = {
// If message author is bot
if (message.author.bot) return;
// Get counter object
const counter = await counters.findOne({
guildId: message.guild.id,
channelId: message.channel.id,
});
// If counter for the message channel
if (counter) {
// If message content is not strictly the same as counter word
if (message.content !== counter.word) {
// Delete the message
await message.delete();
} else {
// Add 1 to the counter object
await counters.findOneAndUpdate(
{
guildId: message.guild.id,
channelId: message.channel.id,
},
{ $inc: { counter: 1 } }
);
}
}
// Create user if not already created
await users.findOne(
{ userId: message.author.id },

View file

@ -1,5 +1,7 @@
const logger = require('../handlers/logger');
const { database, deployCommands } = require('../helpers');
module.exports = {
name: 'ready',
once: true,
@ -14,5 +16,7 @@ module.exports = {
],
status: 'online',
});
await deployCommands();
},
};

13
src/handlers/commands.js Normal file
View file

@ -0,0 +1,13 @@
const fs = require('fs'); // fs
const { Collection } = require('discord.js'); // discord.js
module.exports = async (client) => {
client.commands = new Collection();
const commandFiles = fs.readdirSync('./src/commands');
for (const file of commandFiles) {
// eslint-disable-next-line import/no-dynamic-require, global-require
const command = require(`../commands/${file}`);
client.commands.set(command.data.name, command);
}
};

16
src/handlers/events.js Normal file
View file

@ -0,0 +1,16 @@
const fs = require('fs'); // fs
module.exports = async (client) => {
const eventFiles = fs
.readdirSync('./src/events')
.filter((file) => file.endsWith('.js'));
for (const file of eventFiles) {
const event = require(`../events/${file}`);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
};

5
src/handlers/index.js Normal file
View file

@ -0,0 +1,5 @@
const events = require('./events');
const commands = require('./commands');
const locale = require('./locale');
module.exports = { events, commands, locale };

View file

@ -0,0 +1,34 @@
const mongoose = require('mongoose');
const counterSchema = new mongoose.Schema(
{
guildId: {
type: mongoose.SchemaTypes.Decimal128,
required: true,
unique: false,
index: true,
},
channelId: {
type: mongoose.SchemaTypes.String,
required: true,
unique: true,
index: true,
},
word: {
type: mongoose.SchemaTypes.String,
required: true,
unique: false,
index: true,
},
counter: {
type: mongoose.SchemaTypes.Number,
required: true,
unique: false,
index: true,
default: 0,
},
},
{ timestamps: true }
);
module.exports = mongoose.model('counter', counterSchema);

View file

@ -4,6 +4,7 @@ const users = require('./userSchema');
const guilds = require('./guildSchema');
const apis = require('./apiSchema');
const timeouts = require('./timeoutSchema');
const counters = require('./counterSchema');
module.exports = {
credits,
@ -12,4 +13,5 @@ module.exports = {
guilds,
apis,
timeouts,
counters,
};

View file

@ -1,22 +1,16 @@
/* eslint-disable no-restricted-syntax */
const config = require('../config.json');
const logger = require('./handlers/logger');
const config = require('../../config.json');
const logger = require('../handlers/logger');
const fs = require('fs');
const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');
module.exports = async () => {
// eslint-disable-next-line global-require
const fs = require('fs');
// eslint-disable-next-line global-require
const { REST } = require('@discordjs/rest');
// eslint-disable-next-line global-require
const { Routes } = require('discord-api-types/v9');
const commands = [];
const commandFiles = fs.readdirSync('./src/commands');
for (const file of commandFiles) {
// eslint-disable-next-line import/no-dynamic-require, global-require
const command = require(`./commands/${file}`);
const command = require(`../commands/${file}`);
commands.push(command.data.toJSON());
}

4
src/helpers/index.js Normal file
View file

@ -0,0 +1,4 @@
const database = require('./database');
const deployCommands = require('./deployCommands');
module.exports = { database, deployCommands };

View file

@ -1,37 +1,21 @@
const fs = require('fs');
const { Client, Collection, Intents } = require('discord.js');
// Dependencies
const { Client, Intents } = require('discord.js'); // discord.js
require('./deploy-commands')();
require('./helpers/database')();
require('./handlers/locale')();
const { database } = require('./helpers'); // helpers
const { events, commands, locale } = require('./handlers'); // handlers
const config = require('../config.json');
const config = require('../config.json'); // config.json
const client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES],
});
(async () => {
// Initialize discord.js client
const client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES],
});
const eventFiles = fs
.readdirSync('./src/events')
.filter((file) => file.endsWith('.js'));
await database();
await locale();
await events(client);
await commands(client);
client.commands = new Collection();
const commandFiles = fs.readdirSync('./src/commands');
for (const file of commandFiles) {
// eslint-disable-next-line import/no-dynamic-require, global-require
const command = require(`./commands/${file}`);
client.commands.set(command.data.name, command);
}
for (const file of eventFiles) {
// eslint-disable-next-line import/no-dynamic-require, global-require
const event = require(`./events/${file}`);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
client.login(config.bot.token);
await client.login(config.bot.token);
})();