initial commit

This commit is contained in:
2023-08-13 16:48:04 +03:00
commit 73b7dbb0a6
1267 changed files with 1017047 additions and 0 deletions

1377
node_modules/grammy/out/core/api.d.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

1596
node_modules/grammy/out/core/api.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

163
node_modules/grammy/out/core/client.d.ts generated vendored Normal file
View File

@ -0,0 +1,163 @@
/// <reference types="node-fetch" />
import { type ApiMethods as Telegram, type ApiResponse, type Opts } from "../types.js";
export type Methods<R extends RawApi> = string & keyof R;
/**
* Represents the raw Telegram Bot API with all methods specified 1:1 as
* documented on the website (https://core.telegram.org/bots/api).
*
* Every method takes an optional `AbortSignal` object that allows to cancel the
* API call if desired.
*/
export type RawApi = {
[M in keyof Telegram]: Parameters<Telegram[M]>[0] extends undefined ? (signal?: AbortSignal) => Promise<ReturnType<Telegram[M]>> : (args: Opts<M>, signal?: AbortSignal) => Promise<ReturnType<Telegram[M]>>;
};
export type Payload<M extends Methods<R>, R extends RawApi> = M extends unknown ? R[M] extends (signal?: AbortSignal) => unknown ? {} : R[M] extends (args: any, signal?: AbortSignal) => unknown ? Parameters<R[M]>[0] : never : never;
/**
* Small utility interface that abstracts from webhook reply calls of different
* web frameworks.
*/
export interface WebhookReplyEnvelope {
send?: (payload: string) => void | Promise<void>;
}
/**
* Type of a function that can perform an API call. Used for Transformers.
*/
export type ApiCallFn<R extends RawApi = RawApi> = <M extends Methods<R>>(method: M, payload: Payload<M, R>, signal?: AbortSignal) => Promise<ApiResponse<ApiCallResult<M, R>>>;
type ApiCallResult<M extends Methods<R>, R extends RawApi> = R[M] extends (...args: unknown[]) => unknown ? Awaited<ReturnType<R[M]>> : never;
/**
* API call transformers are functions that can access and modify the method and
* payload of an API call on the fly. This can be useful if you want to
* implement rate limiting or other things against the Telegram Bot API.
*
* Confer the grammY
* [documentation](https://grammy.dev/advanced/transformers.html) to read more
* about how to use transformers.
*/
export type Transformer<R extends RawApi = RawApi> = <M extends Methods<R>>(prev: ApiCallFn<R>, method: M, payload: Payload<M, R>, signal?: AbortSignal) => Promise<ApiResponse<ApiCallResult<M, R>>>;
export type TransformerConsumer<R extends RawApi = RawApi> = TransformableApi<R>["use"];
/**
* A transformable API enhances the `RawApi` type by transformers.
*/
export interface TransformableApi<R extends RawApi = RawApi> {
/**
* Access to the raw API that the transformers will be installed on.
*/
raw: R;
/**
* Can be used to register any number of transformers on the API.
*/
use: (...transformers: Transformer<R>[]) => this;
/**
* Returns a readonly list or the currently installed transformers. The list
* is sorted by time of installation where index 0 represents the
* transformer that was installed first.
*/
installedTransformers: Transformer<R>[];
}
/**
* Options to pass to the API client that eventually connects to the Telegram
* Bot API server and makes the HTTP requests.
*/
export interface ApiClientOptions {
/**
* Root URL of the Telegram Bot API server. Default:
* https://api.telegram.org
*/
apiRoot?: string;
/**
* URL builder function for API calls. Can be used to modify which API
* server should be called.
*
* @param root The URL that was passed in `apiRoot`, or its default value
* @param token The bot's token that was passed when creating the bot
* @param method The API method to be called, e.g. `getMe`
* @returns The URL that will be fetched during the API call
*/
buildUrl?: (root: string, token: string, method: string) => string | URL;
/**
* Maximum number of seconds that a request to the Bot API server may take.
* If a request has not completed before this time has elapsed, grammY
* aborts the request and errors. Without such a timeout, networking issues
* may cause your bot to leave open a connection indefinitely, which may
* effectively make your bot freeze.
*
* You probably do not have to care about this option. In rare cases, you
* may want to adjust it if you are transferring large files via slow
* connections to your own Bot API server.
*
* The default number of seconds is `500`, which corresponds to 8 minutes
* and 20 seconds. Note that this is also the value that is hard-coded in
* the official Bot API server, so you cannot perform any successful
* requests that exceed this time frame (even if you would allow it in
* grammY). Setting this option to higher than the default only makes sense
* with a custom Bot API server.
*/
timeoutSeconds?: number;
/**
* If the bot is running on webhooks, as soon as the bot receives an update
* from Telegram, it is possible to make up to one API call in the response
* to the webhook request. As a benefit, this saves your bot from making up
* to one HTTP request per update. However, there are a number of drawbacks
* to using this:
* 1) You will not be able to handle potential errors of the respective API
* call. This includes rate limiting errors, so sent messages can be
* swallowed by the Bot API server and there is no way to detect if a
* message was actually sent or not.
* 2) More importantly, you also won't have access to the response object,
* so e.g. calling `sendMessage` will not give you access to the message
* you sent.
* 3) Furthermore, it is not possible to cancel the request. The
* `AbortSignal` will be disregarded.
* 4) Note also that the types in grammY do not reflect the consequences of
* a performed webhook callback! For instance, they indicate that you
* always receive a response object, so it is your own responsibility to
* make sure you're not screwing up while using this minor performance
* optimization.
*
* With this warning out of the way, here is what you can do with the
* `canUseWebhookReply` option: it can be used to pass a function that
* determines whether to use webhook reply for the given method. It will
* only be invoked if the payload can be sent as JSON. It will not be
* invoked again for a given update after it returned `true`, indicating
* that the API call should be performed as a webhook send. In other words,
* subsequent API calls (during the same update) will always perform their
* own HTTP requests.
*
* @param method The method to call
*/
canUseWebhookReply?: (method: string) => boolean;
/**
* Base configuration for `fetch` calls. Specify any additional parameters
* to use when fetching a method of the Telegram Bot API. Default: `{
* compress: true }` (Node), `{}` (Deno)
*/
baseFetchConfig?: Omit<NonNullable<Parameters<typeof fetch>[1]>, "method" | "headers" | "body">;
/**
* When the network connection is unreliable and some API requests fail
* because of that, grammY will throw errors that tell you exactly which
* requests failed. However, the error messages do not disclose the fetched
* URL as it contains your bot's token. Logging it may lead to token leaks.
*
* If you are sure that no logs are ever posted in Telegram chats, GitHub
* issues, or otherwise shared, you can set this option to `true` in order
* to obtain more detailed logs that may help you debug your bot. The
* default value is `false`, meaning that the bot token is not logged.
*/
sensitiveLogs?: boolean;
}
/**
* Creates a new transformable API, i.e. an object that lets you perform raw API
* calls to the Telegram Bot API server but pass the calls through a stack of
* transformers before. This will create a new API client instance under the
* hood that will be used to connect to the Telegram servers. You therefore need
* to pass the bot token. In addition, you may pass API client options as well
* as a webhook reply envelope that allows the client to perform up to one HTTP
* request in response to a webhook call if this is desired.
*
* @param token The bot's token
* @param options A number of options to pass to the created API client
* @param webhookReplyEnvelope The webhook reply envelope that will be used
*/
export declare function createRawApi<R extends RawApi>(token: string, options?: ApiClientOptions, webhookReplyEnvelope?: WebhookReplyEnvelope): TransformableApi<R>;
import { AbortSignal, fetch } from "./../shim.node.js";
export {};

180
node_modules/grammy/out/core/client.js generated vendored Normal file
View File

@ -0,0 +1,180 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRawApi = void 0;
const platform_node_js_1 = require("../platform.node.js");
const error_js_1 = require("./error.js");
const payload_js_1 = require("./payload.js");
const debug = (0, platform_node_js_1.debug)("grammy:core");
// Transformer base functions
function concatTransformer(prev, trans) {
return (method, payload, signal) => trans(prev, method, payload, signal);
}
class ApiClient {
constructor(token, options = {}, webhookReplyEnvelope = {}) {
var _a, _b, _c, _d, _e;
this.token = token;
this.webhookReplyEnvelope = webhookReplyEnvelope;
this.hasUsedWebhookReply = false;
this.installedTransformers = [];
this.call = async (method, p, signal) => {
const payload = p !== null && p !== void 0 ? p : {};
debug(`Calling ${method}`);
// General config
const opts = this.options;
const formDataRequired = (0, payload_js_1.requiresFormDataUpload)(payload);
// Short-circuit on webhook reply
if (this.webhookReplyEnvelope.send !== undefined &&
!this.hasUsedWebhookReply &&
!formDataRequired &&
opts.canUseWebhookReply(method)) {
this.hasUsedWebhookReply = true;
const config = (0, payload_js_1.createJsonPayload)({ ...payload, method });
await this.webhookReplyEnvelope.send(config.body);
return { ok: true, result: true };
}
// Handle timeouts and errors in the underlying form-data stream
const controller = createAbortControllerFromSignal(signal);
const timeout = createTimeout(controller, opts.timeoutSeconds, method);
const streamErr = createStreamError(controller);
// Build request URL and config
const url = opts.buildUrl(opts.apiRoot, this.token, method);
const config = formDataRequired
? (0, payload_js_1.createFormDataPayload)(payload, (err) => streamErr.catch(err))
: (0, payload_js_1.createJsonPayload)(payload);
const sig = controller.signal;
const options = { ...opts.baseFetchConfig, signal: sig, ...config };
// Perform fetch call, and handle networking errors
const successPromise = (0, shim_node_js_1.fetch)(url instanceof URL ? url.href : url, options).catch((0, error_js_1.toHttpError)(method, opts.sensitiveLogs));
// Those are the three possible outcomes of the fetch call:
const operations = [successPromise, streamErr.promise, timeout.promise];
// Wait for result
try {
const res = await Promise.race(operations);
return await res.json();
}
finally {
if (timeout.handle !== undefined)
clearTimeout(timeout.handle);
}
};
const apiRoot = (_a = options.apiRoot) !== null && _a !== void 0 ? _a : "https://api.telegram.org";
this.options = {
apiRoot,
buildUrl: (_b = options.buildUrl) !== null && _b !== void 0 ? _b : ((root, token, method) => `${root}/bot${token}/${method}`),
timeoutSeconds: (_c = options.timeoutSeconds) !== null && _c !== void 0 ? _c : 500,
baseFetchConfig: {
...(0, platform_node_js_1.baseFetchConfig)(apiRoot),
...options.baseFetchConfig,
},
canUseWebhookReply: (_d = options.canUseWebhookReply) !== null && _d !== void 0 ? _d : (() => false),
sensitiveLogs: (_e = options.sensitiveLogs) !== null && _e !== void 0 ? _e : 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}')`);
}
}
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 (0, error_js_1.toGrammyError)(data, method, payload);
}
}
/**
* Creates a new transformable API, i.e. an object that lets you perform raw API
* calls to the Telegram Bot API server but pass the calls through a stack of
* transformers before. This will create a new API client instance under the
* hood that will be used to connect to the Telegram servers. You therefore need
* to pass the bot token. In addition, you may pass API client options as well
* as a webhook reply envelope that allows the client to perform up to one HTTP
* request in response to a webhook call if this is desired.
*
* @param token The bot's token
* @param options A number of options to pass to the created API client
* @param webhookReplyEnvelope The webhook reply envelope that will be used
*/
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;
}
exports.createRawApi = createRawApi;
const proxyMethods = {
set() {
return false;
},
defineProperty() {
return false;
},
deleteProperty() {
return false;
},
ownKeys() {
return [];
},
};
/** Creates a timeout error which aborts a given controller */
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 };
}
/** Creates a stream error which abort a given controller */
function createStreamError(abortController) {
let onError = (err) => {
// Re-throw by default, but will be overwritten immediately
throw err;
};
const promise = new Promise((_, reject) => {
onError = (err) => {
reject(err);
abortController.abort();
};
});
return { promise, catch: onError };
}
function createAbortControllerFromSignal(signal) {
const abortController = new shim_node_js_1.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 };
}
const shim_node_js_1 = require("./../shim.node.js");

53
node_modules/grammy/out/core/error.d.ts generated vendored Normal file
View File

@ -0,0 +1,53 @@
import { type ApiError, type ResponseParameters } from "../types.js";
/**
* This class represents errors that are thrown by grammY because the Telegram
* Bot API responded with an error.
*
* Instances of this class hold the information that the Telegram backend
* returned.
*
* If this error is thrown, grammY could successfully communicate with the
* Telegram Bot API servers, however, an error code was returned for the
* respective method call.
*/
export declare class GrammyError extends Error implements ApiError {
/** The called method name which caused this error to be thrown. */
readonly method: string;
/** The payload that was passed when calling the method. */
readonly payload: Record<string, unknown>;
/** Flag that this request was unsuccessful. Always `false`. */
readonly ok: false;
/** An integer holding Telegram's error code. Subject to change. */
readonly error_code: number;
/** A human-readable description of the error. */
readonly description: string;
/** Further parameters that may help to automatically handle the error. */
readonly parameters: ResponseParameters;
constructor(message: string, err: ApiError,
/** The called method name which caused this error to be thrown. */
method: string,
/** The payload that was passed when calling the method. */
payload: Record<string, unknown>);
}
export declare function toGrammyError(err: ApiError, method: string, payload: Record<string, unknown>): GrammyError;
/**
* This class represents errors that are thrown by grammY because an HTTP call
* to the Telegram Bot API failed.
*
* Instances of this class hold the error object that was created because the
* fetch call failed. It can be inspected to determine why exactly the network
* request failed.
*
* If an [API transformer
* function](https://grammy.dev/advanced/transformers.html) throws an error,
* grammY will regard this as if the network request failed. The contained error
* will then be the error that was thrown by the transformer function.
*/
export declare class HttpError extends Error {
/** The thrown error object. */
readonly error: unknown;
constructor(message: string,
/** The thrown error object. */
error: unknown);
}
export declare function toHttpError(method: string, sensitiveLogs: boolean): (err: unknown) => never;

77
node_modules/grammy/out/core/error.js generated vendored Normal file
View File

@ -0,0 +1,77 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toHttpError = exports.HttpError = exports.toGrammyError = exports.GrammyError = void 0;
/**
* This class represents errors that are thrown by grammY because the Telegram
* Bot API responded with an error.
*
* Instances of this class hold the information that the Telegram backend
* returned.
*
* If this error is thrown, grammY could successfully communicate with the
* Telegram Bot API servers, however, an error code was returned for the
* respective method call.
*/
class GrammyError extends Error {
constructor(message, err,
/** The called method name which caused this error to be thrown. */
method,
/** The payload that was passed when calling the method. */
payload) {
var _a;
super(`${message} (${err.error_code}: ${err.description})`);
this.method = method;
this.payload = payload;
/** Flag that this request was unsuccessful. Always `false`. */
this.ok = false;
this.name = "GrammyError";
this.error_code = err.error_code;
this.description = err.description;
this.parameters = (_a = err.parameters) !== null && _a !== void 0 ? _a : {};
}
}
exports.GrammyError = GrammyError;
function toGrammyError(err, method, payload) {
return new GrammyError(`Call to '${method}' failed!`, err, method, payload);
}
exports.toGrammyError = toGrammyError;
/**
* This class represents errors that are thrown by grammY because an HTTP call
* to the Telegram Bot API failed.
*
* Instances of this class hold the error object that was created because the
* fetch call failed. It can be inspected to determine why exactly the network
* request failed.
*
* If an [API transformer
* function](https://grammy.dev/advanced/transformers.html) throws an error,
* grammY will regard this as if the network request failed. The contained error
* will then be the error that was thrown by the transformer function.
*/
class HttpError extends Error {
constructor(message,
/** The thrown error object. */
error) {
super(message);
this.error = error;
this.name = "HttpError";
}
}
exports.HttpError = HttpError;
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);
};
}
exports.toHttpError = toHttpError;

40
node_modules/grammy/out/core/payload.d.ts generated vendored Normal file
View File

@ -0,0 +1,40 @@
/// <reference types="node" />
/**
* Determines for a given payload if it may be sent as JSON, or if it has to be
* uploaded via multipart/form-data. Returns `true` in the latter case and
* `false` in the former.
*
* @param payload The payload to analyze
*/
export declare function requiresFormDataUpload(payload: unknown): boolean;
/**
* Turns a payload into an options object that can be passed to a `fetch` call
* by setting the necessary headers and method. May only be called for payloads
* `P` that let `requiresFormDataUpload(P)` return `false`.
*
* @param payload The payload to wrap
*/
export declare function createJsonPayload(payload: Record<string, unknown>): {
method: string;
headers: {
"content-type": string;
connection: string;
};
body: string;
};
/**
* Turns a payload into an options object that can be passed to a `fetch` call
* by setting the necessary headers and method. Note that this method creates a
* multipart/form-data stream under the hood. If possible, a JSON payload should
* be created instead for performance reasons.
*
* @param payload The payload to wrap
*/
export declare function createFormDataPayload(payload: Record<string, unknown>, onError: (err: unknown) => void): {
method: string;
headers: {
"content-type": string;
connection: string;
};
body: import("stream").Readable;
};

200
node_modules/grammy/out/core/payload.js generated vendored Normal file
View File

@ -0,0 +1,200 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFormDataPayload = exports.createJsonPayload = exports.requiresFormDataUpload = void 0;
const platform_node_js_1 = require("../platform.node.js");
const types_js_1 = require("../types.js");
// === Payload types (JSON vs. form data)
/**
* Determines for a given payload if it may be sent as JSON, or if it has to be
* uploaded via multipart/form-data. Returns `true` in the latter case and
* `false` in the former.
*
* @param payload The payload to analyze
*/
function requiresFormDataUpload(payload) {
return payload instanceof types_js_1.InputFile || (typeof payload === "object" &&
payload !== null &&
Object.values(payload).some((v) => Array.isArray(v)
? v.some(requiresFormDataUpload)
: v instanceof types_js_1.InputFile || requiresFormDataUpload(v)));
}
exports.requiresFormDataUpload = requiresFormDataUpload;
/**
* Calls `JSON.stringify` but removes `null` values from objects before
* serialization
*
* @param value value
* @returns stringified value
*/
function str(value) {
return JSON.stringify(value, (_, v) => v !== null && v !== void 0 ? v : undefined);
}
/**
* Turns a payload into an options object that can be passed to a `fetch` call
* by setting the necessary headers and method. May only be called for payloads
* `P` that let `requiresFormDataUpload(P)` return `false`.
*
* @param payload The payload to wrap
*/
function createJsonPayload(payload) {
return {
method: "POST",
headers: {
"content-type": "application/json",
connection: "keep-alive",
},
body: str(payload),
};
}
exports.createJsonPayload = createJsonPayload;
async function* protectItr(itr, onError) {
try {
yield* itr;
}
catch (err) {
onError(err);
}
}
/**
* Turns a payload into an options object that can be passed to a `fetch` call
* by setting the necessary headers and method. Note that this method creates a
* multipart/form-data stream under the hood. If possible, a JSON payload should
* be created instead for performance reasons.
*
* @param payload The payload to wrap
*/
function createFormDataPayload(payload, onError) {
const boundary = createBoundary();
const itr = payloadToMultipartItr(payload, boundary);
const safeItr = protectItr(itr, onError);
const stream = (0, platform_node_js_1.itrToStream)(safeItr);
return {
method: "POST",
headers: {
"content-type": `multipart/form-data; boundary=${boundary}`,
connection: "keep-alive",
},
body: stream,
};
}
exports.createFormDataPayload = createFormDataPayload;
// === Form data creation
function createBoundary() {
// Taken from Deno std lib
return "----------" + randomId(32);
}
function randomId(length = 16) {
return Array.from(Array(length))
.map(() => Math.random().toString(36)[2] || 0)
.join("");
}
const enc = new TextEncoder();
/**
* Takes a payload object and produces a valid multipart/form-data stream. The
* stream is an iterator of `Uint8Array` objects. You also need to specify the
* boundary string that was used in the Content-Type header of the HTTP request.
*
* @param payload a payload object
* @param boundary the boundary string to use between the parts
*/
async function* payloadToMultipartItr(payload, boundary) {
const files = extractFiles(payload);
// Start multipart/form-data protocol
yield enc.encode(`--${boundary}\r\n`);
// Send all payload fields
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;
}
// Send all files
for (const { id, origin, file } of files) {
if (!first)
yield separator;
yield* filePart(id, origin, file);
first = false;
}
// End multipart/form-data protocol
yield enc.encode(`\r\n--${boundary}--\r\n`);
}
/**
* Replaces all instances of `InputFile` in a given payload by attach://
* strings. This alters the passed object. After calling this method, the
* payload object can be stringified.
*
* Returns a list of `InputFile` instances along with the random identifiers
* that were used in the corresponding attach:// strings, as well as the origin
* keys of the original payload object.
*
* @param value a payload object, or a part of it
* @param key the origin key of the payload object, if a part of it is passed
* @returns the cleaned payload object
*/
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 types_js_1.InputFile) {
const id = randomId();
// Overwrite `InputFile` instance with attach:// string
Object.assign(value, { [k]: `attach://${id}` });
const origin = k === "media" &&
"type" in value && typeof value.type === "string"
? value.type // use `type` for `InputMedia*`
: k; // use property key otherwise
return { id, origin, file: v };
}
else
return extractFiles(v);
});
}
/** Turns a regular value into a `Uint8Array` */
function valuePart(key, value) {
return enc.encode(`content-disposition:form-data;name="${key}"\r\n\r\n${value}`);
}
/** Turns an InputFile into a generator of `Uint8Array`s */
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;
}
/** Returns the default file extension for an API property name */
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";
}
}