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