import { type InputFileProxy } from "@grammyjs/types";import { Agent as HttpAgent } from "http";import { Agent as HttpsAgent } from "https";import fetch from "node-fetch";import { basename } from "path";import { Readable } from "stream";import { type ReadStream } from "fs";import { URL } from "url";import { createReadStream } from "fs";
export * from "@grammyjs/types";
import { debug as d } from "debug";export { d as debug };const debug = d("grammy:warn");
export const itrToStream = (itr: AsyncIterable<Uint8Array>) => Readable.from(itr, { objectMode: false });
export function baseFetchConfig(apiRoot: string) { if (apiRoot.startsWith("https:")) { return { compress: true, agent: new HttpsAgent({ keepAlive: true }) }; } else if (apiRoot.startsWith("http:")) { return { agent: new HttpAgent({ keepAlive: true }) }; } else return {};}
interface URLLike { url: string;}
export const toRaw = Symbol("InputFile data");
export class InputFile { private consumed = false; private readonly fileData: ConstructorParameters<typeof InputFile>[0]; public readonly filename?: string; constructor( file: | string | URL | URLLike | Uint8Array | ReadStream | Iterable<Uint8Array> | AsyncIterable<Uint8Array>, filename?: string, ) { this.fileData = file; filename ??= this.guessFilename(file); this.filename = filename; if ( typeof file === "string" && (file.startsWith("http:") || file.startsWith("https:")) ) { debug( `InputFile received the local file path '${file}' that looks like a URL. Is this a mistake?`, ); } } private guessFilename( file: ConstructorParameters<typeof InputFile>[0], ): string | undefined { if (typeof file === "string") return basename(file); if (typeof file !== "object") return undefined; if ("url" in file) return basename(file.url); if (!(file instanceof URL)) return undefined; return basename(file.pathname) || basename(file.hostname); } [toRaw](): Uint8Array | Iterable<Uint8Array> | AsyncIterable<Uint8Array> { if (this.consumed) { throw new Error("Cannot reuse InputFile data source!"); } const data = this.fileData; if (typeof data === "string") return createReadStream(data); if (data instanceof URL) { return data.protocol === "file" ? createReadStream(data.pathname) : fetchFile(data); } if ("url" in data) return fetchFile(data.url); if (!(data instanceof Uint8Array)) this.consumed = true; return data; }}
async function* fetchFile(url: string | URL): AsyncIterable<Uint8Array> { const { body } = await fetch(url); for await (const chunk of body) { if (typeof chunk === "string") { throw new Error( `Could not transfer file, received string data instead of bytes from '${url}'`, ); } yield chunk; }}
type GrammyTypes = InputFileProxy<InputFile>;
export type Telegram = GrammyTypes["Telegram"];
export type Opts<M extends keyof GrammyTypes["Telegram"]> = GrammyTypes["Opts"][M];
export type InputMedia = GrammyTypes["InputMedia"];export type InputMediaPhoto = GrammyTypes["InputMediaPhoto"];export type InputMediaVideo = GrammyTypes["InputMediaVideo"];export type InputMediaAnimation = GrammyTypes["InputMediaAnimation"];export type InputMediaAudio = GrammyTypes["InputMediaAudio"];export type InputMediaDocument = GrammyTypes["InputMediaDocument"];