Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (async () => {
- const { Client, GatewayIntentBits, Partials, Options, Collection, ChannelType, PermissionsBitField, VoiceConnectionStatus , InteractionType } = require('discord.js')
- const { ActionRowBuilder, StringSelectMenuOptionBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder,StringSelectMenuBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ComponentType } = require('discord.js');
- // const { addDeletedMessage, deleteOldMessages } = require('./database');
- const { connectToDatabase, getCollections } = require('./database/connection');
- await connectToDatabase();
- const {
- channelsCollection,
- usersCollection,
- gamesCollection,
- rankingsCollection,
- prefixesCollection,
- commandStatusCollection,
- loveDataCollection,
- wordchainChannelsCollection,
- wordchainRoundsCollection,
- wordchainWordsCollection,
- toggleStatesCollection,
- countChannelsCollection,
- romanCountChannelsCollection,
- restrictionsCollection,
- afkUsersCollection,
- afkTagsCollection,
- } = getCollections();
- const chokidar = require('chokidar');
- const path = require('path');
- const config = require('./config.json');
- const defaultPrefix = config.prefix;
- const fs = require('fs');
- const NodeCache = require('node-cache');
- const wordsE = fs.readFileSync(path.resolve(__dirname, './data/wordsE.txt'), 'utf-8').split('\n').map(word => word.trim().toLowerCase());
- const dataPath = path.resolve(__dirname, './data/data.json')
- const wordDataPath = path.resolve(__dirname, './data/word-data.json')
- const queryPath = path.resolve(__dirname, './data/query.txt')
- const wordPlayedPath = path.resolve(__dirname, './data/word-played.txt')
- const roundPlayedPath = path.resolve(__dirname, './data/round-played.txt')
- const wordDataUrl = 'https://edit.thanhxuan.xyz/words.txt'
- const wordDatabasePath = path.resolve(__dirname, './data/words.txt')
- const rankingPath = path.resolve(__dirname, './data/ranking.json')
- const reportWordsPath = path.resolve(__dirname, './data/report-words.txt')
- const officalWordsPath = path.resolve(__dirname, './data/official-words.txt')
- const axios = require('axios')
- const dictionary = require('./utils/dictionary')
- const stats = require('./utils/stats')
- if (!fs.existsSync(dataPath)) {fs.writeFileSync(dataPath, JSON.stringify(emptyData))} else {}
- if (!fs.existsSync(wordDataPath)) {fs.writeFileSync(wordDataPath, JSON.stringify(emptyData))} else {}
- if (!fs.existsSync(queryPath)) {fs.writeFileSync(queryPath, '0')} else {}
- if (!fs.existsSync(rankingPath)) {fs.writeFileSync(rankingPath, JSON.stringify(emptyData))} else {}
- if (!fs.existsSync(reportWordsPath)) {fs.writeFileSync(reportWordsPath, '')} else {}
- if (!fs.existsSync(officalWordsPath)) {fs.writeFileSync(officalWordsPath, '')} else {}
- if (!fs.existsSync(wordPlayedPath)) {fs.writeFileSync(wordPlayedPath, '0')} else {}
- if (!fs.existsSync(roundPlayedPath)) {fs.writeFileSync(roundPlayedPath, '0')} else {}
- const numberEmojis = [
- '<:0_:1257549818553827348>',
- '<:1_:1257549823767216178>',
- '<:2_:1257549815773003859>',
- '<:3_:1257549813730250913>',
- '<:4_:1257549811524308992>',
- '<:5_:1257549809091608586>',
- '<:6_:1257549806717370379>',
- '<:7_:1257549804582473828>',
- '<:8_:1257549802468802691>',
- '<:9_:1257549800069533818>',
- ];
- // Bắt các lỗi Promise chưa được xử lý trên toàn bộ quá trình
- process.on('unhandledRejection', (reason, promise) => {
- console.error('Unhandled Rejection at:', promise, 'reason:', reason);
- });
- const client = new Client({
- intents: [
- GatewayIntentBits.GuildMembers,
- GatewayIntentBits.Guilds,
- GatewayIntentBits.GuildMessages,
- GatewayIntentBits.MessageContent, // Lấy nội dung tin nhắn
- // GatewayIntentBits.DirectMessages,
- GatewayIntentBits.GuildVoiceStates,
- GatewayIntentBits.GuildMessageReactions
- ]
- // ,partials: [
- // Partials.Message,
- // Partials.Channel,
- // Partials.Reaction,
- // Partials.GuildMember,
- // Partials.User,
- // Partials.GuildScheduledEvent
- // ],
- // makeCache: Options.cacheWithLimits({
- // MessageManager: 300,
- // PresenceManager: 0,
- // GuildMemberManager: 200,
- // UserManager: 200
- // }),
- // restTimeOffset: 250,
- });
- // client.on('debug', console.log);
- // client.rest.on('rateLimited', console.log);
- // load word data
- if (!fs.existsSync(wordDatabasePath)) {
- axios.get(wordDataUrl)
- .then(async res => {
- const lines = res.data.trim().split('\n')
- const wordsdb = lines.map(line => JSON.parse(line).text)
- fs.writeFileSync(wordDatabasePath, wordsdb.join('\n'))
- await continueExecution()
- })
- .catch(err => {
- return
- })
- } else {
- continueExecution()
- }
- let debounceTimeout = null;
- async function continueExecution() {
- fs.readFile(wordDatabasePath, 'utf-8', (err, data) => {
- if (err) {
- return;
- }
- const tempWord = data.toLowerCase().split('\n');
- global.dicData = tempWord.filter(w => w.split(' ').length == 2 && !w.includes('-') && !w.includes('(') && !w.includes(')'));
- });
- }
- // Debouncing function
- function debounce(func, wait) {
- return function(...args) {
- // Clear existing timeout if any
- if (debounceTimeout) clearTimeout(debounceTimeout);
- // Set a new timeout
- debounceTimeout = setTimeout(() => {
- func.apply(this, args);
- debounceTimeout = null; // Reset timeout after execution
- }, wait);
- };
- }
- // Watch for file changes and use debounced reload
- fs.watch(wordDatabasePath, (eventType, filename) => {
- if (eventType === 'change') {
- debounce(continueExecution, 300000)(); // 5 minutes
- }
- });
- // global config
- const START_COMMAND = 'startvi'
- const STOP_COMMAND = `resetvi`
- const PREFIX_SET = '?noitu'
- let queryCount = stats.getQuery()
- client.on('guildCreate', async guild => {
- const webhookUrl = 'https://discord.com/api/webhooks/1254802426134003743/ivIE3AKEWcCAjWdH3myXMY1Ab2ZGTisU9S2oJoVMjFZ6DzfxZpxg4VtTmr2boYVAUOMh';
- const embed = new EmbedBuilder()
- .setTitle('Bot Joined a New Server')
- .setDescription(`Joined **${guild.name}**`)
- .setThumbnail(guild.iconURL({ dynamic: true }))
- .setTimestamp()
- .setAuthor({ name: client.user.tag, iconURL: client.user.displayAvatarURL() })
- .addFields(
- { name: 'Server ID', value: guild.id, inline: false },
- { name: 'Member Count', value: `${guild.memberCount}`, inline: false }
- );
- axios.post(webhookUrl, {
- embeds: [embed.toJSON()]
- }).then(response => {
- console.log('Webhook sent successfully:', response.data);
- }).catch(error => {
- console.error('Error sending webhook:', error);
- });
- });
- // Tải các sự kiện
- const eventFiles = fs.readdirSync(path.join(__dirname, '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));
- }
- }
- const { createCaptchaImage, generateCaptchaText } = require('./utils/captcha'); // Import các tiện ích captcha
- client.commands = new Collection();
- client.commands2 = new Collection();
- client.aliases = new Collection();
- const cooldowns = new Collection();
- // Lắng nghe sự kiện xóa tin nhắn
- // client.on('messageDelete', async (message) => {
- // if (!message.author || message.author.bot || message.partial || !message.guild || !message.content) return;
- // await addDeletedMessage(message);
- // });
- // slashcommand
- const command2Files = fs
- .readdirSync('./commands')
- .filter((file) => file.endsWith('.js'))
- for (const file of command2Files) {
- const command2 = require(`./commands/${file}`)
- client.commands2.set(command2.data.name, command2)
- }
- // Hàm đệ quy để lấy tất cả các tệp lệnh từ các thư mục con
- function getAllCommand2Files(dir) {
- let command2Files = [];
- const files = fs.readdirSync(dir);
- for (const file of files) {
- const filePath = path.join(dir, file);
- const stats = fs.statSync(filePath);
- if (stats.isDirectory()) {
- command2Files = command2Files.concat(getAllCommand2Files(filePath));
- } else if (file.endsWith('.js')) {
- command2Files.push(filePath);
- }
- }
- return command2Files;
- }
- const REQUIRED_TIME = 1800; // 30 phút
- const INTIMACY_POINTS = 10;
- // Sự kiện khi một người thay đổi trạng thái voice
- client.on('voiceStateUpdate', async (oldState, newState) => {
- // Chỉ quan tâm khi người dùng join hoặc leave voice channel
- if (oldState.channelId === newState.channelId) return;
- const userId = newState.id;
- const voiceChannel = newState.channel || oldState.channel;
- if (!voiceChannel) return;
- // Kiểm tra người yêu trong cùng kênh voice
- const partner = await findPartnerInVoiceChannel(voiceChannel, userId, loveDataCollection);
- if (!partner) return;
- const loveData = await loveDataCollection.findOne({
- $or: [
- { user1_id: userId, user2_id: partner.id },
- { user1_id: partner.id, user2_id: userId }
- ],
- success_time: { $exists: true }
- });
- if (!loveData) return;
- const joinedTime = Date.now();
- const updateTime = async () => {
- const currentTime = Date.now();
- const timeSpentTogether = Math.floor((currentTime - joinedTime) / 1000);
- if (timeSpentTogether >= REQUIRED_TIME) {
- const totalVoiceTime = loveData.total_voice_time || 0;
- await updateIntimacyAndTime(loveDataCollection, userId, partner.id, INTIMACY_POINTS, totalVoiceTime + timeSpentTogether);
- }
- };
- // Kiểm tra điều kiện kênh voice mỗi 30 phút
- setTimeout(updateTime, REQUIRED_TIME * 1000);
- });
- // Hàm kiểm tra người yêu trong kênh voice
- async function findPartnerInVoiceChannel(voiceChannel, userId, loveDataCollection) {
- const members = voiceChannel.members;
- if (members.size !== 2 || members.some(member => member.user.bot)) {
- return null;
- }
- const [partner] = members.filter(member => member.id !== userId).values();
- const isPartner = await loveDataCollection.findOne({
- $or: [
- { user1_id: userId, user2_id: partner.id },
- { user1_id: partner.id, user2_id: userId }
- ],
- success_time: { $exists: true }
- });
- return isPartner ? partner : null;
- }
- // Hàm cập nhật điểm thân mật và thời gian tổng cộng
- async function updateIntimacyAndTime(loveDataCollection, userId, partnerId, points, newTotalTime) {
- await loveDataCollection.updateOne(
- { $or: [{ user1_id: userId, user2_id: partnerId }, { user1_id: partnerId, user2_id: userId }] },
- { $inc: { intimacy_level: points }, $set: { total_voice_time: newTotalTime } }
- );
- }
- function getAllCommandFiles(dir) {
- let results = [];
- const list = fs.readdirSync(dir);
- list.forEach(file => {
- const filePath = path.join(dir, file);
- const stat = fs.statSync(filePath);
- if (stat && stat.isDirectory()) {
- results = results.concat(getAllCommandFiles(filePath));
- } else if (file.endsWith('.js')) {
- results.push(filePath);
- }
- });
- return results;
- }
- const commandsPath = path.join(__dirname, 'cmds');
- const commandFiles = getAllCommandFiles(commandsPath);
- function loadCommand(filePath) {
- try {
- delete require.cache[require.resolve(filePath)];
- const command = require(filePath);
- if ('name' in command && 'execute' in command) {
- client.commands.set(command.name, command);
- if (command.aliases && Array.isArray(command.aliases)) {
- command.aliases.forEach(alias => client.aliases.set(alias, command.name));
- }
- } else {
- console.log(`[CẢNH BÁO] Lệnh tại ${filePath} thiếu thuộc tính "name" hoặc "execute".`);
- }
- } catch (error) {
- console.error(`Không thể tải lại lệnh tại ${filePath}:`, error);
- }
- }
- for (const filePath of commandFiles) {
- loadCommand(filePath);
- }
- const watcher = chokidar.watch(commandsPath, {
- persistent: true,
- ignoreInitial: true
- });
- watcher.on('change', filePath => {
- console.log(`[TẢI LẠI] Phát hiện thay đổi tại ${filePath}. Tải lại lệnh...`);
- loadCommand(filePath);
- });
- // client.once('ready', () => {
- // console.log(`Logged in as ${client.user.tag}!`);
- // console.log(`Running on Shard ${client.shard.ids[0]}`);
- // });
- const WEBHOOK_URL = 'https://discord.com/api/webhooks/1308259857882677259/e48uhQYlWnpi8a01YpOaqo-pI2vXIkepjDwcTijDidndliur8RxgX4GmbtajHPAzDoJd';
- client.on('rateLimit', async (info) => {
- const embed = {
- title: `Rate Limit Được Phát Hiện`,
- color: 15158332, // Đỏ
- description: `Shard: ${client.shard?.ids[0] || '0'}`,
- fields: [
- { name: 'Route', value: info.route || 'Không rõ', inline: true },
- { name: 'Method', value: info.method || 'Không rõ', inline: true },
- { name: 'Thời gian chờ', value: `${info.timeout}ms`, inline: true },
- ],
- timestamp: new Date().toISOString(),
- };
- try {
- await axios.post(WEBHOOK_URL, {
- embeds: [embed],
- });
- } catch (error) {
- console.error(`[WEBHOOK ERROR] Không thể gửi Rate Limit log: ${error}`);
- }
- });
- const { updateLevel } = require('./utils/levelSystem');
- const channelId = '1311189048777375846';
- // File lưu trữ ID tin nhắn
- const messageFile = './trackedMessage.json';
- // Danh sách game và vai trò tương ứng
- const games = [
- { emoji: '<:xumimi:1261591338290511973>', label: 'Mua bán Xu Mimi', roleId: '1321426469423157268' },
- { emoji: '🛒', label: 'Mua Xu Mimi', roleId: '1321419839729958985' },
- { emoji: '<:DStore_buy:1301627802768117820>', label: 'Bán Xu Mimi', roleId: '1321419816791445555' }
- ];
- // Hàm lưu ID tin nhắn vào file
- function saveMessageId(messageId) {
- fs.writeFileSync(messageFile, JSON.stringify({ messageId }, null, 2));
- }
- // Hàm lấy ID tin nhắn từ file
- function getMessageId() {
- if (fs.existsSync(messageFile)) {
- const data = JSON.parse(fs.readFileSync(messageFile));
- return data.messageId;
- }
- return null;
- }
- // Khi bot sẵn sàng
- client.on('ready', async () => {
- console.log(`Logged in as ${client.user.tag}`);
- const channel = await client.channels.fetch(channelId);
- // Lấy ID tin nhắn đã lưu
- let messageId = getMessageId();
- let message;
- if (messageId) {
- try {
- // Thử lấy lại tin nhắn từ ID đã lưu
- message = await channel.messages.fetch(messageId);
- } catch (error) {
- console.error('Không tìm thấy tin nhắn cũ, gửi lại embed mới.');
- messageId = null;
- }
- }
- // Nếu không có tin nhắn hợp lệ, gửi embed mới
- if (!messageId) {
- const embed = new EmbedBuilder()
- .setColor(0x0099ff)
- .setTitle('Chọn role mua bán để truy cập kênh mua bán riêng!')
- .setDescription(
- 'Chọn từ menu bên dưới để thêm vai trò tương ứng.\nNếu đã chọn, bạn có thể gỡ vai trò bằng cách chọn lại.'
- );
- const options = games.map((game) =>
- new StringSelectMenuOptionBuilder()
- .setLabel(game.label)
- .setEmoji(game.emoji)
- .setValue(game.roleId)
- );
- const selectMenu = new StringSelectMenuBuilder()
- .setCustomId('select-games')
- .setPlaceholder('Chọn vai trò bạn cần!')
- .setMinValues(0)
- .setMaxValues(games.length)
- .addOptions(options);
- const row = new ActionRowBuilder().addComponents(selectMenu);
- message = await channel.send({ embeds: [embed], components: [row] });
- // Lưu ID tin nhắn mới
- saveMessageId(message.id);
- }
- console.log(`Theo dõi tin nhắn với ID: ${message.id}`);
- });
- // Xử lý tương tác từ menu
- client.on('interactionCreate', async (interaction) => {
- // Xử lý lệnh Slash Command
- if (interaction.isCommand()) {
- const command = client.commands2.get(interaction.commandName);
- if (!command) return;
- // Ghi log và xử lý lệnh
- try {
- console.log(
- `[${interaction.guild.name}] ${interaction.user.username} used /${interaction.commandName}`
- );
- await command.execute(interaction, client);
- } catch (error) {
- console.error(error);
- return interaction.reply({
- content: "An error occurred while executing this command!",
- ephemeral: true,
- fetchReply: true,
- });
- }
- }
- // Xử lý tương tác từ menu
- if (interaction.isStringSelectMenu()) {
- if (interaction.customId !== 'select-games') return;
- const member = interaction.member;
- const selectedRoles = interaction.values;
- const rolesToAdd = [];
- const rolesToRemove = [];
- games.forEach((game) => {
- const hasRole = member.roles.cache.has(game.roleId);
- if (selectedRoles.includes(game.roleId)) {
- if (!hasRole) rolesToAdd.push(game.roleId);
- } else {
- if (hasRole) rolesToRemove.push(game.roleId);
- }
- });
- // Thêm vai trò
- if (rolesToAdd.length > 0) {
- await member.roles.add(rolesToAdd);
- }
- // Gỡ vai trò
- if (rolesToRemove.length > 0) {
- await member.roles.remove(rolesToRemove);
- }
- // Phản hồi người dùng
- await interaction.reply({
- content: `Cập nhật thành công!\n\n**Đã thêm vai trò**: ${
- rolesToAdd.length > 0
- ? rolesToAdd.map((id) => `<@&${id}>`).join(', ')
- : 'Không có'
- }\n**Đã gỡ vai trò**: ${
- rolesToRemove.length > 0
- ? rolesToRemove.map((id) => `<@&${id}>`).join(', ')
- : 'Không có'
- }`,
- ephemeral: true,
- });
- }
- // if (!interaction.isStringSelectMenu()) return;
- // if (interaction.customId !== 'select-games') return;
- // const member = interaction.member;
- // const selectedRoles = interaction.values;
- // const rolesToAdd = [];
- // const rolesToRemove = [];
- // games.forEach((game) => {
- // const hasRole = member.roles.cache.has(game.roleId);
- // if (selectedRoles.includes(game.roleId)) {
- // if (!hasRole) rolesToAdd.push(game.roleId);
- // } else {
- // if (hasRole) rolesToRemove.push(game.roleId);
- // }
- // });
- // // Thêm vai trò
- // if (rolesToAdd.length > 0) {
- // await member.roles.add(rolesToAdd);
- // }
- // // Gỡ vai trò
- // if (rolesToRemove.length > 0) {
- // await member.roles.remove(rolesToRemove);
- // }
- // // Phản hồi người dùng
- // await interaction.reply({
- // content: `Cập nhật thành công!\n\n**Đã thêm vai trò**: ${
- // rolesToAdd.length > 0
- // ? rolesToAdd.map((id) => `<@&${id}>`).join(', ')
- // : 'Không có'
- // }\n**Đã gỡ vai trò**: ${
- // rolesToRemove.length > 0
- // ? rolesToRemove.map((id) => `<@&${id}>`).join(', ')
- // : 'Không có'
- // }`,
- // ephemeral: true
- // });
- });
- // Xác minh captcha từ tin nhắn riêng
- client.on('messageCreate', async message => {
- // if (message.author.id !== "1145030539074600970") return;
- if (message.author.bot) return;
- if (!message.guild) return;
- // Kết nối MongoDB
- // const captchaCollection = db.collection('user_captchas');
- // // Xử lý tin nhắn DM cho xác minh captcha
- // if (message.channel.type === ChannelType.DM) {
- // const userCaptchaData = await captchaCollection.findOne({ userId: message.author.id });
- // if (userCaptchaData && userCaptchaData.text) {
- // console.log(`Nhận được trả lời captcha từ ${message.author.tag}: ${message.content}`);
- // try {
- // // Kiểm tra nếu nội dung tin nhắn trùng với captcha
- // if (message.content === userCaptchaData.text) {
- // await message.reply('<a:hyc_decor_verifypink:1300326469804884000> Xác minh captcha thành công! Bạn có thể tiếp tục sử dụng các lệnh Economy.');
- // // Xóa captcha khỏi cơ sở dữ liệu sau khi xác minh thành công
- // await captchaCollection.deleteOne({ userId: message.author.id });
- // console.log(`Captcha của ${message.author.tag} đã được xác minh thành công và xóa khỏi cơ sở dữ liệu.`);
- // } else {
- // await message.reply('<:x_:1300327193293099059> Captcha không chính xác. Vui lòng thử lại.');
- // console.log(`Captcha nhập sai từ ${message.author.tag}`);
- // }
- // } catch (error) {
- // console.error(`Lỗi khi xử lý phản hồi captcha của ${message.author.tag}:`, error);
- // }
- // return;
- // }
- // }
- // Cập nhật cấp độ của người dùng khi gửi tin nhắn
- const xpGain = Math.floor(Math.random() * 10) + 5; // Nhận ngẫu nhiên từ 5-15 XP mỗi lần nhắn
- await updateLevel(message.author.id, message, xpGain);
- // Kiểm tra người dùng được tag có AFK không
- message.mentions.users.forEach(async (user) => {
- const afkUser = await afkUsersCollection.findOne({ userId: user.id });
- if (afkUser) {
- await afkTagsCollection.insertOne({
- userId: user.id,
- taggerId: message.author.id,
- content: message.content,
- messageId: message.id,
- channelId: message.channel.id,
- timestamp: Date.now(),
- });
- }
- });
- // console.log("duoc")
- // Kiểm tra nếu người dùng AFK gửi tin nhắn
- const afkUser = await afkUsersCollection.findOne({ userId: message.author.id });
- if (afkUser) {
- // Tăng số lượng tin nhắn của người dùng AFK
- const newMessageCount = (afkUser.messageCount || 0) + 1;
- await afkUsersCollection.updateOne(
- { userId: message.author.id },
- { $set: { messageCount: newMessageCount } }
- );
- // Nếu người dùng đã gửi quá 3 tin nhắn, xóa trạng thái AFK
- if (newMessageCount > 1) {
- await afkUsersCollection.deleteOne({ userId: message.author.id });
- const tags = await afkTagsCollection.find({ userId: message.author.id }).toArray();
- await afkTagsCollection.deleteMany({ userId: message.author.id });
- if (tags.length === 0) {
- message.reply(`Bạn đã thoát AFK trong <t:${afkUser.timestamp}:R>.`);
- } else {
- const afkEmbed = new EmbedBuilder()
- .setAuthor({ name: message.author.tag, iconURL: message.author.displayAvatarURL() })
- .setTitle('AFK Logs')
- .setDescription(`Bạn đã thoát AFK trong <t:${Math.floor(afkUser.timestamp)}:R>.`)
- .setColor('#FFB6C1');
- tags.forEach((tag, index) => {
- afkEmbed.addFields({
- name: ` `,
- value: `${index + 1}: <@${tag.taggerId}> - https://discord.com/channels/${message.guild.id}/${tag.channelId}/${tag.messageId}\n${tag.content}`,
- inline: false,
- });
- });
- let currentIndex = 0;
- const rowButtons = new ActionRowBuilder().addComponents(
- new ButtonBuilder().setCustomId('previous').setLabel('⏮').setStyle(ButtonStyle.Primary),
- new ButtonBuilder().setCustomId('next').setLabel('⏭').setStyle(ButtonStyle.Primary)
- );
- const messageWithEmbed = await message.reply({ embeds: [afkEmbed], components: [rowButtons] });
- if (tags.length > 1) {
- const filter = (i) =>
- ['previous', 'next'].includes(i.customId) && i.user.id === message.author.id;
- const collector = messageWithEmbed.createMessageComponentCollector({
- filter,
- time: 60000,
- });
- collector.on('collect', async (i) => {
- if (i.customId === 'next') {
- currentIndex = (currentIndex + 1) % tags.length;
- } else if (i.customId === 'previous') {
- currentIndex = (currentIndex - 1 + tags.length) % tags.length;
- }
- afkEmbed.fields = [];
- afkEmbed.addFields({
- name: `${currentIndex + 1}) <@${tags[currentIndex].taggerId}>`,
- value: `${`https://discord.com/channels/${message.guild.id}/${tags[currentIndex].channelId}/${tags[currentIndex].messageId}`}\n${tags[currentIndex].content}`,
- inline: false,
- });
- await i.update({ embeds: [afkEmbed], components: [rowButtons] });
- });
- collector.on('end', () => {
- messageWithEmbed.edit({ components: [] });
- });
- }
- }
- }
- }
- // Kiểm tra nếu người dùng đang tag người dùng AFK
- message.mentions.users.forEach(async (user) => {
- const afkUser = await afkUsersCollection.findOne({ userId: user.id });
- if (afkUser) {
- const embedafk = new EmbedBuilder()
- .setAuthor({ name: message.author.tag, iconURL: message.author.displayAvatarURL() })
- .setDescription(
- `${user.tag} đang AFK: **${afkUser.reason}** từ <t:${Math.floor(afkUser.timestamp)}:R>.`
- )
- .setColor('#F5B7B1');
- message.reply({ embeds: [embedafk] });
- }
- });
- const guildId = message.guild.id;
- let prefix;
- try {
- const result = await prefixesCollection.findOne({ guildId: message.guild.id });
- // Sử dụng prefix từ MongoDB hoặc mặc định nếu không có
- prefix = result ? result.prefix : defaultPrefix;
- } catch (error) {
- console.error('Lỗi khi lấy prefix từ MongoDB:', error);
- prefix = defaultPrefix; // Nếu có lỗi, dùng prefix mặc định
- }
- // if (message.content.includes('prefix') && message.author.id === '1145030539074600970') {
- // const result = await prefixesCollection.findOne({ guildId: message.guild.id });
- // const currentPrefix = result ? result.prefix : defaultPrefix;
- // const embed = new EmbedBuilder()
- // .setTitle('Prefix hiện tại')
- // .setDescription(`Prefix hiện tại của server là: \`${currentPrefix}\``)
- // .setColor('#FF69B4');
- // message.channel.send({ embeds: [embed] });
- // }
- if (message.content.includes('mimiprefix')) {
- const result = await prefixesCollection.findOne({ guildId: message.guild.id });
- const currentPrefix = result ? result.prefix : defaultPrefix;
- const embed = new EmbedBuilder()
- .setTitle('Prefix hiện tại')
- .setDescription(`Prefix hiện tại của server là: \`${currentPrefix}\``)
- .setColor('#FF69B4');
- message.channel.send({ embeds: [embed] });
- }
- // Nếu tin nhắn không bắt đầu bằng prefix, kiểm tra trò chơi nối chữ
- if (!message.content.startsWith(prefix)) {
- try {
- const romanCountData = await romanCountChannelsCollection.findOne({ guildId });
- if (romanCountData) {
- const { channelId, currentNumber: romanCurrentNumber, lastUserId } = romanCountData;
- if (message.channel.id === channelId) {
- const roman = message.content.trim().toUpperCase();
- const resetRole = message.guild.roles.cache.find(role => role.name === "Nối từ");
- if (message.content.toLowerCase() === "resetlama" &&
- resetRole &&
- message.member.roles.cache.has(resetRole.id))
- {
- await resetRomanCountGame(message.channel, guildId, romanCountChannelsCollection);
- return;
- }
- if (!validateRoman(roman)) {
- await message.react('<:x_:1300327193293099059>');
- return message.reply('Vui lòng gửi một số La Mã hợp lệ!').then(msg => setTimeout(() => msg.delete(), 2000));
- }
- // Chuyển đổi currentNumber từ La Mã sang số
- const currentNumber = fromRoman(romanCurrentNumber);
- const newNumber = fromRoman(roman);
- const nextNumber = currentNumber + 1;
- const nextRomanNumber = toRoman(nextNumber);
- if (newNumber !== nextNumber) {
- await message.react('<:x_:1300327193293099059>');
- return message.reply(`Số La Mã tiếp theo phải là ${nextRomanNumber}!`).then(msg => setTimeout(() => msg.delete(), 2000));
- }
- if (lastUserId === message.author.id) {
- await message.react('<:x_:1300327193293099059>');
- return message.reply('Bạn không thể gửi liên tiếp! Vui lòng chờ người khác.').then(msg => setTimeout(() => msg.delete(), 2000));
- }
- // Cập nhật currentNumber trong cơ sở dữ liệu thành La Mã
- await romanCountChannelsCollection.updateOne(
- { guildId },
- { $set: { currentNumber: nextRomanNumber, lastUserId: message.author.id } }
- );
- await message.react('<a:hyc_decor_verifypink:1300326469804884000>');
- }
- }
- } catch (err) {
- console.error('Có lỗi xảy ra trong quá trình xử lý đếm số La Mã:', err);
- message.reply('Có lỗi xảy ra trong quá trình đếm số La Mã. Vui lòng thử lại.');
- }
- try {
- const countChannelData = await countChannelsCollection.findOne({ guildId });
- if (countChannelData) {
- const { channelId, currentNumber, lastUserId } = countChannelData;
- // Kiểm tra xem tin nhắn có gửi trong kênh đếm số đã thiết lập hay không
- if (message.channel.id === channelId) {
- const newNumber = parseInt(message.content.trim());
- const resetRole = message.guild.roles.cache.find(role => role.name === "Nối từ");
- // Reset nếu người gửi có vai trò và nhập lệnh reset
- if (message.content.toLowerCase() === "resetso" &&
- resetRole &&
- message.member.roles.cache.has(resetRole.id))
- {
- await resetCountGame(message.channel, guildId, countChannelsCollection);
- return;
- }
- // Kiểm tra nếu tin nhắn không phải là số hợp lệ
- if (isNaN(newNumber)) {
- await message.react('<:x_:1300327193293099059>');
- return message.reply('Vui lòng gửi một số hợp lệ!').then(msg => setTimeout(() => msg.delete(), 2000));
- }
- // Kiểm tra nếu người gửi số tiếp theo đúng
- if (newNumber !== currentNumber + 1) {
- await message.react('<:x_:1300327193293099059>');
- return message.reply(`Số tiếp theo phải là ${currentNumber + 1}!`).then(msg => setTimeout(() => msg.delete(), 2000));
- }
- // Kiểm tra nếu người gửi trùng với người trước đó
- if (lastUserId === message.author.id) {
- await message.react('<:x_:1300327193293099059>');
- return message.reply('Bạn không thể gửi liên tiếp! Vui lòng chờ người khác.').then(msg => setTimeout(() => msg.delete(), 2000));
- }
- // Cập nhật số hiện tại và người gửi cuối cùng
- await countChannelsCollection.updateOne(
- { guildId },
- { $set: { currentNumber: newNumber, lastUserId: message.author.id } }
- );
- // Xác nhận số hợp lệ
- await message.react('<a:hyc_decor_verifypink:1300326469804884000>');
- }
- }
- } catch (err) {
- console.error('Có lỗi xảy ra trong quá trình xử lý đếm số:', err);
- message.reply('Có lỗi xảy ra trong quá trình đếm số. Vui lòng thử lại.');
- }
- // Hàm loại bỏ dấu để so sánh chính xác ký tự
- function removeDiacritics(str) {
- return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
- }
- try {
- const guildId = message.guild.id;
- // Kiểm tra xem kênh hiện tại có phải là kênh nối chữ không
- const wordChainChannel = await wordchainChannelsCollection.findOne({ guildId });
- if (wordChainChannel && message.channel.id === wordChainChannel.channelId) {
- const word = message.content.trim().toLowerCase();
- // Kiểm tra nếu tin nhắn chỉ chứa khoảng trắng, trống hoặc chỉ có ký tự đặc biệt/dấu câu
- if (!message.content.trim() || /^[^a-zA-Z0-9\u00C0-\u017F]+$/.test(message.content.trim())) {
- return;
- // await message.react('<:x_:1300327193293099059>');
- // return message.reply('Tin nhắn không được để trống, chỉ chứa khoảng trắng hoặc chỉ có ký tự đặc biệt!').then(msg => setTimeout(() => msg.delete(), 2000));
- }
- // Kiểm tra vai trò "Nối từ" và tin nhắn "restarten"
- const resetRole = message.guild.roles.cache.find(role => role.name === "Nối từ");
- if (word === "restarten" &&
- resetRole &&
- message.member.roles.cache.has(resetRole.id))
- {
- await resetGame(message.channel, guildId, collections);
- return;
- }
- const roundData = await wordchainRoundsCollection.findOne({ guildId });
- if (roundData) {
- const { word: lastWord, lastUser, roundNumber } = roundData;
- // Kiểm tra nếu người chơi vừa gửi tin nhắn là người đã chơi lượt trước
- if (lastUser === message.author.id) {
- await message.react('<:x_:1300327193293099059>');
- return message.reply('Vui lòng đợi người tiếp theo nối chữ!').then(msg => setTimeout(() => msg.delete(), 2000));
- }
- // Lấy ký tự cuối của lastWord và ký tự đầu của word mới
- const lastChar = removeDiacritics(lastWord[lastWord.length - 1]);
- const firstChar = removeDiacritics(word[0]);
- const toggleState = await toggleStatesCollection.findOne({ guildId });
- const isWordChainActive = toggleState && toggleState.state;
- if (isWordChainActive) {
- // Kiểm tra nếu từ mới không nối được với từ cuối
- if (lastChar !== firstChar) {
- await message.react('<:x_:1300327193293099059>');
- message.reply('Từ này không nối được với từ trước, và bị mất chuỗi win!').then(msg => setTimeout(() => msg.delete(), 2000));
- resetGame(message.channel, guildId, db);
- return;
- }
- // Kiểm tra nếu từ mới không có trong từ điển
- if (!wordsE || !wordsE.includes(word)) {
- await message.react('<:x_:1300327193293099059>');
- message.reply('Từ này không có trong từ điển tiếng Anh, và bị mất chuỗi win!').then(msg => setTimeout(() => msg.delete(), 2000));
- resetGame(message.channel, guildId, db);
- return;
- }
- }
- if (!isWordChainActive) {
- // Kiểm tra nếu từ mới không nối được với từ cuối
- if (lastChar !== firstChar) {
- await message.react('<:x_:1300327193293099059>');
- message.reply('Từ này không nối được với từ trước!').then(msg => setTimeout(() => msg.delete(), 2000));
- return;
- }
- // Kiểm tra nếu từ mới không có trong từ điển
- if (!wordsE || !wordsE.includes(word)) {
- await message.react('<:x_:1300327193293099059>');
- message.reply('Từ này không có trong từ điển tiếng Anh!').then(msg => setTimeout(() => msg.delete(), 2000));
- return;
- }
- }
- // Kiểm tra nếu từ đã được sử dụng trước đó
- const usedWord = await wordchainWordsCollection.findOne({ guildId, word });
- if (usedWord) {
- await message.react('<:x_:1300327193293099059>');
- message.reply('Từ này đã được sử dụng rồi!').then(msg => setTimeout(() => msg.delete(), 2000));
- return;
- }
- // Cập nhật vòng chơi mới và lưu từ đã sử dụng
- const newRoundNumber = roundNumber + 1;
- await wordchainWordsCollection.insertOne({ guildId, word });
- await wordchainRoundsCollection.updateOne(
- { guildId },
- { $set: { word, lastUser: message.author.id, roundNumber: newRoundNumber } }
- );
- await message.react('<a:hyc_decor_verifypink:1300326469804884000>');
- const emojis = newRoundNumber.toString().split('').map(num => numberEmojis[parseInt(num)]).join(' ');
- emojis.split(' ').forEach(async emoji => await message.react(emoji));
- // Cập nhật số tiền và điểm win của người dùng
- await usersCollection.updateOne(
- { userId: message.author.id }, // Đảm bảo dùng đúng trường userId
- {
- $inc: { coins: 12, winen: 1 } // Tăng thêm 1 điểm win
- },
- { upsert: true }
- );
- } else {
- return;
- }
- }
- } catch (err) {
- message.reply(`Có lỗi xảy ra trong quá trình nối chữ. Vui lòng thử lại.\n ${err}`);
- }
- }
- // Nếu tin nhắn không bắt đầu bằng prefix, kiểm tra trò chơi nối chữ
- if (!message.content.startsWith(prefix)) {
- // noituvi
- let queryCount = 0;
- try {
- const blackListWords = dictionary.getReportWords();
- global.dicData = global.dicData.filter(item => !blackListWords.includes(item));
- const checkDict = (word) => global.dicData.includes(word.toLowerCase());
- const sendMessageToChannel = async (msg, channelId) => {
- const channel = message.client.channels.cache.get(channelId);
- if (channel) {
- await channel.send({ content: msg });
- }
- };
- const sendAutoDeleteMessageToChannel = async (msg, channelId, seconds = 15) => {
- const channel = message.client.channels.cache.get(channelId);
- if (channel) {
- const sentMessage = await channel.send({ content: msg });
- setTimeout(() => sentMessage.delete(), seconds * 1000);
- }
- };
- // Kiểm tra xem từ có đáp án hợp lệ trong từ điển không
- const checkIfHaveAnswer = (word) => {
- const wordParts = word.split(/ +/);
- const lastPart = wordParts[wordParts.length - 1].toLowerCase();
- for (let i = 0; i < global.dicData.length; i++) {
- const tempWord = global.dicData[i];
- const tempParts = tempWord.split(/ +/);
- // Kiểm tra nếu từ tiếp theo có thể bắt đầu bằng phần cuối của từ trước
- if (tempParts.length > 1 && tempParts[0].toLowerCase() === lastPart && tempWord !== word) {
- return true;
- }
- }
- return false;
- };
- // Kiểm tra nếu từ tiếp theo của người chơi hợp lệ dựa vào từ cuối của từ trước đó
- const checkIfValidNextWord = (lastWord, nextWord) => {
- const lastWordParts = lastWord.split(/ +/);
- const lastPart = lastWordParts[lastWordParts.length - 1].toLowerCase();
- const nextWordParts = nextWord.split(/ +/);
- const firstPart = nextWordParts[0].toLowerCase();
- // Từ tiếp theo phải bắt đầu với phần cuối của từ trước
- return firstPart === lastPart;
- };
- const checkIfGameEnds = (lastWord) => {
- const lastPart = lastWord.split(/ +/).pop().toLowerCase();
- return global.dicData.some(word => word.startsWith(lastPart) && word !== lastWord);
- };
- const checkIfHaveAnswerInDb = async (word, usedWords) => {
- const lastPart = word.split(/ +/).pop().toLowerCase();
- for (const temp of global.dicData) {
- queryCount++;
- const tempParts = temp.split(/ +/);
- if (tempParts[0].toLowerCase() === lastPart && !usedWords.includes(temp)) {
- return true;
- }
- }
- return false;
- };
- const randomWord = () => {
- const wordIndex = Math.floor(Math.random() * (global.dicData.length - 1))
- queryCount += wordIndex + 1
- const rWord = global.dicData[wordIndex]
- return checkIfHaveAnswer(rWord) ? rWord : randomWord()
- }
- const startGame = async (channelId) => {
- const word = randomWord();
- const newGame = {
- guildId: message.guild.id,
- channelId,
- running: true,
- currentPlayer: {},
- words: [word],
- };
- await gamesCollection.updateOne(
- { guildId: message.guild.id, channelId },
- { $set: newGame },
- { upsert: true }
- );
- sendMessageToChannel(`Từ bắt đầu: **${word}**`, channelId);
- };
- const endGame = async (channelId, lastPlayerId, wordCount) => {
- await gamesCollection.updateOne(
- { guildId: message.guild.id, channelId },
- { $set: { running: false } }
- );
- const DAILY_COINS = Math.floor(Math.random() * 100) + 1;
- sendMessageToChannel(
- `<@${lastPlayerId}> đã chiến thắng sau ${wordCount} lượt! Nhận ${DAILY_COINS} <:xumimi:1261591338290511973> - 1 lượt đúng nhận 12 <:xumimi:1261591338290511973> \n trò chơi mới sẽ bắt đầu.`,
- channelId
- );
- stats.addRoundPlayedCount();
- await startGame(channelId);
- const now = new Date();
- // Cập nhật số tiền của người dùng và thời gian nhận thưởng lần cuối
- await usersCollection.updateOne(
- { lastPlayerId },
- { $inc: { coins: DAILY_COINS, winvi: 1 }, $set: { lastDaily: now } },
- { upsert: true }
- );
- };
- const stopGame = async (channelId) => {
- await gamesCollection.updateOne(
- { guildId: message.guild.id, channelId },
- { $set: { running: false } }
- );
- };
- const checkIfWordUsed = async (channelId, word) => {
- const gameData = await gamesCollection.findOne({ guildId: message.guild.id, channelId });
- return gameData?.words.includes(word);
- };
- // Kiểm tra kênh cấu hình cho trò chơi
- const channelConfig = await channelsCollection.findOne({ guildId: message.guild.id });
- if (!channelConfig || !channelConfig.channelId) {
- return;
- }
- const configChannel = channelConfig.channelId;
- if (message.channel.id !== configChannel) return;
- // Khởi tạo trò chơi nếu chưa tồn tại
- const gameData = await gamesCollection.findOne({ guildId: message.guild.id, channelId: configChannel });
- if (!gameData) {
- await startGame(configChannel);
- }
- // Lấy danh sách `words` từ MongoDB
- const words = gameData.words;
- if (message.content === START_COMMAND) {
- if (message.author.id === "1145030539074600970") {
- const isRunning = gameData?.running;
- if (!isRunning) {
- sendMessageToChannel(`Trò chơi đã bắt đầu!`, configChannel);
- await startGame(configChannel);
- } else {
- sendMessageToChannel('Trò chơi vẫn đang tiếp tục. Bạn có thể dùng `resetvi`', configChannel);
- }
- }
- if(!message.member.permissionsIn(configChannel).has(PermissionsBitField.Flags.ManageChannels) && !message.member.roles.cache.some(role => role.name === 'Nối từ')) {
- message.reply({
- content: 'Lệnh chỉ dành cho Manager Channel hoặc người dùng có name role: `Nối từ`',
- ephemeral: true
- })
- return
- }
- const isRunning = gameData?.running;
- if (!isRunning) {
- sendMessageToChannel(`Trò chơi đã bắt đầu!`, configChannel);
- await startGame(configChannel);
- } else {
- sendMessageToChannel('Trò chơi vẫn đang tiếp tục. Bạn có thể dùng `resetvi`', configChannel);
- }
- return;
- } else if (message.content === STOP_COMMAND) {
- if (message.author.id === "1145030539074600970") {
- await stopGame(configChannel);
- sendMessageToChannel('Trò chơi đã kết thúc.', configChannel);
- sendMessageToChannel(`Trò chơi mới bắt đầu!`, configChannel);
- await startGame(configChannel);
- return;
- }
- if(!message.member.permissionsIn(configChannel).has(PermissionsBitField.Flags.ManageChannels) &&
- !message.member.roles.cache.some(role => role.name === 'Nối từ'))
- {
- message.reply({
- content: 'Lệnh chỉ dành cho Manager Channel hoặc người dùng có name role: `Nối từ`',
- ephemeral: true
- })
- return
- }
- await stopGame(configChannel);
- sendMessageToChannel('Trò chơi đã kết thúc.', configChannel);
- sendMessageToChannel(`Trò chơi mới bắt đầu!`, configChannel);
- await startGame(configChannel);
- return;
- }
- const currentWord = message.content.trim().toLowerCase();
- if (await checkIfWordUsed(configChannel, currentWord)) {
- message.react('<:x_:1300327193293099059>')
- return sendAutoDeleteMessageToChannel('Từ này đã được sử dụng!', configChannel);
- }
- // if (!checkDict(currentWord)) {
- // message.react('<:x_:1300327193293099059>')
- // return sendAutoDeleteMessageToChannel('Từ này không có trong từ điển!', configChannel);
- // }
- if (!checkDict(currentWord)) {
- message.react('<:x_:1300327193293099059>');
- // Kiểm tra quyền SEND_MESSAGES của bot trong kênh
- // if (configChannel.permissionsFor(message.guild.me).has(PermissionsBitField.Flags.SendMessages)) {
- sendAutoDeleteMessageToChannel('Từ này không có trong từ điển!', configChannel);
- // } else {
- // console.warn(`Bot không có quyền gửi tin nhắn trong kênh ${configChannel.id}`);
- // }
- return;
- }
- // Kiểm tra xem người chơi có phải là người đã nối trước đó không
- if (gameData.currentPlayer && gameData.currentPlayer.id === message.author.id) {
- message.react('<:x_:1300327193293099059>');
- return sendAutoDeleteMessageToChannel('Bạn không thể nối tiếp chính mình!', configChannel);
- }
- if (words.length > 0) {
- const lastWord = words[words.length - 1];
- // Kiểm tra nếu từ tiếp theo bắt đầu bằng từ cuối của từ trước
- if (!checkIfValidNextWord(lastWord, message.content.trim().toLowerCase())) {
- message.react('<:x_:1300327193293099059>');
- sendAutoDeleteMessageToChannel(`Từ này không bắt đầu với "${lastWord.split(/ +/).slice(-1)[0]}"`, configChannel);
- return;
- }
- }
- // Cập nhật từ mới và người chơi hiện tại trong trò chơi
- await gamesCollection.updateOne(
- { guildId: message.guild.id, channelId: configChannel },
- {
- $push: { words: currentWord },
- $set: { 'currentPlayer.id': message.author.id, 'currentPlayer.name': message.author.username },
- }
- );
- message.react('<a:hyc_decor_verifypink:1300326469804884000>')
- // Cập nhật số tiền của người dùng và thời gian nhận thưởng lần cuối
- await usersCollection.updateOne(
- { lastPlayerId },
- {
- $inc: { coins: 12 }
- },
- { upsert: true }
- );
- stats.addWordPlayedCount();
- if (!await checkIfHaveAnswerInDb(currentWord, words)) {
- await endGame(configChannel, message.author.id, words.length);
- }
- } catch (error) {
- console.error('Lỗi khi thực thi trò chơi:', error);
- }
- return;
- }
- if (!message.content.startsWith(prefix)) return;
- // Kiểm tra xem bot có đang quản lý shard của server này không
- // const shard = client.shard?.ids?.[0];
- // const shardId = client.guilds.cache.get(message.guild.id)?.shardId;
- // if (shard !== shardId) return; // Bỏ qua nếu không phải shard của worker này
- const args = message.content.startsWith(prefix)
- ? message.content.slice(prefix.length).trim().split(/ +/)
- : message.content.split(/ +/).slice(1);
- const commandName = args.shift().toLowerCase();
- const command = client.commands.get(commandName) || client.commands.get(client.aliases.get(commandName));
- if (!command) return;
- // Fetch the disabled commands and categories for this guild and channel
- const disabledData = await commandStatusCollection.findOne({ guild_id: message.guild.id, channel_id: message.channel.id }) || {};
- const disabledCommands = disabledData.disabled_commands || [];
- const disabledCategories = disabledData.disabled_categories || [];
- // Check if the command or its category is disabled
- if (disabledCommands.includes(command.name) || disabledCategories.includes(command.category)) {
- return message.reply(`⚠️ Lệnh \`${command.name}\` đã bị tắt trong kênh này.`).then(msg => {
- setTimeout(() => msg.delete(), 5000);
- }).catch(console.error);
- }
- const now = Date.now();
- const timestamps = cooldowns.get(command.name) || new Collection();
- const cooldownAmount = (command.cooldown || 1) * 1000;
- // Check if the user is the one to bypass the cooldown
- if (message.author.id !== '1145030539074600970' && message.author.id !== '476138981273239563') {
- if (timestamps.has(message.author.id)) {
- const expirationTime = timestamps.get(message.author.id) + cooldownAmount;
- if (now < expirationTime) {
- const timeLeft = Math.ceil((expirationTime - now) / 1000);
- message.reply(`Xin hãy chờ <t:${Math.floor(expirationTime / 1000)}:R> nữa trước khi sử dụng lệnh \`${command.name}\` một lần nữa.`).then(msg => setTimeout(() => msg.delete(), expirationTime - now));
- return;
- }
- }
- timestamps.set(message.author.id, now);
- cooldowns.set(command.name, timestamps);
- setTimeout(() => timestamps.delete(message.author.id), cooldownAmount);
- }
- const userId = message.author.id;
- // // Kiểm tra trạng thái cấm từ cơ sở dữ liệu
- // const restriction = await restrictionsCollection.findOne({ userId });
- // if (restriction && now < restriction.until) {
- // const remaining = Math.ceil((restriction.until - now) / 1000 / 60); // Thời gian còn lại tính bằng phút
- // return message.reply(`Bạn đã bị cấm sử dụng lệnh trong danh mục Economy. Hết hạn trong ${remaining} phút.`);
- // } else if (restriction && now >= restriction.until) {
- // await restrictionsCollection.deleteOne({ userId }); // Xóa khỏi cơ sở dữ liệu nếu đã hết hạn
- // }
- // // Kiểm tra nếu lệnh thuộc danh mục Economy
- // if (command.category === 'Economy') {
- // const userCaptchaData = await captchaCollection.findOne({ userId });
- // const userCaptchaCount = userCaptchaData ? userCaptchaData.count || 0 : 0;
- // const lastCommandAt = userCaptchaData ? userCaptchaData.lastCommandAt || 0 : 0;
- // const currentTime = Date.now();
- // // Thời gian chờ trước khi reset số lần (đơn vị: mili giây)
- // const cooldownTime = 60 * 1000; // 60 giây
- // // Nếu quá thời gian chờ, reset số lượng lệnh Economy đã sử dụng
- // let newCount;
- // if (currentTime - lastCommandAt > cooldownTime) {
- // newCount = 1;
- // } else {
- // newCount = userCaptchaCount + 1;
- // }
- // // Nếu người dùng spam quá nhiều lệnh Economy trong thời gian ngắn, gửi captcha
- // if (newCount > 20) {
- // if (!userCaptchaData || !userCaptchaData.text) {
- // const captcha = generateCaptchaText();
- // const captchaImage = await createCaptchaImage(captcha);
- // // Lưu captcha mới vào cơ sở dữ liệu
- // await captchaCollection.updateOne(
- // { userId },
- // { $set: { userId, text: captcha, createdAt: Date.now(), count: newCount } },
- // { upsert: true }
- // );
- // try {
- // await message.author.send({
- // content: 'Bạn đang sử dụng lệnh trong danh mục Economy quá nhanh. Vui lòng hoàn thành captcha để tiếp tục.',
- // files: [captchaImage],
- // });
- // message.reply('Vui lòng kiểm tra tin nhắn riêng để hoàn thành captcha xác minh.');
- // // Xóa ảnh sau khi gửi thành công
- // fs.unlinkSync(captchaImage);
- // } catch (err) {
- // console.error('Lỗi khi gửi DM:', err);
- // message.reply('Không thể gửi DM. Vui lòng bật DMs từ các thành viên trong máy chủ.');
- // // Xóa ảnh sau khi gửi thành công
- // fs.unlinkSync(captchaImage);
- // }
- // // Kiểm tra sau 15 phút nếu captcha chưa được giải
- // setTimeout(async () => {
- // const captchaData = await captchaCollection.findOne({ userId });
- // if (captchaData && captchaData.text === captcha) {
- // const attempts = (captchaData.attempts || 0) + 1;
- // let duration = 0;
- // if (attempts === 1) duration = 24 * 60 * 60 * 1000; // 1 ngày
- // else if (attempts === 2) duration = 30 * 24 * 60 * 60 * 1000; // 1 tháng
- // else if (attempts >= 3) duration = Infinity; // Vĩnh viễn
- // // Xóa captcha chưa giải và cập nhật trạng thái cấm vào cơ sở dữ liệu
- // await captchaCollection.deleteOne({ userId });
- // await restrictionsCollection.updateOne(
- // { userId },
- // { $set: { userId, until: duration !== Infinity ? Date.now() + duration : Infinity, attempts } },
- // { upsert: true }
- // );
- // if (duration !== Infinity) {
- // await message.author.send(`Bạn đã bị cấm sử dụng lệnh trong danh mục Economy trong ${attempts === 1 ? '1 ngày' : '1 tháng'}.`);
- // } else {
- // await message.author.send('Bạn đã bị cấm sử dụng lệnh trong danh mục Economy vĩnh viễn.');
- // }
- // }
- // }, 15 * 60 * 1000); // 15 phút
- // }
- // return;
- // }
- // // Cập nhật lại số lượng lệnh Economy đã sử dụng và thời gian thực hiện lệnh cuối
- // await captchaCollection.updateOne(
- // { userId },
- // { $set: { userId, count: newCount, lastCommandAt: currentTime } },
- // { upsert: true }
- // );
- // }
- // // Kiểm tra nếu người dùng có captcha chưa hoàn thành trước khi cho phép thực thi lệnh
- // const userCaptchaData = await captchaCollection.findOne({ userId });
- // if (userCaptchaData && userCaptchaData.text) {
- // return message.reply('Vui lòng hoàn thành captcha trong tin nhắn riêng để tiếp tục sử dụng các lệnh Economy.');
- // }
- try {
- await command.execute(message, args, client, collections);
- } catch (error) {
- console.error(`Lỗi khi thực thi lệnh: ${commandName}`, error);
- // Gửi lỗi đến kênh hoặc log ra console
- // await message.reply('Đã xảy ra lỗi khi thực thi lệnh này!').catch(console.error);
- // await message.channel.send(`Lỗi: \`\`\`${error.message}\`\`\``).catch(console.error);
- // await message.channel.send(`Vị trí lỗi: \`\`\`${error.stack}\`\`\``).catch(console.error);
- }
- });
- const WEBHOOK_URL2 = 'https://discord.com/api/webhooks/1316262829346521149/s3KnlNX8CykPxrcRnuHaTawd-BgiVzMDJTzIlNJSJF9LZRrmanNkjT382iiO6H59PCHh';
- // Hàm gửi thông báo đến webhook
- async function sendToWebhook(embed) {
- try {
- await axios.post(WEBHOOK_URL2, {
- embeds: [embed],
- });
- } catch (error) {
- console.error(`[WEBHOOK ERROR] Không thể gửi log đến webhook: ${error}`);
- }
- }
- process.on('uncaughtException', (error) => {
- const errorDetails = error.stack || 'Không thể lấy thông tin lỗi.';
- sendToWebhook({
- title: 'Lỗi chưa xử lý toàn cục',
- description: `Đã xảy ra lỗi chưa xử lý trong ứng dụng.\n\n**Lỗi**:\n${error.message}\n\n**Chi tiết**:\n${errorDetails}`,
- color: 16711680, // Màu đỏ để chỉ lỗi
- timestamp: new Date().toISOString(),
- });
- // Ghi lỗi vào file log
- const fs = require('fs');
- fs.appendFileSync('error.log', `${new Date().toISOString()} - ${errorDetails}\n`);
- // Nếu muốn dừng bot khi có lỗi không xử lý:
- // process.exit(1);
- });
- // process.on('unhandledRejection', (reason, promise) => {
- // sendToWebhook({
- // title: 'Lỗi chưa xử lý Rejection',
- // description: `Một Promise đã bị từ chối mà không có xử lý:\n\n**Lý do**:\n${reason}\n\n**Promise**:\n${JSON.stringify(promise)}`,
- // color: 16711680, // Màu đỏ để chỉ lỗi
- // timestamp: new Date().toISOString(),
- // });
- // });
- process.on('unhandledRejection', (reason, promise) => {
- let errorDetails;
- if (reason instanceof Error) {
- // Nếu lý do là một đối tượng lỗi (Error), lấy chi tiết stack
- errorDetails = reason.stack;
- } else {
- // Nếu lý do không phải Error, chuyển đổi thành chuỗi để log
- errorDetails = JSON.stringify(reason, null, 2);
- }
- console.error('Promise không được xử lý:', errorDetails);
- // Gửi thông tin lỗi đến webhook hoặc ghi vào file
- sendToWebhook({
- title: 'Promise không được xử lý',
- description: `Đã xảy ra lỗi trong Promise mà không được bắt.\n\n**Chi tiết lỗi:**\n\`\`\`${errorDetails}\`\`\``,
- color: 16744448,
- timestamp: new Date().toISOString(),
- });
- // Ghi lỗi vào file log
- const fs = require('fs');
- fs.appendFileSync('error.log', `${new Date().toISOString()} - Promise không được xử lý:\n${errorDetails}\n\n`);
- });
- client.login(config.token);
- // Hàm resetGame để khởi động lại trò chơi
- async function resetGame(channel, guildId, db) {
- const wordsE = fs.readFileSync(path.resolve(__dirname, './data/wordsE.txt'), 'utf-8').split('\n').map(word => word.trim().toLowerCase());
- const startingWord = wordsE[Math.floor(Math.random() * wordsE.length)];
- await wordchainRoundsCollection.updateOne(
- { guildId },
- { $set: { word: startingWord, lastUser: '', roundNumber: 1 } },
- { upsert: true }
- );
- await wordchainWordsCollection.deleteMany({ guildId });
- await channel.send(`Trò chơi nối chữ bắt đầu lại với từ: **${startingWord}**`);
- }
- // Hàm để reset trò chơi đếm số
- // async function resetCountGame(channel, guildId) {
- // try {
- // // Reset số về 0 và cập nhật cơ sở dữ liệu
- // await dataBetaDev.query(
- // `UPDATE count_channels SET current_number = 0, last_user_id = '' WHERE guild_id = ?`,
- // [guildId]
- // );
- // channel.send('Trò chơi đếm số đã được khởi động lại. Con số bắt đầu là 0.');
- // } catch (err) {
- // console.error('Có lỗi khi reset trò chơi đếm số:', err);
- // }
- // }
- // Hàm kiểm tra số La Mã hợp lệ
- function validateRoman(roman) {
- const romanRegex = /^(?=[MDCLXVI])(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/;
- return romanRegex.test(roman);
- }
- // Hàm chuyển đổi số La Mã thành số nguyên
- function fromRoman(roman) {
- const romanMap = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 };
- let num = 0;
- let prev = 0;
- for (let i = roman.length - 1; i >= 0; i--) {
- const current = romanMap[roman[i]];
- // Kiểm tra nếu ký tự không hợp lệ
- if (!current) return NaN;
- if (current < prev) {
- num -= current;
- } else {
- num += current;
- }
- prev = current;
- }
- return num;
- }
- function toRoman(num) {
- if (num <= 0) return ''; // Đảm bảo không tạo chuỗi rỗng cho số không hợp lệ
- const romanNumerals = [
- ["M", 1000],
- ["CM", 900],
- ["D", 500],
- ["CD", 400],
- ["C", 100],
- ["XC", 90],
- ["L", 50],
- ["XL", 40],
- ["X", 10],
- ["IX", 9],
- ["V", 5],
- ["IV", 4],
- ["I", 1]
- ];
- let roman = "";
- for (const [letter, value] of romanNumerals) {
- while (num >= value) {
- roman += letter;
- num -= value;
- }
- }
- return roman;
- }
- // Hàm reset trò chơi đếm số La Mã
- async function resetRomanCountGame(channel, guildId, romanCountChannelsCollection) {
- await romanCountChannelsCollection.updateOne(
- { guildId },
- { $set: { currentNumber: 1, lastUserId: '' } }
- );
- channel.send('Trò chơi đếm số La Mã đã được reset! Con số bắt đầu là I.');
- }
- })();
Advertisement
Add Comment
Please, Sign In to add comment