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 };
