diff --git a/packages/client/src/types/files/utils.ts b/packages/client/src/types/files/utils.ts index 1f9029a4..734cb26c 100644 --- a/packages/client/src/types/files/utils.ts +++ b/packages/client/src/types/files/utils.ts @@ -3,6 +3,7 @@ import type { Readable } from 'stream' import type { ReadStream } from 'fs' import { UploadedFile } from './uploaded-file' import { FileLocation } from './file-location' +import { tdFileId } from '@mtcute/file-id' /** * Describes types that can be used in {@link TelegramClient.uploadFile} @@ -26,11 +27,27 @@ export type UploadFileLike = * Describes types that can be used as an input * to any methods that send media (like {@link TelegramClient.sendPhoto}) * - * In addition to all the types available in {@link UploadFileLike}, you - * can also pass {@link UploadedFile} returned from {@link TelegramClient.uploadFile}, - * raw `tl.TypeInputFile` and URLs to remote files + * Can be one of: + * - `Buffer`, which will be interpreted as raw file contents + * - `File` (from the Web API) + * - `ReadStream` (for NodeJS, from the `fs` module) + * - `ReadableStream` (from the Web API, base readable stream) + * - `Readable` (for NodeJS, base readable stream) + * - {@link UploadedFile} returned from {@link TelegramClient.uploadFile} + * - `tl.TypeInputFile` and `tl.TypeInputMedia` TL objects + * - `string` with a URL to remote files (e.g. `https://example.com/image.jpg`) + * - `string` with TDLib and Bot API compatible File ID. + * - `td.RawFullRemoteFileLocation` (parsed File ID) + * + * > **Note**: Unlike {@link UploadFileLike}, you can't pass + * > a file path directly. Use `fs.createReadStream('/path/to/file.png')` */ -export type InputFileLike = UploadFileLike | UploadedFile | tl.TypeInputFile | tl.TypeInputMedia +export type InputFileLike = + | UploadFileLike + | UploadedFile + | tl.TypeInputFile + | tl.TypeInputMedia + | tdFileId.RawFullRemoteFileLocation export interface FileDownloadParameters { /** diff --git a/packages/client/src/types/media/audio.ts b/packages/client/src/types/media/audio.ts index 4b6b2c95..7b13cdaf 100644 --- a/packages/client/src/types/media/audio.ts +++ b/packages/client/src/types/media/audio.ts @@ -2,6 +2,7 @@ import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { RawDocument } from './document' import { makeInspectable } from '../utils' +import { tdFileId } from '@mtcute/file-id' /** * An audio file @@ -10,6 +11,10 @@ export class Audio extends RawDocument { readonly doc: tl.RawDocument readonly attr: tl.RawDocumentAttributeAudio + protected _fileIdType(): tdFileId.FileType { + return tdFileId.FileType.Audio + } + constructor( client: TelegramClient, doc: tl.RawDocument, diff --git a/packages/client/src/types/media/document.ts b/packages/client/src/types/media/document.ts index 90610106..a3f5b60e 100644 --- a/packages/client/src/types/media/document.ts +++ b/packages/client/src/types/media/document.ts @@ -4,6 +4,7 @@ import { Thumbnail } from './thumbnail' import { TelegramClient } from '../../client' import { makeInspectable } from '../utils' import { InputMediaLike } from './input-media' +import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id' /** * A file that is represented as a document in MTProto. @@ -124,6 +125,47 @@ export class RawDocument extends FileLocation { // other fields are not needed since it's a forwarded media } } + + protected _fileIdType(): td.FileType { + return td.FileType.Document + } + + protected _fileId?: string + /** + * Get TDLib and Bot API compatible File ID + * representing this document. + */ + get fileId(): string { + if (!this._fileId) { + this._fileId = toFileId({ + type: this._fileIdType(), + dcId: this.doc.dcId, + fileReference: this.doc.fileReference, + location: { + _: 'common', + id: this.doc.id, + accessHash: this.doc.accessHash, + }, + }) + } + + return this._fileId + } + + protected _uniqueFileId?: string + /** + * Get a unique File ID representing this document. + */ + get uniqueFileId(): string { + if (!this._uniqueFileId) { + this._uniqueFileId = toUniqueFileId(td.FileType.Document, { + _: 'common', + id: this.doc.id, + }) + } + + return this._uniqueFileId + } } /** diff --git a/packages/client/src/types/media/input-media.ts b/packages/client/src/types/media/input-media.ts index 64cea9f3..fcd2dd28 100644 --- a/packages/client/src/types/media/input-media.ts +++ b/packages/client/src/types/media/input-media.ts @@ -260,7 +260,8 @@ export namespace InputMedia { * Create a document to be sent, which subtype * is inferred automatically by file contents. * - * **Does not** infer photos, they will be sent as simple files. + * Only infers photos from the File ID, otherwise + * photos will be sent as documents. */ export function auto( file: InputFileLike, diff --git a/packages/client/src/types/media/sticker.ts b/packages/client/src/types/media/sticker.ts index 2a5ca39b..df65f663 100644 --- a/packages/client/src/types/media/sticker.ts +++ b/packages/client/src/types/media/sticker.ts @@ -3,6 +3,7 @@ import { TelegramClient } from '../../client' import { tl } from '@mtcute/tl' import { makeInspectable } from '../utils' import { StickerSet } from '../misc' +import { tdFileId } from '@mtcute/file-id' /** * A sticker @@ -11,6 +12,10 @@ export class Sticker extends RawDocument { readonly attr: tl.RawDocumentAttributeSticker readonly attrSize?: tl.RawDocumentAttributeImageSize + protected _fileIdType(): tdFileId.FileType { + return tdFileId.FileType.Sticker + } + constructor( client: TelegramClient, doc: tl.RawDocument, diff --git a/packages/client/src/types/media/video.ts b/packages/client/src/types/media/video.ts index e92ab02f..e1c4bcad 100644 --- a/packages/client/src/types/media/video.ts +++ b/packages/client/src/types/media/video.ts @@ -2,6 +2,7 @@ import { RawDocument } from './document' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { makeInspectable } from '../utils' +import { tdFileId } from '@mtcute/file-id' /** * A video, round video message or GIF animation. @@ -13,6 +14,14 @@ export class Video extends RawDocument { | tl.RawDocumentAttributeVideo | tl.RawDocumentAttributeImageSize + protected _fileIdType(): tdFileId.FileType { + return this.isRound + ? tdFileId.FileType.VideoNote + : this.isAnimation + ? tdFileId.FileType.Animation + : tdFileId.FileType.Video + } + constructor( client: TelegramClient, doc: tl.RawDocument, diff --git a/packages/client/src/types/media/voice.ts b/packages/client/src/types/media/voice.ts index 93374a8f..553e6b04 100644 --- a/packages/client/src/types/media/voice.ts +++ b/packages/client/src/types/media/voice.ts @@ -2,6 +2,7 @@ import { RawDocument } from './document' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { makeInspectable } from '../utils' +import { tdFileId } from '@mtcute/file-id' /** * An voice note. @@ -10,6 +11,10 @@ export class Voice extends RawDocument { readonly doc: tl.RawDocument readonly attr: tl.RawDocumentAttributeAudio + protected _fileIdType(): tdFileId.FileType { + return tdFileId.FileType.VoiceNote + } + constructor( client: TelegramClient, doc: tl.RawDocument,