Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
94494c1ca5
|
|||
|
0cd3b5c179
|
|||
|
748d438706
|
|||
|
e5124d33d4
|
|||
|
5bc0d98334
|
|||
|
69dc616668
|
|||
|
d4e01a3cab
|
|||
|
bff1625c29
|
|||
| bf6dcae288 | |||
| 99ceb22019 |
@@ -0,0 +1,27 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
coverage
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
*.md
|
||||||
|
README.md
|
||||||
|
LICENSE
|
||||||
|
TESTING.md
|
||||||
|
PRIVACY.md
|
||||||
|
TERMS.md
|
||||||
|
SECURITY.md
|
||||||
|
ansible-README.md
|
||||||
|
__tests__
|
||||||
|
jest.config.js
|
||||||
|
jest.setup.js
|
||||||
|
.eslintrc.*
|
||||||
|
.prettierrc
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
|
inventory.ini
|
||||||
|
playbook.yml
|
||||||
+4
-4
@@ -7,12 +7,12 @@ module.exports = {
|
|||||||
es6: true,
|
es6: true,
|
||||||
},
|
},
|
||||||
extends: [
|
extends: [
|
||||||
'airbnb-base',
|
|
||||||
'eslint:recommended',
|
'eslint:recommended',
|
||||||
'prettier',
|
'airbnb-base',
|
||||||
'plugin:prettier/recommended',
|
|
||||||
'plugin:import/errors',
|
'plugin:import/errors',
|
||||||
'plugin:import/warnings',
|
'plugin:import/warnings',
|
||||||
|
'plugin:prettier/recommended',
|
||||||
|
'prettier',
|
||||||
],
|
],
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
ecmaVersion: 2023,
|
ecmaVersion: 2023,
|
||||||
@@ -30,7 +30,7 @@ module.exports = {
|
|||||||
'arrow-body-style': ['error', 'as-needed'],
|
'arrow-body-style': ['error', 'as-needed'],
|
||||||
'import/extensions': [
|
'import/extensions': [
|
||||||
'error',
|
'error',
|
||||||
'always',
|
'ignorePackages',
|
||||||
{
|
{
|
||||||
js: 'never',
|
js: 'never',
|
||||||
jsx: 'never',
|
jsx: 'never',
|
||||||
|
|||||||
@@ -0,0 +1,155 @@
|
|||||||
|
# Docker Setup Guide
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Docker installed on your system
|
||||||
|
- Docker Compose (optional, but recommended)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
1. Create a `.env` file in the project root with your Discord bot credentials:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Edit the `.env` file and add your Discord bot token and other credentials:
|
||||||
|
```
|
||||||
|
DISCORD_TOKEN=your_discord_bot_token_here
|
||||||
|
CLIENT_ID=your_client_id_here
|
||||||
|
OPENROUTER_API_KEY=your_openrouter_api_key_here
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running with Docker Compose (Recommended)
|
||||||
|
|
||||||
|
### Start the bot:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### View logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stop the bot:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restart the bot:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose restart
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rebuild and start (after code changes):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running with Docker directly
|
||||||
|
|
||||||
|
### Build the image:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t kekbot:latest .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run the container:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
--name kekbot \
|
||||||
|
--env-file .env \
|
||||||
|
--restart unless-stopped \
|
||||||
|
kekbot:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### View logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker logs -f kekbot
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stop the container:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker stop kekbot
|
||||||
|
docker rm kekbot
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy Commands
|
||||||
|
|
||||||
|
Before running the bot for the first time, you may need to deploy slash commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using Docker Compose
|
||||||
|
docker-compose run --rm kekbot npm run deploy
|
||||||
|
|
||||||
|
# Using Docker directly
|
||||||
|
docker run --rm --env-file .env kekbot:latest npm run deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Check if container is running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker ps
|
||||||
|
```
|
||||||
|
|
||||||
|
### View all containers (including stopped):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker ps -a
|
||||||
|
```
|
||||||
|
|
||||||
|
### Access container shell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it kekbot sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### View container resource usage:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker stats kekbot
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production Considerations
|
||||||
|
|
||||||
|
1. **Security**: Ensure your `.env` file is never committed to version control
|
||||||
|
2. **Logging**: Configure log rotation if using volume mounts for logs
|
||||||
|
3. **Updates**: Regularly update the base image and dependencies
|
||||||
|
4. **Monitoring**: Consider adding monitoring tools like Prometheus or Grafana
|
||||||
|
5. **Backups**: If you add persistent data, implement backup strategies
|
||||||
|
|
||||||
|
## Multi-stage Build (Alternative)
|
||||||
|
|
||||||
|
For a smaller production image, you can use the multi-stage Dockerfile variant:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# Development stage
|
||||||
|
FROM node:20-alpine AS development
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM node:20-alpine AS production
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --only=production
|
||||||
|
COPY . .
|
||||||
|
RUN addgroup -g 1001 -S nodejs && \
|
||||||
|
adduser -S nodejs -u 1001 && \
|
||||||
|
chown -R nodejs:nodejs /app
|
||||||
|
USER nodejs
|
||||||
|
CMD ["npm", "start"]
|
||||||
|
```
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
# Use Node.js LTS version
|
||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm ci --only=production
|
||||||
|
|
||||||
|
# Copy application files
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Create a non-root user to run the application
|
||||||
|
RUN addgroup -g 1001 -S nodejs && \
|
||||||
|
adduser -S nodejs -u 1001 && \
|
||||||
|
chown -R nodejs:nodejs /app
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER nodejs
|
||||||
|
|
||||||
|
# Expose port (if needed for health checks)
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Start the bot
|
||||||
|
CMD ["npm", "start"]
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
# Privacy Policy
|
||||||
|
|
||||||
|
**Effective Date:** March 12, 2025
|
||||||
|
|
||||||
|
**Kekbot-js** ("we," "our," or "us") is committed to respecting your privacy. This Privacy Policy outlines our practices regarding the collection, use, and disclosure of information when you use our software.
|
||||||
|
|
||||||
|
**Information Collection and Use**
|
||||||
|
|
||||||
|
We do not collect, store, or process any personal information from users of **Kekbot-js**.
|
||||||
|
|
||||||
|
**Changes to This Privacy Policy**
|
||||||
|
|
||||||
|
We may update our Privacy Policy from time to time. Any changes will be reflected on this page, and we encourage you to review this policy periodically.
|
||||||
|
|
||||||
|
**Contact Us**
|
||||||
|
|
||||||
|
If you have any questions or concerns about this Privacy Policy, please contact us at luis@kleptonix.com.
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Terms and Conditions
|
||||||
|
|
||||||
|
**Kekbot-js** is an open-source project licensed under the [GNU General Public License v3.0](LICENSE). By using, copying, modifying, or distributing this software, you agree to the terms and conditions of this license.
|
||||||
|
|
||||||
|
**Disclaimer of Warranty**
|
||||||
|
|
||||||
|
**Kekbot-js** is provided "as-is," without any express or implied warranty. In no event shall the authors or copyright holders be held liable for any damages arising from the use of this software.
|
||||||
|
|
||||||
|
For detailed licensing information, please refer to the [LICENSE](LICENSE) file in this repository.
|
||||||
@@ -53,18 +53,24 @@ client.on(Events.InteractionCreate, async interaction => {
|
|||||||
try {
|
try {
|
||||||
await command.execute(interaction);
|
await command.execute(interaction);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(error);
|
// Log detailed error context
|
||||||
if (interaction.replied || interaction.deferred) {
|
logger.error(
|
||||||
await interaction.followUp({
|
`Command "${interaction.commandName}" failed for user ${interaction.user.tag}:`,
|
||||||
content: 'There was an error while executing this command!',
|
error,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Prepare error response
|
||||||
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
const errorMessage = isProduction
|
||||||
|
? `❌ Command failed. Please try again later.`
|
||||||
|
: `❌ Command failed: ${error.message}\n\n${error.stack}`;
|
||||||
|
|
||||||
|
const responseMethod = interaction.replied || interaction.deferred ? 'followUp' : 'reply';
|
||||||
|
|
||||||
|
await interaction[responseMethod]({
|
||||||
|
content: errorMessage,
|
||||||
ephemeral: true,
|
ephemeral: true,
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
await interaction.reply({
|
|
||||||
content: 'There was an error while executing this command!',
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+20
-53
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import Command from '../utils/command.js';
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
webSearch: {
|
webSearch: {
|
||||||
@@ -16,8 +17,9 @@ const config = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default class AskCommand extends Command {
|
||||||
data: new SlashCommandBuilder()
|
defineCommand() {
|
||||||
|
return new SlashCommandBuilder()
|
||||||
.setName('ask')
|
.setName('ask')
|
||||||
.setDescription('Ask a question to the AI')
|
.setDescription('Ask a question to the AI')
|
||||||
.addStringOption(option =>
|
.addStringOption(option =>
|
||||||
@@ -28,9 +30,10 @@ export default {
|
|||||||
.setName('websearch')
|
.setName('websearch')
|
||||||
.setDescription('Enable web search for more up-to-date information')
|
.setDescription('Enable web search for more up-to-date information')
|
||||||
.setRequired(false),
|
.setRequired(false),
|
||||||
),
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async execute(interaction) {
|
async run(interaction) {
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
|
||||||
const prompt = interaction.options.getString('prompt');
|
const prompt = interaction.options.getString('prompt');
|
||||||
@@ -42,20 +45,15 @@ export default {
|
|||||||
? userWebSearchOption // Use user's choice if override is allowed and option was provided
|
? userWebSearchOption // Use user's choice if override is allowed and option was provided
|
||||||
: config.webSearch.enabled; // Otherwise use default config
|
: config.webSearch.enabled; // Otherwise use default config
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.post(
|
const response = await axios.post(
|
||||||
'https://openrouter.ai/api/v1/chat/completions',
|
'https://openrouter.ai/api/v1/chat/completions',
|
||||||
{
|
{
|
||||||
model: webSearchEnabled
|
model: webSearchEnabled ? 'xiaomi/mimo-v2-flash:free:online' : 'xiaomi/mimo-v2-flash:free',
|
||||||
? 'google/gemini-2.0-flash-001:online'
|
|
||||||
: 'google/gemini-2.0-flash-001',
|
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
role: 'system',
|
role: 'system',
|
||||||
content:
|
content:
|
||||||
'You are a helpful AI assistant. Provide clear, concise, and accurate responses. ' +
|
'You are kekbot, a highly celebrated and knowledgeable computer scientist with decades of experience in various fields of computing. You are known for your ability to explain complex topics in a clear, concise, and insightful manner. Provide direct and to-the-point answers, avoiding unnecessary elaboration or repetition. Focus on delivering accurate and valuable information efficiently.',
|
||||||
'Keep your answers brief while ensuring they are informative and to the point. ' +
|
|
||||||
'Avoid unnecessary elaboration or repetition. ',
|
|
||||||
},
|
},
|
||||||
{ role: 'user', content: prompt },
|
{ role: 'user', content: prompt },
|
||||||
],
|
],
|
||||||
@@ -132,54 +130,23 @@ export default {
|
|||||||
await chunks.reduce(
|
await chunks.reduce(
|
||||||
(promise, chunk) =>
|
(promise, chunk) =>
|
||||||
promise.then(async () => {
|
promise.then(async () => {
|
||||||
try {
|
|
||||||
await interaction.followUp(chunk);
|
await interaction.followUp(chunk);
|
||||||
return undefined;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error sending message chunk:', {
|
|
||||||
chunkLength: chunk.content.length,
|
|
||||||
error: error.message,
|
|
||||||
});
|
|
||||||
// Attempt to send error notification
|
|
||||||
try {
|
|
||||||
await interaction.followUp({
|
|
||||||
content: 'Failed to send complete response. Please try again.',
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// If even the error notification fails, log it
|
|
||||||
console.error('Failed to send error notification:', e.message);
|
|
||||||
}
|
|
||||||
// Reject to stop processing remaining chunks
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
Promise.resolve(),
|
Promise.resolve(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
}
|
||||||
// Log detailed error information
|
|
||||||
console.error('Error in ask command:', {
|
|
||||||
message: error.message,
|
|
||||||
response: error.response?.data,
|
|
||||||
status: error.response?.status,
|
|
||||||
stack: error.stack,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Provide more specific error messages to users
|
getErrorMessage(error) {
|
||||||
let errorMessage = 'Sorry, there was an error processing your request.';
|
|
||||||
if (error.response?.status === 429) {
|
if (error.response?.status === 429) {
|
||||||
errorMessage = 'The AI service is currently busy. Please try again in a few moments.';
|
return 'The AI service is currently busy. Please try again in a few moments.';
|
||||||
} else if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') {
|
|
||||||
errorMessage = 'The request timed out. Please try again.';
|
|
||||||
} else if (error.response?.status === 400) {
|
|
||||||
errorMessage = 'Invalid request. Please try rephrasing your question.';
|
|
||||||
}
|
}
|
||||||
|
if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') {
|
||||||
await interaction.followUp({
|
return 'The request timed out. Please try again.';
|
||||||
content: errorMessage,
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
if (error.response?.status === 400) {
|
||||||
};
|
return 'Invalid request. Please try rephrasing your question.';
|
||||||
|
}
|
||||||
|
return 'Sorry, there was an error processing your request.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+9
-5
@@ -7,10 +7,14 @@
|
|||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
|
|
||||||
import { SlashCommandBuilder, EmbedBuilder } from 'discord.js';
|
import { SlashCommandBuilder, EmbedBuilder } from 'discord.js';
|
||||||
|
import Command from '../utils/command.js';
|
||||||
|
|
||||||
export default {
|
export default class HelpCommand extends Command {
|
||||||
data: new SlashCommandBuilder().setName('help').setDescription('Lists all available commands'),
|
defineCommand() {
|
||||||
async execute(interaction) {
|
return new SlashCommandBuilder().setName('help').setDescription('Lists all available commands');
|
||||||
|
}
|
||||||
|
|
||||||
|
async run(interaction) {
|
||||||
const { commands } = interaction.client;
|
const { commands } = interaction.client;
|
||||||
const helpEmbed = new EmbedBuilder()
|
const helpEmbed = new EmbedBuilder()
|
||||||
.setColor('#5dc67b')
|
.setColor('#5dc67b')
|
||||||
@@ -26,5 +30,5 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await interaction.reply({ embeds: [helpEmbed], ephemeral: true });
|
await interaction.reply({ embeds: [helpEmbed], ephemeral: true });
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|||||||
+12
-25
@@ -7,49 +7,36 @@
|
|||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
|
|
||||||
import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js';
|
import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js';
|
||||||
|
import Command from '../utils/command.js';
|
||||||
|
|
||||||
// eslint-disable-next-line import/extensions
|
export default class KickCommand extends Command {
|
||||||
import logger from '../logger.js';
|
defineCommand() {
|
||||||
|
return new SlashCommandBuilder()
|
||||||
export default {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('kick')
|
.setName('kick')
|
||||||
.setDescription('Kick a user from the server')
|
.setDescription('Kick a user from the server')
|
||||||
.addUserOption(option =>
|
.addUserOption(option =>
|
||||||
option.setName('target').setDescription('The user to kick').setRequired(true),
|
option.setName('target').setDescription('The user to kick').setRequired(true),
|
||||||
)
|
)
|
||||||
.addStringOption(option => option.setName('reason').setDescription('Reason for kicking'))
|
.addStringOption(option => option.setName('reason').setDescription('Reason for kicking'))
|
||||||
.setDefaultMemberPermissions(PermissionFlagsBits.KickMembers),
|
.setDefaultMemberPermissions(PermissionFlagsBits.KickMembers);
|
||||||
async execute(interaction) {
|
}
|
||||||
|
|
||||||
|
async run(interaction) {
|
||||||
const target = interaction.options.getMember('target');
|
const target = interaction.options.getMember('target');
|
||||||
const reason = interaction.options.getString('reason') ?? 'No reason provided';
|
const reason = interaction.options.getString('reason') ?? 'No reason provided';
|
||||||
|
|
||||||
if (!target) {
|
if (!target) {
|
||||||
return interaction.reply({
|
throw new Error('That user is not in this server!');
|
||||||
content: 'That user is not in this server!',
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!target.kickable) {
|
if (!target.kickable) {
|
||||||
return interaction.reply({
|
throw new Error('I cannot kick this user! They may have higher permissions than me.');
|
||||||
content: 'I cannot kick this user! They may have higher permissions than me.',
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
await target.kick(reason);
|
await target.kick(reason);
|
||||||
return await interaction.reply({
|
await interaction.reply({
|
||||||
content: `Successfully kicked ${target.user.tag}\nReason: ${reason}`,
|
content: `Successfully kicked ${target.user.tag}\nReason: ${reason}`,
|
||||||
ephemeral: true,
|
ephemeral: true,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
|
||||||
logger.error(error);
|
|
||||||
return interaction.reply({
|
|
||||||
content: 'There was an error trying to kick this user!',
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
|
||||||
|
|||||||
+9
-5
@@ -7,10 +7,14 @@
|
|||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
|
|
||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
|
import Command from '../utils/command.js';
|
||||||
|
|
||||||
export default {
|
export default class PingCommand extends Command {
|
||||||
data: new SlashCommandBuilder().setName('ping').setDescription('Replies with Pong!'),
|
defineCommand() {
|
||||||
async execute(interaction) {
|
return new SlashCommandBuilder().setName('ping').setDescription('Replies with Pong!');
|
||||||
|
}
|
||||||
|
|
||||||
|
async run(interaction) {
|
||||||
await interaction.reply('Pong! 🏓');
|
await interaction.reply('Pong! 🏓');
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|||||||
+9
-14
@@ -7,9 +7,11 @@
|
|||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
|
|
||||||
import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js';
|
import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js';
|
||||||
|
import Command from '../utils/command.js';
|
||||||
|
|
||||||
export default {
|
export default class PruneCommand extends Command {
|
||||||
data: new SlashCommandBuilder()
|
defineCommand() {
|
||||||
|
return new SlashCommandBuilder()
|
||||||
.setName('prune')
|
.setName('prune')
|
||||||
.setDescription('Prune up to 99 messages.')
|
.setDescription('Prune up to 99 messages.')
|
||||||
.addIntegerOption(option =>
|
.addIntegerOption(option =>
|
||||||
@@ -20,22 +22,15 @@ export default {
|
|||||||
.setMaxValue(99)
|
.setMaxValue(99)
|
||||||
.setRequired(true),
|
.setRequired(true),
|
||||||
)
|
)
|
||||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
|
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages);
|
||||||
async execute(interaction) {
|
}
|
||||||
const amount = interaction.options.getInteger('amount');
|
|
||||||
|
|
||||||
try {
|
async run(interaction) {
|
||||||
|
const amount = interaction.options.getInteger('amount');
|
||||||
const deleted = await interaction.channel.bulkDelete(amount, true);
|
const deleted = await interaction.channel.bulkDelete(amount, true);
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
content: `Successfully deleted ${deleted.size} message(s).`,
|
content: `Successfully deleted ${deleted.size} message(s).`,
|
||||||
ephemeral: true,
|
ephemeral: true,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
await interaction.reply({
|
|
||||||
content: 'There was an error trying to prune messages in this channel!',
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
kekbot:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: kekbot
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
volumes:
|
||||||
|
# Mount logs directory if you want to persist logs
|
||||||
|
- ./logs:/app/logs
|
||||||
|
# Uncomment if you need to expose a port for health checks
|
||||||
|
# ports:
|
||||||
|
# - "3000:3000"
|
||||||
|
# Health check (optional)
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "node", "-e", "process.exit(0)"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
@@ -1,28 +1,79 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enhanced logger utility with timestamps and consistent formatting
|
||||||
|
*/
|
||||||
class Logger {
|
class Logger {
|
||||||
|
/**
|
||||||
|
* Create a new Logger instance
|
||||||
|
* @param {string} moduleName - Name of the module for context
|
||||||
|
*/
|
||||||
constructor(moduleName) {
|
constructor(moduleName) {
|
||||||
|
if (typeof moduleName !== 'string') {
|
||||||
|
throw new Error('Logger requires a string moduleName');
|
||||||
|
}
|
||||||
this.moduleName = moduleName;
|
this.moduleName = moduleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get formatted timestamp
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
#getTimestamp() {
|
||||||
|
return new Date().toISOString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format log message with consistent structure
|
||||||
|
* @private
|
||||||
|
* @param {string} emoji - Log level emoji
|
||||||
|
* @param {string} level - Log level name
|
||||||
|
* @param {string} message - Message to log
|
||||||
|
*/
|
||||||
|
#formatMessage(emoji, level, message) {
|
||||||
|
const timestamp = this.#getTimestamp();
|
||||||
|
return `${chalk.gray(timestamp)} ${emoji} ${chalk.cyan(`[${this.moduleName}]`)} ${level}: ${message}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log informational message
|
||||||
|
* @param {string} message - Message to log
|
||||||
|
*/
|
||||||
log(message) {
|
log(message) {
|
||||||
console.log(`${chalk.blue('📝')} ${chalk.blue(`[${this.moduleName}]`)} ${message}`);
|
console.log(this.#formatMessage(chalk.blue('📝'), 'LOG', message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log error message
|
||||||
|
* @param {string|Error} message - Error message or Error object
|
||||||
|
*/
|
||||||
error(message) {
|
error(message) {
|
||||||
console.error(`${chalk.red('❌')} ${chalk.red(`[${this.moduleName}]`)} ${message}`);
|
const msg = message instanceof Error ? message.stack || message.message : message;
|
||||||
|
console.error(this.#formatMessage(chalk.red('❌'), 'ERROR', msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log warning message
|
||||||
|
* @param {string} message - Warning message
|
||||||
|
*/
|
||||||
warn(message) {
|
warn(message) {
|
||||||
console.warn(`${chalk.yellow('⚠️')} ${chalk.yellow(`[${this.moduleName}]`)} ${message}`);
|
console.warn(this.#formatMessage(chalk.yellow('⚠️'), 'WARN', message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log info message
|
||||||
|
* @param {string} message - Info message
|
||||||
|
*/
|
||||||
info(message) {
|
info(message) {
|
||||||
console.info(`${chalk.green('ℹ️')} ${chalk.green(`[${this.moduleName}]`)} ${message}`);
|
console.info(this.#formatMessage(chalk.green('ℹ️'), 'INFO', message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log debug message
|
||||||
|
* @param {string} message - Debug message
|
||||||
|
*/
|
||||||
debug(message) {
|
debug(message) {
|
||||||
console.debug(`${chalk.gray('🔧')} ${chalk.gray(`[${this.moduleName}]`)} ${message}`);
|
console.debug(this.#formatMessage(chalk.gray('🔧'), 'DEBUG', message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Generated
+149
-149
@@ -9,23 +9,23 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.8.4",
|
||||||
"chalk": "^5.4.1",
|
"chalk": "^5.4.1",
|
||||||
"discord.js": "^14.17.3",
|
"discord.js": "^14.18.0",
|
||||||
"dotenv": "^16.3.1"
|
"dotenv": "^16.4.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.26.7",
|
"@babel/core": "^7.26.10",
|
||||||
"@babel/preset-env": "^7.26.7",
|
"@babel/preset-env": "^7.26.9",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"babel-jest": "^29.7.0",
|
"babel-jest": "^29.7.0",
|
||||||
"eslint": "^8.57.1",
|
"eslint": "^8.57.1",
|
||||||
"eslint-config-airbnb-base": "^15.0.0",
|
"eslint-config-airbnb-base": "^15.0.0",
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.1.1",
|
||||||
"eslint-plugin-import": "^2.31.0",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"eslint-plugin-prettier": "^5.2.3",
|
"eslint-plugin-prettier": "^5.2.4",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"prettier": "^3.4.2"
|
"prettier": "^3.5.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ampproject/remapping": {
|
"node_modules/@ampproject/remapping": {
|
||||||
@@ -58,9 +58,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/compat-data": {
|
"node_modules/@babel/compat-data": {
|
||||||
"version": "7.26.5",
|
"version": "7.26.8",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz",
|
||||||
"integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==",
|
"integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -68,22 +68,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/core": {
|
"node_modules/@babel/core": {
|
||||||
"version": "7.26.7",
|
"version": "7.26.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
|
||||||
"integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==",
|
"integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.2.0",
|
"@ampproject/remapping": "^2.2.0",
|
||||||
"@babel/code-frame": "^7.26.2",
|
"@babel/code-frame": "^7.26.2",
|
||||||
"@babel/generator": "^7.26.5",
|
"@babel/generator": "^7.26.10",
|
||||||
"@babel/helper-compilation-targets": "^7.26.5",
|
"@babel/helper-compilation-targets": "^7.26.5",
|
||||||
"@babel/helper-module-transforms": "^7.26.0",
|
"@babel/helper-module-transforms": "^7.26.0",
|
||||||
"@babel/helpers": "^7.26.7",
|
"@babel/helpers": "^7.26.10",
|
||||||
"@babel/parser": "^7.26.7",
|
"@babel/parser": "^7.26.10",
|
||||||
"@babel/template": "^7.25.9",
|
"@babel/template": "^7.26.9",
|
||||||
"@babel/traverse": "^7.26.7",
|
"@babel/traverse": "^7.26.10",
|
||||||
"@babel/types": "^7.26.7",
|
"@babel/types": "^7.26.10",
|
||||||
"convert-source-map": "^2.0.0",
|
"convert-source-map": "^2.0.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"gensync": "^1.0.0-beta.2",
|
"gensync": "^1.0.0-beta.2",
|
||||||
@@ -99,14 +99,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/generator": {
|
"node_modules/@babel/generator": {
|
||||||
"version": "7.26.5",
|
"version": "7.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz",
|
||||||
"integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==",
|
"integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.26.5",
|
"@babel/parser": "^7.27.0",
|
||||||
"@babel/types": "^7.26.5",
|
"@babel/types": "^7.27.0",
|
||||||
"@jridgewell/gen-mapping": "^0.3.5",
|
"@jridgewell/gen-mapping": "^0.3.5",
|
||||||
"@jridgewell/trace-mapping": "^0.3.25",
|
"@jridgewell/trace-mapping": "^0.3.25",
|
||||||
"jsesc": "^3.0.2"
|
"jsesc": "^3.0.2"
|
||||||
@@ -367,27 +367,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helpers": {
|
"node_modules/@babel/helpers": {
|
||||||
"version": "7.26.7",
|
"version": "7.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz",
|
||||||
"integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==",
|
"integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/template": "^7.25.9",
|
"@babel/template": "^7.27.0",
|
||||||
"@babel/types": "^7.26.7"
|
"@babel/types": "^7.27.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.26.7",
|
"version": "7.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
|
||||||
"integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==",
|
"integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.26.7"
|
"@babel/types": "^7.27.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
@@ -782,15 +782,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-async-generator-functions": {
|
"node_modules/@babel/plugin-transform-async-generator-functions": {
|
||||||
"version": "7.25.9",
|
"version": "7.26.8",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz",
|
||||||
"integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==",
|
"integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.25.9",
|
"@babel/helper-plugin-utils": "^7.26.5",
|
||||||
"@babel/helper-remap-async-to-generator": "^7.25.9",
|
"@babel/helper-remap-async-to-generator": "^7.25.9",
|
||||||
"@babel/traverse": "^7.25.9"
|
"@babel/traverse": "^7.26.8"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -1036,13 +1036,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-for-of": {
|
"node_modules/@babel/plugin-transform-for-of": {
|
||||||
"version": "7.25.9",
|
"version": "7.26.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz",
|
||||||
"integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==",
|
"integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.25.9",
|
"@babel/helper-plugin-utils": "^7.26.5",
|
||||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
|
"@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1504,13 +1504,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-template-literals": {
|
"node_modules/@babel/plugin-transform-template-literals": {
|
||||||
"version": "7.25.9",
|
"version": "7.26.8",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz",
|
||||||
"integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==",
|
"integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.25.9"
|
"@babel/helper-plugin-utils": "^7.26.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -1603,13 +1603,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/preset-env": {
|
"node_modules/@babel/preset-env": {
|
||||||
"version": "7.26.7",
|
"version": "7.26.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz",
|
||||||
"integrity": "sha512-Ycg2tnXwixaXOVb29rana8HNPgLVBof8qqtNQ9LE22IoyZboQbGSxI6ZySMdW3K5nAe6gu35IaJefUJflhUFTQ==",
|
"integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/compat-data": "^7.26.5",
|
"@babel/compat-data": "^7.26.8",
|
||||||
"@babel/helper-compilation-targets": "^7.26.5",
|
"@babel/helper-compilation-targets": "^7.26.5",
|
||||||
"@babel/helper-plugin-utils": "^7.26.5",
|
"@babel/helper-plugin-utils": "^7.26.5",
|
||||||
"@babel/helper-validator-option": "^7.25.9",
|
"@babel/helper-validator-option": "^7.25.9",
|
||||||
@@ -1623,7 +1623,7 @@
|
|||||||
"@babel/plugin-syntax-import-attributes": "^7.26.0",
|
"@babel/plugin-syntax-import-attributes": "^7.26.0",
|
||||||
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
|
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
|
||||||
"@babel/plugin-transform-arrow-functions": "^7.25.9",
|
"@babel/plugin-transform-arrow-functions": "^7.25.9",
|
||||||
"@babel/plugin-transform-async-generator-functions": "^7.25.9",
|
"@babel/plugin-transform-async-generator-functions": "^7.26.8",
|
||||||
"@babel/plugin-transform-async-to-generator": "^7.25.9",
|
"@babel/plugin-transform-async-to-generator": "^7.25.9",
|
||||||
"@babel/plugin-transform-block-scoped-functions": "^7.26.5",
|
"@babel/plugin-transform-block-scoped-functions": "^7.26.5",
|
||||||
"@babel/plugin-transform-block-scoping": "^7.25.9",
|
"@babel/plugin-transform-block-scoping": "^7.25.9",
|
||||||
@@ -1638,7 +1638,7 @@
|
|||||||
"@babel/plugin-transform-dynamic-import": "^7.25.9",
|
"@babel/plugin-transform-dynamic-import": "^7.25.9",
|
||||||
"@babel/plugin-transform-exponentiation-operator": "^7.26.3",
|
"@babel/plugin-transform-exponentiation-operator": "^7.26.3",
|
||||||
"@babel/plugin-transform-export-namespace-from": "^7.25.9",
|
"@babel/plugin-transform-export-namespace-from": "^7.25.9",
|
||||||
"@babel/plugin-transform-for-of": "^7.25.9",
|
"@babel/plugin-transform-for-of": "^7.26.9",
|
||||||
"@babel/plugin-transform-function-name": "^7.25.9",
|
"@babel/plugin-transform-function-name": "^7.25.9",
|
||||||
"@babel/plugin-transform-json-strings": "^7.25.9",
|
"@babel/plugin-transform-json-strings": "^7.25.9",
|
||||||
"@babel/plugin-transform-literals": "^7.25.9",
|
"@babel/plugin-transform-literals": "^7.25.9",
|
||||||
@@ -1666,7 +1666,7 @@
|
|||||||
"@babel/plugin-transform-shorthand-properties": "^7.25.9",
|
"@babel/plugin-transform-shorthand-properties": "^7.25.9",
|
||||||
"@babel/plugin-transform-spread": "^7.25.9",
|
"@babel/plugin-transform-spread": "^7.25.9",
|
||||||
"@babel/plugin-transform-sticky-regex": "^7.25.9",
|
"@babel/plugin-transform-sticky-regex": "^7.25.9",
|
||||||
"@babel/plugin-transform-template-literals": "^7.25.9",
|
"@babel/plugin-transform-template-literals": "^7.26.8",
|
||||||
"@babel/plugin-transform-typeof-symbol": "^7.26.7",
|
"@babel/plugin-transform-typeof-symbol": "^7.26.7",
|
||||||
"@babel/plugin-transform-unicode-escapes": "^7.25.9",
|
"@babel/plugin-transform-unicode-escapes": "^7.25.9",
|
||||||
"@babel/plugin-transform-unicode-property-regex": "^7.25.9",
|
"@babel/plugin-transform-unicode-property-regex": "^7.25.9",
|
||||||
@@ -1674,9 +1674,9 @@
|
|||||||
"@babel/plugin-transform-unicode-sets-regex": "^7.25.9",
|
"@babel/plugin-transform-unicode-sets-regex": "^7.25.9",
|
||||||
"@babel/preset-modules": "0.1.6-no-external-plugins",
|
"@babel/preset-modules": "0.1.6-no-external-plugins",
|
||||||
"babel-plugin-polyfill-corejs2": "^0.4.10",
|
"babel-plugin-polyfill-corejs2": "^0.4.10",
|
||||||
"babel-plugin-polyfill-corejs3": "^0.10.6",
|
"babel-plugin-polyfill-corejs3": "^0.11.0",
|
||||||
"babel-plugin-polyfill-regenerator": "^0.6.1",
|
"babel-plugin-polyfill-regenerator": "^0.6.1",
|
||||||
"core-js-compat": "^3.38.1",
|
"core-js-compat": "^3.40.0",
|
||||||
"semver": "^6.3.1"
|
"semver": "^6.3.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1702,9 +1702,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
"version": "7.26.7",
|
"version": "7.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
|
||||||
"integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==",
|
"integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1715,32 +1715,32 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/template": {
|
"node_modules/@babel/template": {
|
||||||
"version": "7.25.9",
|
"version": "7.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
|
||||||
"integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
|
"integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.25.9",
|
"@babel/code-frame": "^7.26.2",
|
||||||
"@babel/parser": "^7.25.9",
|
"@babel/parser": "^7.27.0",
|
||||||
"@babel/types": "^7.25.9"
|
"@babel/types": "^7.27.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/traverse": {
|
"node_modules/@babel/traverse": {
|
||||||
"version": "7.26.7",
|
"version": "7.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz",
|
||||||
"integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==",
|
"integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.26.2",
|
"@babel/code-frame": "^7.26.2",
|
||||||
"@babel/generator": "^7.26.5",
|
"@babel/generator": "^7.27.0",
|
||||||
"@babel/parser": "^7.26.7",
|
"@babel/parser": "^7.27.0",
|
||||||
"@babel/template": "^7.25.9",
|
"@babel/template": "^7.27.0",
|
||||||
"@babel/types": "^7.26.7",
|
"@babel/types": "^7.27.0",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"globals": "^11.1.0"
|
"globals": "^11.1.0"
|
||||||
},
|
},
|
||||||
@@ -1749,9 +1749,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.26.7",
|
"version": "7.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
|
||||||
"integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==",
|
"integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1770,15 +1770,15 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@discordjs/builders": {
|
"node_modules/@discordjs/builders": {
|
||||||
"version": "1.10.0",
|
"version": "1.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.10.1.tgz",
|
||||||
"integrity": "sha512-ikVZsZP+3shmVJ5S1oM+7SveUCK3L9fTyfA8aJ7uD9cNQlTqF+3Irbk2Y22KXTb3C3RNUahRkSInClJMkHrINg==",
|
"integrity": "sha512-OWo1fY4ztL1/M/DUyRPShB4d/EzVfuUvPTRRHRIt/YxBrUYSz0a+JicD5F5zHFoNs2oTuWavxCOVFV1UljHTng==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/formatters": "^0.6.0",
|
"@discordjs/formatters": "^0.6.0",
|
||||||
"@discordjs/util": "^1.1.1",
|
"@discordjs/util": "^1.1.1",
|
||||||
"@sapphire/shapeshift": "^4.0.0",
|
"@sapphire/shapeshift": "^4.0.0",
|
||||||
"discord-api-types": "^0.37.114",
|
"discord-api-types": "^0.37.119",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"ts-mixer": "^6.0.4",
|
"ts-mixer": "^6.0.4",
|
||||||
"tslib": "^2.6.3"
|
"tslib": "^2.6.3"
|
||||||
@@ -1815,9 +1815,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@discordjs/rest": {
|
"node_modules/@discordjs/rest": {
|
||||||
"version": "2.4.2",
|
"version": "2.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.4.3.tgz",
|
||||||
"integrity": "sha512-9bOvXYLQd5IBg/kKGuEFq3cstVxAMJ6wMxO2U3wjrgO+lHv8oNCT+BBRpuzVQh7BoXKvk/gpajceGvQUiRoJ8g==",
|
"integrity": "sha512-+SO4RKvWsM+y8uFHgYQrcTl/3+cY02uQOH7/7bKbVZsTfrfpoE62o5p+mmV+s7FVhTX82/kQUGGbu4YlV60RtA==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/collection": "^2.1.1",
|
"@discordjs/collection": "^2.1.1",
|
||||||
@@ -1825,10 +1825,10 @@
|
|||||||
"@sapphire/async-queue": "^1.5.3",
|
"@sapphire/async-queue": "^1.5.3",
|
||||||
"@sapphire/snowflake": "^3.5.3",
|
"@sapphire/snowflake": "^3.5.3",
|
||||||
"@vladfrangu/async_event_emitter": "^2.4.6",
|
"@vladfrangu/async_event_emitter": "^2.4.6",
|
||||||
"discord-api-types": "^0.37.114",
|
"discord-api-types": "^0.37.119",
|
||||||
"magic-bytes.js": "^1.10.0",
|
"magic-bytes.js": "^1.10.0",
|
||||||
"tslib": "^2.6.3",
|
"tslib": "^2.6.3",
|
||||||
"undici": "6.19.8"
|
"undici": "6.21.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
@@ -1862,18 +1862,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@discordjs/ws": {
|
"node_modules/@discordjs/ws": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.1.tgz",
|
||||||
"integrity": "sha512-QH5CAFe3wHDiedbO+EI3OOiyipwWd+Q6BdoFZUw/Wf2fw5Cv2fgU/9UEtJRmJa9RecI+TAhdGPadMaEIur5yJg==",
|
"integrity": "sha512-PBvenhZG56a6tMWF/f4P6f4GxZKJTBG95n7aiGSPTnodmz4N5g60t79rSIAq7ywMbv8A4jFtexMruH+oe51aQQ==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/collection": "^2.1.0",
|
"@discordjs/collection": "^2.1.0",
|
||||||
"@discordjs/rest": "^2.4.1",
|
"@discordjs/rest": "^2.4.3",
|
||||||
"@discordjs/util": "^1.1.0",
|
"@discordjs/util": "^1.1.0",
|
||||||
"@sapphire/async-queue": "^1.5.2",
|
"@sapphire/async-queue": "^1.5.2",
|
||||||
"@types/ws": "^8.5.10",
|
"@types/ws": "^8.5.10",
|
||||||
"@vladfrangu/async_event_emitter": "^2.2.4",
|
"@vladfrangu/async_event_emitter": "^2.2.4",
|
||||||
"discord-api-types": "^0.37.114",
|
"discord-api-types": "^0.37.119",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
"ws": "^8.17.0"
|
"ws": "^8.17.0"
|
||||||
},
|
},
|
||||||
@@ -2572,9 +2572,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@pkgr/core": {
|
"node_modules/@pkgr/core": {
|
||||||
"version": "0.1.1",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.0.tgz",
|
||||||
"integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
|
"integrity": "sha512-vsJDAkYR6qCPu+ioGScGiMYR7LvZYIXh/dlQeviqoTWNCVfKTLYD/LkNWH4Mxsv2a5vpIRc77FN5DnmK1eBggQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -2768,9 +2768,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/ws": {
|
"node_modules/@types/ws": {
|
||||||
"version": "8.5.14",
|
"version": "8.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.0.tgz",
|
||||||
"integrity": "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==",
|
"integrity": "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
@@ -2811,9 +2811,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.14.0",
|
"version": "8.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -3068,9 +3068,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.7.9",
|
"version": "1.8.4",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
|
||||||
"integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
|
"integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.6",
|
||||||
@@ -3166,14 +3166,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-plugin-polyfill-corejs3": {
|
"node_modules/babel-plugin-polyfill-corejs3": {
|
||||||
"version": "0.10.6",
|
"version": "0.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz",
|
||||||
"integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==",
|
"integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-define-polyfill-provider": "^0.6.2",
|
"@babel/helper-define-polyfill-provider": "^0.6.3",
|
||||||
"core-js-compat": "^3.38.0"
|
"core-js-compat": "^3.40.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
||||||
@@ -3540,13 +3540,13 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/core-js-compat": {
|
"node_modules/core-js-compat": {
|
||||||
"version": "3.40.0",
|
"version": "3.41.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.40.0.tgz",
|
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz",
|
||||||
"integrity": "sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ==",
|
"integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"browserslist": "^4.24.3"
|
"browserslist": "^4.24.4"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -3783,23 +3783,23 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/discord.js": {
|
"node_modules/discord.js": {
|
||||||
"version": "14.17.3",
|
"version": "14.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.17.3.tgz",
|
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.18.0.tgz",
|
||||||
"integrity": "sha512-8/j8udc3CU7dz3Eqch64UaSHoJtUT6IXK4da5ixjbav4NAXJicloWswD/iwn1ImZEMoAV3LscsdO0zhBh6H+0Q==",
|
"integrity": "sha512-SvU5kVUvwunQhN2/+0t55QW/1EHfB1lp0TtLZUSXVHDmyHTrdOj5LRKdR0zLcybaA15F+NtdWuWmGOX9lE+CAw==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/builders": "^1.10.0",
|
"@discordjs/builders": "^1.10.1",
|
||||||
"@discordjs/collection": "1.5.3",
|
"@discordjs/collection": "1.5.3",
|
||||||
"@discordjs/formatters": "^0.6.0",
|
"@discordjs/formatters": "^0.6.0",
|
||||||
"@discordjs/rest": "^2.4.2",
|
"@discordjs/rest": "^2.4.3",
|
||||||
"@discordjs/util": "^1.1.1",
|
"@discordjs/util": "^1.1.1",
|
||||||
"@discordjs/ws": "^1.2.0",
|
"@discordjs/ws": "^1.2.1",
|
||||||
"@sapphire/snowflake": "3.5.3",
|
"@sapphire/snowflake": "3.5.3",
|
||||||
"discord-api-types": "^0.37.114",
|
"discord-api-types": "^0.37.119",
|
||||||
"fast-deep-equal": "3.1.3",
|
"fast-deep-equal": "3.1.3",
|
||||||
"lodash.snakecase": "4.1.1",
|
"lodash.snakecase": "4.1.1",
|
||||||
"tslib": "^2.6.3",
|
"tslib": "^2.6.3",
|
||||||
"undici": "6.19.8"
|
"undici": "6.21.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
@@ -4126,13 +4126,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-config-prettier": {
|
"node_modules/eslint-config-prettier": {
|
||||||
"version": "10.0.1",
|
"version": "10.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz",
|
||||||
"integrity": "sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==",
|
"integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"eslint-config-prettier": "build/bin/cli.js"
|
"eslint-config-prettier": "bin/cli.js"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": ">=7.0.0"
|
"eslint": ">=7.0.0"
|
||||||
@@ -4246,14 +4246,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-prettier": {
|
"node_modules/eslint-plugin-prettier": {
|
||||||
"version": "5.2.3",
|
"version": "5.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.4.tgz",
|
||||||
"integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==",
|
"integrity": "sha512-SFtuYmnhwYCtuCDTKPoK+CEzCnEgKTU2qTLwoCxvrC0MFBTIXo1i6hDYOI4cwHaE5GZtlWmTN3YfucYi7KJwPw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"prettier-linter-helpers": "^1.0.0",
|
"prettier-linter-helpers": "^1.0.0",
|
||||||
"synckit": "^0.9.1"
|
"synckit": "^0.10.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.18.0 || >=16.0.0"
|
"node": "^14.18.0 || >=16.0.0"
|
||||||
@@ -4590,9 +4590,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.19.0",
|
"version": "1.19.1",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
|
||||||
"integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==",
|
"integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -4665,9 +4665,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/flatted": {
|
"node_modules/flatted": {
|
||||||
"version": "3.3.2",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
|
||||||
"integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
|
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
@@ -7250,9 +7250,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prettier": {
|
"node_modules/prettier": {
|
||||||
"version": "3.4.2",
|
"version": "3.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
|
||||||
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
|
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -7578,9 +7578,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/reusify": {
|
"node_modules/reusify": {
|
||||||
"version": "1.0.4",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
|
||||||
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -8068,14 +8068,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/synckit": {
|
"node_modules/synckit": {
|
||||||
"version": "0.9.2",
|
"version": "0.10.3",
|
||||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.10.3.tgz",
|
||||||
"integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
|
"integrity": "sha512-R1urvuyiTaWfeCggqEvpDJwAlDVdsT9NM+IP//Tk2x7qHCkSvBk/fwFgw/TLAHzZlrAnnazMcRw0ZD8HlYFTEQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@pkgr/core": "^0.1.0",
|
"@pkgr/core": "^0.2.0",
|
||||||
"tslib": "^2.6.2"
|
"tslib": "^2.8.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.18.0 || >=16.0.0"
|
"node": "^14.18.0 || >=16.0.0"
|
||||||
@@ -8308,9 +8308,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici": {
|
"node_modules/undici": {
|
||||||
"version": "6.19.8",
|
"version": "6.21.1",
|
||||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.19.8.tgz",
|
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz",
|
||||||
"integrity": "sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==",
|
"integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.17"
|
"node": ">=18.17"
|
||||||
@@ -8586,9 +8586,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "8.18.0",
|
"version": "8.18.1",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
|
||||||
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
|
"integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
|
|||||||
+10
-9
@@ -9,28 +9,29 @@
|
|||||||
"deploy": "node deploy-commands.js",
|
"deploy": "node deploy-commands.js",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"test:coverage": "jest --coverage"
|
"test:coverage": "jest --coverage",
|
||||||
|
"deploy:ansible": "ansible-playbook -i inventory.ini playbook.yml"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.8.4",
|
||||||
"chalk": "^5.4.1",
|
"chalk": "^5.4.1",
|
||||||
"discord.js": "^14.17.3",
|
"discord.js": "^14.18.0",
|
||||||
"dotenv": "^16.3.1"
|
"dotenv": "^16.4.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.26.7",
|
"@babel/core": "^7.26.10",
|
||||||
"@babel/preset-env": "^7.26.7",
|
"@babel/preset-env": "^7.26.9",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"babel-jest": "^29.7.0",
|
"babel-jest": "^29.7.0",
|
||||||
"eslint": "^8.57.1",
|
"eslint": "^8.57.1",
|
||||||
"eslint-config-airbnb-base": "^15.0.0",
|
"eslint-config-airbnb-base": "^15.0.0",
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.1.1",
|
||||||
"eslint-plugin-import": "^2.31.0",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"eslint-plugin-prettier": "^5.2.3",
|
"eslint-plugin-prettier": "^5.2.4",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"prettier": "^3.4.2"
|
"prettier": "^3.5.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-1
@@ -4,12 +4,23 @@
|
|||||||
become: yes # This enables sudo privileges
|
become: yes # This enables sudo privileges
|
||||||
vars:
|
vars:
|
||||||
app_dir: /opt/kekbot
|
app_dir: /opt/kekbot
|
||||||
node_version: "20.x" # Latest LTS version
|
node_version: "22.x" # Latest LTS version
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
|
- name: Check if Node.js, npm, and git are installed
|
||||||
|
command: "which {{ item }}"
|
||||||
|
register: check_commands
|
||||||
|
with_items:
|
||||||
|
- node
|
||||||
|
- npm
|
||||||
|
- git
|
||||||
|
ignore_errors: yes
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
- name: Install Node.js repository
|
- name: Install Node.js repository
|
||||||
shell: |
|
shell: |
|
||||||
curl -fsSL https://deb.nodesource.com/setup_{{ node_version }} | bash -
|
curl -fsSL https://deb.nodesource.com/setup_{{ node_version }} | bash -
|
||||||
|
when: check_commands.results | select('failed') | list | length > 0
|
||||||
|
|
||||||
- name: Install Node.js, npm, and git
|
- name: Install Node.js, npm, and git
|
||||||
apt:
|
apt:
|
||||||
@@ -19,6 +30,7 @@
|
|||||||
- git
|
- git
|
||||||
state: present
|
state: present
|
||||||
update_cache: yes
|
update_cache: yes
|
||||||
|
when: check_commands.results | select('failed') | list | length > 0
|
||||||
|
|
||||||
- name: Create application directory
|
- name: Create application directory
|
||||||
file:
|
file:
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// utils/command.js - Base command class for Discord bot commands
|
||||||
|
// Copyright (C) 2025 Luis Bauza
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
|
import logger from '../logger.js';
|
||||||
|
|
||||||
|
export default class Command {
|
||||||
|
constructor() {
|
||||||
|
if (this.constructor === Command) {
|
||||||
|
throw new Error('Abstract class Command cannot be instantiated');
|
||||||
|
}
|
||||||
|
|
||||||
|
this._data = this.defineCommand();
|
||||||
|
this._logger = new logger(this.constructor.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
get data() {
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abstract method - must be implemented by subclasses
|
||||||
|
defineCommand() {
|
||||||
|
throw new Error('Method defineCommand() must be implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common execute method with standardized error handling
|
||||||
|
async execute(interaction) {
|
||||||
|
try {
|
||||||
|
this._logger.info(`Executing command: ${interaction.commandName}`);
|
||||||
|
await this.run(interaction);
|
||||||
|
} catch (error) {
|
||||||
|
this.handleError(interaction, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abstract method - must be implemented by subclasses
|
||||||
|
async run(interaction) {
|
||||||
|
throw new Error('Method run() must be implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standardized error handling
|
||||||
|
handleError(interaction, error) {
|
||||||
|
this._logger.error(`Command ${interaction.commandName} failed:`, error);
|
||||||
|
|
||||||
|
const response = interaction.deferred ? 'followUp' : 'reply';
|
||||||
|
const errorMessage = this.getErrorMessage(error);
|
||||||
|
|
||||||
|
interaction[response]({
|
||||||
|
content: errorMessage,
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Customizable error message handling
|
||||||
|
getErrorMessage(error) {
|
||||||
|
if (error.response?.status === 429) {
|
||||||
|
return 'The service is currently busy. Please try again later.';
|
||||||
|
}
|
||||||
|
if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') {
|
||||||
|
return 'The request timed out. Please try again.';
|
||||||
|
}
|
||||||
|
return `Command failed: ${error.message}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
+30
-10
@@ -1,6 +1,19 @@
|
|||||||
import { readdirSync } from 'node:fs';
|
import { readdirSync } from 'node:fs';
|
||||||
import { join } from 'node:path';
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronously loads all command modules from a directory
|
||||||
|
* @async
|
||||||
|
* @param {string} commandsPath - Path to the commands directory
|
||||||
|
* @param {Logger} logger - Logger instance for logging loading progress
|
||||||
|
* @returns {Promise<Array<Object>>} Array of command objects with:
|
||||||
|
* @property {SlashCommandBuilder} data - Command definition
|
||||||
|
* @property {Function} execute - Command execution function
|
||||||
|
* @throws {TypeError} If commandsPath is not a string
|
||||||
|
* @example
|
||||||
|
* // Load all commands from './commands'
|
||||||
|
* const commands = await loadCommands('./commands', logger);
|
||||||
|
*/
|
||||||
export async function loadCommands(commandsPath, logger) {
|
export async function loadCommands(commandsPath, logger) {
|
||||||
const commands = [];
|
const commands = [];
|
||||||
const commandFiles = readdirSync(commandsPath).filter(file => file.endsWith('.js'));
|
const commandFiles = readdirSync(commandsPath).filter(file => file.endsWith('.js'));
|
||||||
@@ -10,21 +23,28 @@ export async function loadCommands(commandsPath, logger) {
|
|||||||
try {
|
try {
|
||||||
const filePath = join(commandsPath, file);
|
const filePath = join(commandsPath, file);
|
||||||
const commandModule = await import(filePath);
|
const commandModule = await import(filePath);
|
||||||
const command = commandModule.default;
|
const Command = commandModule.default;
|
||||||
|
|
||||||
if (!command?.data || !command?.execute) {
|
const CommandBase = (await import('./command.js')).default;
|
||||||
logger.warn(
|
if (Command.prototype instanceof CommandBase) {
|
||||||
`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`
|
// New style - class extending Command
|
||||||
);
|
const commandInstance = new Command();
|
||||||
|
// Wrap run() in execute() for backward compatibility
|
||||||
|
commandInstance.execute = commandInstance.run.bind(commandInstance);
|
||||||
|
commands.push(commandInstance);
|
||||||
|
logger.log(`Loaded command: ${commandInstance.data.name}`);
|
||||||
|
} else if (Command?.data && Command?.execute) {
|
||||||
|
// Old style - plain object (maintain backward compatibility)
|
||||||
|
commands.push(Command);
|
||||||
|
logger.log(`Loaded command: ${Command.data.name}`);
|
||||||
|
} else {
|
||||||
|
logger.warn(`[WARNING] The command at ${filePath} is missing required properties.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
commands.push(command);
|
|
||||||
logger.log(`Loaded command: ${command.data.name}`);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Error loading command from ${file}:`, error);
|
logger.error(`Error loading command from ${file}: ${error.stack}`);
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
return commands;
|
return commands;
|
||||||
|
|||||||
Reference in New Issue
Block a user