diff --git a/bot.js b/bot.js index 64e7984..d5d0309 100644 --- a/bot.js +++ b/bot.js @@ -1,27 +1,80 @@ const { Telegraf } = require('telegraf'); +const path = require('path'); +const fs = require('fs'); const Config = require('./props/config.json'); const { isOnSpamWatch } = require('./plugins/lib-spamwatch/spamwatch.js'); const bot = new Telegraf(Config.botToken); +const MAX_RETRIES = 5; +let restartCount = 0; + const loadCommands = () => { - const fs = require('fs'); - const path = require('path'); const commandsPath = path.join(__dirname, 'commands'); - fs.readdirSync(commandsPath).forEach((file) => { - const command = require(path.join(commandsPath, file)); - if (typeof command === 'function') { - command(bot, isOnSpamWatch); + try { + fs.readdirSync(commandsPath).forEach((file) => { + try { + const command = require(path.join(commandsPath, file)); + if (typeof command === 'function') { + command(bot, isOnSpamWatch); + } + } catch (fileError) { + console.error(`Failed to load command file ${file}: ${fileError.message}`); + } + }); + } catch (dirError) { + console.error(`Failed to read commands directory: ${dirError.message}`); + } +}; + + +const sendMessage = async (ctx, text, options = {}) => { + try { + await ctx.reply(text, options); + } catch (error) { + console.error('Error sending message:', error.message); + } +}; + +// Função para iniciar o bot +const startBot = async () => { + try { + await bot.launch(); + console.log('Bot is running...'); + restartCount = 0; + } catch (error) { + console.error('Failed to start bot:', error.message); + if (restartCount < MAX_RETRIES) { + restartCount++; + console.log(`Retrying to start bot... Attempt ${restartCount}`); + setTimeout(startBot, 5000); + } else { + console.error('Maximum retry attempts reached. Exiting.'); + process.exit(1); } + } +}; + +const handleShutdown = (signal) => { + console.log(`Received ${signal}. Stopping bot...`); + bot.stop(signal).then(() => { + console.log('Bot stopped.'); + process.exit(0); }); }; -loadCommands(); +process.once('SIGINT', () => handleShutdown('SIGINT')); +process.once('SIGTERM', () => handleShutdown('SIGTERM')); -bot.launch().then(() => { - console.log('Bot está rodando...'); +process.on('uncaughtException', (error) => { + console.error('Uncaught Exception:', error.message); + console.error(error.stack); }); -process.once('SIGINT', () => bot.stop('SIGINT')); -process.once('SIGTERM', () => bot.stop('SIGTERM')); +process.on('unhandledRejection', (reason, promise) => { + console.error('Unhandled Rejection at:', promise, 'reason:', reason); +}); + +loadCommands(); +startBot(); diff --git a/commands/admin.js b/commands/admin.js index 1bc54ea..cfb1de1 100644 --- a/commands/admin.js +++ b/commands/admin.js @@ -15,88 +15,50 @@ async function collectInfo(ctx) { return { Strings, chatId, userId, isAdmin, onCrew }; } +async function handleMember(ctx, action, successMessage, errorMessage) { + const { Strings, chatId, userId, isAdmin, onCrew } = await collectInfo(ctx); + + if (onCrew || isAdmin) { + if (isNaN(userId)) { + return ctx.reply(Strings.invalidId, { + parse_mode: 'Markdown', + reply_to_message_id: ctx.message.message_id + }); + } + try { + await action(chatId, userId); + const report = successMessage.replace('{userId}', userId); + ctx.reply(report, { + parse_mode: 'Markdown', + reply_to_message_id: ctx.message.message_id + }); + } catch (err) { + const error = errorMessage.replace('{tgErr}', err.message); + ctx.reply(error, { + parse_mode: 'Markdown', + reply_to_message_id: ctx.message.message_id + }); + } + } else { + ctx.reply(Strings.noPermission, { + parse_mode: 'Markdown', + reply_to_message_id: ctx.message.message_id + }); + } +} + module.exports = (bot) => { - bot.command('ban', spamwatchMiddleware, async (ctx) => { - const info = await collectInfo(ctx); - const { Strings, chatId, userId, isAdmin, onCrew } = info; - - if (onCrew || isAdmin) { - if (userId === NaN) { - return ctx.reply( - Strings.invalidId, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - } else { - try { - await ctx.telegram.kickChatMember(chatId, userId); - const banReport = Strings.banSuccess.replace('{userId}', userId); - ctx.reply( - banReport, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - } catch (err) { - const banErr = Strings.banErr.replace('{tgErr}', err); - ctx.reply( - banErr, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - }; - }; - } else { - ctx.reply( - Strings.noPermission, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - }; + bot.command('ban', spamwatchMiddleware, (ctx) => { + handleMember(ctx, (chatId, userId) => ctx.telegram.kickChatMember(chatId, userId), + getStrings(ctx.from.language_code).banSuccess, + getStrings(ctx.from.language_code).banErr + ); }); - bot.command('unban', spamwatchMiddleware, async (ctx) => { - const info = await collectInfo(ctx); - const { Strings, chatId, userId, isAdmin, onCrew } = info; - - if (onCrew || isAdmin) { - if (userId === NaN) { - return ctx.reply( - Strings.invalidId, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - } else { - try { - await ctx.telegram.unbanChatMember(chatId, userId); - const unBanReport = Strings.unBanSuccess.replace('{userId}', userId); - ctx.reply( - unBanReport, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - } catch (err) { - const unBanErr = Strings.unBanErr.replace('{tgErr}', err); - ctx.reply( - unBanErr, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - }; - }; - } else { - ctx.reply( - Strings.noPermission, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - }; + bot.command('unban', spamwatchMiddleware, (ctx) => { + handleMember(ctx, (chatId, userId) => ctx.telegram.unbanChatMember(chatId, userId), + getStrings(ctx.from.language_code).unBanSuccess, + getStrings(ctx.from.language_code).unBanErr + ); }); -}; \ No newline at end of file +}; diff --git a/commands/crew.js b/commands/crew.js index c1ad07b..f98e03b 100644 --- a/commands/crew.js +++ b/commands/crew.js @@ -12,120 +12,76 @@ function formatUptime(uptime) { } function getSystemInfo() { - const platform = os.platform(); - const release = os.release(); - const arch = os.arch(); - const cpuModel = os.cpus()[0].model; - const cpuCores = os.cpus().length; - const totalMemory = (os.totalmem() / (1024 ** 3)).toFixed(2) + ' GB'; - const freeMemory = (os.freemem() / (1024 ** 3)).toFixed(2) + ' GB'; - const loadAverage = os.loadavg().map(avg => avg.toFixed(2)).join(', '); - const uptime = formatUptime(os.uptime()); - const nodeVersion = process.version; - + const { platform, release, arch, cpus, totalmem, freemem, loadavg, uptime } = os; + const [cpu] = cpus(); return `*Server Stats*\n\n` + - `*OS:* \`${platform} ${release}\`\n` + - `*Arch:* \`${arch}\`\n` + - `*Node.js Version:* \`${nodeVersion}\`\n` + - `*CPU:* \`${cpuModel}\`\n` + - `*CPU Cores:* \`${cpuCores} cores\`\n` + - `*RAM:* \`${freeMemory} / ${totalMemory}\`\n` + - `*Load Average:* \`${loadAverage}\`\n` + - `*Uptime:* \`${uptime}\`\n\n`; + `*OS:* \`${platform()} ${release()}\`\n` + + `*Arch:* \`${arch()}\`\n` + + `*Node.js Version:* \`${process.version}\`\n` + + `*CPU:* \`${cpu.model}\`\n` + + `*CPU Cores:* \`${cpus().length} cores\`\n` + + `*RAM:* \`${(freemem() / (1024 ** 3)).toFixed(2)} GB / ${(totalmem() / (1024 ** 3)).toFixed(2)} GB\`\n` + + `*Load Average:* \`${loadavg().map(avg => avg.toFixed(2)).join(', ')}\`\n` + + `*Uptime:* \`${formatUptime(uptime())}\`\n\n`; +} + +async function handleAdminCommand(ctx, action, successMessage, errorMessage) { + const Strings = getStrings(ctx.from.language_code); + const userId = ctx.from.id; + if (Config.admins.includes(userId)) { + try { + await action(); + ctx.reply(successMessage, { + parse_mode: 'Markdown', + reply_to_message_id: ctx.message.message_id + }); + } catch (error) { + ctx.reply(errorMessage.replace('{error}', error.message), { + parse_mode: 'Markdown', + reply_to_message_id: ctx.message.message_id + }); + } + } else { + ctx.reply(Strings.botAdminOnly, { + reply_to_message_id: ctx.message.message_id + }); + } } module.exports = (bot) => { bot.command('getbotstats', spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); - const userId = ctx.from.id || Strings.unKnown; - if (Config.admins.includes(userId)) { - const machineStats = getSystemInfo(); - ctx.reply( - machineStats, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ).catch(error => ctx.reply( - "Error when getting server status:\n" + error, { - reply_to_message_id: ctx.message.message_id - } - )); - } else { - ctx.reply(Strings.botAdminOnly, { + handleAdminCommand(ctx, async () => { + const stats = getSystemInfo(); + await ctx.reply(stats, { + parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id }); - } + }, '', Strings.errorRetrievingStats); // No success message }); bot.command('setbotname', spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); - const userId = ctx.from.id || Strings.unKnown; - if (Config.admins.includes(userId)) { - const botName = ctx.message.text.split(' ').slice(1).join(' '); - const botNameReport = Strings.botNameChanged ? Strings.botNameChanged.replace('{botName}', botName) : `Bot name changed to ${botName}`; - try { - await ctx.telegram.setMyName(botName); - ctx.reply( - botNameReport, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - } catch (error) { - const botNameErr = Strings.botNameErr ? Strings.botNameErr.replace('{tgErr}', error.message) : `Error setting bot name: ${error.message}`; - ctx.reply( - botNameErr, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - } - } else { - ctx.reply(Strings.botAdminOnly, { - reply_to_message_id: ctx.message.message_id - }); - } + const botName = ctx.message.text.split(' ').slice(1).join(' '); + handleAdminCommand(ctx, async () => { + await ctx.telegram.setMyName(botName); + }, Strings.botNameChanged.replace('{botName}', botName), Strings.botNameErr.replace('{tgErr}', '{error}')); }); bot.command('setbotdesc', spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); - const userId = ctx.from.id || Strings.unKnown; - if (Config.admins.includes(userId)) { - const botDesc = ctx.message.text.split(' ').slice(1).join(' '); - const botDescReport = Strings.botDescChanged ? Strings.botDescChanged.replace('{botDesc}', botDesc) : `Bot description changed to ${botDesc}`; - try { - await ctx.telegram.setMyDescription(botDesc); - ctx.reply( - botDescReport, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - } catch (error) { - const botDescErr = Strings.botDescErr ? Strings.botDescErr.replace('{tgErr}', error.message) : `Error setting bot description: ${error.message}`; - ctx.reply( - botDescErr, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - } - } else { - ctx.reply( - Strings.botAdminOnly, { - reply_to_message_id: ctx.message.message_id - }); - } + const botDesc = ctx.message.text.split(' ').slice(1).join(' '); + handleAdminCommand(ctx, async () => { + await ctx.telegram.setMyDescription(botDesc); + }, Strings.botDescChanged.replace('{botDesc}', botDesc), Strings.botDescErr.replace('{tgErr}', '{error}')); }); bot.command('botkickme', spamwatchMiddleware, async (ctx) => { const Strings = getStrings(ctx.from.language_code); - const chatId = ctx.chat.id || Strings.unKnown; - ctx.reply( - Strings.kickingMyself, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id + ctx.reply(Strings.kickingMyself, { + parse_mode: 'Markdown', + reply_to_message_id: ctx.message.message_id }); - ctx.telegram.leaveChat(chatId); + await ctx.telegram.leaveChat(ctx.chat.id); }); }; diff --git a/commands/fun.js b/commands/fun.js index f700fbd..975afe4 100644 --- a/commands/fun.js +++ b/commands/fun.js @@ -3,69 +3,73 @@ const { getStrings } = require('../plugins/checklang.js'); const { isOnSpamWatch } = require('../plugins/lib-spamwatch/spamwatch.js'); const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(isOnSpamWatch); -function furryFunction(ctx) { +function sendRandomReply(ctx, gifUrl, textKey, notTextKey) { const Strings = getStrings(ctx.from.language_code); - if (Math.random() < 0.5 ? "yes" : "no" === "yes") { - ctx.replyWithAnimation( - resources.furryGif, { - caption: Strings.isFurry, + const shouldSendGif = Math.random() < 0.5; + + if (shouldSendGif) { + ctx.replyWithAnimation(gifUrl, { + caption: Strings[textKey], + parse_mode: 'Markdown', + reply_to_message_id: ctx.message.message_id + }).catch(err => { + gifErr = gifErr.replace('{err}', err); + + ctx.reply(Strings.gifErr, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id - } - ); + }); + }); } else { - ctx.reply( - Strings.isNtFurry, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); + ctx.reply(Strings[notTextKey], { + parse_mode: 'Markdown', + reply_to_message_id: ctx.message.message_id + }); } } -function gayFunction(ctx) { + +async function handleDiceCommand(ctx, emoji, delay) { const Strings = getStrings(ctx.from.language_code); - if (Math.random() < 0.5 ? "yes" : "no" === "yes") { - ctx.replyWithAnimation( - resources.gayFlag, { - caption: Strings.isGay, - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - } else { - ctx.reply( - Strings.isNtGay, { - parse_mode: 'Markdown', - reply_to_message_id: ctx.message.message_id - } - ); - } + + const result = await ctx.sendDice({ emoji, reply_to_message_id: ctx.message.message_id }); + const botResponse = Strings.funEmojiResult + .replace('{emoji}', result.dice.emoji) + .replace('{value}', result.dice.value); + + setTimeout(() => { + ctx.reply(botResponse, { + parse_mode: 'Markdown', + reply_to_message_id: ctx.message.message_id + }); + }, delay); } module.exports = (bot) => { bot.command('dice', spamwatchMiddleware, async (ctx) => { - ctx.telegram.sendDice( - ctx.chat.id, { - reply_to_message_id: ctx.message.message_id - } - ); + await handleDiceCommand(ctx, undefined, 4000); }); bot.command('slot', spamwatchMiddleware, async (ctx) => { - ctx.telegram.sendDice( - ctx.chat.id, { - emoji: '🎰', - reply_to_message_id: ctx.message.message_id - } - ); + await handleDiceCommand(ctx, '🎰', 3000); + }); + + bot.command('ball', spamwatchMiddleware, async (ctx) => { + await handleDiceCommand(ctx, '⚽', 3000); + }); + + bot.command('idice', spamwatchMiddleware, async (ctx) => { + const stickerId = "CAACAgQAAxkBAAJxjWbSSP-8ZNEhEpAJjQsHsGf-UuEPAAJCAAPI-uwTAAEBVWWh4ucINQQ"; + ctx.replyWithSticker(stickerId, { + reply_to_message_id: ctx.message.message_id + }); }); bot.command('furry', spamwatchMiddleware, async (ctx) => { - furryFunction(ctx); + sendRandomReply(ctx, resources.furryGif, 'isFurry', 'isNtFurry'); }); bot.command('gay', spamwatchMiddleware, async (ctx) => { - gayFunction(ctx); + sendRandomReply(ctx, resources.gayFlag, 'isGay', 'isNtGay'); }); -}; \ No newline at end of file +}; diff --git a/commands/getinfo.js b/commands/getinfo.js index 8874a2c..d7a80c8 100644 --- a/commands/getinfo.js +++ b/commands/getinfo.js @@ -4,48 +4,29 @@ const spamwatchMiddleware = require('../plugins/lib-spamwatch/Middleware.js')(is async function getUserInfo(ctx) { const Strings = getStrings(ctx.from.language_code); - let userInfoTemplate = Strings.userInfo; - const userName = ctx.from.first_name || Strings.unKnown; - const userId = ctx.from.id || Strings.unKnown; - const userHandle = ctx.from.username ? `@${ctx.from.username}` : Strings.varNone; - const isBot = ctx.from.is_bot ? Strings.varYes : Strings.varNo; - const userPremium = ctx.from.is_premium ? Strings.varYes : Strings.varNo; - const userLang = ctx.from.language_code || Strings.unKnown; + userInfo = Strings.userInfo + .replace('{userName}', ctx.from.first_name || Strings.unKnown) + .replace('{userId}', ctx.from.id || Strings.unKnown) + .replace('{userHandle}', ctx.from.username ? `@${ctx.from.username}` : Strings.varNone) + .replace('{userPremium}', ctx.from.is_premium ? Strings.varYes : Strings.varNo) + .replace('{userLang}', ctx.from.language_code || Strings.unKnown); - userInfoTemplate = userInfoTemplate - .replace('{userName}', userName) - .replace('{userId}', userId) - .replace('{userHandle}', userHandle) - .replace('{isBot}', isBot) - .replace('{userPremium}', userPremium) - .replace('{userLang}', userLang); - - return userInfoTemplate; + return userInfo; } async function getChatInfo(ctx) { const Strings = getStrings(ctx.from.language_code); if (ctx.chat.type === 'group' || ctx.chat.type === 'supergroup') { - let chatInfoTemplate = Strings.chatInfo; - - const chatId = ctx.chat.id || Strings.unKnown; - const chatName = ctx.chat.title; - const chatHandle = ctx.chat.username ? `@${ctx.chat.username}` : Strings.varNone; - const chatType = ctx.chat.type || Strings.unKnown; + chatInfo = Strings.chatInfo + .replace('{chatId}', ctx.chat.id || Strings.unKnown) + .replace('{chatName}', ctx.chat.title || Strings.unKnown) + .replace('{chatHandle}', ctx.chat.username ? `@${ctx.chat.username}` : Strings.varNone) + .replace('{chatMembersCount}', await ctx.getChatMembersCount(ctx.chat.id || Strings.unKnown)) + .replace('{chatType}', ctx.chat.type || Strings.unKnown) + .replace('{isForum}', ctx.chat.is_forum ? Strings.varYes : Strings.varNo); - const chatMembersCount = await ctx.telegram.getChatMembersCount(chatId); - const isForum = ctx.chat.is_forum ? Strings.varYes : Strings.varNo; - - chatInfoTemplate = chatInfoTemplate - .replace('{chatId}', chatId) - .replace('{chatName}', chatName) - .replace('{chatHandle}', chatHandle) - .replace('{chatMembersCount}', chatMembersCount) - .replace('{chatType}', chatType) - .replace('{isForum}', isForum); - - return chatInfoTemplate; + return chatInfo; } else { return ctx.reply( Strings.groupOnly, { diff --git a/locales/english.json b/locales/english.json index f405c87..c2fd887 100644 --- a/locales/english.json +++ b/locales/english.json @@ -11,10 +11,10 @@ "botAdminOnly": "This command is exclusive to the bot's general administrators. I can't disclose who they are, nor what this command does.", "privateOnly": "This command should be used only on private chats, and not on groups.", "groupOnly": "This command should be used only on groups, and not on private chats.", - "botNameChanged": "*Bot name changed to* `{botName}`", - "botNameErr": "*Error when changing bot name:*\n\n{tgErr}", - "botDescChanged": "*Bot description changed to* `{botDesc}`", - "botDescErr": "*Error when changing bot description:*\n\n{tgErr}", + "botNameChanged": "*Bot name changed to* `{botName}.`", + "botNameErr": "*Error when changing bot name:*\n{tgErr}", + "botDescChanged": "*Bot description changed to* `{botDesc}.`", + "botDescErr": "*Error when changing bot description:*\n{tgErr}", "invalidId": "Please enter a valid user ID.", "banSuccess": "User with ID `{userId}` has been banned.", "banErr": "Could not ban the user. Please check if the ID is correct and if the bot has admin permissions.\n\n{tgErr}", @@ -22,9 +22,11 @@ "unBanErr": "Could not unban the user. Please check if the ID is correct and if the bot has admin permissions.\n\n{tgErr}", "isGay": "Yes, you are *gay*!", "isNtGay": "Aahhh. You are not gay!", - "isFurry": "Yes, you are a freaky *furry*!", + "isFurry": "Yes, you are *furry*!", "isNtFurry": "Aahhh. You are not a furry!", - "randomNum": "*Generated number (0-10):* `{number}`", - "userInfo": "*User info*\n\n*Your name is:* `{userName}`\n*Your username is:* `{userHandle}`\n*Your ID is:* `{userId}`\n*You are a bot:* `{isBot}`\n*Your language:* `{userLang}`\n*You are a Premium user:* `{userPremium}`", - "chatInfo": "*Group info*\n\n*Chat name:* `{chatName}`\n*Chat ID:* `{chatId}`\n*Chat handle:* `{chatHandle}`\n*Chat type:* `{chatType}`\n*Chat members count:* `{chatMembersCount}`\n*Is a forum:* `{isForum}`" + "randomNum": "*Generated number (0-10):* `{number}.`", + "userInfo": "*User info*\n\n*Name:* `{userName}`\n*Username:* `{userHandle}`\n*User ID:* `{userId}`\n*Language:* `{userLang}`\n*Premium user:* `{userPremium}`", + "chatInfo": "*Chat info*\n\n*Name:* `{chatName}`\n*Chat ID:* `{chatId}`\n*Handle:* `{chatHandle}`\n*Type:* `{chatType}`\n*Members:* `{chatMembersCount}`\n*Is a forum:* `{isForum}`", + "funEmojiResult": "*You rolled {emoji} and got *`{value}`*!*\nYou don't know what that means? Me too!", + "gifErr": "*Something went wrong while sending the GIF. Please try again later.*\n\n{err}" } \ No newline at end of file diff --git a/locales/portuguese.json b/locales/portuguese.json index 5f8312e..00f2f8c 100644 --- a/locales/portuguese.json +++ b/locales/portuguese.json @@ -11,10 +11,10 @@ "botAdminOnly": "Esse comando é exclusivo a administradores gerais do bot. Não posso informar quem são, e nem o que esse comando faz.", "privateOnly": "Esse comando deve ser utilizado apenas em chats privados, e não em grupos.", "groupOnly": "Esse comando deve ser utilizado apenas em grupos, e não em chats privados.", - "botNameChanged": "*Nome do bot alterado para* `{botName}`", - "botNameErr": "*Erro ao alterar o nome do bot:*\n\n`{tgErr}`", - "botDescChanged": "*Descrição do bot alterada para* `{botDesc}`", - "botDescErr": "*Erro ao alterar a descrição do bot:*\n\n`{tgErr}`", + "botNameChanged": "*Nome do bot alterado para* `{botName}.`", + "botNameErr": "*Erro ao alterar o nome do bot:*\n`{tgErr}`", + "botDescChanged": "*Descrição do bot alterada para* `{botDesc}.`", + "botDescErr": "*Erro ao alterar a descrição do bot:*\n`{tgErr}`", "invalidId": "Por favor, insira um ID de usuário válido.", "banSuccess": "Usuário com ID `{userId}` foi banido.", "banErr": "Não foi possível banir o usuário. Verifique se o ID está correto e se o bot tem permissões de administrador.\n\n`{tgErr}`", @@ -22,9 +22,11 @@ "unBanErr": "Não foi possível desbanir o usuário. Verifique se o ID está correto e se o bot tem permissões de administrador.\n\n`{tgErr}`", "isGay": "Sim, você é *gay*!", "isNtGay": "Aahhh. Você não é gay!", - "isFurry": "Sim, você é um *furry* esquisito!", + "isFurry": "Sim, você é *furry*!", "isNtFurry": "Aahhh. Você não é um furry!", - "randomNum": "*Número gerado (0-10):* `{number}`", - "userInfo": "*Informações do usuário*\n\n*Seu nome é:* `{userName}`\n*Seu usuário é:* `{userHandle}`\n*Seu ID é:* `{userId}`\n*Você é um bot:* `{isBot}`\n*Seu idioma:* `{userLang}`\n*Você é um usuário premium:* `{userPremium}`", - "chatInfo": "*Informações do chat*\n\n*Nome do chat:* `{chatName}`\n*ID do chat:* `{chatId}`\n*Identificador:* `{chatHandle}`\n*Tipo de chat:* `{chatType}`\n*Número de membros:* `{chatMembersCount}`\n*É um fórum:* `{isForum}`" + "randomNum": "*Número gerado (0-10):* `{number}.`", + "userInfo": "*Informações do usuário*\n\n*Nome:* `{userName}`\n*Usuário:* `{userHandle}`\n*ID:* `{userId}`\n*Idioma:* `{userLang}`\n*Usuário Premium:* `{userPremium}`", + "chatInfo": "*Informações do chat*\n\n*Nome:* `{chatName}`\n*ID do chat:* `{chatId}`\n*Identificador:* `{chatHandle}`\n*Tipo:* `{chatType}`\n*Membros:* `{chatMembersCount}`\n*É um fórum:* `{isForum}`", + "funEmojiResult": "*Você lançou {emoji} e obteve *`{value}`*!*\nVocê não sabe o que isso significa? Nem eu!", + "gifErr": "*Algo deu errado ao enviar o GIF. Tente novamente mais tarde.*\n\n{err}" } \ No newline at end of file