UNPKG

@gramio/files

Version:

Set of utils to work with files uploading to Telegram Bot API

338 lines (335 loc) 10.7 kB
let isWarned = false; function isBlob(blob) { if (!blob || typeof blob !== "object") return false; if (blob instanceof Promise) { if (!isWarned) { const error = new Error( "Promise<File> is deprecated. Please put await before." ); console.warn(error); isWarned = true; } return true; } return blob instanceof Blob; } const MEDIA_METHODS = { setWebhook: [(params) => isBlob(params.certificate), null], sendPhoto: [(params) => isBlob(params.photo), null], sendLivePhoto: [ (params) => isBlob(params.live_photo) || isBlob(params.photo), null ], sendAudio: [ (params) => isBlob(params.audio) || isBlob(params.thumbnail), null ], sendDocument: [ (params) => isBlob(params.document) || isBlob(params.thumbnail), null ], sendVideo: [ (params) => isBlob(params.video) || isBlob(params.thumbnail) || isBlob(params.cover), null ], sendAnimation: [ (params) => isBlob(params.animation) || isBlob(params.thumbnail), null ], sendVoice: [(params) => isBlob(params.voice), null], sendVideoNote: [ (params) => isBlob(params.video_note) || isBlob(params.thumbnail), null ], sendPaidMedia: [ (params) => params.media.some((x) => "media" in x && isBlob(x.media)) || params.media.some((x) => "photo" in x && isBlob(x.photo)) || params.media.some((x) => "thumbnail" in x && isBlob(x.thumbnail)) || params.media.some((x) => "cover" in x && isBlob(x.cover)), [ { name: "media", property: "media", type: "array" }, { name: "photo", property: "media", type: "array" }, { name: "thumbnail", property: "media", type: "array" }, { name: "cover", property: "media", type: "array" } ] ], sendMediaGroup: [ (params) => params.media.some((x) => "media" in x && isBlob(x.media)) || params.media.some((x) => "thumbnail" in x && isBlob(x.thumbnail)) || params.media.some((x) => "photo" in x && isBlob(x.photo)) || params.media.some((x) => "cover" in x && isBlob(x.cover)), [ { name: "media", property: "media", type: "array" }, { name: "thumbnail", property: "media", type: "array" }, { name: "photo", property: "media", type: "array" }, { name: "cover", property: "media", type: "array" } ] ], sendPoll: [ (params) => !!params.explanation_media && "media" in params.explanation_media && isBlob(params.explanation_media.media) || !!params.explanation_media && "thumbnail" in params.explanation_media && isBlob(params.explanation_media.thumbnail) || params.explanation_media?.type === "live_photo" && isBlob(params.explanation_media.photo) || params.explanation_media?.type === "video" && isBlob(params.explanation_media.cover) || !!params.media && "media" in params.media && isBlob(params.media.media) || !!params.media && "thumbnail" in params.media && isBlob(params.media.thumbnail) || params.media?.type === "live_photo" && isBlob(params.media.photo) || params.media?.type === "video" && isBlob(params.media.cover), [ { name: "media", property: "explanation_media", type: "union" }, { name: "thumbnail", property: "explanation_media", type: "union" }, { name: "photo", property: "explanation_media", type: "union" }, { name: "cover", property: "explanation_media", type: "union" }, { name: "media", property: "media", type: "union" }, { name: "thumbnail", property: "media", type: "union" }, { name: "photo", property: "media", type: "union" }, { name: "cover", property: "media", type: "union" } ] ], setChatPhoto: [(params) => isBlob(params.photo), null], setMyProfilePhoto: [ (params) => params.photo?.type === "static" && isBlob(params.photo.photo) || params.photo?.type === "animated" && isBlob(params.photo.animation), [ { name: "photo", property: "photo", type: "union" }, { name: "animation", property: "photo", type: "union" } ] ], setBusinessAccountProfilePhoto: [ (params) => params.photo?.type === "static" && isBlob(params.photo.photo) || params.photo?.type === "animated" && isBlob(params.photo.animation), [ { name: "photo", property: "photo", type: "union" }, { name: "animation", property: "photo", type: "union" } ] ], postStory: [ (params) => params.content?.type === "photo" && isBlob(params.content.photo) || params.content?.type === "video" && isBlob(params.content.video), [ { name: "photo", property: "content", type: "union" }, { name: "video", property: "content", type: "union" } ] ], editStory: [ (params) => params.content?.type === "photo" && isBlob(params.content.photo) || params.content?.type === "video" && isBlob(params.content.video), [ { name: "photo", property: "content", type: "union" }, { name: "video", property: "content", type: "union" } ] ], editMessageMedia: [ (params) => !!params.media && "media" in params.media && isBlob(params.media.media) || !!params.media && "thumbnail" in params.media && isBlob(params.media.thumbnail) || params.media?.type === "live_photo" && isBlob(params.media.photo) || params.media?.type === "video" && isBlob(params.media.cover), [ { name: "media", property: "media", type: "union" }, { name: "thumbnail", property: "media", type: "union" }, { name: "photo", property: "media", type: "union" }, { name: "cover", property: "media", type: "union" } ] ], sendSticker: [(params) => isBlob(params.sticker), null], uploadStickerFile: [(params) => isBlob(params.sticker), null], createNewStickerSet: [ (params) => params.stickers.some((x) => "sticker" in x && isBlob(x.sticker)), [ { name: "sticker", property: "stickers", type: "array" } ] ], addStickerToSet: [(params) => isBlob(params.sticker.sticker), null], replaceStickerInSet: [(params) => isBlob(params.sticker.sticker), null], setStickerSetThumbnail: [(params) => isBlob(params.thumbnail), null] }; function isMediaUpload(method, params) { const mediaMethod = MEDIA_METHODS[method]; if (!mediaMethod) return false; return mediaMethod[0](params); } function isExtractor(value, type, params) { return value.type === type; } async function convertJsonToFormData(method, params) { const formData = new FormData(); const mediaMethod = MEDIA_METHODS[method]; const extractor = mediaMethod?.[1] ?? []; let attachId = 0; for (const extractorValue of extractor) { if (isExtractor(extractorValue, "union")) { let file = params[extractorValue.property][extractorValue.name]; if (file instanceof Promise) file = await file; if (!(file instanceof Blob)) continue; const currentAttachId = attachId++; formData.set(`file-${currentAttachId}`, file); params[extractorValue.property][extractorValue.name] = `attach://file-${currentAttachId}`; } if (isExtractor(extractorValue, "array")) { const array = params[extractorValue.property]; for (const [index, element] of array.entries()) { let file = element[extractorValue.name]; if (file instanceof Promise) file = await file; if (!(file instanceof Blob)) continue; const currentAttachId = attachId++; formData.set(`file-${currentAttachId}`, file); params[extractorValue.property][index][extractorValue.name] = `attach://file-${currentAttachId}`; } } } for (let [key, value] of Object.entries(params)) { if (value instanceof Promise) value = await value; if (value === void 0) continue; if (value instanceof Blob) formData.append(key, value); else if (typeof value === "object") formData.append(key, JSON.stringify(value)); else formData.append(key, String(value)); } return formData; } async function extractFilesToFormData(method, params) { const formData = new FormData(); let isEmpty = true; const mediaMethod = MEDIA_METHODS[method]; const extractor = mediaMethod?.[1] ?? []; let attachId = 0; for (const extractorValue of extractor) { if (isExtractor(extractorValue, "union")) { let file = params[extractorValue.property][extractorValue.name]; if (file instanceof Promise) file = await file; if (!(file instanceof Blob)) continue; const currentAttachId = attachId++; formData.set(`file-${currentAttachId}`, file); isEmpty = false; params[extractorValue.property][extractorValue.name] = `attach://file-${currentAttachId}`; } if (isExtractor(extractorValue, "array")) { const array = params[extractorValue.property]; for (const [index, element] of array.entries()) { let file = element[extractorValue.name]; if (file instanceof Promise) file = await file; if (!(file instanceof Blob)) continue; const currentAttachId = attachId++; formData.set(`file-${currentAttachId}`, file); isEmpty = false; params[extractorValue.property][index][extractorValue.name] = `attach://file-${currentAttachId}`; } } } for (let [key, value] of Object.entries(params)) { if (value instanceof Promise) value = await value; if (value === void 0) continue; if (value instanceof Blob) { formData.append(key, value); isEmpty = false; delete params[key]; } } return [isEmpty ? void 0 : formData, params]; } function convertStreamToBuffer(stream) { return new Promise((resolve) => { const chunks = []; stream.on("data", (chunk) => { const bufferChunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk); chunks.push(bufferChunk); }); stream.on("end", () => resolve(Buffer.concat(chunks))); }); } export { MEDIA_METHODS as M, convertJsonToFormData as a, isMediaUpload as b, convertStreamToBuffer as c, extractFilesToFormData as e, isBlob as i };