2023-08-13 16:48:04 +03:00

5693 lines
178 KiB
JavaScript

function matchFilter(filter) {
const parsed = parse(filter);
const predicate = compile(parsed);
return (ctx)=>predicate(ctx);
}
function parse(filter) {
return Array.isArray(filter) ? filter.map((q)=>q.split(":")) : [
filter.split(":")
];
}
function compile(parsed) {
const preprocessed = parsed.flatMap((q)=>check(q, preprocess(q)));
const ltree = treeify(preprocessed);
const predicate = arborist(ltree);
return (ctx)=>!!predicate(ctx.update, ctx);
}
function preprocess(filter) {
const valid = UPDATE_KEYS;
const expanded = [
filter
].flatMap((q)=>{
const [l1, l2, l3] = q;
if (!(l1 in L1_SHORTCUTS)) return [
q
];
if (!l1 && !l2 && !l3) return [
q
];
const targets = L1_SHORTCUTS[l1];
const expanded = targets.map((s)=>[
s,
l2,
l3
]);
if (l2 === undefined) return expanded;
if (l2 in L2_SHORTCUTS && (l2 || l3)) return expanded;
return expanded.filter(([s])=>!!valid[s]?.[l2]);
}).flatMap((q)=>{
const [l1, l2, l3] = q;
if (!(l2 in L2_SHORTCUTS)) return [
q
];
if (!l2 && !l3) return [
q
];
const targets = L2_SHORTCUTS[l2];
const expanded = targets.map((s)=>[
l1,
s,
l3
]);
if (l3 === undefined) return expanded;
return expanded.filter(([, s])=>!!valid[l1]?.[s]?.[l3]);
});
if (expanded.length === 0) {
throw new Error(`Shortcuts in '${filter.join(":")}' do not expand to any valid filter query`);
}
return expanded;
}
function check(original, preprocessed) {
if (preprocessed.length === 0) throw new Error("Empty filter query given");
const errors = preprocessed.map(checkOne).filter((r)=>r !== true);
if (errors.length === 0) return preprocessed;
else if (errors.length === 1) throw new Error(errors[0]);
else {
throw new Error(`Invalid filter query '${original.join(":")}'. There are ${errors.length} errors after expanding the contained shortcuts: ${errors.join("; ")}`);
}
}
function checkOne(filter) {
const [l1, l2, l3, ...n] = filter;
if (l1 === undefined) return "Empty filter query given";
if (!(l1 in UPDATE_KEYS)) {
const permitted = Object.keys(UPDATE_KEYS);
return `Invalid L1 filter '${l1}' given in '${filter.join(":")}'. \
Permitted values are: ${permitted.map((k)=>`'${k}'`).join(", ")}.`;
}
if (l2 === undefined) return true;
const l1Obj = UPDATE_KEYS[l1];
if (!(l2 in l1Obj)) {
const permitted = Object.keys(l1Obj);
return `Invalid L2 filter '${l2}' given in '${filter.join(":")}'. \
Permitted values are: ${permitted.map((k)=>`'${k}'`).join(", ")}.`;
}
if (l3 === undefined) return true;
const l2Obj = l1Obj[l2];
if (!(l3 in l2Obj)) {
const permitted = Object.keys(l2Obj);
return `Invalid L3 filter '${l3}' given in '${filter.join(":")}'. ${permitted.length === 0 ? `No further filtering is possible after '${l1}:${l2}'.` : `Permitted values are: ${permitted.map((k)=>`'${k}'`).join(", ")}.`}`;
}
if (n.length === 0) return true;
return `Cannot filter further than three levels, ':${n.join(":")}' is invalid!`;
}
function treeify(paths) {
const tree = {};
for (const [l1, l2, l3] of paths){
const subtree = tree[l1] ??= {};
if (l2 !== undefined) {
const set = subtree[l2] ??= new Set();
if (l3 !== undefined) set.add(l3);
}
}
return tree;
}
function or(left, right) {
return (obj, ctx)=>left(obj, ctx) || right(obj, ctx);
}
function concat(get, test) {
return (obj, ctx)=>{
const nextObj = get(obj, ctx);
return nextObj && test(nextObj, ctx);
};
}
function leaf(pred) {
return (obj, ctx)=>pred(obj, ctx) != null;
}
function arborist(tree) {
const l1Predicates = Object.entries(tree).map(([l1, subtree])=>{
const l1Pred = (obj)=>obj[l1];
const l2Predicates = Object.entries(subtree).map(([l2, set])=>{
const l2Pred = (obj)=>obj[l2];
const l3Predicates = Array.from(set).map((l3)=>{
const l3Pred = l3 === "me" ? (obj, ctx)=>{
const me = ctx.me.id;
return testMaybeArray(obj, (u)=>u.id === me);
} : (obj)=>testMaybeArray(obj, (e)=>e[l3] || e.type === l3);
return l3Pred;
});
return l3Predicates.length === 0 ? leaf(l2Pred) : concat(l2Pred, l3Predicates.reduce(or));
});
return l2Predicates.length === 0 ? leaf(l1Pred) : concat(l1Pred, l2Predicates.reduce(or));
});
if (l1Predicates.length === 0) {
throw new Error("Cannot create filter function for empty query");
}
return l1Predicates.reduce(or);
}
function testMaybeArray(t, pred) {
const p = (x)=>x != null && pred(x);
return Array.isArray(t) ? t.some(p) : p(t);
}
const ENTITY_KEYS = {
mention: {},
hashtag: {},
cashtag: {},
bot_command: {},
url: {},
email: {},
phone_number: {},
bold: {},
italic: {},
underline: {},
strikethrough: {},
spoiler: {},
code: {},
pre: {},
text_link: {},
text_mention: {},
custom_emoji: {}
};
const USER_KEYS = {
me: {},
is_bot: {},
is_premium: {},
added_to_attachment_menu: {}
};
const STICKER_KEYS = {
is_video: {},
is_animated: {},
premium_animation: {}
};
const EDITABLE_MESSAGE_KEYS = {
text: {},
animation: {},
audio: {},
document: {},
photo: {},
video: {},
game: {},
location: {},
entities: ENTITY_KEYS,
caption_entities: ENTITY_KEYS,
has_media_spoiler: {},
caption: {}
};
const COMMON_MESSAGE_KEYS = {
...EDITABLE_MESSAGE_KEYS,
sticker: STICKER_KEYS,
video_note: {},
voice: {},
contact: {},
dice: {},
poll: {},
venue: {},
new_chat_title: {},
new_chat_photo: {},
delete_chat_photo: {},
message_auto_delete_timer_changed: {},
pinned_message: {},
invoice: {},
proximity_alert_triggered: {},
video_chat_scheduled: {},
video_chat_started: {},
video_chat_ended: {},
video_chat_participants_invited: {},
web_app_data: {},
forward_date: {},
is_topic_message: {},
is_automatic_forward: {}
};
const MESSAGE_KEYS = {
...COMMON_MESSAGE_KEYS,
new_chat_members: USER_KEYS,
left_chat_member: USER_KEYS,
group_chat_created: {},
supergroup_chat_created: {},
migrate_to_chat_id: {},
migrate_from_chat_id: {},
successful_payment: {},
user_shared: {},
chat_shared: {},
connected_website: {},
write_access_allowed: {},
passport_data: {},
forum_topic_created: {},
forum_topic_edited: {
name: {},
icon_custom_emoji_id: {}
},
forum_topic_closed: {},
forum_topic_reopened: {},
general_forum_topic_hidden: {},
general_forum_topic_unhidden: {}
};
const CHANNEL_POST_KEYS = {
...COMMON_MESSAGE_KEYS,
channel_chat_created: {}
};
const CALLBACK_QUERY_KEYS = {
data: {},
game_short_name: {}
};
const CHAT_MEMBER_UPDATED_KEYS = {
from: USER_KEYS
};
const UPDATE_KEYS = {
message: MESSAGE_KEYS,
edited_message: MESSAGE_KEYS,
channel_post: CHANNEL_POST_KEYS,
edited_channel_post: CHANNEL_POST_KEYS,
inline_query: {},
chosen_inline_result: {},
callback_query: CALLBACK_QUERY_KEYS,
shipping_query: {},
pre_checkout_query: {},
poll: {},
poll_answer: {},
my_chat_member: CHAT_MEMBER_UPDATED_KEYS,
chat_member: CHAT_MEMBER_UPDATED_KEYS,
chat_join_request: {}
};
const L1_SHORTCUTS = {
"": [
"message",
"channel_post"
],
msg: [
"message",
"channel_post"
],
edit: [
"edited_message",
"edited_channel_post"
]
};
const L2_SHORTCUTS = {
"": [
"entities",
"caption_entities"
],
media: [
"photo",
"video"
],
file: [
"photo",
"animation",
"audio",
"document",
"video",
"video_note",
"voice",
"sticker"
]
};
const checker = {
filterQuery (filter) {
const pred = matchFilter(filter);
return (ctx)=>pred(ctx);
},
text (trigger) {
const hasText = checker.filterQuery([
":text",
":caption"
]);
const trg = triggerFn(trigger);
return (ctx)=>{
if (!hasText(ctx)) return false;
const msg = ctx.message ?? ctx.channelPost;
const txt = msg.text ?? msg.caption;
return match(ctx, txt, trg);
};
},
command (command) {
const hasEntities = checker.filterQuery(":entities:bot_command");
const atCommands = new Set();
const noAtCommands = new Set();
toArray(command).forEach((cmd)=>{
if (cmd.startsWith("/")) {
throw new Error(`Do not include '/' when registering command handlers (use '${cmd.substring(1)}' not '${cmd}')`);
}
const set = cmd.indexOf("@") === -1 ? noAtCommands : atCommands;
set.add(cmd);
});
return (ctx)=>{
if (!hasEntities(ctx)) return false;
const msg = ctx.message ?? ctx.channelPost;
const txt = msg.text ?? msg.caption;
return msg.entities.some((e)=>{
if (e.type !== "bot_command") return false;
if (e.offset !== 0) return false;
const cmd = txt.substring(1, e.length);
if (noAtCommands.has(cmd) || atCommands.has(cmd)) {
ctx.match = txt.substring(cmd.length + 1).trimStart();
return true;
}
const index = cmd.indexOf("@");
if (index === -1) return false;
const atTarget = cmd.substring(index + 1);
if (atTarget !== ctx.me.username) return false;
const atCommand = cmd.substring(0, index);
if (noAtCommands.has(atCommand)) {
ctx.match = txt.substring(cmd.length + 1).trimStart();
return true;
}
return false;
});
};
},
chatType (chatType) {
const set = new Set(toArray(chatType));
return (ctx)=>ctx.chat?.type !== undefined && set.has(ctx.chat.type);
},
callbackQuery (trigger) {
const hasCallbackQuery = checker.filterQuery("callback_query:data");
const trg = triggerFn(trigger);
return (ctx)=>hasCallbackQuery(ctx) && match(ctx, ctx.callbackQuery.data, trg);
},
gameQuery (trigger) {
const hasGameQuery = checker.filterQuery("callback_query:game_short_name");
const trg = triggerFn(trigger);
return (ctx)=>hasGameQuery(ctx) && match(ctx, ctx.callbackQuery.game_short_name, trg);
},
inlineQuery (trigger) {
const hasInlineQuery = checker.filterQuery("inline_query");
const trg = triggerFn(trigger);
return (ctx)=>hasInlineQuery(ctx) && match(ctx, ctx.inlineQuery.query, trg);
},
chosenInlineResult (trigger) {
const hasChosenInlineResult = checker.filterQuery("chosen_inline_result");
const trg = triggerFn(trigger);
return (ctx)=>hasChosenInlineResult(ctx) && match(ctx, ctx.chosenInlineResult.result_id, trg);
}
};
class Context {
match;
constructor(update, api, me){
this.update = update;
this.api = api;
this.me = me;
}
get message() {
return this.update.message;
}
get editedMessage() {
return this.update.edited_message;
}
get channelPost() {
return this.update.channel_post;
}
get editedChannelPost() {
return this.update.edited_channel_post;
}
get inlineQuery() {
return this.update.inline_query;
}
get chosenInlineResult() {
return this.update.chosen_inline_result;
}
get callbackQuery() {
return this.update.callback_query;
}
get shippingQuery() {
return this.update.shipping_query;
}
get preCheckoutQuery() {
return this.update.pre_checkout_query;
}
get poll() {
return this.update.poll;
}
get pollAnswer() {
return this.update.poll_answer;
}
get myChatMember() {
return this.update.my_chat_member;
}
get chatMember() {
return this.update.chat_member;
}
get chatJoinRequest() {
return this.update.chat_join_request;
}
get msg() {
return this.message ?? this.editedMessage ?? this.callbackQuery?.message ?? this.channelPost ?? this.editedChannelPost;
}
get chat() {
return (this.msg ?? this.myChatMember ?? this.chatMember ?? this.chatJoinRequest)?.chat;
}
get senderChat() {
return this.msg?.sender_chat;
}
get from() {
return (this.callbackQuery ?? this.inlineQuery ?? this.shippingQuery ?? this.preCheckoutQuery ?? this.chosenInlineResult ?? this.msg ?? this.myChatMember ?? this.chatMember ?? this.chatJoinRequest)?.from;
}
get inlineMessageId() {
return this.callbackQuery?.inline_message_id ?? this.chosenInlineResult?.inline_message_id;
}
entities(types) {
const message = this.msg;
if (message === undefined) return [];
const text = message.text ?? message.caption;
if (text === undefined) return [];
let entities = message.entities ?? message.caption_entities;
if (entities === undefined) return [];
if (types !== undefined) {
const filters = new Set(toArray(types));
entities = entities.filter((entity)=>filters.has(entity.type));
}
return entities.map((entity)=>({
...entity,
text: text.substring(entity.offset, entity.offset + entity.length)
}));
}
static has = checker;
has(filter) {
return Context.has.filterQuery(filter)(this);
}
hasText(trigger) {
return Context.has.text(trigger)(this);
}
hasCommand(command) {
return Context.has.command(command)(this);
}
hasChatType(chatType) {
return Context.has.chatType(chatType)(this);
}
hasCallbackQuery(trigger) {
return Context.has.callbackQuery(trigger)(this);
}
hasGameQuery(trigger) {
return Context.has.gameQuery(trigger)(this);
}
hasInlineQuery(trigger) {
return Context.has.inlineQuery(trigger)(this);
}
hasChosenInlineResult(trigger) {
return Context.has.chosenInlineResult(trigger)(this);
}
reply(text, other, signal) {
return this.api.sendMessage(orThrow(this.chat, "sendMessage").id, text, other, signal);
}
forwardMessage(chat_id, other, signal) {
return this.api.forwardMessage(chat_id, orThrow(this.chat, "forwardMessage").id, orThrow(this.msg, "forwardMessage").message_id, other, signal);
}
copyMessage(chat_id, other, signal) {
return this.api.copyMessage(chat_id, orThrow(this.chat, "copyMessage").id, orThrow(this.msg, "copyMessage").message_id, other, signal);
}
replyWithPhoto(photo, other, signal) {
return this.api.sendPhoto(orThrow(this.chat, "sendPhoto").id, photo, other, signal);
}
replyWithAudio(audio, other, signal) {
return this.api.sendAudio(orThrow(this.chat, "sendAudio").id, audio, other, signal);
}
replyWithDocument(document1, other, signal) {
return this.api.sendDocument(orThrow(this.chat, "sendDocument").id, document1, other, signal);
}
replyWithVideo(video, other, signal) {
return this.api.sendVideo(orThrow(this.chat, "sendVideo").id, video, other, signal);
}
replyWithAnimation(animation, other, signal) {
return this.api.sendAnimation(orThrow(this.chat, "sendAnimation").id, animation, other, signal);
}
replyWithVoice(voice, other, signal) {
return this.api.sendVoice(orThrow(this.chat, "sendVoice").id, voice, other, signal);
}
replyWithVideoNote(video_note, other, signal) {
return this.api.sendVideoNote(orThrow(this.chat, "sendVideoNote").id, video_note, other, signal);
}
replyWithMediaGroup(media, other, signal) {
return this.api.sendMediaGroup(orThrow(this.chat, "sendMediaGroup").id, media, other, signal);
}
replyWithLocation(latitude, longitude, other, signal) {
return this.api.sendLocation(orThrow(this.chat, "sendLocation").id, latitude, longitude, other, signal);
}
editMessageLiveLocation(latitude, longitude, other, signal) {
const inlineId = this.inlineMessageId;
return inlineId !== undefined ? this.api.editMessageLiveLocationInline(inlineId, latitude, longitude, other) : this.api.editMessageLiveLocation(orThrow(this.chat, "editMessageLiveLocation").id, orThrow(this.msg, "editMessageLiveLocation").message_id, latitude, longitude, other, signal);
}
stopMessageLiveLocation(other, signal) {
const inlineId = this.inlineMessageId;
return inlineId !== undefined ? this.api.stopMessageLiveLocationInline(inlineId, other) : this.api.stopMessageLiveLocation(orThrow(this.chat, "stopMessageLiveLocation").id, orThrow(this.msg, "stopMessageLiveLocation").message_id, other, signal);
}
replyWithVenue(latitude, longitude, title, address, other, signal) {
return this.api.sendVenue(orThrow(this.chat, "sendVenue").id, latitude, longitude, title, address, other, signal);
}
replyWithContact(phone_number, first_name, other, signal) {
return this.api.sendContact(orThrow(this.chat, "sendContact").id, phone_number, first_name, other, signal);
}
replyWithPoll(question, options, other, signal) {
return this.api.sendPoll(orThrow(this.chat, "sendPoll").id, question, options, other, signal);
}
replyWithDice(emoji, other, signal) {
return this.api.sendDice(orThrow(this.chat, "sendDice").id, emoji, other, signal);
}
replyWithChatAction(action, other, signal) {
return this.api.sendChatAction(orThrow(this.chat, "sendChatAction").id, action, other, signal);
}
getUserProfilePhotos(other, signal) {
return this.api.getUserProfilePhotos(orThrow(this.from, "getUserProfilePhotos").id, other, signal);
}
getFile(signal) {
const m = orThrow(this.msg, "getFile");
const file = m.photo !== undefined ? m.photo[m.photo.length - 1] : m.animation ?? m.audio ?? m.document ?? m.video ?? m.video_note ?? m.voice ?? m.sticker;
return this.api.getFile(orThrow(file, "getFile").file_id, signal);
}
kickAuthor(...args) {
return this.banAuthor(...args);
}
banAuthor(other, signal) {
return this.api.banChatMember(orThrow(this.chat, "banAuthor").id, orThrow(this.from, "banAuthor").id, other, signal);
}
kickChatMember(...args) {
return this.banChatMember(...args);
}
banChatMember(user_id, other, signal) {
return this.api.banChatMember(orThrow(this.chat, "banChatMember").id, user_id, other, signal);
}
unbanChatMember(user_id, other, signal) {
return this.api.unbanChatMember(orThrow(this.chat, "unbanChatMember").id, user_id, other, signal);
}
restrictAuthor(permissions, other, signal) {
return this.api.restrictChatMember(orThrow(this.chat, "restrictAuthor").id, orThrow(this.from, "restrictAuthor").id, permissions, other, signal);
}
restrictChatMember(user_id, permissions, other, signal) {
return this.api.restrictChatMember(orThrow(this.chat, "restrictChatMember").id, user_id, permissions, other, signal);
}
promoteAuthor(other, signal) {
return this.api.promoteChatMember(orThrow(this.chat, "promoteAuthor").id, orThrow(this.from, "promoteAuthor").id, other, signal);
}
promoteChatMember(user_id, other, signal) {
return this.api.promoteChatMember(orThrow(this.chat, "promoteChatMember").id, user_id, other, signal);
}
setChatAdministratorAuthorCustomTitle(custom_title, signal) {
return this.api.setChatAdministratorCustomTitle(orThrow(this.chat, "setChatAdministratorAuthorCustomTitle").id, orThrow(this.from, "setChatAdministratorAuthorCustomTitle").id, custom_title, signal);
}
setChatAdministratorCustomTitle(user_id, custom_title, signal) {
return this.api.setChatAdministratorCustomTitle(orThrow(this.chat, "setChatAdministratorCustomTitle").id, user_id, custom_title, signal);
}
banChatSenderChat(sender_chat_id, signal) {
return this.api.banChatSenderChat(orThrow(this.chat, "banChatSenderChat").id, sender_chat_id, signal);
}
unbanChatSenderChat(sender_chat_id, signal) {
return this.api.unbanChatSenderChat(orThrow(this.chat, "unbanChatSenderChat").id, sender_chat_id, signal);
}
setChatPermissions(permissions, signal) {
return this.api.setChatPermissions(orThrow(this.chat, "setChatPermissions").id, permissions, signal);
}
exportChatInviteLink(signal) {
return this.api.exportChatInviteLink(orThrow(this.chat, "exportChatInviteLink").id, signal);
}
createChatInviteLink(other, signal) {
return this.api.createChatInviteLink(orThrow(this.chat, "createChatInviteLink").id, other, signal);
}
editChatInviteLink(invite_link, other, signal) {
return this.api.editChatInviteLink(orThrow(this.chat, "editChatInviteLink").id, invite_link, other, signal);
}
revokeChatInviteLink(invite_link, signal) {
return this.api.revokeChatInviteLink(orThrow(this.chat, "editChatInviteLink").id, invite_link, signal);
}
approveChatJoinRequest(user_id, signal) {
return this.api.approveChatJoinRequest(orThrow(this.chat, "approveChatJoinRequest").id, user_id, signal);
}
declineChatJoinRequest(user_id, signal) {
return this.api.declineChatJoinRequest(orThrow(this.chat, "declineChatJoinRequest").id, user_id, signal);
}
setChatPhoto(photo, signal) {
return this.api.setChatPhoto(orThrow(this.chat, "setChatPhoto").id, photo, signal);
}
deleteChatPhoto(signal) {
return this.api.deleteChatPhoto(orThrow(this.chat, "deleteChatPhoto").id, signal);
}
setChatTitle(title, signal) {
return this.api.setChatTitle(orThrow(this.chat, "setChatTitle").id, title, signal);
}
setChatDescription(description, signal) {
return this.api.setChatDescription(orThrow(this.chat, "setChatDescription").id, description, signal);
}
pinChatMessage(message_id, other, signal) {
return this.api.pinChatMessage(orThrow(this.chat, "pinChatMessage").id, message_id, other, signal);
}
unpinChatMessage(message_id, signal) {
return this.api.unpinChatMessage(orThrow(this.chat, "unpinChatMessage").id, message_id, signal);
}
unpinAllChatMessages(signal) {
return this.api.unpinAllChatMessages(orThrow(this.chat, "unpinAllChatMessages").id, signal);
}
leaveChat(signal) {
return this.api.leaveChat(orThrow(this.chat, "leaveChat").id, signal);
}
getChat(signal) {
return this.api.getChat(orThrow(this.chat, "getChat").id, signal);
}
getChatAdministrators(signal) {
return this.api.getChatAdministrators(orThrow(this.chat, "getChatAdministrators").id, signal);
}
getChatMembersCount(...args) {
return this.getChatMemberCount(...args);
}
getChatMemberCount(signal) {
return this.api.getChatMemberCount(orThrow(this.chat, "getChatMemberCount").id, signal);
}
getAuthor(signal) {
return this.api.getChatMember(orThrow(this.chat, "getAuthor").id, orThrow(this.from, "getAuthor").id, signal);
}
getChatMember(user_id, signal) {
return this.api.getChatMember(orThrow(this.chat, "getChatMember").id, user_id, signal);
}
setChatStickerSet(sticker_set_name, signal) {
return this.api.setChatStickerSet(orThrow(this.chat, "setChatStickerSet").id, sticker_set_name, signal);
}
deleteChatStickerSet(signal) {
return this.api.deleteChatStickerSet(orThrow(this.chat, "deleteChatStickerSet").id, signal);
}
createForumTopic(name, other, signal) {
return this.api.createForumTopic(orThrow(this.chat, "createForumTopic").id, name, other, signal);
}
editForumTopic(other, signal) {
const message = orThrow(this.msg, "editForumTopic");
const thread = orThrow(message.message_thread_id, "editForumTopic");
return this.api.editForumTopic(message.chat.id, thread, other, signal);
}
closeForumTopic(signal) {
const message = orThrow(this.msg, "closeForumTopic");
const thread = orThrow(message.message_thread_id, "closeForumTopic");
return this.api.closeForumTopic(message.chat.id, thread, signal);
}
reopenForumTopic(signal) {
const message = orThrow(this.msg, "reopenForumTopic");
const thread = orThrow(message.message_thread_id, "reopenForumTopic");
return this.api.reopenForumTopic(message.chat.id, thread, signal);
}
deleteForumTopic(signal) {
const message = orThrow(this.msg, "deleteForumTopic");
const thread = orThrow(message.message_thread_id, "deleteForumTopic");
return this.api.deleteForumTopic(message.chat.id, thread, signal);
}
unpinAllForumTopicMessages(signal) {
const message = orThrow(this.msg, "unpinAllForumTopicMessages");
const thread = orThrow(message.message_thread_id, "unpinAllForumTopicMessages");
return this.api.unpinAllForumTopicMessages(message.chat.id, thread, signal);
}
editGeneralForumTopic(name, signal) {
return this.api.editGeneralForumTopic(orThrow(this.chat, "editGeneralForumTopic").id, name, signal);
}
closeGeneralForumTopic(signal) {
return this.api.closeGeneralForumTopic(orThrow(this.chat, "closeGeneralForumTopic").id, signal);
}
reopenGeneralForumTopic(signal) {
return this.api.reopenGeneralForumTopic(orThrow(this.chat, "reopenGeneralForumTopic").id, signal);
}
hideGeneralForumTopic(signal) {
return this.api.hideGeneralForumTopic(orThrow(this.chat, "hideGeneralForumTopic").id, signal);
}
unhideGeneralForumTopic(signal) {
return this.api.unhideGeneralForumTopic(orThrow(this.chat, "unhideGeneralForumTopic").id, signal);
}
answerCallbackQuery(other, signal) {
return this.api.answerCallbackQuery(orThrow(this.callbackQuery, "answerCallbackQuery").id, typeof other === "string" ? {
text: other
} : other, signal);
}
setChatMenuButton(other, signal) {
return this.api.setChatMenuButton(other, signal);
}
getChatMenuButton(other, signal) {
return this.api.getChatMenuButton(other, signal);
}
setMyDefaultAdministratorRights(other, signal) {
return this.api.setMyDefaultAdministratorRights(other, signal);
}
getMyDefaultAdministratorRights(other, signal) {
return this.api.getMyDefaultAdministratorRights(other, signal);
}
editMessageText(text, other, signal) {
const inlineId = this.inlineMessageId;
return inlineId !== undefined ? this.api.editMessageTextInline(inlineId, text, other) : this.api.editMessageText(orThrow(this.chat, "editMessageText").id, orThrow(this.msg, "editMessageText").message_id, text, other, signal);
}
editMessageCaption(other, signal) {
const inlineId = this.inlineMessageId;
return inlineId !== undefined ? this.api.editMessageCaptionInline(inlineId, other) : this.api.editMessageCaption(orThrow(this.chat, "editMessageCaption").id, orThrow(this.msg, "editMessageCaption").message_id, other, signal);
}
editMessageMedia(media, other, signal) {
const inlineId = this.inlineMessageId;
return inlineId !== undefined ? this.api.editMessageMediaInline(inlineId, media, other) : this.api.editMessageMedia(orThrow(this.chat, "editMessageMedia").id, orThrow(this.msg, "editMessageMedia").message_id, media, other, signal);
}
editMessageReplyMarkup(other, signal) {
const inlineId = this.inlineMessageId;
return inlineId !== undefined ? this.api.editMessageReplyMarkupInline(inlineId, other) : this.api.editMessageReplyMarkup(orThrow(this.chat, "editMessageReplyMarkup").id, orThrow(this.msg, "editMessageReplyMarkup").message_id, other, signal);
}
stopPoll(other, signal) {
return this.api.stopPoll(orThrow(this.chat, "stopPoll").id, orThrow(this.msg, "stopPoll").message_id, other, signal);
}
deleteMessage(signal) {
return this.api.deleteMessage(orThrow(this.chat, "deleteMessage").id, orThrow(this.msg, "deleteMessage").message_id, signal);
}
replyWithSticker(sticker, other, signal) {
return this.api.sendSticker(orThrow(this.chat, "sendSticker").id, sticker, other, signal);
}
getCustomEmojiStickers(signal) {
return this.api.getCustomEmojiStickers((this.msg?.entities ?? []).filter((e)=>e.type === "custom_emoji").map((e)=>e.custom_emoji_id), signal);
}
answerInlineQuery(results, other, signal) {
return this.api.answerInlineQuery(orThrow(this.inlineQuery, "answerInlineQuery").id, results, other, signal);
}
replyWithInvoice(title, description, payload, provider_token, currency, prices, other, signal) {
return this.api.sendInvoice(orThrow(this.chat, "sendInvoice").id, title, description, payload, provider_token, currency, prices, other, signal);
}
answerShippingQuery(ok, other, signal) {
return this.api.answerShippingQuery(orThrow(this.shippingQuery, "answerShippingQuery").id, ok, other, signal);
}
answerPreCheckoutQuery(ok, other, signal) {
return this.api.answerPreCheckoutQuery(orThrow(this.preCheckoutQuery, "answerPreCheckoutQuery").id, ok, typeof other === "string" ? {
error_message: other
} : other, signal);
}
setPassportDataErrors(errors, signal) {
return this.api.setPassportDataErrors(orThrow(this.from, "setPassportDataErrors").id, errors, signal);
}
replyWithGame(game_short_name, other, signal) {
return this.api.sendGame(orThrow(this.chat, "sendGame").id, game_short_name, other, signal);
}
update;
api;
me;
}
function orThrow(value, method) {
if (value === undefined) {
throw new Error(`Missing information for API call to ${method}`);
}
return value;
}
function triggerFn(trigger) {
return toArray(trigger).map((t)=>typeof t === "string" ? (txt)=>txt === t ? t : null : (txt)=>txt.match(t));
}
function match(ctx, content, triggers) {
for (const t of triggers){
const res = t(content);
if (res) {
ctx.match = res;
return true;
}
}
return false;
}
function toArray(e) {
return Array.isArray(e) ? e : [
e
];
}
class BotError extends Error {
constructor(error, ctx){
super(generateBotErrorMessage(error));
this.error = error;
this.ctx = ctx;
this.name = "BotError";
if (error instanceof Error) this.stack = error.stack;
}
error;
ctx;
}
function generateBotErrorMessage(error) {
let msg;
if (error instanceof Error) {
msg = `${error.name} in middleware: ${error.message}`;
} else {
const type = typeof error;
msg = `Non-error value of type ${type} thrown in middleware`;
switch(type){
case "bigint":
case "boolean":
case "number":
case "symbol":
msg += `: ${error}`;
break;
case "string":
msg += `: ${String(error).substring(0, 50)}`;
break;
default:
msg += "!";
break;
}
}
return msg;
}
function flatten(mw) {
return typeof mw === "function" ? mw : (ctx, next)=>mw.middleware()(ctx, next);
}
function concat1(first, andThen) {
return async (ctx, next)=>{
let nextCalled = false;
await first(ctx, async ()=>{
if (nextCalled) throw new Error("`next` already called before!");
else nextCalled = true;
await andThen(ctx, next);
});
};
}
function pass(_ctx, next) {
return next();
}
const leaf1 = ()=>Promise.resolve();
async function run(middleware, ctx) {
await middleware(ctx, leaf1);
}
class Composer {
handler;
constructor(...middleware){
this.handler = middleware.length === 0 ? pass : middleware.map(flatten).reduce(concat1);
}
middleware() {
return this.handler;
}
use(...middleware) {
const composer = new Composer(...middleware);
this.handler = concat1(this.handler, flatten(composer));
return composer;
}
on(filter, ...middleware) {
return this.filter(Context.has.filterQuery(filter), ...middleware);
}
hears(trigger, ...middleware) {
return this.filter(Context.has.text(trigger), ...middleware);
}
command(command, ...middleware) {
return this.filter(Context.has.command(command), ...middleware);
}
chatType(chatType, ...middleware) {
return this.filter(Context.has.chatType(chatType), ...middleware);
}
callbackQuery(trigger, ...middleware) {
return this.filter(Context.has.callbackQuery(trigger), ...middleware);
}
gameQuery(trigger, ...middleware) {
return this.filter(Context.has.gameQuery(trigger), ...middleware);
}
inlineQuery(trigger, ...middleware) {
return this.filter(Context.has.inlineQuery(trigger), ...middleware);
}
chosenInlineResult(resultId, ...middleware) {
return this.filter(Context.has.chosenInlineResult(resultId), ...middleware);
}
filter(predicate, ...middleware) {
const composer = new Composer(...middleware);
this.branch(predicate, composer, pass);
return composer;
}
drop(predicate, ...middleware) {
return this.filter(async (ctx)=>!await predicate(ctx), ...middleware);
}
fork(...middleware) {
const composer = new Composer(...middleware);
const fork = flatten(composer);
this.use((ctx, next)=>Promise.all([
next(),
run(fork, ctx)
]));
return composer;
}
lazy(middlewareFactory) {
return this.use(async (ctx, next)=>{
const middleware = await middlewareFactory(ctx);
const arr = Array.isArray(middleware) ? middleware : [
middleware
];
await flatten(new Composer(...arr))(ctx, next);
});
}
route(router, routeHandlers, fallback = pass) {
return this.lazy(async (ctx)=>{
const route = await router(ctx);
return (route === undefined || !routeHandlers[route] ? fallback : routeHandlers[route]) ?? [];
});
}
branch(predicate, trueMiddleware, falseMiddleware) {
return this.lazy(async (ctx)=>await predicate(ctx) ? trueMiddleware : falseMiddleware);
}
errorBoundary(errorHandler, ...middleware) {
const composer = new Composer(...middleware);
const bound = flatten(composer);
this.use(async (ctx, next)=>{
let nextCalled = false;
const cont = ()=>(nextCalled = true, Promise.resolve());
try {
await bound(ctx, cont);
} catch (err) {
nextCalled = false;
await errorHandler(new BotError(err, ctx), cont);
}
if (nextCalled) await next();
});
return composer;
}
}
var s = 1e3;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var w = d * 7;
var y = d * 365.25;
var ms = function(val, options) {
options = options || {};
var type = typeof val;
if (type === "string" && val.length > 0) {
return parse1(val);
} else if (type === "number" && isFinite(val)) {
return options.long ? fmtLong(val) : fmtShort(val);
}
throw new Error("val is not a non-empty string or a valid number. val=" + JSON.stringify(val));
};
function parse1(str) {
str = String(str);
if (str.length > 100) {
return;
}
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);
if (!match) {
return;
}
var n = parseFloat(match[1]);
var type = (match[2] || "ms").toLowerCase();
switch(type){
case "years":
case "year":
case "yrs":
case "yr":
case "y":
return n * y;
case "weeks":
case "week":
case "w":
return n * w;
case "days":
case "day":
case "d":
return n * d;
case "hours":
case "hour":
case "hrs":
case "hr":
case "h":
return n * h;
case "minutes":
case "minute":
case "mins":
case "min":
case "m":
return n * m;
case "seconds":
case "second":
case "secs":
case "sec":
case "s":
return n * s;
case "milliseconds":
case "millisecond":
case "msecs":
case "msec":
case "ms":
return n;
default:
return void 0;
}
}
function fmtShort(ms2) {
var msAbs = Math.abs(ms2);
if (msAbs >= d) {
return Math.round(ms2 / d) + "d";
}
if (msAbs >= h) {
return Math.round(ms2 / h) + "h";
}
if (msAbs >= m) {
return Math.round(ms2 / m) + "m";
}
if (msAbs >= s) {
return Math.round(ms2 / s) + "s";
}
return ms2 + "ms";
}
function fmtLong(ms2) {
var msAbs = Math.abs(ms2);
if (msAbs >= d) {
return plural(ms2, msAbs, d, "day");
}
if (msAbs >= h) {
return plural(ms2, msAbs, h, "hour");
}
if (msAbs >= m) {
return plural(ms2, msAbs, m, "minute");
}
if (msAbs >= s) {
return plural(ms2, msAbs, s, "second");
}
return ms2 + " ms";
}
function plural(ms2, msAbs, n, name) {
var isPlural = msAbs >= n * 1.5;
return Math.round(ms2 / n) + " " + name + (isPlural ? "s" : "");
}
function defaultSetTimout() {
throw new Error("setTimeout has not been defined");
}
function defaultClearTimeout() {
throw new Error("clearTimeout has not been defined");
}
var cachedSetTimeout = defaultSetTimout;
var cachedClearTimeout = defaultClearTimeout;
var globalContext;
if (typeof window !== "undefined") {
globalContext = window;
} else if (typeof self !== "undefined") {
globalContext = self;
} else {
globalContext = {};
}
if (typeof globalContext.setTimeout === "function") {
cachedSetTimeout = setTimeout;
}
if (typeof globalContext.clearTimeout === "function") {
cachedClearTimeout = clearTimeout;
}
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
return setTimeout(fun, 0);
}
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
return cachedSetTimeout(fun, 0);
} catch (e) {
try {
return cachedSetTimeout.call(null, fun, 0);
} catch (e2) {
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
return clearTimeout(marker);
}
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
return cachedClearTimeout(marker);
} catch (e) {
try {
return cachedClearTimeout.call(null, marker);
} catch (e2) {
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len){
currentQueue = queue;
queue = [];
while(++queueIndex < len){
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
function nextTick(fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for(var i = 1; i < arguments.length; i++){
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
}
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function() {
this.fun.apply(null, this.array);
};
var title = "browser";
var platform = "browser";
var browser = true;
var argv = [];
var version = "";
var versions = {};
var release = {};
var config = {};
function noop() {}
var on = noop;
var addListener = noop;
var once = noop;
var off = noop;
var removeListener = noop;
var removeAllListeners = noop;
var emit = noop;
function binding(name) {
throw new Error("process.binding is not supported");
}
function cwd() {
return "/";
}
function chdir(dir) {
throw new Error("process.chdir is not supported");
}
function umask() {
return 0;
}
var performance = globalContext.performance || {};
var performanceNow = performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function() {
return new Date().getTime();
};
function hrtime(previousTimestamp) {
var clocktime = performanceNow.call(performance) * 1e-3;
var seconds = Math.floor(clocktime);
var nanoseconds = Math.floor(clocktime % 1 * 1e9);
if (previousTimestamp) {
seconds = seconds - previousTimestamp[0];
nanoseconds = nanoseconds - previousTimestamp[1];
if (nanoseconds < 0) {
seconds--;
nanoseconds += 1e9;
}
}
return [
seconds,
nanoseconds
];
}
var startTime = new Date();
function uptime() {
var currentTime = new Date();
var dif = currentTime - startTime;
return dif / 1e3;
}
var process = {
nextTick,
title,
browser,
env: {
NODE_ENV: "production"
},
argv,
version,
versions,
on,
addListener,
once,
off,
removeListener,
removeAllListeners,
emit,
binding,
cwd,
chdir,
umask,
hrtime,
platform,
release,
config,
uptime
};
function createCommonjsModule(fn, basedir, module) {
return module = {
path: basedir,
exports: {},
require: function(path, base) {
return commonjsRequire(path, base === void 0 || base === null ? module.path : base);
}
}, fn(module, module.exports), module.exports;
}
function commonjsRequire() {
throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs");
}
function setup(env) {
createDebug.debug = createDebug;
createDebug.default = createDebug;
createDebug.coerce = coerce;
createDebug.disable = disable;
createDebug.enable = enable;
createDebug.enabled = enabled;
createDebug.humanize = ms;
createDebug.destroy = destroy2;
Object.keys(env).forEach((key)=>{
createDebug[key] = env[key];
});
createDebug.names = [];
createDebug.skips = [];
createDebug.formatters = {};
function selectColor(namespace) {
let hash = 0;
for(let i = 0; i < namespace.length; i++){
hash = (hash << 5) - hash + namespace.charCodeAt(i);
hash |= 0;
}
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
}
createDebug.selectColor = selectColor;
function createDebug(namespace) {
let prevTime;
let enableOverride = null;
let namespacesCache;
let enabledCache;
function debug(...args) {
if (!debug.enabled) {
return;
}
const self2 = debug;
const curr = Number(new Date());
const ms2 = curr - (prevTime || curr);
self2.diff = ms2;
self2.prev = prevTime;
self2.curr = curr;
prevTime = curr;
args[0] = createDebug.coerce(args[0]);
if (typeof args[0] !== "string") {
args.unshift("%O");
}
let index = 0;
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format)=>{
if (match === "%%") {
return "%";
}
index++;
const formatter = createDebug.formatters[format];
if (typeof formatter === "function") {
const val = args[index];
match = formatter.call(self2, val);
args.splice(index, 1);
index--;
}
return match;
});
createDebug.formatArgs.call(self2, args);
const logFn = self2.log || createDebug.log;
logFn.apply(self2, args);
}
debug.namespace = namespace;
debug.useColors = createDebug.useColors();
debug.color = createDebug.selectColor(namespace);
debug.extend = extend;
debug.destroy = createDebug.destroy;
Object.defineProperty(debug, "enabled", {
enumerable: true,
configurable: false,
get: ()=>{
if (enableOverride !== null) {
return enableOverride;
}
if (namespacesCache !== createDebug.namespaces) {
namespacesCache = createDebug.namespaces;
enabledCache = createDebug.enabled(namespace);
}
return enabledCache;
},
set: (v)=>{
enableOverride = v;
}
});
if (typeof createDebug.init === "function") {
createDebug.init(debug);
}
return debug;
}
function extend(namespace, delimiter) {
const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
newDebug.log = this.log;
return newDebug;
}
function enable(namespaces) {
createDebug.save(namespaces);
createDebug.namespaces = namespaces;
createDebug.names = [];
createDebug.skips = [];
let i;
const split = (typeof namespaces === "string" ? namespaces : "").split(/[\s,]+/);
const len = split.length;
for(i = 0; i < len; i++){
if (!split[i]) {
continue;
}
namespaces = split[i].replace(/\*/g, ".*?");
if (namespaces[0] === "-") {
createDebug.skips.push(new RegExp("^" + namespaces.slice(1) + "$"));
} else {
createDebug.names.push(new RegExp("^" + namespaces + "$"));
}
}
}
function disable() {
const namespaces = [
...createDebug.names.map(toNamespace),
...createDebug.skips.map(toNamespace).map((namespace)=>"-" + namespace)
].join(",");
createDebug.enable("");
return namespaces;
}
function enabled(name) {
if (name[name.length - 1] === "*") {
return true;
}
let i;
let len;
for(i = 0, len = createDebug.skips.length; i < len; i++){
if (createDebug.skips[i].test(name)) {
return false;
}
}
for(i = 0, len = createDebug.names.length; i < len; i++){
if (createDebug.names[i].test(name)) {
return true;
}
}
return false;
}
function toNamespace(regexp) {
return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\.\*\?$/, "*");
}
function coerce(val) {
if (val instanceof Error) {
return val.stack || val.message;
}
return val;
}
function destroy2() {
console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
}
createDebug.enable(createDebug.load());
return createDebug;
}
var common = setup;
var browser$1 = createCommonjsModule(function(module, exports) {
exports.formatArgs = formatArgs2;
exports.save = save2;
exports.load = load2;
exports.useColors = useColors2;
exports.storage = localstorage();
exports.destroy = (()=>{
let warned = false;
return ()=>{
if (!warned) {
warned = true;
console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
}
};
})();
exports.colors = [
"#0000CC",
"#0000FF",
"#0033CC",
"#0033FF",
"#0066CC",
"#0066FF",
"#0099CC",
"#0099FF",
"#00CC00",
"#00CC33",
"#00CC66",
"#00CC99",
"#00CCCC",
"#00CCFF",
"#3300CC",
"#3300FF",
"#3333CC",
"#3333FF",
"#3366CC",
"#3366FF",
"#3399CC",
"#3399FF",
"#33CC00",
"#33CC33",
"#33CC66",
"#33CC99",
"#33CCCC",
"#33CCFF",
"#6600CC",
"#6600FF",
"#6633CC",
"#6633FF",
"#66CC00",
"#66CC33",
"#9900CC",
"#9900FF",
"#9933CC",
"#9933FF",
"#99CC00",
"#99CC33",
"#CC0000",
"#CC0033",
"#CC0066",
"#CC0099",
"#CC00CC",
"#CC00FF",
"#CC3300",
"#CC3333",
"#CC3366",
"#CC3399",
"#CC33CC",
"#CC33FF",
"#CC6600",
"#CC6633",
"#CC9900",
"#CC9933",
"#CCCC00",
"#CCCC33",
"#FF0000",
"#FF0033",
"#FF0066",
"#FF0099",
"#FF00CC",
"#FF00FF",
"#FF3300",
"#FF3333",
"#FF3366",
"#FF3399",
"#FF33CC",
"#FF33FF",
"#FF6600",
"#FF6633",
"#FF9900",
"#FF9933",
"#FFCC00",
"#FFCC33"
];
function useColors2() {
if (typeof window !== "undefined" && window.process && (window.process.type === "renderer" || window.process.__nwjs)) {
return true;
}
if (typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
return false;
}
return typeof document !== "undefined" && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || typeof window !== "undefined" && window.console && (window.console.firebug || window.console.exception && window.console.table) || typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 || typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
}
function formatArgs2(args) {
args[0] = (this.useColors ? "%c" : "") + this.namespace + (this.useColors ? " %c" : " ") + args[0] + (this.useColors ? "%c " : " ") + "+" + module.exports.humanize(this.diff);
if (!this.useColors) {
return;
}
const c = "color: " + this.color;
args.splice(1, 0, c, "color: inherit");
let index = 0;
let lastC = 0;
args[0].replace(/%[a-zA-Z%]/g, (match)=>{
if (match === "%%") {
return;
}
index++;
if (match === "%c") {
lastC = index;
}
});
args.splice(lastC, 0, c);
}
exports.log = console.debug || console.log || (()=>{});
function save2(namespaces) {
try {
if (namespaces) {
exports.storage.setItem("debug", namespaces);
} else {
exports.storage.removeItem("debug");
}
} catch (error) {}
}
function load2() {
let r;
try {
r = exports.storage.getItem("debug");
} catch (error) {}
if (!r && typeof process !== "undefined" && "env" in process) {
r = process.env.DEBUG;
}
return r;
}
function localstorage() {
try {
return localStorage;
} catch (error) {}
}
module.exports = common(exports);
const { formatters } = module.exports;
formatters.j = function(v) {
try {
return JSON.stringify(v);
} catch (error) {
return "[UnexpectedJSONParseError]: " + error.message;
}
};
});
browser$1.colors;
browser$1.destroy;
browser$1.formatArgs;
browser$1.load;
browser$1.log;
browser$1.save;
browser$1.storage;
browser$1.useColors;
class DenoStdInternalError extends Error {
constructor(message){
super(message);
this.name = "DenoStdInternalError";
}
}
function assert(expr, msg = "") {
if (!expr) {
throw new DenoStdInternalError(msg);
}
}
function copy(src, dst, off = 0) {
off = Math.max(0, Math.min(off, dst.byteLength));
const dstBytesAvailable = dst.byteLength - off;
if (src.byteLength > dstBytesAvailable) {
src = src.subarray(0, dstBytesAvailable);
}
dst.set(src, off);
return src.byteLength;
}
const MAX_SIZE = 2 ** 32 - 2;
class Buffer1 {
#buf;
#off = 0;
#readable = new ReadableStream({
type: "bytes",
pull: (controller)=>{
const view = new Uint8Array(controller.byobRequest.view.buffer);
if (this.empty()) {
this.reset();
controller.close();
controller.byobRequest.respond(0);
return;
}
const nread = copy(this.#buf.subarray(this.#off), view);
this.#off += nread;
controller.byobRequest.respond(nread);
},
autoAllocateChunkSize: 16_640
});
get readable() {
return this.#readable;
}
#writable = new WritableStream({
write: (chunk)=>{
const m = this.#grow(chunk.byteLength);
copy(chunk, this.#buf, m);
}
});
get writable() {
return this.#writable;
}
constructor(ab){
this.#buf = ab === undefined ? new Uint8Array(0) : new Uint8Array(ab);
}
bytes(options = {
copy: true
}) {
if (options.copy === false) return this.#buf.subarray(this.#off);
return this.#buf.slice(this.#off);
}
empty() {
return this.#buf.byteLength <= this.#off;
}
get length() {
return this.#buf.byteLength - this.#off;
}
get capacity() {
return this.#buf.buffer.byteLength;
}
truncate(n) {
if (n === 0) {
this.reset();
return;
}
if (n < 0 || n > this.length) {
throw Error("bytes.Buffer: truncation out of range");
}
this.#reslice(this.#off + n);
}
reset() {
this.#reslice(0);
this.#off = 0;
}
#tryGrowByReslice(n) {
const l = this.#buf.byteLength;
if (n <= this.capacity - l) {
this.#reslice(l + n);
return l;
}
return -1;
}
#reslice(len) {
assert(len <= this.#buf.buffer.byteLength);
this.#buf = new Uint8Array(this.#buf.buffer, 0, len);
}
#grow(n1) {
const m = this.length;
if (m === 0 && this.#off !== 0) {
this.reset();
}
const i = this.#tryGrowByReslice(n1);
if (i >= 0) {
return i;
}
const c = this.capacity;
if (n1 <= Math.floor(c / 2) - m) {
copy(this.#buf.subarray(this.#off), this.#buf);
} else if (c + n1 > MAX_SIZE) {
throw new Error("The buffer cannot be grown beyond the maximum size.");
} else {
const buf = new Uint8Array(Math.min(2 * c + n1, MAX_SIZE));
copy(this.#buf.subarray(this.#off), buf);
this.#buf = buf;
}
this.#off = 0;
this.#reslice(Math.min(m + n1, MAX_SIZE));
return m;
}
grow(n) {
if (n < 0) {
throw Error("Buffer.grow: negative count");
}
const m = this.#grow(n);
this.#reslice(m);
}
}
function createLPS(pat) {
const lps = new Uint8Array(pat.length);
lps[0] = 0;
let prefixEnd = 0;
let i = 1;
while(i < lps.length){
if (pat[i] == pat[prefixEnd]) {
prefixEnd++;
lps[i] = prefixEnd;
i++;
} else if (prefixEnd === 0) {
lps[i] = 0;
i++;
} else {
prefixEnd = lps[prefixEnd - 1];
}
}
return lps;
}
class BytesList {
#len = 0;
#chunks = [];
constructor(){}
size() {
return this.#len;
}
add(value, start = 0, end = value.byteLength) {
if (value.byteLength === 0 || end - start === 0) {
return;
}
checkRange(start, end, value.byteLength);
this.#chunks.push({
value,
end,
start,
offset: this.#len
});
this.#len += end - start;
}
shift(n) {
if (n === 0) {
return;
}
if (this.#len <= n) {
this.#chunks = [];
this.#len = 0;
return;
}
const idx = this.getChunkIndex(n);
this.#chunks.splice(0, idx);
const [chunk] = this.#chunks;
if (chunk) {
const diff = n - chunk.offset;
chunk.start += diff;
}
let offset = 0;
for (const chunk of this.#chunks){
chunk.offset = offset;
offset += chunk.end - chunk.start;
}
this.#len = offset;
}
getChunkIndex(pos) {
let max = this.#chunks.length;
let min = 0;
while(true){
const i = min + Math.floor((max - min) / 2);
if (i < 0 || this.#chunks.length <= i) {
return -1;
}
const { offset , start , end } = this.#chunks[i];
const len = end - start;
if (offset <= pos && pos < offset + len) {
return i;
} else if (offset + len <= pos) {
min = i + 1;
} else {
max = i - 1;
}
}
}
get(i) {
if (i < 0 || this.#len <= i) {
throw new Error("out of range");
}
const idx = this.getChunkIndex(i);
const { value , offset , start } = this.#chunks[idx];
return value[start + i - offset];
}
*iterator(start = 0) {
const startIdx = this.getChunkIndex(start);
if (startIdx < 0) return;
const first = this.#chunks[startIdx];
let firstOffset = start - first.offset;
for(let i = startIdx; i < this.#chunks.length; i++){
const chunk = this.#chunks[i];
for(let j = chunk.start + firstOffset; j < chunk.end; j++){
yield chunk.value[j];
}
firstOffset = 0;
}
}
slice(start, end = this.#len) {
if (end === start) {
return new Uint8Array();
}
checkRange(start, end, this.#len);
const result = new Uint8Array(end - start);
const startIdx = this.getChunkIndex(start);
const endIdx = this.getChunkIndex(end - 1);
let written = 0;
for(let i = startIdx; i <= endIdx; i++){
const { value: chunkValue , start: chunkStart , end: chunkEnd , offset: chunkOffset } = this.#chunks[i];
const readStart = chunkStart + (i === startIdx ? start - chunkOffset : 0);
const readEnd = i === endIdx ? end - chunkOffset + chunkStart : chunkEnd;
const len = readEnd - readStart;
result.set(chunkValue.subarray(readStart, readEnd), written);
written += len;
}
return result;
}
concat() {
const result = new Uint8Array(this.#len);
let sum = 0;
for (const { value , start , end } of this.#chunks){
result.set(value.subarray(start, end), sum);
sum += end - start;
}
return result;
}
}
function checkRange(start, end, len) {
if (start < 0 || len < start || end < 0 || len < end || end < start) {
throw new Error("invalid range");
}
}
class DelimiterStream extends TransformStream {
#bufs = new BytesList();
#delimiter;
#inspectIndex = 0;
#matchIndex = 0;
#delimLen;
#delimLPS;
#disp;
constructor(delimiter, options){
super({
transform: (chunk, controller)=>{
this.#handle(chunk, controller);
},
flush: (controller)=>{
controller.enqueue(this.#bufs.concat());
}
});
this.#delimiter = delimiter;
this.#delimLen = delimiter.length;
this.#delimLPS = createLPS(delimiter);
this.#disp = options?.disposition ?? "discard";
}
#handle(chunk, controller) {
this.#bufs.add(chunk);
let localIndex = 0;
while(this.#inspectIndex < this.#bufs.size()){
if (chunk[localIndex] === this.#delimiter[this.#matchIndex]) {
this.#inspectIndex++;
localIndex++;
this.#matchIndex++;
if (this.#matchIndex === this.#delimLen) {
const start = this.#inspectIndex - this.#delimLen;
const end = this.#disp == "suffix" ? this.#inspectIndex : start;
const copy = this.#bufs.slice(0, end);
controller.enqueue(copy);
const shift = this.#disp == "prefix" ? start : this.#inspectIndex;
this.#bufs.shift(shift);
this.#inspectIndex = this.#disp == "prefix" ? this.#delimLen : 0;
this.#matchIndex = 0;
}
} else {
if (this.#matchIndex === 0) {
this.#inspectIndex++;
localIndex++;
} else {
this.#matchIndex = this.#delimLPS[this.#matchIndex - 1];
}
}
}
}
}
function readableStreamFromIterable(iterable) {
const iterator = iterable[Symbol.asyncIterator]?.() ?? iterable[Symbol.iterator]?.();
return new ReadableStream({
async pull (controller) {
const { value , done } = await iterator.next();
if (done) {
controller.close();
} else {
controller.enqueue(value);
}
},
async cancel (reason) {
if (typeof iterator.throw == "function") {
try {
await iterator.throw(reason);
} catch {}
}
}
});
}
const baseFetchConfig = (_apiRoot)=>({});
const defaultAdapter = "cloudflare";
class GrammyError extends Error {
ok;
error_code;
description;
parameters;
constructor(message, err, method, payload){
super(`${message} (${err.error_code}: ${err.description})`);
this.method = method;
this.payload = payload;
this.ok = false;
this.name = "GrammyError";
this.error_code = err.error_code;
this.description = err.description;
this.parameters = err.parameters ?? {};
}
method;
payload;
}
function toGrammyError(err, method, payload) {
return new GrammyError(`Call to '${method}' failed!`, err, method, payload);
}
class HttpError extends Error {
constructor(message, error){
super(message);
this.error = error;
this.name = "HttpError";
}
error;
}
function isTelegramError(err) {
return typeof err === "object" && err !== null && "status" in err && "statusText" in err;
}
function toHttpError(method, sensitiveLogs) {
return (err)=>{
let msg = `Network request for '${method}' failed!`;
if (isTelegramError(err)) msg += ` (${err.status}: ${err.statusText})`;
if (sensitiveLogs && err instanceof Error) msg += ` ${err.message}`;
throw new HttpError(msg, err);
};
}
const osType = (()=>{
const { Deno } = globalThis;
if (typeof Deno?.build?.os === "string") {
return Deno.build.os;
}
const { navigator: navigator1 } = globalThis;
if (navigator1?.appVersion?.includes?.("Win")) {
return "windows";
}
return "linux";
})();
const isWindows = osType === "windows";
const CHAR_FORWARD_SLASH = 47;
function assertPath(path) {
if (typeof path !== "string") {
throw new TypeError(`Path must be a string. Received ${JSON.stringify(path)}`);
}
}
function isPosixPathSeparator(code) {
return code === 47;
}
function isPathSeparator(code) {
return isPosixPathSeparator(code) || code === 92;
}
function isWindowsDeviceRoot(code) {
return code >= 97 && code <= 122 || code >= 65 && code <= 90;
}
function normalizeString(path, allowAboveRoot, separator, isPathSeparator) {
let res = "";
let lastSegmentLength = 0;
let lastSlash = -1;
let dots = 0;
let code;
for(let i = 0, len = path.length; i <= len; ++i){
if (i < len) code = path.charCodeAt(i);
else if (isPathSeparator(code)) break;
else code = CHAR_FORWARD_SLASH;
if (isPathSeparator(code)) {
if (lastSlash === i - 1 || dots === 1) {} else if (lastSlash !== i - 1 && dots === 2) {
if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 || res.charCodeAt(res.length - 2) !== 46) {
if (res.length > 2) {
const lastSlashIndex = res.lastIndexOf(separator);
if (lastSlashIndex === -1) {
res = "";
lastSegmentLength = 0;
} else {
res = res.slice(0, lastSlashIndex);
lastSegmentLength = res.length - 1 - res.lastIndexOf(separator);
}
lastSlash = i;
dots = 0;
continue;
} else if (res.length === 2 || res.length === 1) {
res = "";
lastSegmentLength = 0;
lastSlash = i;
dots = 0;
continue;
}
}
if (allowAboveRoot) {
if (res.length > 0) res += `${separator}..`;
else res = "..";
lastSegmentLength = 2;
}
} else {
if (res.length > 0) res += separator + path.slice(lastSlash + 1, i);
else res = path.slice(lastSlash + 1, i);
lastSegmentLength = i - lastSlash - 1;
}
lastSlash = i;
dots = 0;
} else if (code === 46 && dots !== -1) {
++dots;
} else {
dots = -1;
}
}
return res;
}
function _format(sep, pathObject) {
const dir = pathObject.dir || pathObject.root;
const base = pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
if (!dir) return base;
if (base === sep) return dir;
if (dir === pathObject.root) return dir + base;
return dir + sep + base;
}
const WHITESPACE_ENCODINGS = {
"\u0009": "%09",
"\u000A": "%0A",
"\u000B": "%0B",
"\u000C": "%0C",
"\u000D": "%0D",
"\u0020": "%20"
};
function encodeWhitespace(string) {
return string.replaceAll(/[\s]/g, (c)=>{
return WHITESPACE_ENCODINGS[c] ?? c;
});
}
function lastPathSegment(path, isSep, start = 0) {
let matchedNonSeparator = false;
let end = path.length;
for(let i = path.length - 1; i >= start; --i){
if (isSep(path.charCodeAt(i))) {
if (matchedNonSeparator) {
start = i + 1;
break;
}
} else if (!matchedNonSeparator) {
matchedNonSeparator = true;
end = i + 1;
}
}
return path.slice(start, end);
}
function stripTrailingSeparators(segment, isSep) {
if (segment.length <= 1) {
return segment;
}
let end = segment.length;
for(let i = segment.length - 1; i > 0; i--){
if (isSep(segment.charCodeAt(i))) {
end = i;
} else {
break;
}
}
return segment.slice(0, end);
}
function stripSuffix(name, suffix) {
if (suffix.length >= name.length) {
return name;
}
const lenDiff = name.length - suffix.length;
for(let i = suffix.length - 1; i >= 0; --i){
if (name.charCodeAt(lenDiff + i) !== suffix.charCodeAt(i)) {
return name;
}
}
return name.slice(0, -suffix.length);
}
const sep = "\\";
const delimiter = ";";
function resolve(...pathSegments) {
let resolvedDevice = "";
let resolvedTail = "";
let resolvedAbsolute = false;
for(let i = pathSegments.length - 1; i >= -1; i--){
let path;
const { Deno } = globalThis;
if (i >= 0) {
path = pathSegments[i];
} else if (!resolvedDevice) {
if (typeof Deno?.cwd !== "function") {
throw new TypeError("Resolved a drive-letter-less path without a CWD.");
}
path = Deno.cwd();
} else {
if (typeof Deno?.env?.get !== "function" || typeof Deno?.cwd !== "function") {
throw new TypeError("Resolved a relative path without a CWD.");
}
path = Deno.cwd();
if (path === undefined || path.slice(0, 3).toLowerCase() !== `${resolvedDevice.toLowerCase()}\\`) {
path = `${resolvedDevice}\\`;
}
}
assertPath(path);
const len = path.length;
if (len === 0) continue;
let rootEnd = 0;
let device = "";
let isAbsolute = false;
const code = path.charCodeAt(0);
if (len > 1) {
if (isPathSeparator(code)) {
isAbsolute = true;
if (isPathSeparator(path.charCodeAt(1))) {
let j = 2;
let last = j;
for(; j < len; ++j){
if (isPathSeparator(path.charCodeAt(j))) break;
}
if (j < len && j !== last) {
const firstPart = path.slice(last, j);
last = j;
for(; j < len; ++j){
if (!isPathSeparator(path.charCodeAt(j))) break;
}
if (j < len && j !== last) {
last = j;
for(; j < len; ++j){
if (isPathSeparator(path.charCodeAt(j))) break;
}
if (j === len) {
device = `\\\\${firstPart}\\${path.slice(last)}`;
rootEnd = j;
} else if (j !== last) {
device = `\\\\${firstPart}\\${path.slice(last, j)}`;
rootEnd = j;
}
}
}
} else {
rootEnd = 1;
}
} else if (isWindowsDeviceRoot(code)) {
if (path.charCodeAt(1) === 58) {
device = path.slice(0, 2);
rootEnd = 2;
if (len > 2) {
if (isPathSeparator(path.charCodeAt(2))) {
isAbsolute = true;
rootEnd = 3;
}
}
}
}
} else if (isPathSeparator(code)) {
rootEnd = 1;
isAbsolute = true;
}
if (device.length > 0 && resolvedDevice.length > 0 && device.toLowerCase() !== resolvedDevice.toLowerCase()) {
continue;
}
if (resolvedDevice.length === 0 && device.length > 0) {
resolvedDevice = device;
}
if (!resolvedAbsolute) {
resolvedTail = `${path.slice(rootEnd)}\\${resolvedTail}`;
resolvedAbsolute = isAbsolute;
}
if (resolvedAbsolute && resolvedDevice.length > 0) break;
}
resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, "\\", isPathSeparator);
return resolvedDevice + (resolvedAbsolute ? "\\" : "") + resolvedTail || ".";
}
function normalize(path) {
assertPath(path);
const len = path.length;
if (len === 0) return ".";
let rootEnd = 0;
let device;
let isAbsolute = false;
const code = path.charCodeAt(0);
if (len > 1) {
if (isPathSeparator(code)) {
isAbsolute = true;
if (isPathSeparator(path.charCodeAt(1))) {
let j = 2;
let last = j;
for(; j < len; ++j){
if (isPathSeparator(path.charCodeAt(j))) break;
}
if (j < len && j !== last) {
const firstPart = path.slice(last, j);
last = j;
for(; j < len; ++j){
if (!isPathSeparator(path.charCodeAt(j))) break;
}
if (j < len && j !== last) {
last = j;
for(; j < len; ++j){
if (isPathSeparator(path.charCodeAt(j))) break;
}
if (j === len) {
return `\\\\${firstPart}\\${path.slice(last)}\\`;
} else if (j !== last) {
device = `\\\\${firstPart}\\${path.slice(last, j)}`;
rootEnd = j;
}
}
}
} else {
rootEnd = 1;
}
} else if (isWindowsDeviceRoot(code)) {
if (path.charCodeAt(1) === 58) {
device = path.slice(0, 2);
rootEnd = 2;
if (len > 2) {
if (isPathSeparator(path.charCodeAt(2))) {
isAbsolute = true;
rootEnd = 3;
}
}
}
}
} else if (isPathSeparator(code)) {
return "\\";
}
let tail;
if (rootEnd < len) {
tail = normalizeString(path.slice(rootEnd), !isAbsolute, "\\", isPathSeparator);
} else {
tail = "";
}
if (tail.length === 0 && !isAbsolute) tail = ".";
if (tail.length > 0 && isPathSeparator(path.charCodeAt(len - 1))) {
tail += "\\";
}
if (device === undefined) {
if (isAbsolute) {
if (tail.length > 0) return `\\${tail}`;
else return "\\";
} else if (tail.length > 0) {
return tail;
} else {
return "";
}
} else if (isAbsolute) {
if (tail.length > 0) return `${device}\\${tail}`;
else return `${device}\\`;
} else if (tail.length > 0) {
return device + tail;
} else {
return device;
}
}
function isAbsolute(path) {
assertPath(path);
const len = path.length;
if (len === 0) return false;
const code = path.charCodeAt(0);
if (isPathSeparator(code)) {
return true;
} else if (isWindowsDeviceRoot(code)) {
if (len > 2 && path.charCodeAt(1) === 58) {
if (isPathSeparator(path.charCodeAt(2))) return true;
}
}
return false;
}
function join(...paths) {
const pathsCount = paths.length;
if (pathsCount === 0) return ".";
let joined;
let firstPart = null;
for(let i = 0; i < pathsCount; ++i){
const path = paths[i];
assertPath(path);
if (path.length > 0) {
if (joined === undefined) joined = firstPart = path;
else joined += `\\${path}`;
}
}
if (joined === undefined) return ".";
let needsReplace = true;
let slashCount = 0;
assert(firstPart != null);
if (isPathSeparator(firstPart.charCodeAt(0))) {
++slashCount;
const firstLen = firstPart.length;
if (firstLen > 1) {
if (isPathSeparator(firstPart.charCodeAt(1))) {
++slashCount;
if (firstLen > 2) {
if (isPathSeparator(firstPart.charCodeAt(2))) ++slashCount;
else {
needsReplace = false;
}
}
}
}
}
if (needsReplace) {
for(; slashCount < joined.length; ++slashCount){
if (!isPathSeparator(joined.charCodeAt(slashCount))) break;
}
if (slashCount >= 2) joined = `\\${joined.slice(slashCount)}`;
}
return normalize(joined);
}
function relative(from, to) {
assertPath(from);
assertPath(to);
if (from === to) return "";
const fromOrig = resolve(from);
const toOrig = resolve(to);
if (fromOrig === toOrig) return "";
from = fromOrig.toLowerCase();
to = toOrig.toLowerCase();
if (from === to) return "";
let fromStart = 0;
let fromEnd = from.length;
for(; fromStart < fromEnd; ++fromStart){
if (from.charCodeAt(fromStart) !== 92) break;
}
for(; fromEnd - 1 > fromStart; --fromEnd){
if (from.charCodeAt(fromEnd - 1) !== 92) break;
}
const fromLen = fromEnd - fromStart;
let toStart = 0;
let toEnd = to.length;
for(; toStart < toEnd; ++toStart){
if (to.charCodeAt(toStart) !== 92) break;
}
for(; toEnd - 1 > toStart; --toEnd){
if (to.charCodeAt(toEnd - 1) !== 92) break;
}
const toLen = toEnd - toStart;
const length = fromLen < toLen ? fromLen : toLen;
let lastCommonSep = -1;
let i = 0;
for(; i <= length; ++i){
if (i === length) {
if (toLen > length) {
if (to.charCodeAt(toStart + i) === 92) {
return toOrig.slice(toStart + i + 1);
} else if (i === 2) {
return toOrig.slice(toStart + i);
}
}
if (fromLen > length) {
if (from.charCodeAt(fromStart + i) === 92) {
lastCommonSep = i;
} else if (i === 2) {
lastCommonSep = 3;
}
}
break;
}
const fromCode = from.charCodeAt(fromStart + i);
const toCode = to.charCodeAt(toStart + i);
if (fromCode !== toCode) break;
else if (fromCode === 92) lastCommonSep = i;
}
if (i !== length && lastCommonSep === -1) {
return toOrig;
}
let out = "";
if (lastCommonSep === -1) lastCommonSep = 0;
for(i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i){
if (i === fromEnd || from.charCodeAt(i) === 92) {
if (out.length === 0) out += "..";
else out += "\\..";
}
}
if (out.length > 0) {
return out + toOrig.slice(toStart + lastCommonSep, toEnd);
} else {
toStart += lastCommonSep;
if (toOrig.charCodeAt(toStart) === 92) ++toStart;
return toOrig.slice(toStart, toEnd);
}
}
function toNamespacedPath(path) {
if (typeof path !== "string") return path;
if (path.length === 0) return "";
const resolvedPath = resolve(path);
if (resolvedPath.length >= 3) {
if (resolvedPath.charCodeAt(0) === 92) {
if (resolvedPath.charCodeAt(1) === 92) {
const code = resolvedPath.charCodeAt(2);
if (code !== 63 && code !== 46) {
return `\\\\?\\UNC\\${resolvedPath.slice(2)}`;
}
}
} else if (isWindowsDeviceRoot(resolvedPath.charCodeAt(0))) {
if (resolvedPath.charCodeAt(1) === 58 && resolvedPath.charCodeAt(2) === 92) {
return `\\\\?\\${resolvedPath}`;
}
}
}
return path;
}
function dirname(path) {
assertPath(path);
const len = path.length;
if (len === 0) return ".";
let rootEnd = -1;
let end = -1;
let matchedSlash = true;
let offset = 0;
const code = path.charCodeAt(0);
if (len > 1) {
if (isPathSeparator(code)) {
rootEnd = offset = 1;
if (isPathSeparator(path.charCodeAt(1))) {
let j = 2;
let last = j;
for(; j < len; ++j){
if (isPathSeparator(path.charCodeAt(j))) break;
}
if (j < len && j !== last) {
last = j;
for(; j < len; ++j){
if (!isPathSeparator(path.charCodeAt(j))) break;
}
if (j < len && j !== last) {
last = j;
for(; j < len; ++j){
if (isPathSeparator(path.charCodeAt(j))) break;
}
if (j === len) {
return path;
}
if (j !== last) {
rootEnd = offset = j + 1;
}
}
}
}
} else if (isWindowsDeviceRoot(code)) {
if (path.charCodeAt(1) === 58) {
rootEnd = offset = 2;
if (len > 2) {
if (isPathSeparator(path.charCodeAt(2))) rootEnd = offset = 3;
}
}
}
} else if (isPathSeparator(code)) {
return path;
}
for(let i = len - 1; i >= offset; --i){
if (isPathSeparator(path.charCodeAt(i))) {
if (!matchedSlash) {
end = i;
break;
}
} else {
matchedSlash = false;
}
}
if (end === -1) {
if (rootEnd === -1) return ".";
else end = rootEnd;
}
return stripTrailingSeparators(path.slice(0, end), isPosixPathSeparator);
}
function basename(path, suffix = "") {
assertPath(path);
if (path.length === 0) return path;
if (typeof suffix !== "string") {
throw new TypeError(`Suffix must be a string. Received ${JSON.stringify(suffix)}`);
}
let start = 0;
if (path.length >= 2) {
const drive = path.charCodeAt(0);
if (isWindowsDeviceRoot(drive)) {
if (path.charCodeAt(1) === 58) start = 2;
}
}
const lastSegment = lastPathSegment(path, isPathSeparator, start);
const strippedSegment = stripTrailingSeparators(lastSegment, isPathSeparator);
return suffix ? stripSuffix(strippedSegment, suffix) : strippedSegment;
}
function extname(path) {
assertPath(path);
let start = 0;
let startDot = -1;
let startPart = 0;
let end = -1;
let matchedSlash = true;
let preDotState = 0;
if (path.length >= 2 && path.charCodeAt(1) === 58 && isWindowsDeviceRoot(path.charCodeAt(0))) {
start = startPart = 2;
}
for(let i = path.length - 1; i >= start; --i){
const code = path.charCodeAt(i);
if (isPathSeparator(code)) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code === 46) {
if (startDot === -1) startDot = i;
else if (preDotState !== 1) preDotState = 1;
} else if (startDot !== -1) {
preDotState = -1;
}
}
if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
return "";
}
return path.slice(startDot, end);
}
function format(pathObject) {
if (pathObject === null || typeof pathObject !== "object") {
throw new TypeError(`The "pathObject" argument must be of type Object. Received type ${typeof pathObject}`);
}
return _format("\\", pathObject);
}
function parse2(path) {
assertPath(path);
const ret = {
root: "",
dir: "",
base: "",
ext: "",
name: ""
};
const len = path.length;
if (len === 0) return ret;
let rootEnd = 0;
let code = path.charCodeAt(0);
if (len > 1) {
if (isPathSeparator(code)) {
rootEnd = 1;
if (isPathSeparator(path.charCodeAt(1))) {
let j = 2;
let last = j;
for(; j < len; ++j){
if (isPathSeparator(path.charCodeAt(j))) break;
}
if (j < len && j !== last) {
last = j;
for(; j < len; ++j){
if (!isPathSeparator(path.charCodeAt(j))) break;
}
if (j < len && j !== last) {
last = j;
for(; j < len; ++j){
if (isPathSeparator(path.charCodeAt(j))) break;
}
if (j === len) {
rootEnd = j;
} else if (j !== last) {
rootEnd = j + 1;
}
}
}
}
} else if (isWindowsDeviceRoot(code)) {
if (path.charCodeAt(1) === 58) {
rootEnd = 2;
if (len > 2) {
if (isPathSeparator(path.charCodeAt(2))) {
if (len === 3) {
ret.root = ret.dir = path;
ret.base = "\\";
return ret;
}
rootEnd = 3;
}
} else {
ret.root = ret.dir = path;
return ret;
}
}
}
} else if (isPathSeparator(code)) {
ret.root = ret.dir = path;
ret.base = "\\";
return ret;
}
if (rootEnd > 0) ret.root = path.slice(0, rootEnd);
let startDot = -1;
let startPart = rootEnd;
let end = -1;
let matchedSlash = true;
let i = path.length - 1;
let preDotState = 0;
for(; i >= rootEnd; --i){
code = path.charCodeAt(i);
if (isPathSeparator(code)) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code === 46) {
if (startDot === -1) startDot = i;
else if (preDotState !== 1) preDotState = 1;
} else if (startDot !== -1) {
preDotState = -1;
}
}
if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
if (end !== -1) {
ret.base = ret.name = path.slice(startPart, end);
}
} else {
ret.name = path.slice(startPart, startDot);
ret.base = path.slice(startPart, end);
ret.ext = path.slice(startDot, end);
}
ret.base = ret.base || "\\";
if (startPart > 0 && startPart !== rootEnd) {
ret.dir = path.slice(0, startPart - 1);
} else ret.dir = ret.root;
return ret;
}
function fromFileUrl(url) {
url = url instanceof URL ? url : new URL(url);
if (url.protocol != "file:") {
throw new TypeError("Must be a file URL.");
}
let path = decodeURIComponent(url.pathname.replace(/\//g, "\\").replace(/%(?![0-9A-Fa-f]{2})/g, "%25")).replace(/^\\*([A-Za-z]:)(\\|$)/, "$1\\");
if (url.hostname != "") {
path = `\\\\${url.hostname}${path}`;
}
return path;
}
function toFileUrl(path) {
if (!isAbsolute(path)) {
throw new TypeError("Must be an absolute path.");
}
const [, hostname, pathname] = path.match(/^(?:[/\\]{2}([^/\\]+)(?=[/\\](?:[^/\\]|$)))?(.*)/);
const url = new URL("file:///");
url.pathname = encodeWhitespace(pathname.replace(/%/g, "%25"));
if (hostname != null && hostname != "localhost") {
url.hostname = hostname;
if (!url.hostname) {
throw new TypeError("Invalid hostname.");
}
}
return url;
}
const mod = {
sep: sep,
delimiter: delimiter,
resolve: resolve,
normalize: normalize,
isAbsolute: isAbsolute,
join: join,
relative: relative,
toNamespacedPath: toNamespacedPath,
dirname: dirname,
basename: basename,
extname: extname,
format: format,
parse: parse2,
fromFileUrl: fromFileUrl,
toFileUrl: toFileUrl
};
const sep1 = "/";
const delimiter1 = ":";
function resolve1(...pathSegments) {
let resolvedPath = "";
let resolvedAbsolute = false;
for(let i = pathSegments.length - 1; i >= -1 && !resolvedAbsolute; i--){
let path;
if (i >= 0) path = pathSegments[i];
else {
const { Deno } = globalThis;
if (typeof Deno?.cwd !== "function") {
throw new TypeError("Resolved a relative path without a CWD.");
}
path = Deno.cwd();
}
assertPath(path);
if (path.length === 0) {
continue;
}
resolvedPath = `${path}/${resolvedPath}`;
resolvedAbsolute = isPosixPathSeparator(path.charCodeAt(0));
}
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, "/", isPosixPathSeparator);
if (resolvedAbsolute) {
if (resolvedPath.length > 0) return `/${resolvedPath}`;
else return "/";
} else if (resolvedPath.length > 0) return resolvedPath;
else return ".";
}
function normalize1(path) {
assertPath(path);
if (path.length === 0) return ".";
const isAbsolute = isPosixPathSeparator(path.charCodeAt(0));
const trailingSeparator = isPosixPathSeparator(path.charCodeAt(path.length - 1));
path = normalizeString(path, !isAbsolute, "/", isPosixPathSeparator);
if (path.length === 0 && !isAbsolute) path = ".";
if (path.length > 0 && trailingSeparator) path += "/";
if (isAbsolute) return `/${path}`;
return path;
}
function isAbsolute1(path) {
assertPath(path);
return path.length > 0 && isPosixPathSeparator(path.charCodeAt(0));
}
function join1(...paths) {
if (paths.length === 0) return ".";
let joined;
for(let i = 0, len = paths.length; i < len; ++i){
const path = paths[i];
assertPath(path);
if (path.length > 0) {
if (!joined) joined = path;
else joined += `/${path}`;
}
}
if (!joined) return ".";
return normalize1(joined);
}
function relative1(from, to) {
assertPath(from);
assertPath(to);
if (from === to) return "";
from = resolve1(from);
to = resolve1(to);
if (from === to) return "";
let fromStart = 1;
const fromEnd = from.length;
for(; fromStart < fromEnd; ++fromStart){
if (!isPosixPathSeparator(from.charCodeAt(fromStart))) break;
}
const fromLen = fromEnd - fromStart;
let toStart = 1;
const toEnd = to.length;
for(; toStart < toEnd; ++toStart){
if (!isPosixPathSeparator(to.charCodeAt(toStart))) break;
}
const toLen = toEnd - toStart;
const length = fromLen < toLen ? fromLen : toLen;
let lastCommonSep = -1;
let i = 0;
for(; i <= length; ++i){
if (i === length) {
if (toLen > length) {
if (isPosixPathSeparator(to.charCodeAt(toStart + i))) {
return to.slice(toStart + i + 1);
} else if (i === 0) {
return to.slice(toStart + i);
}
} else if (fromLen > length) {
if (isPosixPathSeparator(from.charCodeAt(fromStart + i))) {
lastCommonSep = i;
} else if (i === 0) {
lastCommonSep = 0;
}
}
break;
}
const fromCode = from.charCodeAt(fromStart + i);
const toCode = to.charCodeAt(toStart + i);
if (fromCode !== toCode) break;
else if (isPosixPathSeparator(fromCode)) lastCommonSep = i;
}
let out = "";
for(i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i){
if (i === fromEnd || isPosixPathSeparator(from.charCodeAt(i))) {
if (out.length === 0) out += "..";
else out += "/..";
}
}
if (out.length > 0) return out + to.slice(toStart + lastCommonSep);
else {
toStart += lastCommonSep;
if (isPosixPathSeparator(to.charCodeAt(toStart))) ++toStart;
return to.slice(toStart);
}
}
function toNamespacedPath1(path) {
return path;
}
function dirname1(path) {
if (path.length === 0) return ".";
let end = -1;
let matchedNonSeparator = false;
for(let i = path.length - 1; i >= 1; --i){
if (isPosixPathSeparator(path.charCodeAt(i))) {
if (matchedNonSeparator) {
end = i;
break;
}
} else {
matchedNonSeparator = true;
}
}
if (end === -1) {
return isPosixPathSeparator(path.charCodeAt(0)) ? "/" : ".";
}
return stripTrailingSeparators(path.slice(0, end), isPosixPathSeparator);
}
function basename1(path, suffix = "") {
assertPath(path);
if (path.length === 0) return path;
if (typeof suffix !== "string") {
throw new TypeError(`Suffix must be a string. Received ${JSON.stringify(suffix)}`);
}
const lastSegment = lastPathSegment(path, isPosixPathSeparator);
const strippedSegment = stripTrailingSeparators(lastSegment, isPosixPathSeparator);
return suffix ? stripSuffix(strippedSegment, suffix) : strippedSegment;
}
function extname1(path) {
assertPath(path);
let startDot = -1;
let startPart = 0;
let end = -1;
let matchedSlash = true;
let preDotState = 0;
for(let i = path.length - 1; i >= 0; --i){
const code = path.charCodeAt(i);
if (isPosixPathSeparator(code)) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code === 46) {
if (startDot === -1) startDot = i;
else if (preDotState !== 1) preDotState = 1;
} else if (startDot !== -1) {
preDotState = -1;
}
}
if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
return "";
}
return path.slice(startDot, end);
}
function format1(pathObject) {
if (pathObject === null || typeof pathObject !== "object") {
throw new TypeError(`The "pathObject" argument must be of type Object. Received type ${typeof pathObject}`);
}
return _format("/", pathObject);
}
function parse3(path) {
assertPath(path);
const ret = {
root: "",
dir: "",
base: "",
ext: "",
name: ""
};
if (path.length === 0) return ret;
const isAbsolute = isPosixPathSeparator(path.charCodeAt(0));
let start;
if (isAbsolute) {
ret.root = "/";
start = 1;
} else {
start = 0;
}
let startDot = -1;
let startPart = 0;
let end = -1;
let matchedSlash = true;
let i = path.length - 1;
let preDotState = 0;
for(; i >= start; --i){
const code = path.charCodeAt(i);
if (isPosixPathSeparator(code)) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code === 46) {
if (startDot === -1) startDot = i;
else if (preDotState !== 1) preDotState = 1;
} else if (startDot !== -1) {
preDotState = -1;
}
}
if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
if (end !== -1) {
if (startPart === 0 && isAbsolute) {
ret.base = ret.name = path.slice(1, end);
} else {
ret.base = ret.name = path.slice(startPart, end);
}
}
ret.base = ret.base || "/";
} else {
if (startPart === 0 && isAbsolute) {
ret.name = path.slice(1, startDot);
ret.base = path.slice(1, end);
} else {
ret.name = path.slice(startPart, startDot);
ret.base = path.slice(startPart, end);
}
ret.ext = path.slice(startDot, end);
}
if (startPart > 0) {
ret.dir = stripTrailingSeparators(path.slice(0, startPart - 1), isPosixPathSeparator);
} else if (isAbsolute) ret.dir = "/";
return ret;
}
function fromFileUrl1(url) {
url = url instanceof URL ? url : new URL(url);
if (url.protocol != "file:") {
throw new TypeError("Must be a file URL.");
}
return decodeURIComponent(url.pathname.replace(/%(?![0-9A-Fa-f]{2})/g, "%25"));
}
function toFileUrl1(path) {
if (!isAbsolute1(path)) {
throw new TypeError("Must be an absolute path.");
}
const url = new URL("file:///");
url.pathname = encodeWhitespace(path.replace(/%/g, "%25").replace(/\\/g, "%5C"));
return url;
}
const mod1 = {
sep: sep1,
delimiter: delimiter1,
resolve: resolve1,
normalize: normalize1,
isAbsolute: isAbsolute1,
join: join1,
relative: relative1,
toNamespacedPath: toNamespacedPath1,
dirname: dirname1,
basename: basename1,
extname: extname1,
format: format1,
parse: parse3,
fromFileUrl: fromFileUrl1,
toFileUrl: toFileUrl1
};
const path = isWindows ? mod : mod1;
const { join: join2 , normalize: normalize2 } = path;
const path1 = isWindows ? mod : mod1;
const { basename: basename2 , delimiter: delimiter2 , dirname: dirname2 , extname: extname2 , format: format2 , fromFileUrl: fromFileUrl2 , isAbsolute: isAbsolute2 , join: join3 , normalize: normalize3 , parse: parse4 , relative: relative2 , resolve: resolve2 , toFileUrl: toFileUrl2 , toNamespacedPath: toNamespacedPath2 } = path1;
class InputFile {
consumed = false;
fileData;
filename;
constructor(file, filename){
this.fileData = file;
filename ??= this.guessFilename(file);
this.filename = filename;
}
guessFilename(file) {
if (typeof file === "string") return basename2(file);
if (typeof file !== "object") return undefined;
if ("url" in file) return basename2(file.url);
if (!(file instanceof URL)) return undefined;
return basename2(file.pathname) || basename2(file.hostname);
}
toRaw() {
if (this.consumed) {
throw new Error("Cannot reuse InputFile data source!");
}
const data = this.fileData;
if (data instanceof Blob) return data.stream();
if (data instanceof URL) return fetchFile(data);
if ("url" in data) return fetchFile(data.url);
if (!(data instanceof Uint8Array)) this.consumed = true;
return data;
}
}
async function* fetchFile(url) {
const { body } = await fetch(url);
if (body === null) {
throw new Error(`Download failed, no response body from '${url}'`);
}
yield* body;
}
function requiresFormDataUpload(payload) {
return payload instanceof InputFile || typeof payload === "object" && payload !== null && Object.values(payload).some((v)=>Array.isArray(v) ? v.some(requiresFormDataUpload) : v instanceof InputFile || requiresFormDataUpload(v));
}
function str(value) {
return JSON.stringify(value, (_, v)=>v ?? undefined);
}
function createJsonPayload(payload) {
return {
method: "POST",
headers: {
"content-type": "application/json",
connection: "keep-alive"
},
body: str(payload)
};
}
async function* protectItr(itr, onError) {
try {
yield* itr;
} catch (err) {
onError(err);
}
}
function createFormDataPayload(payload, onError) {
const boundary = createBoundary();
const itr = payloadToMultipartItr(payload, boundary);
const safeItr = protectItr(itr, onError);
const stream = readableStreamFromIterable(safeItr);
return {
method: "POST",
headers: {
"content-type": `multipart/form-data; boundary=${boundary}`,
connection: "keep-alive"
},
body: stream
};
}
function createBoundary() {
return "----------" + randomId(32);
}
function randomId(length = 16) {
return Array.from(Array(length)).map(()=>Math.random().toString(36)[2] || 0).join("");
}
const enc = new TextEncoder();
async function* payloadToMultipartItr(payload, boundary) {
const files = extractFiles(payload);
yield enc.encode(`--${boundary}\r\n`);
const separator = enc.encode(`\r\n--${boundary}\r\n`);
let first = true;
for (const [key, value] of Object.entries(payload)){
if (value == null) continue;
if (!first) yield separator;
yield valuePart(key, typeof value === "object" ? str(value) : value);
first = false;
}
for (const { id , origin , file } of files){
if (!first) yield separator;
yield* filePart(id, origin, file);
first = false;
}
yield enc.encode(`\r\n--${boundary}--\r\n`);
}
function extractFiles(value) {
if (typeof value !== "object" || value === null) return [];
return Object.entries(value).flatMap(([k, v])=>{
if (Array.isArray(v)) return v.flatMap((p)=>extractFiles(p));
else if (v instanceof InputFile) {
const id = randomId();
Object.assign(value, {
[k]: `attach://${id}`
});
const origin = k === "media" && "type" in value && typeof value.type === "string" ? value.type : k;
return {
id,
origin,
file: v
};
} else return extractFiles(v);
});
}
function valuePart(key, value) {
return enc.encode(`content-disposition:form-data;name="${key}"\r\n\r\n${value}`);
}
async function* filePart(id, origin, input) {
const filename = input.filename || `${origin}.${getExt(origin)}`;
if (filename.includes("\r") || filename.includes("\n")) {
throw new Error(`File paths cannot contain carriage-return (\\r) \
or newline (\\n) characters! Filename for property '${origin}' was:
"""
${filename}
"""`);
}
yield enc.encode(`content-disposition:form-data;name="${id}";filename=${filename}\r\ncontent-type:application/octet-stream\r\n\r\n`);
const data = await input.toRaw();
if (data instanceof Uint8Array) yield data;
else yield* data;
}
function getExt(key) {
switch(key){
case "certificate":
return "pem";
case "photo":
case "thumbnail":
return "jpg";
case "voice":
return "ogg";
case "audio":
return "mp3";
case "animation":
case "video":
case "video_note":
return "mp4";
case "sticker":
return "webp";
default:
return "dat";
}
}
const debug = browser$1("grammy:core");
function concatTransformer(prev, trans) {
return (method, payload, signal)=>trans(prev, method, payload, signal);
}
class ApiClient {
options;
hasUsedWebhookReply;
installedTransformers;
constructor(token, options = {}, webhookReplyEnvelope = {}){
this.token = token;
this.webhookReplyEnvelope = webhookReplyEnvelope;
this.hasUsedWebhookReply = false;
this.installedTransformers = [];
this.call = async (method, p, signal)=>{
const payload = p ?? {};
debug(`Calling ${method}`);
const opts = this.options;
const formDataRequired = requiresFormDataUpload(payload);
if (this.webhookReplyEnvelope.send !== undefined && !this.hasUsedWebhookReply && !formDataRequired && opts.canUseWebhookReply(method)) {
this.hasUsedWebhookReply = true;
const config = createJsonPayload({
...payload,
method
});
await this.webhookReplyEnvelope.send(config.body);
return {
ok: true,
result: true
};
}
const controller = createAbortControllerFromSignal(signal);
const timeout = createTimeout(controller, opts.timeoutSeconds, method);
const streamErr = createStreamError(controller);
const url = opts.buildUrl(opts.apiRoot, this.token, method);
const config = formDataRequired ? createFormDataPayload(payload, (err)=>streamErr.catch(err)) : createJsonPayload(payload);
const sig = controller.signal;
const options = {
...opts.baseFetchConfig,
signal: sig,
...config
};
const successPromise = fetch(url instanceof URL ? url.href : url, options).catch(toHttpError(method, opts.sensitiveLogs));
const operations = [
successPromise,
streamErr.promise,
timeout.promise
];
try {
const res = await Promise.race(operations);
return await res.json();
} finally{
if (timeout.handle !== undefined) clearTimeout(timeout.handle);
}
};
const apiRoot = options.apiRoot ?? "https://api.telegram.org";
this.options = {
apiRoot,
buildUrl: options.buildUrl ?? ((root, token, method)=>`${root}/bot${token}/${method}`),
timeoutSeconds: options.timeoutSeconds ?? 500,
baseFetchConfig: {
...baseFetchConfig(apiRoot),
...options.baseFetchConfig
},
canUseWebhookReply: options.canUseWebhookReply ?? (()=>false),
sensitiveLogs: options.sensitiveLogs ?? false
};
if (this.options.apiRoot.endsWith("/")) {
throw new Error(`Remove the trailing '/' from the 'apiRoot' option (use '${this.options.apiRoot.substring(0, this.options.apiRoot.length - 1)}' instead of '${this.options.apiRoot}')`);
}
}
call;
use(...transformers) {
this.call = transformers.reduce(concatTransformer, this.call);
this.installedTransformers.push(...transformers);
return this;
}
async callApi(method, payload, signal) {
const data = await this.call(method, payload, signal);
if (data.ok) return data.result;
else throw toGrammyError(data, method, payload);
}
token;
webhookReplyEnvelope;
}
function createRawApi(token, options, webhookReplyEnvelope) {
const client = new ApiClient(token, options, webhookReplyEnvelope);
const proxyHandler = {
get (_, m) {
return m === "toJSON" ? "__internal" : client.callApi.bind(client, m);
},
...proxyMethods
};
const raw = new Proxy({}, proxyHandler);
const installedTransformers = client.installedTransformers;
const api = {
raw,
installedTransformers,
use: (...t)=>{
client.use(...t);
return api;
}
};
return api;
}
const proxyMethods = {
set () {
return false;
},
defineProperty () {
return false;
},
deleteProperty () {
return false;
},
ownKeys () {
return [];
}
};
function createTimeout(controller, seconds, method) {
let handle = undefined;
const promise = new Promise((_, reject)=>{
handle = setTimeout(()=>{
const msg = `Request to '${method}' timed out after ${seconds} seconds`;
reject(new Error(msg));
controller.abort();
}, 1000 * seconds);
});
return {
promise,
handle
};
}
function createStreamError(abortController) {
let onError = (err)=>{
throw err;
};
const promise = new Promise((_, reject)=>{
onError = (err)=>{
reject(err);
abortController.abort();
};
});
return {
promise,
catch: onError
};
}
function createAbortControllerFromSignal(signal) {
const abortController = new AbortController();
if (signal === undefined) return abortController;
const sig = signal;
function abort() {
abortController.abort();
sig.removeEventListener("abort", abort);
}
if (sig.aborted) abort();
else sig.addEventListener("abort", abort);
return {
abort,
signal: abortController.signal
};
}
class Api {
raw;
config;
constructor(token, config, webhookReplyEnvelope){
const { raw , use , installedTransformers } = createRawApi(token, config, webhookReplyEnvelope);
this.raw = raw;
this.config = {
use,
installedTransformers: ()=>[
...installedTransformers
]
};
}
getUpdates(other, signal) {
return this.raw.getUpdates({
...other
}, signal);
}
setWebhook(url, other, signal) {
return this.raw.setWebhook({
url,
...other
}, signal);
}
deleteWebhook(other, signal) {
return this.raw.deleteWebhook({
...other
}, signal);
}
getWebhookInfo(signal) {
return this.raw.getWebhookInfo(signal);
}
getMe(signal) {
return this.raw.getMe(signal);
}
logOut(signal) {
return this.raw.logOut(signal);
}
close(signal) {
return this.raw.close(signal);
}
sendMessage(chat_id, text, other, signal) {
return this.raw.sendMessage({
chat_id,
text,
...other
}, signal);
}
forwardMessage(chat_id, from_chat_id, message_id, other, signal) {
return this.raw.forwardMessage({
chat_id,
from_chat_id,
message_id,
...other
}, signal);
}
copyMessage(chat_id, from_chat_id, message_id, other, signal) {
return this.raw.copyMessage({
chat_id,
from_chat_id,
message_id,
...other
}, signal);
}
sendPhoto(chat_id, photo, other, signal) {
return this.raw.sendPhoto({
chat_id,
photo,
...other
}, signal);
}
sendAudio(chat_id, audio, other, signal) {
return this.raw.sendAudio({
chat_id,
audio,
...other
}, signal);
}
sendDocument(chat_id, document1, other, signal) {
return this.raw.sendDocument({
chat_id,
document: document1,
...other
}, signal);
}
sendVideo(chat_id, video, other, signal) {
return this.raw.sendVideo({
chat_id,
video,
...other
}, signal);
}
sendAnimation(chat_id, animation, other, signal) {
return this.raw.sendAnimation({
chat_id,
animation,
...other
}, signal);
}
sendVoice(chat_id, voice, other, signal) {
return this.raw.sendVoice({
chat_id,
voice,
...other
}, signal);
}
sendVideoNote(chat_id, video_note, other, signal) {
return this.raw.sendVideoNote({
chat_id,
video_note,
...other
}, signal);
}
sendMediaGroup(chat_id, media, other, signal) {
return this.raw.sendMediaGroup({
chat_id,
media,
...other
}, signal);
}
sendLocation(chat_id, latitude, longitude, other, signal) {
return this.raw.sendLocation({
chat_id,
latitude,
longitude,
...other
}, signal);
}
editMessageLiveLocation(chat_id, message_id, latitude, longitude, other, signal) {
return this.raw.editMessageLiveLocation({
chat_id,
message_id,
latitude,
longitude,
...other
}, signal);
}
editMessageLiveLocationInline(inline_message_id, latitude, longitude, other, signal) {
return this.raw.editMessageLiveLocation({
inline_message_id,
latitude,
longitude,
...other
}, signal);
}
stopMessageLiveLocation(chat_id, message_id, other, signal) {
return this.raw.stopMessageLiveLocation({
chat_id,
message_id,
...other
}, signal);
}
stopMessageLiveLocationInline(inline_message_id, other, signal) {
return this.raw.stopMessageLiveLocation({
inline_message_id,
...other
}, signal);
}
sendVenue(chat_id, latitude, longitude, title, address, other, signal) {
return this.raw.sendVenue({
chat_id,
latitude,
longitude,
title,
address,
...other
}, signal);
}
sendContact(chat_id, phone_number, first_name, other, signal) {
return this.raw.sendContact({
chat_id,
phone_number,
first_name,
...other
}, signal);
}
sendPoll(chat_id, question, options, other, signal) {
return this.raw.sendPoll({
chat_id,
question,
options,
...other
}, signal);
}
sendDice(chat_id, emoji, other, signal) {
return this.raw.sendDice({
chat_id,
emoji,
...other
}, signal);
}
sendChatAction(chat_id, action, other, signal) {
return this.raw.sendChatAction({
chat_id,
action,
...other
}, signal);
}
getUserProfilePhotos(user_id, other, signal) {
return this.raw.getUserProfilePhotos({
user_id,
...other
}, signal);
}
getFile(file_id, signal) {
return this.raw.getFile({
file_id
}, signal);
}
kickChatMember(...args) {
return this.banChatMember(...args);
}
banChatMember(chat_id, user_id, other, signal) {
return this.raw.banChatMember({
chat_id,
user_id,
...other
}, signal);
}
unbanChatMember(chat_id, user_id, other, signal) {
return this.raw.unbanChatMember({
chat_id,
user_id,
...other
}, signal);
}
restrictChatMember(chat_id, user_id, permissions, other, signal) {
return this.raw.restrictChatMember({
chat_id,
user_id,
permissions,
...other
}, signal);
}
promoteChatMember(chat_id, user_id, other, signal) {
return this.raw.promoteChatMember({
chat_id,
user_id,
...other
}, signal);
}
setChatAdministratorCustomTitle(chat_id, user_id, custom_title, signal) {
return this.raw.setChatAdministratorCustomTitle({
chat_id,
user_id,
custom_title
}, signal);
}
banChatSenderChat(chat_id, sender_chat_id, signal) {
return this.raw.banChatSenderChat({
chat_id,
sender_chat_id
}, signal);
}
unbanChatSenderChat(chat_id, sender_chat_id, signal) {
return this.raw.unbanChatSenderChat({
chat_id,
sender_chat_id
}, signal);
}
setChatPermissions(chat_id, permissions, signal) {
return this.raw.setChatPermissions({
chat_id,
permissions
}, signal);
}
exportChatInviteLink(chat_id, signal) {
return this.raw.exportChatInviteLink({
chat_id
}, signal);
}
createChatInviteLink(chat_id, other, signal) {
return this.raw.createChatInviteLink({
chat_id,
...other
}, signal);
}
editChatInviteLink(chat_id, invite_link, other, signal) {
return this.raw.editChatInviteLink({
chat_id,
invite_link,
...other
}, signal);
}
revokeChatInviteLink(chat_id, invite_link, signal) {
return this.raw.revokeChatInviteLink({
chat_id,
invite_link
}, signal);
}
approveChatJoinRequest(chat_id, user_id, signal) {
return this.raw.approveChatJoinRequest({
chat_id,
user_id
}, signal);
}
declineChatJoinRequest(chat_id, user_id, signal) {
return this.raw.declineChatJoinRequest({
chat_id,
user_id
}, signal);
}
setChatPhoto(chat_id, photo, signal) {
return this.raw.setChatPhoto({
chat_id,
photo
}, signal);
}
deleteChatPhoto(chat_id, signal) {
return this.raw.deleteChatPhoto({
chat_id
}, signal);
}
setChatTitle(chat_id, title, signal) {
return this.raw.setChatTitle({
chat_id,
title
}, signal);
}
setChatDescription(chat_id, description, signal) {
return this.raw.setChatDescription({
chat_id,
description
}, signal);
}
pinChatMessage(chat_id, message_id, other, signal) {
return this.raw.pinChatMessage({
chat_id,
message_id,
...other
}, signal);
}
unpinChatMessage(chat_id, message_id, signal) {
return this.raw.unpinChatMessage({
chat_id,
message_id
}, signal);
}
unpinAllChatMessages(chat_id, signal) {
return this.raw.unpinAllChatMessages({
chat_id
}, signal);
}
leaveChat(chat_id, signal) {
return this.raw.leaveChat({
chat_id
}, signal);
}
getChat(chat_id, signal) {
return this.raw.getChat({
chat_id
}, signal);
}
getChatAdministrators(chat_id, signal) {
return this.raw.getChatAdministrators({
chat_id
}, signal);
}
getChatMembersCount(...args) {
return this.getChatMemberCount(...args);
}
getChatMemberCount(chat_id, signal) {
return this.raw.getChatMemberCount({
chat_id
}, signal);
}
getChatMember(chat_id, user_id, signal) {
return this.raw.getChatMember({
chat_id,
user_id
}, signal);
}
setChatStickerSet(chat_id, sticker_set_name, signal) {
return this.raw.setChatStickerSet({
chat_id,
sticker_set_name
}, signal);
}
deleteChatStickerSet(chat_id, signal) {
return this.raw.deleteChatStickerSet({
chat_id
}, signal);
}
getForumTopicIconStickers(signal) {
return this.raw.getForumTopicIconStickers(signal);
}
createForumTopic(chat_id, name, other, signal) {
return this.raw.createForumTopic({
chat_id,
name,
...other
}, signal);
}
editForumTopic(chat_id, message_thread_id, other, signal) {
return this.raw.editForumTopic({
chat_id,
message_thread_id,
...other
}, signal);
}
closeForumTopic(chat_id, message_thread_id, signal) {
return this.raw.closeForumTopic({
chat_id,
message_thread_id
}, signal);
}
reopenForumTopic(chat_id, message_thread_id, signal) {
return this.raw.reopenForumTopic({
chat_id,
message_thread_id
}, signal);
}
deleteForumTopic(chat_id, message_thread_id, signal) {
return this.raw.deleteForumTopic({
chat_id,
message_thread_id
}, signal);
}
unpinAllForumTopicMessages(chat_id, message_thread_id, signal) {
return this.raw.unpinAllForumTopicMessages({
chat_id,
message_thread_id
}, signal);
}
editGeneralForumTopic(chat_id, name, signal) {
return this.raw.editGeneralForumTopic({
chat_id,
name
}, signal);
}
closeGeneralForumTopic(chat_id, signal) {
return this.raw.closeGeneralForumTopic({
chat_id
}, signal);
}
reopenGeneralForumTopic(chat_id, signal) {
return this.raw.reopenGeneralForumTopic({
chat_id
}, signal);
}
hideGeneralForumTopic(chat_id, signal) {
return this.raw.hideGeneralForumTopic({
chat_id
}, signal);
}
unhideGeneralForumTopic(chat_id, signal) {
return this.raw.unhideGeneralForumTopic({
chat_id
}, signal);
}
answerCallbackQuery(callback_query_id, other, signal) {
return this.raw.answerCallbackQuery({
callback_query_id,
...other
}, signal);
}
setMyName(name, other, signal) {
return this.raw.setMyName({
name,
...other
}, signal);
}
getMyName(other, signal) {
return this.raw.getMyName(other ?? {}, signal);
}
setMyCommands(commands, other, signal) {
return this.raw.setMyCommands({
commands,
...other
}, signal);
}
deleteMyCommands(other, signal) {
return this.raw.deleteMyCommands({
...other
}, signal);
}
getMyCommands(other, signal) {
return this.raw.getMyCommands({
...other
}, signal);
}
setMyDescription(description, other, signal) {
return this.raw.setMyDescription({
description,
...other
}, signal);
}
getMyDescription(other, signal) {
return this.raw.getMyDescription({
...other
}, signal);
}
setMyShortDescription(short_description, other, signal) {
return this.raw.setMyShortDescription({
short_description,
...other
}, signal);
}
getMyShortDescription(other, signal) {
return this.raw.getMyShortDescription({
...other
}, signal);
}
setChatMenuButton(other, signal) {
return this.raw.setChatMenuButton({
...other
}, signal);
}
getChatMenuButton(other, signal) {
return this.raw.getChatMenuButton({
...other
}, signal);
}
setMyDefaultAdministratorRights(other, signal) {
return this.raw.setMyDefaultAdministratorRights({
...other
}, signal);
}
getMyDefaultAdministratorRights(other, signal) {
return this.raw.getMyDefaultAdministratorRights({
...other
}, signal);
}
editMessageText(chat_id, message_id, text, other, signal) {
return this.raw.editMessageText({
chat_id,
message_id,
text,
...other
}, signal);
}
editMessageTextInline(inline_message_id, text, other, signal) {
return this.raw.editMessageText({
inline_message_id,
text,
...other
}, signal);
}
editMessageCaption(chat_id, message_id, other, signal) {
return this.raw.editMessageCaption({
chat_id,
message_id,
...other
}, signal);
}
editMessageCaptionInline(inline_message_id, other, signal) {
return this.raw.editMessageCaption({
inline_message_id,
...other
}, signal);
}
editMessageMedia(chat_id, message_id, media, other, signal) {
return this.raw.editMessageMedia({
chat_id,
message_id,
media,
...other
}, signal);
}
editMessageMediaInline(inline_message_id, media, other, signal) {
return this.raw.editMessageMedia({
inline_message_id,
media,
...other
}, signal);
}
editMessageReplyMarkup(chat_id, message_id, other, signal) {
return this.raw.editMessageReplyMarkup({
chat_id,
message_id,
...other
}, signal);
}
editMessageReplyMarkupInline(inline_message_id, other, signal) {
return this.raw.editMessageReplyMarkup({
inline_message_id,
...other
}, signal);
}
stopPoll(chat_id, message_id, other, signal) {
return this.raw.stopPoll({
chat_id,
message_id,
...other
}, signal);
}
deleteMessage(chat_id, message_id, signal) {
return this.raw.deleteMessage({
chat_id,
message_id
}, signal);
}
sendSticker(chat_id, sticker, other, signal) {
return this.raw.sendSticker({
chat_id,
sticker,
...other
}, signal);
}
getStickerSet(name, signal) {
return this.raw.getStickerSet({
name
}, signal);
}
getCustomEmojiStickers(custom_emoji_ids, signal) {
return this.raw.getCustomEmojiStickers({
custom_emoji_ids
}, signal);
}
uploadStickerFile(user_id, sticker_format, sticker, signal) {
return this.raw.uploadStickerFile({
user_id,
sticker_format,
sticker
}, signal);
}
createNewStickerSet(user_id, name, title, stickers, sticker_format, other, signal) {
return this.raw.createNewStickerSet({
user_id,
name,
title,
stickers,
sticker_format,
...other
}, signal);
}
addStickerToSet(user_id, name, sticker, signal) {
return this.raw.addStickerToSet({
user_id,
name,
sticker
}, signal);
}
setStickerPositionInSet(sticker, position, signal) {
return this.raw.setStickerPositionInSet({
sticker,
position
}, signal);
}
deleteStickerFromSet(sticker, signal) {
return this.raw.deleteStickerFromSet({
sticker
}, signal);
}
setStickerEmojiList(sticker, emoji_list, signal) {
return this.raw.setStickerEmojiList({
sticker,
emoji_list
}, signal);
}
setStickerKeywords(sticker, keywords, signal) {
return this.raw.setStickerKeywords({
sticker,
keywords
}, signal);
}
setStickerMaskPosition(sticker, mask_position, signal) {
return this.raw.setStickerMaskPosition({
sticker,
mask_position
}, signal);
}
setStickerSetTitle(name, title, signal) {
return this.raw.setStickerSetTitle({
name,
title
}, signal);
}
deleteStickerSet(name, signal) {
return this.raw.deleteStickerSet({
name
}, signal);
}
setStickerSetThumbnail(name, user_id, thumbnail, signal) {
return this.raw.setStickerSetThumbnail({
name,
user_id,
thumbnail
}, signal);
}
setCustomEmojiStickerSetThumbnail(name, custom_emoji_id, signal) {
return this.raw.setCustomEmojiStickerSetThumbnail({
name,
custom_emoji_id
}, signal);
}
answerInlineQuery(inline_query_id, results, other, signal) {
return this.raw.answerInlineQuery({
inline_query_id,
results,
...other
}, signal);
}
answerWebAppQuery(web_app_query_id, result, signal) {
return this.raw.answerWebAppQuery({
web_app_query_id,
result
}, signal);
}
sendInvoice(chat_id, title, description, payload, provider_token, currency, prices, other, signal) {
return this.raw.sendInvoice({
chat_id,
title,
description,
payload,
provider_token,
currency,
prices,
...other
}, signal);
}
createInvoiceLink(title, description, payload, provider_token, currency, prices, other, signal) {
return this.raw.createInvoiceLink({
title,
description,
payload,
provider_token,
currency,
prices,
...other
}, signal);
}
answerShippingQuery(shipping_query_id, ok, other, signal) {
return this.raw.answerShippingQuery({
shipping_query_id,
ok,
...other
}, signal);
}
answerPreCheckoutQuery(pre_checkout_query_id, ok, other, signal) {
return this.raw.answerPreCheckoutQuery({
pre_checkout_query_id,
ok,
...other
}, signal);
}
setPassportDataErrors(user_id, errors, signal) {
return this.raw.setPassportDataErrors({
user_id,
errors
}, signal);
}
sendGame(chat_id, game_short_name, other, signal) {
return this.raw.sendGame({
chat_id,
game_short_name,
...other
}, signal);
}
setGameScore(chat_id, message_id, user_id, score, other, signal) {
return this.raw.setGameScore({
chat_id,
message_id,
user_id,
score,
...other
}, signal);
}
setGameScoreInline(inline_message_id, user_id, score, other, signal) {
return this.raw.setGameScore({
inline_message_id,
user_id,
score,
...other
}, signal);
}
getGameHighScores(chat_id, message_id, user_id, signal) {
return this.raw.getGameHighScores({
chat_id,
message_id,
user_id
}, signal);
}
getGameHighScoresInline(inline_message_id, user_id, signal) {
return this.raw.getGameHighScores({
inline_message_id,
user_id
}, signal);
}
}
const debug1 = browser$1("grammy:bot");
const debugWarn = browser$1("grammy:warn");
const debugErr = browser$1("grammy:error");
const DEFAULT_UPDATE_TYPES = [
"message",
"edited_message",
"channel_post",
"edited_channel_post",
"inline_query",
"chosen_inline_result",
"callback_query",
"shipping_query",
"pre_checkout_query",
"poll",
"poll_answer",
"my_chat_member",
"chat_join_request"
];
class Bot extends Composer {
pollingRunning;
pollingAbortController;
lastTriedUpdateId;
api;
me;
mePromise;
clientConfig;
ContextConstructor;
observedUpdateTypes;
errorHandler;
constructor(token, config){
super();
this.token = token;
this.pollingRunning = false;
this.lastTriedUpdateId = 0;
this.observedUpdateTypes = new Set();
this.errorHandler = async (err)=>{
console.error("Error in middleware while handling update", err.ctx?.update?.update_id, err.error);
console.error("No error handler was set!");
console.error("Set your own error handler with `bot.catch = ...`");
if (this.pollingRunning) {
console.error("Stopping bot");
await this.stop();
}
throw err;
};
if (!token) throw new Error("Empty token!");
this.me = config?.botInfo;
this.clientConfig = config?.client;
this.ContextConstructor = config?.ContextConstructor ?? Context;
this.api = new Api(token, this.clientConfig);
}
set botInfo(botInfo) {
this.me = botInfo;
}
get botInfo() {
if (this.me === undefined) {
throw new Error("Bot information unavailable! Make sure to call `await bot.init()` before accessing `bot.botInfo`!");
}
return this.me;
}
on(filter, ...middleware) {
for (const [u] of parse(filter).flatMap(preprocess)){
this.observedUpdateTypes.add(u);
}
return super.on(filter, ...middleware);
}
isInited() {
return this.me !== undefined;
}
async init(signal) {
if (!this.isInited()) {
debug1("Initializing bot");
this.mePromise ??= withRetries(()=>this.api.getMe(signal), signal);
let me;
try {
me = await this.mePromise;
} finally{
this.mePromise = undefined;
}
if (this.me === undefined) this.me = me;
else debug1("Bot info was set by now, will not overwrite");
}
debug1(`I am ${this.me.username}!`);
}
async handleUpdates(updates) {
for (const update of updates){
this.lastTriedUpdateId = update.update_id;
try {
await this.handleUpdate(update);
} catch (err) {
if (err instanceof BotError) {
await this.errorHandler(err);
} else {
console.error("FATAL: grammY unable to handle:", err);
throw err;
}
}
}
}
async handleUpdate(update, webhookReplyEnvelope) {
if (this.me === undefined) {
throw new Error("Bot not initialized! Either call `await bot.init()`, \
or directly set the `botInfo` option in the `Bot` constructor to specify \
a known bot info object.");
}
debug1(`Processing update ${update.update_id}`);
const api = new Api(this.token, this.clientConfig, webhookReplyEnvelope);
const t = this.api.config.installedTransformers();
if (t.length > 0) api.config.use(...t);
const ctx = new this.ContextConstructor(update, api, this.me);
try {
await run(this.middleware(), ctx);
} catch (err) {
debugErr(`Error in middleware for update ${update.update_id}`);
throw new BotError(err, ctx);
}
}
async start(options) {
if (!this.isInited()) {
await this.init(this.pollingAbortController?.signal);
}
if (this.pollingRunning) {
debug1("Simple long polling already running!");
return;
} else {
this.pollingRunning = true;
this.pollingAbortController = new AbortController();
}
await withRetries(()=>this.api.deleteWebhook({
drop_pending_updates: options?.drop_pending_updates
}, this.pollingAbortController?.signal), this.pollingAbortController?.signal);
await options?.onStart?.(this.botInfo);
if (!this.pollingRunning) return;
validateAllowedUpdates(this.observedUpdateTypes, options?.allowed_updates);
this.use = noUseFunction;
debug1("Starting simple long polling");
await this.loop(options);
debug1("Middleware is done running");
}
async stop() {
if (this.pollingRunning) {
debug1("Stopping bot, saving update offset");
this.pollingRunning = false;
this.pollingAbortController?.abort();
const offset = this.lastTriedUpdateId + 1;
await this.api.getUpdates({
offset,
limit: 1
}).finally(()=>this.pollingAbortController = undefined);
} else {
debug1("Bot is not running!");
}
}
catch(errorHandler) {
this.errorHandler = errorHandler;
}
async loop(options) {
const limit = options?.limit;
const timeout = options?.timeout ?? 30;
let allowed_updates = options?.allowed_updates ?? [];
while(this.pollingRunning){
const updates = await this.fetchUpdates({
limit,
timeout,
allowed_updates
});
if (updates === undefined) break;
await this.handleUpdates(updates);
allowed_updates = undefined;
}
}
async fetchUpdates({ limit , timeout , allowed_updates }) {
const offset = this.lastTriedUpdateId + 1;
let updates = undefined;
do {
try {
updates = await this.api.getUpdates({
offset,
limit,
timeout,
allowed_updates
}, this.pollingAbortController?.signal);
} catch (error) {
await this.handlePollingError(error);
}
}while (updates === undefined && this.pollingRunning)
return updates;
}
async handlePollingError(error) {
if (!this.pollingRunning) {
debug1("Pending getUpdates request cancelled");
return;
}
let sleepSeconds = 3;
if (error instanceof GrammyError) {
debugErr(error.message);
if (error.error_code === 401) {
debugErr("Make sure you are using the bot token you obtained from @BotFather (https://t.me/BotFather).");
throw error;
} else if (error.error_code === 409) {
debugErr("Consider revoking the bot token if you believe that no other instance is running.");
throw error;
} else if (error.error_code === 429) {
debugErr("Bot API server is closing.");
sleepSeconds = error.parameters.retry_after ?? sleepSeconds;
}
} else debugErr(error);
debugErr(`Call to getUpdates failed, retrying in ${sleepSeconds} seconds ...`);
await sleep(sleepSeconds);
}
token;
}
async function withRetries(task, signal) {
const INITIAL_DELAY = 50;
let lastDelay = 50;
async function handleError(error) {
let delay = false;
let strategy = "rethrow";
if (error instanceof HttpError) {
delay = true;
strategy = "retry";
} else if (error instanceof GrammyError) {
if (error.error_code >= 500) {
delay = true;
strategy = "retry";
} else if (error.error_code === 429) {
const retryAfter = error.parameters.retry_after;
if (typeof retryAfter === "number") {
await sleep(retryAfter, signal);
lastDelay = INITIAL_DELAY;
} else {
delay = true;
}
strategy = "retry";
}
}
if (delay) {
if (lastDelay !== 50) {
await sleep(lastDelay, signal);
}
const TWENTY_MINUTES = 20 * 60 * 1000;
lastDelay = Math.min(TWENTY_MINUTES, 2 * lastDelay);
}
return strategy;
}
let result = {
ok: false
};
while(!result.ok){
try {
result = {
ok: true,
value: await task()
};
} catch (error) {
debugErr(error);
const strategy = await handleError(error);
switch(strategy){
case "retry":
continue;
case "rethrow":
throw error;
}
}
}
return result.value;
}
async function sleep(seconds, signal) {
let handle;
let reject;
function abort() {
reject?.(new Error("Aborted delay"));
if (handle !== undefined) clearTimeout(handle);
}
try {
await new Promise((res, rej)=>{
reject = rej;
if (signal?.aborted) {
abort();
return;
}
signal?.addEventListener("abort", abort);
handle = setTimeout(res, 1000 * seconds);
});
} finally{
signal?.removeEventListener("abort", abort);
}
}
function validateAllowedUpdates(updates, allowed = DEFAULT_UPDATE_TYPES) {
const impossible = Array.from(updates).filter((u)=>!allowed.includes(u));
if (impossible.length > 0) {
debugWarn(`You registered listeners for the following update types, \
but you did not specify them in \`allowed_updates\` \
so they may not be received: ${impossible.map((u)=>`'${u}'`).join(", ")}`);
}
}
function noUseFunction() {
throw new Error(`It looks like you are registering more listeners \
on your bot from within other listeners! This means that every time your bot \
handles a message like this one, new listeners will be added. This list grows until \
your machine crashes, so grammY throws this error to tell you that you should \
probably do things a bit differently. If you're unsure how to resolve this problem, \
you can ask in the group chat: https://telegram.me/grammyjs
On the other hand, if you actually know what you're doing and you do need to install \
further middleware while your bot is running, consider installing a composer \
instance on your bot, and in turn augment the composer after the fact. This way, \
you can circumvent this protection against memory leaks.`);
}
const ALL_UPDATE_TYPES = [
...DEFAULT_UPDATE_TYPES,
"chat_member"
];
const ALL_CHAT_PERMISSIONS = {
can_send_messages: true,
can_send_audios: true,
can_send_documents: true,
can_send_photos: true,
can_send_videos: true,
can_send_video_notes: true,
can_send_voice_notes: true,
can_send_polls: true,
can_send_other_messages: true,
can_add_web_page_previews: true,
can_change_info: true,
can_invite_users: true,
can_pin_messages: true,
can_manage_topics: true
};
const API_CONSTANTS = Object.freeze({
ALL_UPDATE_TYPES,
ALL_CHAT_PERMISSIONS
});
export { API_CONSTANTS as API_CONSTANTS };
function inputMessage(queryTemplate) {
return {
...queryTemplate,
...inputMessageMethods(queryTemplate)
};
}
function inputMessageMethods(queryTemplate) {
return {
text (message_text, options = {}) {
const content = {
message_text,
...options
};
return {
...queryTemplate,
input_message_content: content
};
},
location (latitude, longitude, options = {}) {
const content = {
latitude,
longitude,
...options
};
return {
...queryTemplate,
input_message_content: content
};
},
venue (title, latitude, longitude, address, options) {
const content = {
title,
latitude,
longitude,
address,
...options
};
return {
...queryTemplate,
input_message_content: content
};
},
contact (first_name, phone_number, options = {}) {
const content = {
first_name,
phone_number,
...options
};
return {
...queryTemplate,
input_message_content: content
};
},
invoice (title, description, payload, provider_token, currency, prices, options = {}) {
const content = {
title,
description,
payload,
provider_token,
currency,
prices,
...options
};
return {
...queryTemplate,
input_message_content: content
};
}
};
}
const InlineQueryResultBuilder = {
article (id, title, options = {}) {
return inputMessageMethods({
type: "article",
id,
title,
...options
});
},
audio (id, title, audio_url, options = {}) {
return inputMessage({
type: "audio",
id,
title,
audio_url: typeof audio_url === "string" ? audio_url : audio_url.href,
...options
});
},
audioCached (id, audio_file_id, options = {}) {
return inputMessage({
type: "audio",
id,
audio_file_id,
...options
});
},
contact (id, phone_number, first_name, options = {}) {
return inputMessage({
type: "contact",
id,
phone_number,
first_name,
...options
});
},
documentPdf (id, title, document_url, options = {}) {
return inputMessage({
type: "document",
mime_type: "application/pdf",
id,
title,
document_url: typeof document_url === "string" ? document_url : document_url.href,
...options
});
},
documentZip (id, title, document_url, options = {}) {
return inputMessage({
type: "document",
mime_type: "application/zip",
id,
title,
document_url: typeof document_url === "string" ? document_url : document_url.href,
...options
});
},
documentCached (id, title, document_file_id, options = {}) {
return inputMessage({
type: "document",
id,
title,
document_file_id,
...options
});
},
game (id, game_short_name, options = {}) {
return {
type: "game",
id,
game_short_name,
...options
};
},
gif (id, gif_url, thumbnail_url, options = {}) {
return inputMessage({
type: "gif",
id,
gif_url: typeof gif_url === "string" ? gif_url : gif_url.href,
thumbnail_url: typeof thumbnail_url === "string" ? thumbnail_url : thumbnail_url.href,
...options
});
},
gifCached (id, gif_file_id, options = {}) {
return inputMessage({
type: "gif",
id,
gif_file_id,
...options
});
},
location (id, title, latitude, longitude, options = {}) {
return inputMessage({
type: "location",
id,
title,
latitude,
longitude,
...options
});
},
mpeg4gif (id, mpeg4_url, thumbnail_url, options = {}) {
return inputMessage({
type: "mpeg4_gif",
id,
mpeg4_url: typeof mpeg4_url === "string" ? mpeg4_url : mpeg4_url.href,
thumbnail_url: typeof thumbnail_url === "string" ? thumbnail_url : thumbnail_url.href,
...options
});
},
mpeg4gifCached (id, mpeg4_file_id, options = {}) {
return inputMessage({
type: "mpeg4_gif",
id,
mpeg4_file_id,
...options
});
},
photo (id, photo_url, options = {
thumbnail_url: typeof photo_url === "string" ? photo_url : photo_url.href
}) {
return inputMessage({
type: "photo",
id,
photo_url: typeof photo_url === "string" ? photo_url : photo_url.href,
...options
});
},
photoCached (id, photo_file_id, options = {}) {
return inputMessage({
type: "photo",
id,
photo_file_id,
...options
});
},
stickerCached (id, sticker_file_id, options = {}) {
return inputMessage({
type: "sticker",
id,
sticker_file_id,
...options
});
},
venue (id, title, latitude, longitude, address, options = {}) {
return inputMessage({
type: "venue",
id,
title,
latitude,
longitude,
address,
...options
});
},
videoHtml (id, title, video_url, thumbnail_url, options = {}) {
return inputMessageMethods({
type: "video",
mime_type: "text/html",
id,
title,
video_url: typeof video_url === "string" ? video_url : video_url.href,
thumbnail_url: typeof thumbnail_url === "string" ? thumbnail_url : thumbnail_url.href,
...options
});
},
videoMp4 (id, title, video_url, thumbnail_url, options = {}) {
return inputMessage({
type: "video",
mime_type: "video/mp4",
id,
title,
video_url: typeof video_url === "string" ? video_url : video_url.href,
thumbnail_url: typeof thumbnail_url === "string" ? thumbnail_url : thumbnail_url.href,
...options
});
},
videoCached (id, title, video_file_id, options = {}) {
return inputMessage({
type: "video",
id,
title,
video_file_id,
...options
});
},
voice (id, title, voice_url, options = {}) {
return inputMessage({
type: "voice",
id,
title,
voice_url: typeof voice_url === "string" ? voice_url : voice_url.href,
...options
});
},
voiceCached (id, title, voice_file_id, options = {}) {
return inputMessage({
type: "voice",
id,
title,
voice_file_id,
...options
});
}
};
export { InlineQueryResultBuilder as InlineQueryResultBuilder };
const InputMediaBuilder = {
photo (media, options = {}) {
return {
type: "photo",
media,
...options
};
},
video (media, options = {}) {
return {
type: "video",
media,
...options
};
},
animation (media, options = {}) {
return {
type: "animation",
media,
...options
};
},
audio (media, options = {}) {
return {
type: "audio",
media,
...options
};
},
document (media, options = {}) {
return {
type: "document",
media,
...options
};
}
};
export { InputMediaBuilder as InputMediaBuilder };
class Keyboard {
is_persistent;
selective;
one_time_keyboard;
resize_keyboard;
input_field_placeholder;
constructor(keyboard = [
[]
]){
this.keyboard = keyboard;
}
add(...buttons) {
this.keyboard[this.keyboard.length - 1]?.push(...buttons);
return this;
}
row(...buttons) {
this.keyboard.push(buttons);
return this;
}
text(text) {
return this.add(Keyboard.text(text));
}
static text(text) {
return {
text
};
}
requestUser(text, requestId, options = {}) {
return this.add(Keyboard.requestUser(text, requestId, options));
}
static requestUser(text, requestId, options = {}) {
return {
text,
request_user: {
request_id: requestId,
...options
}
};
}
requestChat(text, requestId, options = {
chat_is_channel: false
}) {
return this.add(Keyboard.requestChat(text, requestId, options));
}
static requestChat(text, requestId, options = {
chat_is_channel: false
}) {
return {
text,
request_chat: {
request_id: requestId,
...options
}
};
}
requestContact(text) {
return this.add(Keyboard.requestContact(text));
}
static requestContact(text) {
return {
text,
request_contact: true
};
}
requestLocation(text) {
return this.add(Keyboard.requestLocation(text));
}
static requestLocation(text) {
return {
text,
request_location: true
};
}
requestPoll(text, type) {
return this.add(Keyboard.requestPoll(text, type));
}
static requestPoll(text, type) {
return {
text,
request_poll: {
type
}
};
}
webApp(text, url) {
return this.add(Keyboard.webApp(text, url));
}
static webApp(text, url) {
return {
text,
web_app: {
url
}
};
}
persistent(isEnabled = true) {
this.is_persistent = isEnabled;
return this;
}
selected(isEnabled = true) {
this.selective = isEnabled;
return this;
}
oneTime(isEnabled = true) {
this.one_time_keyboard = isEnabled;
return this;
}
resized(isEnabled = true) {
this.resize_keyboard = isEnabled;
return this;
}
placeholder(value) {
this.input_field_placeholder = value;
return this;
}
toTransposed() {
const original = this.keyboard;
const transposed = transpose(original);
return this.clone(transposed);
}
toFlowed(columns, options = {}) {
const original = this.keyboard;
const flowed = reflow(original, columns, options);
return this.clone(flowed);
}
clone(keyboard = this.keyboard) {
const clone = new Keyboard(keyboard.map((row)=>row.slice()));
clone.is_persistent = this.is_persistent;
clone.selective = this.selective;
clone.one_time_keyboard = this.one_time_keyboard;
clone.resize_keyboard = this.resize_keyboard;
clone.input_field_placeholder = this.input_field_placeholder;
return clone;
}
append(...sources) {
for (const source of sources){
const keyboard = Keyboard.from(source);
this.keyboard.push(...keyboard.keyboard.map((row)=>row.slice()));
}
return this;
}
build() {
return this.keyboard;
}
static from(source) {
if (source instanceof Keyboard) return source.clone();
function toButton(btn) {
return typeof btn === "string" ? Keyboard.text(btn) : btn;
}
return new Keyboard(source.map((row)=>row.map(toButton)));
}
keyboard;
}
class InlineKeyboard {
constructor(inline_keyboard = [
[]
]){
this.inline_keyboard = inline_keyboard;
}
add(...buttons) {
this.inline_keyboard[this.inline_keyboard.length - 1]?.push(...buttons);
return this;
}
row(...buttons) {
this.inline_keyboard.push(buttons);
return this;
}
url(text, url) {
return this.add(InlineKeyboard.url(text, url));
}
static url(text, url) {
return {
text,
url
};
}
text(text, data = text) {
return this.add(InlineKeyboard.text(text, data));
}
static text(text, data = text) {
return {
text,
callback_data: data
};
}
webApp(text, url) {
return this.add(InlineKeyboard.webApp(text, url));
}
static webApp(text, url) {
return {
text,
web_app: {
url
}
};
}
login(text, loginUrl) {
return this.add(InlineKeyboard.login(text, loginUrl));
}
static login(text, loginUrl) {
return {
text,
login_url: typeof loginUrl === "string" ? {
url: loginUrl
} : loginUrl
};
}
switchInline(text, query = "") {
return this.add(InlineKeyboard.switchInline(text, query));
}
static switchInline(text, query = "") {
return {
text,
switch_inline_query: query
};
}
switchInlineCurrent(text, query = "") {
return this.add(InlineKeyboard.switchInlineCurrent(text, query));
}
static switchInlineCurrent(text, query = "") {
return {
text,
switch_inline_query_current_chat: query
};
}
switchInlineChosen(text, query = {}) {
return this.add(InlineKeyboard.switchInlineChosen(text, query));
}
static switchInlineChosen(text, query = {}) {
return {
text,
switch_inline_query_chosen_chat: query
};
}
game(text) {
return this.add(InlineKeyboard.game(text));
}
static game(text) {
return {
text,
callback_game: {}
};
}
pay(text) {
return this.add(InlineKeyboard.pay(text));
}
static pay(text) {
return {
text,
pay: true
};
}
toTransposed() {
const original = this.inline_keyboard;
const transposed = transpose(original);
return new InlineKeyboard(transposed);
}
toFlowed(columns, options = {}) {
const original = this.inline_keyboard;
const flowed = reflow(original, columns, options);
return new InlineKeyboard(flowed);
}
clone() {
return new InlineKeyboard(this.inline_keyboard.map((row)=>row.slice()));
}
append(...sources) {
for (const source of sources){
const keyboard = InlineKeyboard.from(source);
this.inline_keyboard.push(...keyboard.inline_keyboard.map((row)=>row.slice()));
}
return this;
}
static from(source) {
if (source instanceof InlineKeyboard) return source.clone();
return new InlineKeyboard(source.map((row)=>row.slice()));
}
inline_keyboard;
}
function transpose(grid) {
const transposed = [];
for(let i = 0; i < grid.length; i++){
const row = grid[i];
for(let j = 0; j < row.length; j++){
const button = row[j];
(transposed[j] ??= []).push(button);
}
}
return transposed;
}
function reflow(grid, columns, { fillLastRow =false }) {
let first = columns;
if (fillLastRow) {
const buttonCount = grid.map((row)=>row.length).reduce((a, b)=>a + b, 0);
first = buttonCount % columns;
}
const reflowed = [];
for (const row of grid){
for (const button of row){
const at = Math.max(0, reflowed.length - 1);
const max = at === 0 ? first : columns;
let next = reflowed[at] ??= [];
if (next.length === max) {
next = [];
reflowed.push(next);
}
next.push(button);
}
}
return reflowed;
}
export { Keyboard as Keyboard };
export { InlineKeyboard as InlineKeyboard };
const debug2 = browser$1("grammy:session");
function session(options = {}) {
return options.type === "multi" ? strictMultiSession(options) : strictSingleSession(options);
}
function strictSingleSession(options) {
const { initial , storage , getSessionKey , custom } = fillDefaults(options);
return async (ctx, next)=>{
const propSession = new PropertySession(storage, ctx, "session", initial);
const key = await getSessionKey(ctx);
await propSession.init(key, {
custom,
lazy: false
});
await next();
await propSession.finish();
};
}
function strictMultiSession(options) {
const props = Object.keys(options).filter((k)=>k !== "type");
const defaults = Object.fromEntries(props.map((prop)=>[
prop,
fillDefaults(options[prop])
]));
return async (ctx, next)=>{
ctx.session = {};
const propSessions = await Promise.all(props.map(async (prop)=>{
const { initial , storage , getSessionKey , custom } = defaults[prop];
const s = new PropertySession(storage, ctx.session, prop, initial);
const key = await getSessionKey(ctx);
await s.init(key, {
custom,
lazy: false
});
return s;
}));
await next();
if (ctx.session == null) propSessions.forEach((s)=>s.delete());
await Promise.all(propSessions.map((s)=>s.finish()));
};
}
function lazySession(options = {}) {
if (options.type !== undefined && options.type !== "single") {
throw new Error("Cannot use lazy multi sessions!");
}
const { initial , storage , getSessionKey , custom } = fillDefaults(options);
return async (ctx, next)=>{
const propSession = new PropertySession(storage, ctx, "session", initial);
const key = await getSessionKey(ctx);
await propSession.init(key, {
custom,
lazy: true
});
await next();
await propSession.finish();
};
}
class PropertySession {
key;
value;
promise;
fetching;
read;
wrote;
constructor(storage, obj, prop, initial){
this.storage = storage;
this.obj = obj;
this.prop = prop;
this.initial = initial;
this.fetching = false;
this.read = false;
this.wrote = false;
}
load() {
if (this.key === undefined) {
return;
}
if (this.wrote) {
return;
}
if (this.promise === undefined) {
this.fetching = true;
this.promise = Promise.resolve(this.storage.read(this.key)).then((val)=>{
this.fetching = false;
if (this.wrote) {
return this.value;
}
if (val !== undefined) {
this.value = val;
return val;
}
val = this.initial?.();
if (val !== undefined) {
this.wrote = true;
this.value = val;
}
return val;
});
}
return this.promise;
}
async init(key, opts) {
this.key = key;
if (!opts.lazy) await this.load();
Object.defineProperty(this.obj, this.prop, {
enumerable: true,
get: ()=>{
if (key === undefined) {
const msg = undef("access", opts);
throw new Error(msg);
}
this.read = true;
if (!opts.lazy || this.wrote) return this.value;
this.load();
return this.fetching ? this.promise : this.value;
},
set: (v)=>{
if (key === undefined) {
const msg = undef("assign", opts);
throw new Error(msg);
}
this.wrote = true;
this.fetching = false;
this.value = v;
}
});
}
delete() {
Object.assign(this.obj, {
[this.prop]: undefined
});
}
async finish() {
if (this.key !== undefined) {
if (this.read) await this.load();
if (this.read || this.wrote) {
const value = await this.value;
if (value == null) await this.storage.delete(this.key);
else await this.storage.write(this.key, value);
}
}
}
storage;
obj;
prop;
initial;
}
function fillDefaults(opts = {}) {
let { getSessionKey =defaultGetSessionKey , initial , storage } = opts;
if (storage == null) {
debug2("Storing session data in memory, all data will be lost when the bot restarts.");
storage = new MemorySessionStorage();
}
const custom = getSessionKey !== defaultGetSessionKey;
return {
initial,
storage,
getSessionKey,
custom
};
}
function defaultGetSessionKey(ctx) {
return ctx.chat?.id.toString();
}
function undef(op, opts) {
const { lazy =false , custom } = opts;
const reason = custom ? "the custom `getSessionKey` function returned undefined for this update" : "this update does not belong to a chat, so the session key is undefined";
return `Cannot ${op} ${lazy ? "lazy " : ""}session data because ${reason}!`;
}
function isEnhance(value) {
return value === undefined || typeof value === "object" && value !== null && "__d" in value;
}
function enhanceStorage(options) {
let { storage , millisecondsToLive , migrations } = options;
storage = compatStorage(storage);
if (millisecondsToLive !== undefined) {
storage = timeoutStorage(storage, millisecondsToLive);
}
if (migrations !== undefined) {
storage = migrationStorage(storage, migrations);
}
return wrapStorage(storage);
}
function compatStorage(storage) {
return {
read: async (k)=>{
const v = await storage.read(k);
return isEnhance(v) ? v : {
__d: v
};
},
write: (k, v)=>storage.write(k, v),
delete: (k)=>storage.delete(k)
};
}
function timeoutStorage(storage, millisecondsToLive) {
const ttlStorage = {
read: async (k)=>{
const value = await storage.read(k);
if (value === undefined) return undefined;
if (value.e === undefined) {
await ttlStorage.write(k, value);
return value;
}
if (value.e < Date.now()) {
await ttlStorage.delete(k);
return undefined;
}
return value;
},
write: async (k, v)=>{
v.e = addExpiryDate(v, millisecondsToLive).expires;
await storage.write(k, v);
},
delete: (k)=>storage.delete(k)
};
return ttlStorage;
}
function migrationStorage(storage, migrations) {
const versions = Object.keys(migrations).map((v)=>parseInt(v)).sort((a, b)=>a - b);
const count = versions.length;
if (count === 0) throw new Error("No migrations given!");
const earliest = versions[0];
const last = count - 1;
const latest = versions[last];
const index = new Map();
versions.forEach((v, i)=>index.set(v, i));
function nextAfter(current) {
let i = last;
while(current <= versions[i])i--;
return i;
}
return {
read: async (k)=>{
const val = await storage.read(k);
if (val === undefined) return val;
let { __d: value , v: current = earliest - 1 } = val;
let i = 1 + (index.get(current) ?? nextAfter(current));
for(; i < count; i++)value = migrations[versions[i]](value);
return {
...val,
v: latest,
__d: value
};
},
write: (k, v)=>storage.write(k, {
v: latest,
...v
}),
delete: (k)=>storage.delete(k)
};
}
function wrapStorage(storage) {
return {
read: (k)=>Promise.resolve(storage.read(k)).then((v)=>v?.__d),
write: (k, v)=>storage.write(k, {
__d: v
}),
delete: (k)=>storage.delete(k)
};
}
class MemorySessionStorage {
storage;
constructor(timeToLive){
this.timeToLive = timeToLive;
this.storage = new Map();
}
read(key) {
const value = this.storage.get(key);
if (value === undefined) return undefined;
if (value.expires !== undefined && value.expires < Date.now()) {
this.delete(key);
return undefined;
}
return value.session;
}
readAll() {
return this.readAllValues();
}
readAllKeys() {
return Array.from(this.storage.keys());
}
readAllValues() {
return Array.from(this.storage.keys()).map((key)=>this.read(key)).filter((value)=>value !== undefined);
}
readAllEntries() {
return Array.from(this.storage.keys()).map((key)=>[
key,
this.read(key)
]).filter((pair)=>pair[1] !== undefined);
}
has(key) {
return this.storage.has(key);
}
write(key, value) {
this.storage.set(key, addExpiryDate(value, this.timeToLive));
}
delete(key) {
this.storage.delete(key);
}
timeToLive;
}
function addExpiryDate(value, ttl) {
if (ttl !== undefined && ttl < Infinity) {
const now = Date.now();
return {
session: value,
expires: now + ttl
};
} else {
return {
session: value
};
}
}
export { session as session };
export { lazySession as lazySession };
export { enhanceStorage as enhanceStorage };
export { MemorySessionStorage as MemorySessionStorage };
const SECRET_HEADER = "X-Telegram-Bot-Api-Secret-Token";
const SECRET_HEADER_LOWERCASE = SECRET_HEADER.toLowerCase();
const WRONG_TOKEN_ERROR = "secret token is wrong";
const ok = ()=>new Response(null, {
status: 200
});
const okJson = (json)=>new Response(json, {
status: 200,
headers: {
"Content-Type": "application/json"
}
});
const unauthorized = ()=>new Response('"unauthorized"', {
status: 401,
statusText: WRONG_TOKEN_ERROR
});
const express = (req, res)=>({
update: Promise.resolve(req.body),
header: req.header(SECRET_HEADER),
end: ()=>res.end(),
respond: (json)=>{
res.set("Content-Type", "application/json");
res.send(json);
},
unauthorized: ()=>{
res.status(401).send(WRONG_TOKEN_ERROR);
}
});
const koa = (ctx)=>({
update: Promise.resolve(ctx.request.body),
header: ctx.get(SECRET_HEADER),
end: ()=>{
ctx.body = "";
},
respond: (json)=>{
ctx.set("Content-Type", "application/json");
ctx.response.body = json;
},
unauthorized: ()=>{
ctx.status = 401;
}
});
const fastify = (req, reply)=>({
update: Promise.resolve(req.body),
header: req.headers[SECRET_HEADER_LOWERCASE],
end: ()=>reply.status(200).send(),
respond: (json)=>reply.send(json),
unauthorized: ()=>reply.code(401).send(WRONG_TOKEN_ERROR)
});
const serveHttp = (requestEvent)=>({
update: requestEvent.request.json(),
header: requestEvent.request.headers.get(SECRET_HEADER) || undefined,
end: ()=>requestEvent.respondWith(ok()),
respond: (json)=>requestEvent.respondWith(okJson(json)),
unauthorized: ()=>requestEvent.respondWith(unauthorized())
});
const stdHttp = (req)=>{
let resolveResponse;
return {
update: req.json(),
header: req.headers.get(SECRET_HEADER) || undefined,
end: ()=>{
if (resolveResponse) resolveResponse(ok());
},
respond: (json)=>{
if (resolveResponse) resolveResponse(okJson(json));
},
unauthorized: ()=>{
if (resolveResponse) resolveResponse(unauthorized());
},
handlerReturn: new Promise((resolve)=>{
resolveResponse = resolve;
})
};
};
const oak = (ctx)=>({
update: ctx.request.body({
type: "json"
}).value,
header: ctx.request.headers.get(SECRET_HEADER) || undefined,
end: ()=>{
ctx.response.status = 200;
},
respond: (json)=>{
ctx.response.type = "json";
ctx.response.body = json;
},
unauthorized: ()=>{
ctx.response.status = 401;
}
});
const http = (req, res)=>{
const secretHeaderFromRequest = req.headers[SECRET_HEADER_LOWERCASE];
return {
update: new Promise((resolve, reject)=>{
const chunks = [];
req.on("data", (chunk)=>chunks.push(chunk)).once("end", ()=>{
const raw = Buffer.concat(chunks).toString("utf-8");
resolve(JSON.parse(raw));
}).once("error", reject);
}),
header: Array.isArray(secretHeaderFromRequest) ? secretHeaderFromRequest[0] : secretHeaderFromRequest,
end: ()=>res.end(),
respond: (json)=>res.writeHead(200, {
"Content-Type": "application/json"
}).end(json),
unauthorized: ()=>res.writeHead(401).end(WRONG_TOKEN_ERROR)
};
};
const awsLambda = (event, _context, callback)=>({
update: JSON.parse(event.body),
header: event.headers[SECRET_HEADER],
end: ()=>callback(null, {
statusCode: 200
}),
respond: (json)=>callback(null, {
statusCode: 200,
headers: {
"Content-Type": "application/json"
},
body: json
}),
unauthorized: ()=>callback(null, {
statusCode: 401
})
});
const awsLambdaAsync = (event, _context)=>{
let resolveResponse;
return {
update: JSON.parse(event.body),
header: event.headers[SECRET_HEADER],
end: ()=>resolveResponse({
statusCode: 200
}),
respond: (json)=>resolveResponse({
statusCode: 200,
headers: {
"Content-Type": "application/json"
},
body: json
}),
unauthorized: ()=>resolveResponse({
statusCode: 401
}),
handlerReturn: new Promise((resolve)=>{
resolveResponse = resolve;
})
};
};
const azure = (context, req)=>({
update: Promise.resolve(req.body),
header: context.res.headers[SECRET_HEADER],
end: ()=>context.res = {
status: 200,
body: ""
},
respond: (json)=>{
context.res.set("Content-Type", "application/json");
context.res.send(json);
},
unauthorized: ()=>{
context.res.send(401, WRONG_TOKEN_ERROR);
}
});
const nextJs = (req, res)=>({
update: Promise.resolve(req.body),
header: req.headers[SECRET_HEADER_LOWERCASE],
end: ()=>res.end(),
respond: (json)=>res.status(200).json(json),
unauthorized: ()=>res.status(401).send(WRONG_TOKEN_ERROR)
});
const sveltekit = ({ request })=>{
let resolveResponse;
return {
update: Promise.resolve(request.json()),
header: request.headers.get(SECRET_HEADER) || undefined,
end: ()=>{
if (resolveResponse) resolveResponse(ok());
},
respond: (json)=>{
if (resolveResponse) resolveResponse(okJson(json));
},
unauthorized: ()=>{
if (resolveResponse) resolveResponse(unauthorized());
},
handlerReturn: new Promise((resolve)=>{
resolveResponse = resolve;
})
};
};
const cloudflare = (event)=>{
let resolveResponse;
event.respondWith(new Promise((resolve)=>{
resolveResponse = resolve;
}));
return {
update: event.request.json(),
header: event.request.headers.get(SECRET_HEADER) || undefined,
end: ()=>{
resolveResponse(ok());
},
respond: (json)=>{
resolveResponse(okJson(json));
},
unauthorized: ()=>{
resolveResponse(unauthorized());
}
};
};
const cloudflareModule = (request)=>{
let resolveResponse;
return {
update: request.json(),
header: request.headers.get(SECRET_HEADER) || undefined,
end: ()=>{
resolveResponse(ok());
},
respond: (json)=>{
resolveResponse(okJson(json));
},
unauthorized: ()=>{
resolveResponse(unauthorized());
},
handlerReturn: new Promise((resolve)=>{
resolveResponse = resolve;
})
};
};
const hono = (ctx)=>{
let resolveResponse;
return {
update: ctx.req.json(),
header: ctx.req.headers.get(SECRET_HEADER) || undefined,
end: ()=>{
resolveResponse(ctx.body());
},
respond: (json)=>{
ctx.header('Content-Type", "application/json');
resolveResponse(ctx.body(json));
},
unauthorized: ()=>{
ctx.status(401);
ctx.statusText(WRONG_TOKEN_ERROR);
resolveResponse(ctx.body());
},
handlerReturn: new Promise((resolve)=>{
resolveResponse = resolve;
})
};
};
const worktop = (req, res)=>({
update: Promise.resolve(req.body.json()),
header: req.headers.get(SECRET_HEADER),
end: ()=>res.end(),
respond: (json)=>res.send(200, json),
unauthorized: ()=>res.send(401, WRONG_TOKEN_ERROR)
});
const adapters = {
express,
koa,
fastify,
serveHttp,
"std/http": stdHttp,
oak,
http,
https: http,
"aws-lambda": awsLambda,
"aws-lambda-async": awsLambdaAsync,
azure,
"next-js": nextJs,
sveltekit,
cloudflare,
"cloudflare-mod": cloudflareModule,
hono,
worktop
};
const debugErr1 = browser$1("grammy:error");
const callbackAdapter = (update, callback, header, unauthorized = ()=>callback('"unauthorized"'))=>({
update: Promise.resolve(update),
respond: callback,
header,
unauthorized
});
const adapters1 = {
...adapters,
callback: callbackAdapter
};
function webhookCallback(bot, adapter = defaultAdapter, onTimeout = "throw", timeoutMilliseconds = 10_000, secretToken) {
const { onTimeout: timeout = "throw" , timeoutMilliseconds: ms = 10_000 , secretToken: token } = typeof onTimeout === "object" ? onTimeout : {
onTimeout,
timeoutMilliseconds,
secretToken
};
let initialized = false;
const server = typeof adapter === "string" ? adapters1[adapter] : adapter;
return async (...args)=>{
const { update , respond , unauthorized , end , handlerReturn , header } = server(...args);
if (!initialized) {
await bot.init();
initialized = true;
}
if (header !== token) {
await unauthorized();
console.log(handlerReturn);
return handlerReturn;
}
let usedWebhookReply = false;
const webhookReplyEnvelope = {
async send (json) {
usedWebhookReply = true;
await respond(json);
}
};
await timeoutIfNecessary(bot.handleUpdate(await update, webhookReplyEnvelope), typeof timeout === "function" ? ()=>timeout(...args) : timeout, ms);
if (!usedWebhookReply) end?.();
return handlerReturn;
};
}
function timeoutIfNecessary(task, onTimeout, timeout) {
if (timeout === Infinity) return task;
return new Promise((resolve, reject)=>{
const handle = setTimeout(()=>{
if (onTimeout === "throw") {
reject(new Error(`Request timed out after ${timeout} ms`));
} else {
if (typeof onTimeout === "function") onTimeout();
resolve();
}
const now = Date.now();
task.finally(()=>{
const diff = Date.now() - now;
debugErr1(`Request completed ${diff} ms after timeout!`);
});
}, timeout);
task.then(resolve).catch(reject).finally(()=>clearTimeout(handle));
});
}
export { webhookCallback as webhookCallback };
export { Bot as Bot, BotError as BotError };
export { InputFile as InputFile };
export { Context as Context };
export { Composer as Composer };
export { matchFilter as matchFilter };
export { Api as Api };
export { GrammyError as GrammyError, HttpError as HttpError };