UNPKG

@tgsnake/fileid

Version:

core framework for tgsnake for generating file id

134 lines (131 loc) 4.57 kB
/** * tgsnake - Telegram MTProto framework for nodejs. * Copyright (C) 2022 butthx <https://github.com/butthx> * * THIS FILE IS PART OF TGSNAKE * * tgsnake is a free software : you can redistribute it and/or modify * it under the terms of the MIT License as published. */ import { FileType, ThumbnailSource, FileTypeUniqueId, base64_url_encode, rle_encode, Writer, Reader, PHOTO_TYPES, DOCUMENT_TYPES, Options, } from './index.ts'; import { Buffer } from 'node:buffer'; import type { Decode } from './decode.ts'; export class Encode { /** * Identifier for this file, which can be used to download or reuse the file */ fileId!: string; /** * Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file */ fileUniqueId!: string; constructor({ fileId, fileUniqueId, }: { /** * Identifier for this file, which can be used to download or reuse the file */ fileId: string; /** * Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file */ fileUniqueId: string; }) { this.fileId = fileId; this.fileUniqueId = fileUniqueId; } static encode(file: Options | Decode): Encode { return new Encode({ fileId: Encode.fileId(file), fileUniqueId: Encode.uniqueId(file), }); } static fileId(file: Options | Decode): string { let fileType = file.fileType; if (file.fileReference) { fileType |= FileType.FILE_REFERENCE_FLAG; } if (file.url) { fileType |= FileType.WEB_LOCATION_FLAG; } const writer = new Writer(); writer.writeInt(Number(fileType)).writeInt(Number(file.dcId)); if (file.url) { writer.writeString(file.url!); } if (file.fileReference) { writer.writeBuffer(file.fileReference!); } writer.writeBigInt(BigInt(String(file.id))).writeBigInt(BigInt(String(file.accessHash))); if (PHOTO_TYPES.includes(file.fileType)) { writer.writeBigInt(BigInt(String(file.volumeId))); if (file.version >= 4) writer.writeInt(Number(file.thumbnailSource)); switch (file.thumbnailSource) { case ThumbnailSource.LEGACY: writer.writeBigInt(BigInt(String(file.secret))).writeInt(Number(file.localId)); case ThumbnailSource.THUMBNAIL: writer .writeInt(Number(file.thumbnailFileType)) .writeInt(String(file.thumbnailSize).charCodeAt(0)) .writeInt(Number(file.localId)); break; case ThumbnailSource.CHAT_PHOTO_BIG: case ThumbnailSource.CHAT_PHOTO_SMALL: writer .writeBigInt(BigInt(String(file.chatId))) .writeBigInt(BigInt(String(file.chatAccessHash))) .writeInt(Number(file.localId)); break; case ThumbnailSource.STICKER_SET_THUMBNAIL: writer .writeBigInt(BigInt(String(file.stickerSetId))) .writeBigInt(BigInt(String(file.stickerSetAccessHash))) .writeInt(Number(file.localId)); break; default: throw new Error(`unknown encoder for thumbnailSource ${file.thumbnailSource}`); } } else if (DOCUMENT_TYPES.includes(fileType)) { writer.writeInt(file.version); writer.writeInt(file.subVersion); } return base64_url_encode( rle_encode(Buffer.concat([writer.results(), Buffer.from([file.subVersion, file.version])])) ); } static uniqueId(file: Options | Decode): string { let writer: Writer; switch (file.fileTypeUniqueId) { case FileTypeUniqueId.WEB: writer = new Writer(); writer.writeInt(Number(file.fileTypeUniqueId)).writeString(String(file.url)); break; case FileTypeUniqueId.PHOTO: writer = new Writer(); writer .writeInt(Number(file.fileTypeUniqueId)) .writeBigInt(BigInt(String(file.volumeId))) .writeInt(Number(file.localId)); break; case FileTypeUniqueId.DOCUMENT: writer = new Writer(); writer.writeInt(Number(file.fileTypeUniqueId)).writeBigInt(BigInt(String(file.id))); break; default: throw new Error(`unknown encoder for fileTypeUniqueId ${file.fileTypeUniqueId}`); } return base64_url_encode(rle_encode(writer.results())); } }