import { basename } from "https://deno.land/std@0.211.0/path/basename.ts";import { iterateReader } from "https://deno.land/std@0.211.0/streams/iterate_reader.ts";import { type ApiMethods as ApiMethodsF, type InputMedia as InputMediaF, type InputMediaAnimation as InputMediaAnimationF, type InputMediaAudio as InputMediaAudioF, type InputMediaDocument as InputMediaDocumentF, type InputMediaPhoto as InputMediaPhotoF, type InputMediaVideo as InputMediaVideoF, type InputSticker as InputStickerF, type Opts as OptsF,} from "https://deno.land/x/grammy_types@v3.5.2/mod.ts";import { debug as d, isDeno } from "./platform.deno.ts";
const debug = d("grammy:warn");
export * from "https://deno.land/x/grammy_types@v3.5.2/mod.ts";
type MaybeSupplier<T> = T | (() => T | Promise<T>);interface URLLike { url: string;}
export class InputFile { private consumed = false; private readonly fileData: ConstructorParameters<typeof InputFile>[0]; public readonly filename?: string; constructor( file: MaybeSupplier< | string | Blob | Deno.FsFile | Response | URL | URLLike | Uint8Array | ReadableStream<Uint8Array> | 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 ("url" in file) return basename(file.url); if (!(file instanceof URL)) return undefined; if (file.pathname !== "/") { const filename = basename(file.pathname); if (filename) return filename; } return basename(file.hostname); } async toRaw(): Promise< Uint8Array | Iterable<Uint8Array> | AsyncIterable<Uint8Array> > { if (this.consumed) { throw new Error("Cannot reuse InputFile data source!"); } const data = this.fileData; if (typeof data === "string") { if (!isDeno) { throw new Error( "Reading files by path requires a Deno environment", ); } const file = await Deno.open(data); return iterateReader(file); } if (data instanceof Blob) return data.stream(); if (isDenoFile(data)) return iterateReader(data); if (data instanceof Response) { if (data.body === null) throw new Error(`No response body!`); return data.body; } if (data instanceof URL) return fetchFile(data); if ("url" in data) return fetchFile(data.url); if (data instanceof Uint8Array) return data; if (typeof data === "function") { return new InputFile(await data()).toRaw(); } this.consumed = true; return data; }}
async function* fetchFile(url: string | URL): AsyncIterable<Uint8Array> { const { body } = await fetch(url); if (body === null) { throw new Error(`Download failed, no response body from '${url}'`); } yield* body;}function isDenoFile(data: unknown): data is Deno.FsFile { return isDeno && data instanceof Deno.FsFile;}
export type ApiMethods = ApiMethodsF<InputFile>;
export type Opts<M extends keyof ApiMethods> = OptsF<InputFile>[M];
export type InputSticker = InputStickerF<InputFile>;
export type InputMedia = InputMediaF<InputFile>;export type InputMediaPhoto = InputMediaPhotoF<InputFile>;export type InputMediaVideo = InputMediaVideoF<InputFile>;export type InputMediaAnimation = InputMediaAnimationF<InputFile>;export type InputMediaAudio = InputMediaAudioF<InputFile>;export type InputMediaDocument = InputMediaDocumentF<InputFile>;