commands: localize generic bot commands
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import {CallbackCommand} from "../base/callback-command";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Cancel extends CallbackCommand {
|
||||
|
||||
text = "❌ Отменить";
|
||||
text = Environment.cancelText;
|
||||
data = "";
|
||||
|
||||
constructor(text?: string, data?: string) {
|
||||
@@ -19,4 +20,4 @@ export class Cancel extends CallbackCommand {
|
||||
async execute(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import {botUser} from "../index";
|
||||
|
||||
export class AdminsAdd extends Command {
|
||||
command = "addAdmin";
|
||||
title = "/addAdmin";
|
||||
description = "Add user to admins";
|
||||
title = Environment.commandTitles.adminsAdd;
|
||||
description = Environment.commandDescriptions.adminsAdd;
|
||||
|
||||
requirements = Requirements.Build(
|
||||
Requirement.BOT_CREATOR,
|
||||
@@ -24,19 +24,19 @@ export class AdminsAdd extends Command {
|
||||
const text = fullName(msg.reply_to_message.from);
|
||||
|
||||
if (id === botUser.id) {
|
||||
await oldSendMessage(msg, "Бот не может сам себя сделать админом").catch(logError);
|
||||
await oldSendMessage(msg, Environment.botCannotMakeItselfAdminText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (id === Environment.CREATOR_ID) {
|
||||
await oldSendMessage(msg, "Создатель бота и так является админом").catch(logError);
|
||||
await oldSendMessage(msg, Environment.botCreatorAlreadyAdminText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (await Environment.addAdmin(id)) {
|
||||
await oldSendMessage(msg, text + " теперь админ!").catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserIsNowAdminText(text)).catch(logError);
|
||||
} else {
|
||||
await oldSendMessage(msg, text + " и так уже админ 🤔").catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserAlreadyAdminText(text)).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import {Message} from "typescript-telegram-bot-api";
|
||||
import {Requirements} from "../base/requirements";
|
||||
import {Requirement} from "../base/requirement";
|
||||
import {Environment} from "../common/environment";
|
||||
import {fullName, logError, replyToMessage, sendErrorPlaceholder} from "../util/utils";
|
||||
import {escapePlainMarkdownV2, fullName, logError, replyToMessage, sendErrorPlaceholder} from "../util/utils";
|
||||
import {StoredUser} from "../model/stored-user";
|
||||
import {UserStore} from "../common/user-store";
|
||||
|
||||
@@ -29,14 +29,14 @@ export class AdminsList extends Command {
|
||||
}
|
||||
}
|
||||
|
||||
let text = "*Администраторы*:\n\n";
|
||||
let text = Environment.administratorsHeaderText;
|
||||
users.forEach(user => {
|
||||
text += "\\* ";
|
||||
|
||||
if (user) {
|
||||
text += `[${fullName(user)}](tg://user?id=${user.id})`;
|
||||
text += `[${escapePlainMarkdownV2(fullName(user))}](tg://user?id=${user.id})`;
|
||||
} else {
|
||||
text += "Нет информации о пользователе";
|
||||
text += Environment.noUserInfoText;
|
||||
}
|
||||
|
||||
text += "\n";
|
||||
@@ -52,4 +52,4 @@ export class AdminsList extends Command {
|
||||
await sendErrorPlaceholder(msg).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import {botUser} from "../index";
|
||||
|
||||
export class AdminsRemove extends Command {
|
||||
command = "removeAdmin";
|
||||
title = "/removeAdmin";
|
||||
description = "Remove user from admins";
|
||||
title = Environment.commandTitles.adminsRemove;
|
||||
description = Environment.commandDescriptions.adminsRemove;
|
||||
|
||||
requirements = Requirements.Build(
|
||||
Requirement.BOT_CREATOR,
|
||||
@@ -24,19 +24,19 @@ export class AdminsRemove extends Command {
|
||||
const text = fullName(msg.reply_to_message.from);
|
||||
|
||||
if (id === botUser.id) {
|
||||
await oldSendMessage(msg, "Бот не может сам себя убрать из админов").catch(logError);
|
||||
await oldSendMessage(msg, Environment.botCannotRemoveItselfFromAdminsText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (id === Environment.CREATOR_ID) {
|
||||
await oldSendMessage(msg, "Создатель бота не может перестать быть админом").catch(logError);
|
||||
await oldSendMessage(msg, Environment.botCreatorCannotStopBeingAdminText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (await Environment.removeAdmin(id)) {
|
||||
await oldSendMessage(msg, text + " больше не админ!").catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserNoLongerAdminText(text)).catch(logError);
|
||||
} else {
|
||||
await oldSendMessage(msg, text + " и так не был админом 🤔").catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserWasNotAdminText(text)).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-5
@@ -3,14 +3,15 @@ import {Message} from "typescript-telegram-bot-api";
|
||||
import {errorPlaceholder, logError, oldSendMessage} from "../util/utils";
|
||||
import {Requirements} from "../base/requirements";
|
||||
import {Requirement} from "../base/requirement";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Ae extends Command {
|
||||
argsMode = "required" as const;
|
||||
|
||||
command = ["ae"];
|
||||
|
||||
title = "/ae";
|
||||
description = "evaluation";
|
||||
title = Environment.commandTitles.ae;
|
||||
description = Environment.commandDescriptions.ae;
|
||||
|
||||
requirements = Requirements.Build(Requirement.BOT_CREATOR);
|
||||
|
||||
@@ -24,7 +25,7 @@ export class Ae extends Command {
|
||||
const text = e.message.toString();
|
||||
|
||||
if (text.includes("is not defined")) {
|
||||
await oldSendMessage(msg, "variable is not defined").catch(logError);
|
||||
await oldSendMessage(msg, Environment.variableNotDefinedText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,7 +47,7 @@ export class Ae extends Command {
|
||||
const text = e.message.toString();
|
||||
|
||||
if (text.includes("is not defined")) {
|
||||
return "Variable not defined";
|
||||
return Environment.evaluationVariableNotDefinedText;
|
||||
}
|
||||
|
||||
logError(`${text}
|
||||
@@ -55,4 +56,4 @@ export class Ae extends Command {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-9
@@ -5,10 +5,11 @@ import {Message} from "typescript-telegram-bot-api";
|
||||
import {bot, botUser} from "../index";
|
||||
import {fullName, logError, oldSendMessage, oldReplyToMessage} from "../util/utils";
|
||||
import {Environment} from "../common/environment";
|
||||
import {enqueueTelegramApiCall} from "../util/telegram-api-queue";
|
||||
|
||||
export class Ban extends Command {
|
||||
title = "/ban [reply]";
|
||||
description = "ban user from chat";
|
||||
title = Environment.commandTitles.ban;
|
||||
description = Environment.commandDescriptions.ban;
|
||||
|
||||
requirements = Requirements.Build(
|
||||
Requirement.BOT_ADMIN,
|
||||
@@ -25,26 +26,29 @@ export class Ban extends Command {
|
||||
const userId = user.id;
|
||||
|
||||
if (userId === botUser.id) {
|
||||
await oldReplyToMessage(msg, "Используй /leave").catch(logError);
|
||||
await oldReplyToMessage(msg, Environment.useLeaveCommandText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (userId === Environment.CREATOR_ID) {
|
||||
await oldReplyToMessage(msg, "Бот не будет банить своего создателя.").catch(logError);
|
||||
await oldReplyToMessage(msg, Environment.botWillNotBanCreatorText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.from.id !== Environment.CREATOR_ID && Environment.ADMIN_IDS.has(userId)) {
|
||||
await oldReplyToMessage(msg, "Бот не будет банить своих администраторов.").catch(logError);
|
||||
await oldReplyToMessage(msg, Environment.botWillNotBanAdminsText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
bot.banChatMember({chat_id: msg.chat.id, user_id: userId})
|
||||
enqueueTelegramApiCall(
|
||||
() => bot.banChatMember({chat_id: msg.chat.id, user_id: userId}),
|
||||
{method: "banChatMember", chatId: msg.chat.id, chatType: msg.chat.type}
|
||||
)
|
||||
.then(async () => {
|
||||
await oldSendMessage(msg, `${fullName(user)} забанен 🚫`).catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserBannedText(fullName(user))).catch(logError);
|
||||
})
|
||||
.catch(async () => {
|
||||
await oldSendMessage(msg, `Не смог забанить ${fullName(user)} ☹️`).catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserBanFailedText(fullName(user))).catch(logError);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-4
@@ -1,13 +1,15 @@
|
||||
import {Command} from "../base/command";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {logError, oldReplyToMessage, randomValue} from "../util/utils";
|
||||
import {prepareTelegramMarkdownV2} from "../util/markdown-v2-renderer";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Choice extends Command {
|
||||
command = "choice";
|
||||
argsMode = "required" as const;
|
||||
|
||||
title = "/choice a, b, ..., c";
|
||||
description = "Выбор случайного значения";
|
||||
title = Environment.commandTitles.choice;
|
||||
description = Environment.commandDescriptions.choice;
|
||||
|
||||
async execute(msg: Message, match?: RegExpExecArray): Promise<void> {
|
||||
console.log("match", match);
|
||||
@@ -33,7 +35,15 @@ export class Choice extends Command {
|
||||
}
|
||||
|
||||
const random = randomValue(out);
|
||||
if (!random) {
|
||||
await oldReplyToMessage(msg, Environment.noChoicesText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
await oldReplyToMessage(msg, `Выбрал *${random}*`, "Markdown").catch(logError);
|
||||
await oldReplyToMessage(
|
||||
msg,
|
||||
Environment.getChoiceText(prepareTelegramMarkdownV2(random, {mode: "final"})),
|
||||
"MarkdownV2"
|
||||
).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import {Command} from "../base/command";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {getRangedRandomInt, logError, oldReplyToMessage} from "../util/utils";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Coin extends Command {
|
||||
title = "/coin";
|
||||
description = "Heads or tails";
|
||||
title = Environment.commandTitles.coin;
|
||||
description = Environment.commandDescriptions.coin;
|
||||
|
||||
async execute(msg: Message): Promise<void> {
|
||||
const random = getRangedRandomInt(0, 2);
|
||||
const headsOrTails = random === 1 ? "Выпал *Орёл* 🪙" : "Выпала *Решка* 🪙";
|
||||
await oldReplyToMessage(msg, headsOrTails, "Markdown").catch(logError); }
|
||||
}
|
||||
const headsOrTails = Environment.getCoinResultText(random === 1 ? Environment.coinHeadsText : Environment.coinTailsText) + " 🪙";
|
||||
await oldReplyToMessage(msg, headsOrTails, "Markdown").catch(logError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@ import {Message} from "typescript-telegram-bot-api";
|
||||
import {Requirements} from "../base/requirements";
|
||||
import {Requirement} from "../base/requirement";
|
||||
import {logError, replyToMessage} from "../util/utils";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Debug extends Command {
|
||||
title = "/debug";
|
||||
description = "Returns msg (or reply) as json";
|
||||
title = Environment.commandTitles.debug;
|
||||
description = Environment.commandDescriptions.debug;
|
||||
|
||||
requirements = Requirements.Build(Requirement.BOT_ADMIN);
|
||||
|
||||
@@ -17,4 +18,4 @@ export class Debug extends Command {
|
||||
const text = `\`\`\`json\n${json}\n\`\`\``;
|
||||
await replyToMessage({message: msg, text: text, parse_mode: "Markdown"}).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-13
@@ -2,26 +2,31 @@ import {Command} from "../base/command";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {logError, randomValue} from "../util/utils";
|
||||
import {bot} from "../index";
|
||||
import {enqueueTelegramApiCall} from "../util/telegram-api-queue";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
type DiceEmoji = "🎲" | "🎯" | "🏀" | "⚽" | "🎳" | "🎰";
|
||||
const emojis = ["🎲", "🎯", "🏀", "⚽", "🎳", "🎰"];
|
||||
const emojis: readonly DiceEmoji[] = ["🎲", "🎯", "🏀", "⚽", "🎳", "🎰"];
|
||||
|
||||
export class Dice extends Command {
|
||||
title = "/dice";
|
||||
description = "Sends random or specific dice";
|
||||
title = Environment.commandTitles.dice;
|
||||
description = Environment.commandDescriptions.dice;
|
||||
|
||||
async execute(msg: Message): Promise<void> {
|
||||
const split = msg.text?.split("/dice ");
|
||||
const secondPart = split?.[1]?.trim() || "";
|
||||
const emojiIndex = emojis.indexOf(secondPart);
|
||||
const emojiToDice: DiceEmoji = (emojiIndex >= 0 ? emojis[emojiIndex] : randomValue(emojis)) as DiceEmoji;
|
||||
const requestedEmoji = secondPart as DiceEmoji;
|
||||
const emojiToDice = emojis.includes(requestedEmoji) ? requestedEmoji : randomValue(emojis) ?? "🎲";
|
||||
|
||||
await bot.sendDice({
|
||||
chat_id: msg.chat.id,
|
||||
emoji: emojiToDice,
|
||||
reply_parameters: {
|
||||
message_id: msg.message_id
|
||||
}
|
||||
}).catch(logError);
|
||||
await enqueueTelegramApiCall(
|
||||
() => bot.sendDice({
|
||||
chat_id: msg.chat.id,
|
||||
emoji: emojiToDice,
|
||||
reply_parameters: {
|
||||
message_id: msg.message_id
|
||||
}
|
||||
}),
|
||||
{method: "sendDice", chatId: msg.chat.id, chatType: msg.chat.type}
|
||||
).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-12
@@ -2,13 +2,15 @@ import {Command} from "../base/command";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {downloadTelegramFile, extractImageFileId, logError, oldReplyToMessage, waveDistortSharp} from "../util/utils";
|
||||
import {bot} from "../index";
|
||||
import {enqueueTelegramApiCall} from "../util/telegram-api-queue";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Distort extends Command {
|
||||
command = "distort";
|
||||
argsMode = "optional" as const;
|
||||
|
||||
title = "/distort [amp] [wavelength]";
|
||||
description = "Distortion of picture";
|
||||
title = Environment.commandTitles.distort;
|
||||
description = Environment.commandDescriptions.distort;
|
||||
|
||||
async execute(msg: Message, match?: RegExpExecArray): Promise<void> {
|
||||
const chatId = msg.chat.id;
|
||||
@@ -17,7 +19,7 @@ export class Distort extends Command {
|
||||
if (!reply) {
|
||||
await oldReplyToMessage(
|
||||
msg,
|
||||
"Ответь командой /distort на сообщение с картинкой (фото, документ или стикер).\n" + "Пример: /distort 16 80"
|
||||
Environment.distortReplyInstructionText
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -26,7 +28,7 @@ export class Distort extends Command {
|
||||
if (!fileId) {
|
||||
await oldReplyToMessage(
|
||||
msg,
|
||||
"В реплае не вижу картинку. Пришли фото или файл-изображение."
|
||||
Environment.distortMissingImageText
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -37,7 +39,10 @@ export class Distort extends Command {
|
||||
const wavelength = b ? Number(b) : 72;
|
||||
|
||||
try {
|
||||
await bot.sendChatAction({chat_id: chatId, action: "upload_photo"});
|
||||
await enqueueTelegramApiCall(
|
||||
() => bot.sendChatAction({chat_id: chatId, action: "upload_photo"}),
|
||||
{method: "sendChatAction", chatId, chatType: msg.chat.type}
|
||||
);
|
||||
|
||||
const file = await bot.getFile({file_id: fileId});
|
||||
if (!file.file_path) {
|
||||
@@ -49,15 +54,18 @@ export class Distort extends Command {
|
||||
|
||||
const outBuf = await waveDistortSharp(<Buffer>inputBuf, amp, wavelength);
|
||||
|
||||
await bot.sendPhoto({
|
||||
chat_id: chatId,
|
||||
photo: outBuf,
|
||||
caption: `Искажение готово ✅ (amp=${amp}, wavelength=${wavelength})`,
|
||||
});
|
||||
await enqueueTelegramApiCall(
|
||||
() => bot.sendPhoto({
|
||||
chat_id: chatId,
|
||||
photo: outBuf,
|
||||
caption: Environment.getDistortionReadyCaption(amp, wavelength),
|
||||
}),
|
||||
{method: "sendPhoto", chatId, chatType: msg.chat.type}
|
||||
);
|
||||
} catch (e: any) {
|
||||
await oldReplyToMessage(
|
||||
msg, `Не получилось исказить изображение: ${e?.message ?? String(e)}`
|
||||
msg, Environment.getDistortFailedText(e)
|
||||
).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {Environment} from "../common/environment";
|
||||
import fs from "node:fs";
|
||||
import {logError, replyToMessage, sendErrorPlaceholder} from "../util/utils";
|
||||
import {bot} from "../index";
|
||||
import {enqueueTelegramApiCall} from "../util/telegram-api-queue";
|
||||
|
||||
export class ExportDb extends Command {
|
||||
|
||||
@@ -23,20 +24,21 @@ export class ExportDb extends Command {
|
||||
}
|
||||
|
||||
try {
|
||||
const buffer = fs.readFileSync(fullPath);
|
||||
|
||||
await bot.sendDocument({
|
||||
chat_id: Environment.CREATOR_ID,
|
||||
document: new FileOptions(buffer, {filename: "database.db", contentType: "application/sql"}),
|
||||
caption: "Бэкап базы данных",
|
||||
});
|
||||
await enqueueTelegramApiCall(
|
||||
() => bot.sendDocument({
|
||||
chat_id: Environment.CREATOR_ID,
|
||||
document: new FileOptions(fs.createReadStream(fullPath), {filename: "database.db", contentType: "application/sql"}),
|
||||
caption: Environment.databaseBackupCaption,
|
||||
}),
|
||||
{method: "sendDocument", chatId: Environment.CREATOR_ID, chatType: "private"}
|
||||
);
|
||||
|
||||
if (msg.chat.id !== Environment.CREATOR_ID) {
|
||||
await replyToMessage({message: msg, text: "Успешно отправлено в ЛС создателю!"});
|
||||
await replyToMessage({message: msg, text: Environment.databaseBackupSentText});
|
||||
}
|
||||
} catch (e) {
|
||||
logError(e);
|
||||
await sendErrorPlaceholder(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,17 @@ import {chatCommandToString, delay, logError, sendMessage} from "../util/utils";
|
||||
import {Command} from "../base/command";
|
||||
import {commands} from "../index";
|
||||
import {TelegramError} from "typescript-telegram-bot-api/dist/errors";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Help extends Command {
|
||||
command = ["h", "help"];
|
||||
|
||||
title = "/help";
|
||||
description = "Show list of commands";
|
||||
title = Environment.commandTitles.help;
|
||||
description = Environment.commandDescriptions.help;
|
||||
|
||||
async execute(msg: Message) {
|
||||
if (!msg.from) return;
|
||||
let text = "Commands:\n\n";
|
||||
let text = Environment.commandsHeaderText;
|
||||
|
||||
commands.forEach(c => {
|
||||
text += `${chatCommandToString(c)}\n`;
|
||||
@@ -21,7 +22,7 @@ export class Help extends Command {
|
||||
await sendMessage({chat_id: msg.from.id, text: text})
|
||||
.then(async () => {
|
||||
if (msg.chat.type !== "private") {
|
||||
await sendMessage({message: msg, text: "Отправил команды в ЛС 😎"}).catch(logError);
|
||||
await sendMessage({message: msg, text: Environment.sentCommandsInDmText}).catch(logError);
|
||||
}
|
||||
})
|
||||
.catch(async (e) => {
|
||||
@@ -29,7 +30,7 @@ export class Help extends Command {
|
||||
if (e.response?.error_code === 403) {
|
||||
await sendMessage({
|
||||
message: msg,
|
||||
text: "Не смог отправить команды в ЛС ☹️\nТогда отправлю сюда"
|
||||
text: Environment.couldNotSendCommandsInDmText
|
||||
}).catch(logError);
|
||||
|
||||
await delay(1000);
|
||||
@@ -38,4 +39,4 @@ export class Help extends Command {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-9
@@ -1,17 +1,17 @@
|
||||
import {Command} from "../base/command";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {logError, oldReplyToMessage} from "../util/utils";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Id extends Command {
|
||||
title = "/id";
|
||||
description = "ID of chat, user and reply (if replied to any message)";
|
||||
title = Environment.commandTitles.id;
|
||||
description = Environment.commandDescriptions.id;
|
||||
|
||||
async execute(msg: Message): Promise<void> {
|
||||
let text = `chat id: \n\`\`\`${msg.chat.id}\`\`\` \nfrom id: \n\`\`\`${msg.from?.id}\`\`\``;
|
||||
if (msg.reply_to_message) {
|
||||
text += ` \nreply id: \n\`\`\`${msg.reply_to_message.from?.id}\`\`\``;
|
||||
}
|
||||
|
||||
await oldReplyToMessage(msg, text, "MarkdownV2").catch(logError);
|
||||
await oldReplyToMessage(
|
||||
msg,
|
||||
Environment.getIdText(msg.chat.id, msg.from?.id, msg.reply_to_message?.from?.id),
|
||||
"MarkdownV2",
|
||||
).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import {botUser} from "../index";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Ignore extends Command {
|
||||
title = "/ignore";
|
||||
description = "Bot will ignore user";
|
||||
title = Environment.commandTitles.ignore;
|
||||
description = Environment.commandDescriptions.ignore;
|
||||
|
||||
requirements = Requirements.Build(
|
||||
Requirement.BOT_ADMIN,
|
||||
@@ -25,19 +25,19 @@ export class Ignore extends Command {
|
||||
const text = fullName(msg.reply_to_message.from);
|
||||
|
||||
if (id === botUser.id) {
|
||||
await oldSendMessage(msg, "Бот не может сам себя игнорировать").catch(logError);
|
||||
await oldSendMessage(msg, Environment.botWillNotIgnoreItselfText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (id === Environment.CREATOR_ID) {
|
||||
await oldSendMessage(msg, "Бот не будет игнорировать своего создателя").catch(logError);
|
||||
await oldSendMessage(msg, Environment.botWillNotIgnoreCreatorText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (await Environment.addMute(id)) {
|
||||
await oldSendMessage(msg, text + " в муте! 🔇").catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserIgnoredText(text)).catch(logError);
|
||||
} else {
|
||||
await oldSendMessage(msg, text + " уже в муте 🤔").catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserAlreadyIgnoredText(text)).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@ import {Message} from "typescript-telegram-bot-api";
|
||||
import {Requirements} from "../base/requirements";
|
||||
import {Requirement} from "../base/requirement";
|
||||
import {bot} from "../index";
|
||||
import {enqueueTelegramApiCall} from "../util/telegram-api-queue";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Leave extends Command {
|
||||
title = "/leave";
|
||||
description = "Bot will leave current chat";
|
||||
title = Environment.commandTitles.leave;
|
||||
description = Environment.commandDescriptions.leave;
|
||||
|
||||
requirements = Requirements.Build(
|
||||
Requirement.BOT_ADMIN,
|
||||
@@ -14,6 +16,9 @@ export class Leave extends Command {
|
||||
);
|
||||
|
||||
async execute(msg: Message): Promise<void> {
|
||||
await bot.leaveChat({chat_id: msg.chat.id});
|
||||
await enqueueTelegramApiCall(
|
||||
() => bot.leaveChat({chat_id: msg.chat.id}),
|
||||
{method: "leaveChat", chatId: msg.chat.id, chatType: msg.chat.type}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-17
@@ -1,46 +1,38 @@
|
||||
import {logError, sendMessage} from "../util/utils";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {Command} from "../base/command";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Ping extends Command {
|
||||
title = "/ping";
|
||||
description = "Ping between received and sent message";
|
||||
title = Environment.commandTitles.ping;
|
||||
description = Environment.commandDescriptions.ping;
|
||||
|
||||
async execute(msg: Message) {
|
||||
let d = new Date();
|
||||
const u = (n: number): string => n > 9 ? n.toString() : `0${n}`;
|
||||
const date = `${u(d.getDay())}.${u(d.getMonth() + 1)}.${d.getFullYear()}`;
|
||||
const date = `${u(d.getDate())}.${u(d.getMonth() + 1)}.${d.getFullYear()}`;
|
||||
const time = `${u(d.getHours())}:${u(d.getMinutes())}:${u(d.getSeconds())}:${u(d.getMilliseconds())}`;
|
||||
|
||||
const mDate = msg.date;
|
||||
const nowDate = new Date().getTime() / 1000;
|
||||
const diff = nowDate - mDate;
|
||||
const tgPing = diff.toFixed(2);
|
||||
const tgPing = (diff * 1000).toFixed(0);
|
||||
|
||||
d = new Date(mDate * 1000);
|
||||
const msgDate = `${u(d.getDay())}.${u(d.getMonth() + 1)}.${d.getFullYear()}`;
|
||||
const msgDate = `${u(d.getDate())}.${u(d.getMonth() + 1)}.${d.getFullYear()}`;
|
||||
const msgTime = `${u(d.getHours())}:${u(d.getMinutes())}:${u(d.getSeconds())}:${u(d.getMilliseconds())}`;
|
||||
|
||||
const then = Date.now();
|
||||
await sendMessage({message: msg, text: "pong"}).catch(logError);
|
||||
await sendMessage({message: msg, text: Environment.pongText}).catch(logError);
|
||||
const now = Date.now();
|
||||
const msgSendDiff = (now - then).toFixed(2);
|
||||
|
||||
await sendMessage(
|
||||
{
|
||||
message: msg,
|
||||
text:
|
||||
"```ping\n" +
|
||||
`TG: ${tgPing}ms\n` +
|
||||
`API ${msgSendDiff}ms\n\n` +
|
||||
|
||||
`🗓️ Message date: ${msgDate}\n` +
|
||||
`🕒 Message time: ${msgTime}\n\n` +
|
||||
`🗓️ Local date : ${date}\n` +
|
||||
`🕒 Local time: ${time}` +
|
||||
"```",
|
||||
text: Environment.getPingReportText(tgPing, msgSendDiff, msgDate, msgTime, date, time),
|
||||
parse_mode: "Markdown"
|
||||
}
|
||||
).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ import {Environment} from "../common/environment";
|
||||
|
||||
export class PrefixResponse extends Command {
|
||||
async execute(msg: Message): Promise<void> {
|
||||
await replyToMessage({message: msg, text: randomValue(Environment.ANSWERS.prefix)}).catch(logError);
|
||||
await replyToMessage({message: msg, text: randomValue(Environment.ANSWERS.prefix) ?? Environment.prefixFallbackText}).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+31
-23
@@ -1,15 +1,17 @@
|
||||
import {Command} from "../base/command";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {extractMessagePayload, logError, replyToMessage} from "../util/utils";
|
||||
import {escapeHtml, extractMessagePayload, logError, replyToMessage} from "../util/utils";
|
||||
import {bot, botUser} from "../index";
|
||||
import QRCode from "qrcode";
|
||||
import {enqueueTelegramApiCall} from "../util/telegram-api-queue";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Qr extends Command {
|
||||
|
||||
argsMode = "optional" as const;
|
||||
|
||||
title = "/qr";
|
||||
description = "Generates QR-code from text you sent or replied to.";
|
||||
title = Environment.commandTitles.qr;
|
||||
description = Environment.commandDescriptions.qr;
|
||||
|
||||
async execute(msg: Message, match?: RegExpExecArray): Promise<void> {
|
||||
const chatId = msg.chat.id;
|
||||
@@ -19,27 +21,29 @@ export class Qr extends Command {
|
||||
await replyToMessage(
|
||||
{
|
||||
message: msg,
|
||||
text: "Не найден текст для генерации QR-кода."
|
||||
text: Environment.qrCodeMissingTextText
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: 16/02/2026, Danil Nikolaev: escape html symbols in payload
|
||||
|
||||
if (payload.length > 1500) {
|
||||
payload = payload.slice(0, 1500);
|
||||
const maxQrPayloadLength = 1500;
|
||||
if (payload.length > maxQrPayloadLength) {
|
||||
payload = payload.slice(0, maxQrPayloadLength);
|
||||
|
||||
await replyToMessage(
|
||||
{
|
||||
message: msg,
|
||||
text: `Слишком длинный текст для QR (${payload.length} символов). Текст будет обрезан до 1500 символов.`
|
||||
text: Environment.getQrCodeTextTooLongText(payload.length, maxQrPayloadLength)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
await bot.sendChatAction({chat_id: chatId, action: "upload_photo"});
|
||||
await enqueueTelegramApiCall(
|
||||
() => bot.sendChatAction({chat_id: chatId, action: "upload_photo"}),
|
||||
{method: "sendChatAction", chatId, chatType: msg.chat.type}
|
||||
);
|
||||
|
||||
const pngBuffer = await QRCode.toBuffer(payload, {
|
||||
type: "png",
|
||||
@@ -49,23 +53,27 @@ export class Qr extends Command {
|
||||
});
|
||||
|
||||
const maxCaptionLength = botUser.is_premium ? 4096 : 1024;
|
||||
const visiblePayload = payload.length > maxCaptionLength - 80
|
||||
? payload.slice(0, maxCaptionLength - 83) + "..."
|
||||
: payload;
|
||||
|
||||
await bot.sendPhoto({
|
||||
chat_id: chatId,
|
||||
photo: pngBuffer,
|
||||
caption: "QR-код готов ✅\nСодержимое:\n<blockquote expandable>" +
|
||||
`${payload.length > maxCaptionLength ? payload.slice(0, maxCaptionLength - 40) + "..." : payload}` +
|
||||
"</blockquote>",
|
||||
reply_parameters: {
|
||||
message_id: msg.message_id,
|
||||
},
|
||||
parse_mode: "HTML"
|
||||
});
|
||||
await enqueueTelegramApiCall(
|
||||
() => bot.sendPhoto({
|
||||
chat_id: chatId,
|
||||
photo: pngBuffer,
|
||||
caption: Environment.getQrCodeReadyText(escapeHtml(visiblePayload)),
|
||||
reply_parameters: {
|
||||
message_id: msg.message_id,
|
||||
},
|
||||
parse_mode: "HTML"
|
||||
}),
|
||||
{method: "sendPhoto", chatId, chatType: msg.chat.type}
|
||||
);
|
||||
} catch (e: any) {
|
||||
await replyToMessage({
|
||||
message: msg,
|
||||
text: `Не получилось сгенерировать QR: ${e?.message ?? String(e)}`
|
||||
text: Environment.getQrCodeFailedText(e)
|
||||
}).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-19
@@ -17,9 +17,12 @@ import {
|
||||
import {Requirements} from "../base/requirements";
|
||||
import {Requirement} from "../base/requirement";
|
||||
import twemoji from "twemoji";
|
||||
import {enqueueTelegramApiCall} from "../util/telegram-api-queue";
|
||||
import {AsyncSemaphore} from "../util/async-lock";
|
||||
import {Environment} from "../common/environment";
|
||||
import {getLruMapValue, setLruMapValue} from "../util/lru-map";
|
||||
|
||||
try {
|
||||
GlobalFonts.registerFromPath("./assets/Inter_18pt-ExtraThin.ttf", "InterExtraThin");
|
||||
GlobalFonts.registerFromPath("./assets/Inter_18pt-Thin.ttf", "InterThin");
|
||||
GlobalFonts.registerFromPath("./assets/Inter_18pt-Light.ttf", "InterLight");
|
||||
GlobalFonts.registerFromPath("./assets/Inter_18pt-Regular.ttf", "Inter");
|
||||
@@ -40,8 +43,8 @@ export class Quote extends Command {
|
||||
command = ["cit", "citation", "q", "quote"];
|
||||
argsMode = "none" as const;
|
||||
|
||||
title = "/quote";
|
||||
description = "Make quote from text (or quote)";
|
||||
title = Environment.commandTitles.quote;
|
||||
description = Environment.commandDescriptions.quote;
|
||||
|
||||
requirements = Requirements.Build(Requirement.REPLY);
|
||||
|
||||
@@ -53,31 +56,37 @@ export class Quote extends Command {
|
||||
try {
|
||||
const quoteRaw = (msg.quote?.text ?? reply.text ?? reply.caption ?? "").trim();
|
||||
if (quoteRaw.length === 0) {
|
||||
await replyToMessage({message: msg, text: "Не нашёл в сообщении текста 😢"}).catch(logError);
|
||||
await replyToMessage({message: msg, text: Environment.quoteMissingTextText}).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
const quote = quoteRaw.length ? quoteRaw : "…";
|
||||
|
||||
const entities = msg.quote ? msg.quote.entities : reply.entities ?? reply.caption_entities ?? [];
|
||||
const entities = msg.quote ? msg.quote.entities ?? [] : reply.entities ?? reply.caption_entities ?? [];
|
||||
|
||||
const png = await renderQuoteCard(msg, quote, reply, entities);
|
||||
await bot.sendPhoto({
|
||||
chat_id: chatId,
|
||||
photo: png,
|
||||
reply_parameters: {
|
||||
message_id: msg.message_id,
|
||||
},
|
||||
}).catch(logError);
|
||||
const png = await quoteRenderSemaphore.runExclusive(() => renderQuoteCard(msg, quote, reply, entities));
|
||||
await enqueueTelegramApiCall(
|
||||
() => bot.sendPhoto({
|
||||
chat_id: chatId,
|
||||
photo: png,
|
||||
reply_parameters: {
|
||||
message_id: msg.message_id,
|
||||
},
|
||||
}),
|
||||
{method: "sendPhoto", chatId, chatType: msg.chat.type}
|
||||
).catch(logError);
|
||||
} catch (e) {
|
||||
logError(e);
|
||||
await replyToMessage({message: msg, text: "Не смог собрать цитату 😢"}).catch(logError);
|
||||
await replyToMessage({message: msg, text: Environment.quoteBuildFailedText}).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const emojiCache = new Map<string, CanvasImage>();
|
||||
const customEmojiCache = new Map<string, CanvasImage>();
|
||||
const quoteRenderSemaphore = new AsyncSemaphore(2);
|
||||
const EMOJI_CACHE_MAX_ENTRIES = 256;
|
||||
const CUSTOM_EMOJI_CACHE_MAX_ENTRIES = 512;
|
||||
|
||||
function appleEmojiUrl(emoji: string): string {
|
||||
const codePoints = [...emoji]
|
||||
@@ -104,13 +113,13 @@ async function loadEmoji(emoji: string | undefined): Promise<CanvasImage | null>
|
||||
const downloadAndCache = async (url: string): Promise<Image> => {
|
||||
const res = await axios.get<ArrayBuffer>(url, {responseType: "arraybuffer"});
|
||||
const img = await loadImage(Buffer.from(res.data));
|
||||
emojiCache.set(url, img);
|
||||
setLruMapValue(emojiCache, url, img, EMOJI_CACHE_MAX_ENTRIES);
|
||||
return img;
|
||||
};
|
||||
|
||||
const checkIfCached = async (emoji: string, emojiToUrl: (emoji: string) => string): Promise<CanvasImage> => {
|
||||
const url = emojiToUrl(emoji);
|
||||
const cached = emojiCache.get(url);
|
||||
const cached = getLruMapValue(emojiCache, url);
|
||||
if (cached) return cached;
|
||||
return await downloadAndCache(emojiToUrl(emoji));
|
||||
};
|
||||
@@ -128,7 +137,7 @@ async function loadEmoji(emoji: string | undefined): Promise<CanvasImage | null>
|
||||
}
|
||||
|
||||
async function loadCustomEmoji(customEmojiId: string): Promise<CanvasImage | null> {
|
||||
const cached = customEmojiCache.get(customEmojiId);
|
||||
const cached = getLruMapValue(customEmojiCache, customEmojiId);
|
||||
if (cached) return cached;
|
||||
|
||||
try {
|
||||
@@ -159,7 +168,7 @@ async function loadCustomEmoji(customEmojiId: string): Promise<CanvasImage | nul
|
||||
}
|
||||
|
||||
const img = await loadImage(buffer);
|
||||
customEmojiCache.set(customEmojiId, img);
|
||||
setLruMapValue(customEmojiCache, customEmojiId, img, CUSTOM_EMOJI_CACHE_MAX_ENTRIES);
|
||||
return img;
|
||||
} catch (e) {
|
||||
console.warn(`Failed to load custom emoji ${customEmojiId}:`, e);
|
||||
@@ -745,4 +754,4 @@ function getQuoteAuthor(reply: Message): QuoteAuthor {
|
||||
const u = reply.from!;
|
||||
const name = [u.first_name, u.last_name].filter(Boolean).join(" ") || u.username || "Unknown";
|
||||
return {name, username: u.username, userId: u.id};
|
||||
}
|
||||
}
|
||||
|
||||
+20
-12
@@ -1,28 +1,36 @@
|
||||
import {Command} from "../base/command";
|
||||
import {getRandomInt, getRangedRandomInt, logError, oldSendMessage} from "../util/utils";
|
||||
import {getRandomInt, logError, oldSendMessage} from "../util/utils";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class RandomInt extends Command {
|
||||
argsMode = "optional" as const;
|
||||
|
||||
title = "/randomInt";
|
||||
description = "Ranged random integer from parameters";
|
||||
title = Environment.commandTitles.randomInt;
|
||||
description = Environment.commandDescriptions.randomInt;
|
||||
|
||||
async execute(msg: Message) {
|
||||
// TODO: 01/05/2026, Danil Nikolaev: improve
|
||||
if (!msg.text) return;
|
||||
|
||||
const split = msg.text.split(" ");
|
||||
const min = parseInt(split[1]);
|
||||
const max = parseInt(split[2]);
|
||||
const args = msg.text.trim().split(/\s+/).slice(1);
|
||||
const values = args
|
||||
.map(value => Number(value))
|
||||
.filter(value => Number.isSafeInteger(value));
|
||||
const min = values.length === 1 ? 1 : values[0];
|
||||
const max = values.length === 1 ? values[0] : values[1];
|
||||
|
||||
const good = max > min;
|
||||
const sufficient = !!(min && max) && good;
|
||||
const sufficient = Number.isSafeInteger(min) && Number.isSafeInteger(max);
|
||||
if (sufficient && min === max) {
|
||||
await oldSendMessage(msg, Environment.getRandomIntRangeText(min, max, min)).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
const random = !sufficient ? getRandomInt(Math.pow(2, 60)) : getRangedRandomInt(min, max);
|
||||
const from = sufficient ? Math.min(min, max) : 0;
|
||||
const to = sufficient ? Math.max(min, max) : 1_000_000_000;
|
||||
const random = getRandomInt(to - from + 1) + from;
|
||||
|
||||
const randomText = !sufficient ? random.toString() : `[${min}; ${max}]: ${random}`;
|
||||
const randomText = !sufficient ? random.toString() : Environment.getRandomIntRangeText(from, to, random);
|
||||
|
||||
await oldSendMessage(msg, randomText).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
import {Command} from "../base/command";
|
||||
import {getRandomInt, logError, replyToMessage} from "../util/utils";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class RandomString extends Command {
|
||||
argsMode = "optional" as const;
|
||||
|
||||
title = "/randomString";
|
||||
description = "literally random string (up to 4096 symbols)";
|
||||
title = Environment.commandTitles.randomString;
|
||||
description = Environment.commandDescriptions.randomString;
|
||||
|
||||
async execute(msg: Message) {
|
||||
// TODO: 01/05/2026, Danil Nikolaev: improve
|
||||
if (!msg.text) return;
|
||||
|
||||
const split = msg.text.split(" ");
|
||||
const l = parseInt(split.length > 1 ? split[1] : "1");
|
||||
const [, lengthArg] = msg.text.trim().split(/\s+/);
|
||||
const requestedLength = Number(lengthArg ?? 1);
|
||||
|
||||
const length = (l <= 0 || l > 4096) ? 1 : l;
|
||||
const length = Number.isSafeInteger(requestedLength)
|
||||
? Math.min(4096, Math.max(1, requestedLength))
|
||||
: 1;
|
||||
|
||||
const characters = Array.from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя0123456789");
|
||||
let result = "";
|
||||
|
||||
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя0123456789";
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += characters.charAt(getRandomInt(characters.length));
|
||||
result += characters[getRandomInt(characters.length)];
|
||||
}
|
||||
|
||||
await replyToMessage({
|
||||
message: msg,
|
||||
text: "<blockquote expandable>" + result + "</blockquote>",
|
||||
text: Environment.getExpandableBlockquoteText(result),
|
||||
parse_mode: "HTML"
|
||||
}).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-17
@@ -4,45 +4,47 @@ import {Requirements} from "../base/requirements";
|
||||
import {Requirement} from "../base/requirement";
|
||||
import {bot} from "../index";
|
||||
import {delay, logError, randomValue} from "../util/utils";
|
||||
|
||||
const texts = [
|
||||
"ну что-же, господа",
|
||||
"приятно было с вами пообщаться",
|
||||
"но мне пора на покой",
|
||||
"всего хорошего"
|
||||
];
|
||||
import {enqueueTelegramApiCall} from "../util/telegram-api-queue";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
const timings = [1500, 2500];
|
||||
const timer = [3, 2, 1];
|
||||
|
||||
export class Shutdown extends Command {
|
||||
title = "/shutdown";
|
||||
description = "Self-destruction sequence for bot (shutdown)";
|
||||
title = Environment.commandTitles.shutdown;
|
||||
description = Environment.commandDescriptions.shutdown;
|
||||
|
||||
argsMode = "optional" as const;
|
||||
|
||||
requirements = Requirements.Build(Requirement.BOT_CREATOR);
|
||||
|
||||
async execute(msg: Message, match?: RegExpExecArray): Promise<void> {
|
||||
await bot.sendMessage({chat_id: msg.chat.id, text: "..."}).catch(logError);
|
||||
const send = async (text: string) => {
|
||||
await enqueueTelegramApiCall(
|
||||
() => bot.sendMessage({chat_id: msg.chat.id, text}),
|
||||
{method: "sendMessage", chatId: msg.chat.id, chatType: msg.chat.type}
|
||||
).catch(logError);
|
||||
};
|
||||
|
||||
await send(Environment.shutdownFallbackText);
|
||||
|
||||
const now = match?.[3]?.toLowerCase() === "now";
|
||||
if (msg.chat.type !== "private" && !now) {
|
||||
for (const text of texts) {
|
||||
await delay(randomValue(timings));
|
||||
await bot.sendMessage({chat_id: msg.chat.id, text: text}).catch(logError);
|
||||
for (const text of Environment.shutdownSequenceTexts) {
|
||||
await delay(randomValue(timings) ?? 1500);
|
||||
await send(text);
|
||||
}
|
||||
|
||||
await delay(randomValue(timings));
|
||||
await delay(randomValue(timings) ?? 1500);
|
||||
|
||||
for (const t of timer) {
|
||||
await bot.sendMessage({chat_id: msg.chat.id, text: `${t}`}).catch(logError);
|
||||
await send(`${t}`);
|
||||
await delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
await bot.sendMessage({chat_id: msg.chat.id, text: "*R.I.P*"}).catch(logError);
|
||||
await send(Environment.shutdownDoneText);
|
||||
|
||||
delay(2000).then(() => process.exit(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@ import {Command} from "../base/command";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {commands} from "../index";
|
||||
import {Help} from "./help";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Start extends Command {
|
||||
title = "/start";
|
||||
description = "Start the bot";
|
||||
title = Environment.commandTitles.start;
|
||||
description = Environment.commandDescriptions.start;
|
||||
|
||||
async execute(msg: Message): Promise<void> {
|
||||
await commands.find(e => e instanceof Help)?.execute(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
import {Command} from "../base/command";
|
||||
import {logError, replyToMessage} from "../util/utils";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class SystemInfo extends Command {
|
||||
title = "/systemInfo";
|
||||
description = "System information";
|
||||
title = Environment.commandTitles.systemInfo;
|
||||
description = Environment.commandDescriptions.systemInfo;
|
||||
|
||||
private static systemInfoText: string;
|
||||
private static systemInfoParams: Parameters<typeof Environment.getSystemSpecsText>[0] | null = null;
|
||||
|
||||
static setSystemInfo(info: string) {
|
||||
SystemInfo.systemInfoText = info;
|
||||
static setSystemInfo(params: Parameters<typeof Environment.getSystemSpecsText>[0]) {
|
||||
SystemInfo.systemInfoParams = params;
|
||||
}
|
||||
|
||||
async execute(msg: Message) {
|
||||
await replyToMessage({message: msg, text: SystemInfo.systemInfoText}).catch(logError);
|
||||
if (!SystemInfo.systemInfoParams) return;
|
||||
await replyToMessage({message: msg, text: Environment.getSystemSpecsText(SystemInfo.systemInfoParams)}).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ import {Environment} from "../common/environment";
|
||||
|
||||
export class Test extends Command {
|
||||
regexp = /^(test|тест|еуые|ntcn|инноке(нтий|ш|нтич))$/i;
|
||||
title = "тест";
|
||||
description = "System functionality check";
|
||||
title = Environment.commandTitles.test;
|
||||
description = Environment.commandDescriptions.test;
|
||||
|
||||
async execute(msg: Message) {
|
||||
await oldReplyToMessage(msg, randomValue(Environment.ANSWERS.test) || "а").catch(logError);
|
||||
await oldReplyToMessage(msg, randomValue(Environment.ANSWERS.test) || Environment.defaultTestAnswerText).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-5
@@ -4,13 +4,15 @@ import {Requirements} from "../base/requirements";
|
||||
import {Requirement} from "../base/requirement";
|
||||
import {logError, oldReplyToMessage} from "../util/utils";
|
||||
import {bot} from "../index";
|
||||
import {enqueueTelegramApiCall} from "../util/telegram-api-queue";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Title extends Command {
|
||||
command = "title";
|
||||
argsMode = "required" as const;
|
||||
|
||||
title = "/title";
|
||||
description = "Change group title";
|
||||
title = Environment.commandTitles.title;
|
||||
description = Environment.commandDescriptions.title;
|
||||
|
||||
requirements = Requirements.Build(
|
||||
Requirement.BOT_ADMIN,
|
||||
@@ -22,10 +24,13 @@ export class Title extends Command {
|
||||
async execute(msg: Message, match?: RegExpExecArray): Promise<void> {
|
||||
const title = (match?.[3] ?? "").trim();
|
||||
if (title.length === 0) {
|
||||
await oldReplyToMessage(msg, "Не нашёл название...").catch(logError);
|
||||
await oldReplyToMessage(msg, Environment.titleMissingText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
await bot.setChatTitle({chat_id: msg.chat.id, title: title}).catch(logError);
|
||||
await enqueueTelegramApiCall(
|
||||
() => bot.setChatTitle({chat_id: msg.chat.id, title: title}),
|
||||
{method: "setChatTitle", chatId: msg.chat.id, chatType: msg.chat.type}
|
||||
).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {Command} from "../base/command";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {logError, oldReplyToMessage, randomValue} from "../util/utils";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
const EN =
|
||||
"`qwertyuiop[]asdfghjkl;'zxcvbnm,./" +
|
||||
@@ -60,7 +61,7 @@ export function fixLayoutAuto(
|
||||
): string {
|
||||
let guess = detectScript(text);
|
||||
if (guess === "mixed") {
|
||||
guess = randomValue([true, false]) ? "ru" : "en";
|
||||
guess = (randomValue([true, false]) ?? false) ? "ru" : "en";
|
||||
}
|
||||
|
||||
if (guess === "en") {
|
||||
@@ -77,8 +78,8 @@ export function fixLayoutAuto(
|
||||
export class Transliteration extends Command {
|
||||
command = ["transliteration", "tr"];
|
||||
|
||||
title = "/tr [text or reply]";
|
||||
description = "Transliteration EN <--> RU";
|
||||
title = Environment.commandTitles.transliteration;
|
||||
description = Environment.commandDescriptions.transliteration;
|
||||
|
||||
async execute(msg: Message): Promise<void> {
|
||||
if (!msg.text && !msg.caption) return;
|
||||
@@ -102,4 +103,4 @@ export class Transliteration extends Command {
|
||||
|
||||
await oldReplyToMessage(msg, newText).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-9
@@ -5,10 +5,11 @@ import {Message} from "typescript-telegram-bot-api";
|
||||
import {bot, botUser} from "../index";
|
||||
import {fullName, logError, oldReplyToMessage, oldSendMessage} from "../util/utils";
|
||||
import {Environment} from "../common/environment";
|
||||
import {enqueueTelegramApiCall} from "../util/telegram-api-queue";
|
||||
|
||||
export class Unban extends Command {
|
||||
title = "/unban [reply]";
|
||||
description = "unban user from chat";
|
||||
title = Environment.commandTitles.unban;
|
||||
description = Environment.commandDescriptions.unban;
|
||||
|
||||
requirements = Requirements.Build(
|
||||
Requirement.BOT_ADMIN,
|
||||
@@ -25,26 +26,29 @@ export class Unban extends Command {
|
||||
const userId = user.id;
|
||||
|
||||
if (userId === botUser.id) {
|
||||
await oldReplyToMessage(msg, "Бот и так не в бане сам у себя.").catch(logError);
|
||||
await oldReplyToMessage(msg, Environment.botIsNotBannedByItselfText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (userId === Environment.CREATOR_ID) {
|
||||
await oldReplyToMessage(msg, "Создатель бота и так не в бане и никогда не будет.").catch(logError);
|
||||
await oldReplyToMessage(msg, Environment.botCreatorNeverBannedText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.from?.id !== Environment.CREATOR_ID && Environment.ADMIN_IDS.has(userId)) {
|
||||
await oldReplyToMessage(msg, "Админимтраторы бота и так не в бане.").catch(logError);
|
||||
await oldReplyToMessage(msg, Environment.botAdminsNotBannedText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
bot.unbanChatMember({chat_id: msg.chat.id, user_id: userId})
|
||||
enqueueTelegramApiCall(
|
||||
() => bot.unbanChatMember({chat_id: msg.chat.id, user_id: userId}),
|
||||
{method: "unbanChatMember", chatId: msg.chat.id, chatType: msg.chat.type}
|
||||
)
|
||||
.then(async () => {
|
||||
await oldSendMessage(msg, `${fullName(user)} разбанен ⛓️💥`).catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserUnbannedText(fullName(user))).catch(logError);
|
||||
})
|
||||
.catch(async () => {
|
||||
await oldSendMessage(msg, `Не смог разбанить ${fullName(user)} ☹️`).catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserUnbanFailedText(fullName(user))).catch(logError);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import {botUser} from "../index";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Unignore extends Command {
|
||||
title = "/unignore";
|
||||
description = "Bot will start responding to the user";
|
||||
title = Environment.commandTitles.unignore;
|
||||
description = Environment.commandDescriptions.unignore;
|
||||
requirements = Requirements.Build(
|
||||
Requirement.BOT_ADMIN,
|
||||
Requirement.CHAT,
|
||||
@@ -24,19 +24,19 @@ export class Unignore extends Command {
|
||||
const text = fullName(msg.reply_to_message.from);
|
||||
|
||||
if (id === botUser.id) {
|
||||
await oldSendMessage(msg, "Бот и так всегда к себе прислушивается").catch(logError);
|
||||
await oldSendMessage(msg, Environment.botAlreadyAlwaysListensToItselfText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (id === Environment.CREATOR_ID) {
|
||||
await oldSendMessage(msg, "Бот всегда слушает своего создателя").catch(logError);
|
||||
await oldSendMessage(msg, Environment.botAlwaysListensToCreatorText).catch(logError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (await Environment.removeMute(id)) {
|
||||
await oldSendMessage(msg, text + " больше не в муте! 🔈").catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserUnignoredText(text)).catch(logError);
|
||||
} else {
|
||||
await oldSendMessage(msg, text + " не был в муте 🤔").catch(logError);
|
||||
await oldSendMessage(msg, Environment.getUserWasNotIgnoredText(text)).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import {Command} from "../base/command";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {getUptime, logError, oldSendMessage} from "../util/utils";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class Uptime extends Command {
|
||||
title = "/uptime";
|
||||
description = "Bot's uptime";
|
||||
title = Environment.commandTitles.uptime;
|
||||
description = Environment.commandDescriptions.uptime;
|
||||
|
||||
async execute(msg: Message): Promise<void> {
|
||||
await oldSendMessage(msg, getUptime()).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ export class WhatBetter extends Command {
|
||||
command = ["what", "что"];
|
||||
argsMode = "required" as const;
|
||||
|
||||
title = "/what better [a] or [b]";
|
||||
description = "either a or b randomly (50% chance)";
|
||||
title = Environment.commandTitles.whatBetter;
|
||||
description = Environment.commandDescriptions.whatBetter;
|
||||
|
||||
private argsRe = /^(better|лучше)\s+([\s\S]+?)\s+(or|или)\s+([\s\S]+)$/i;
|
||||
|
||||
@@ -19,8 +19,8 @@ export class WhatBetter extends Command {
|
||||
const a = m[2].trim();
|
||||
const b = m[4].trim();
|
||||
|
||||
const text = `${randomValue(Environment.ANSWERS.better)} ${randomValue([a, b])}`;
|
||||
const text = `${randomValue(Environment.ANSWERS.better) ?? Environment.betterFallbackText} ${randomValue([a, b]) ?? a}`;
|
||||
|
||||
await oldSendMessage(msg, text).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-45
@@ -1,92 +1,60 @@
|
||||
import {Command} from "../base/command";
|
||||
import {getRandomInt, getRangedRandomInt, logError, oldReplyToMessage} from "../util/utils";
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {Environment} from "../common/environment";
|
||||
|
||||
export class When extends Command {
|
||||
command = ["when", "когда"];
|
||||
argsMode = "required" as const;
|
||||
|
||||
title = "/when [value]";
|
||||
description = "random date";
|
||||
title = Environment.commandTitles.when;
|
||||
description = Environment.commandDescriptions.when;
|
||||
|
||||
async execute(msg: Message) {
|
||||
let text = "через ";
|
||||
let text = Environment.getWhenPrefixText();
|
||||
|
||||
const type = getRandomInt(8);
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
text = "сейчас";
|
||||
text = Environment.whenNowText;
|
||||
break;
|
||||
case 1:
|
||||
text = "никогда";
|
||||
text = Environment.whenNeverText;
|
||||
break;
|
||||
case 2: //seconds
|
||||
{
|
||||
const seconds = getRangedRandomInt(1, 60);
|
||||
|
||||
text += `${seconds} `;
|
||||
|
||||
text += (
|
||||
(seconds == 1 || seconds % 10 == 1) ? "секунду" :
|
||||
((seconds > 1 && seconds < 5) || (seconds % 10 > 1 && seconds % 10 < 5)) ? "секунды" : "секунд"
|
||||
);
|
||||
text = Environment.getWhenDurationText(seconds, Environment.whenSecondUnitText);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
const minutes = getRangedRandomInt(1, 60);
|
||||
|
||||
text += `${minutes} `;
|
||||
|
||||
text += (
|
||||
(minutes == 1 || minutes % 10 == 1) ? "минуту" :
|
||||
((minutes > 1 && minutes < 5) || (minutes % 10 > 1 && minutes % 10 < 5)) ? "минуты" : "минут"
|
||||
);
|
||||
text = Environment.getWhenDurationText(minutes, Environment.whenMinuteUnitText);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
const hours = getRangedRandomInt(1, 24);
|
||||
|
||||
text += `${hours} `;
|
||||
|
||||
text += (
|
||||
(hours == 1 || hours % 10 == 1) ? "час" :
|
||||
((hours > 1 && hours < 5) || (hours % 10 > 1 && hours % 10 < 5)) ? "часа" : "часов"
|
||||
);
|
||||
text = Environment.getWhenDurationText(hours, Environment.whenHourUnitText);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
const weeks = getRangedRandomInt(1, 4);
|
||||
|
||||
text += `${weeks} `;
|
||||
|
||||
text += (weeks == 1 ? "неделю" : "недель");
|
||||
text = Environment.getWhenDurationText(weeks, Environment.whenWeekUnitText);
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
const months = getRandomInt(12);
|
||||
|
||||
text += `${months} `;
|
||||
|
||||
text += (
|
||||
(months == 1 || months % 10 == 1) ? "месяц" :
|
||||
((months > 1 && months < 5) || (months % 10 > 1 && months % 10 < 5)) ? "месяца" : "месяцев"
|
||||
);
|
||||
text = Environment.getWhenDurationText(months, Environment.whenMonthUnitText);
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
const years = getRangedRandomInt(1, 100);
|
||||
|
||||
text += `${years} `;
|
||||
|
||||
text += (
|
||||
(years == 1 || years % 10 == 1) ? "год" :
|
||||
((years > 1 && years < 5) || (years % 10 > 1 && years % 10 < 5)) ? "года" : "лет"
|
||||
);
|
||||
text = Environment.getWhenDurationText(years, Environment.whenYearUnitText);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await oldReplyToMessage(msg, text).catch(logError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user