@gramio/files
Advanced tools
Comparing version 0.0.11 to 0.0.12
@@ -0,26 +1,102 @@ | ||
import { Readable } from 'node:stream'; | ||
import { APIMethods, APIMethodParams, TelegramInputFile, TelegramInputMediaAnimation, TelegramInputMediaDocument, TelegramInputMediaAudio, TelegramInputMediaPhoto, TelegramInputMediaVideo } from '@gramio/types'; | ||
/** Guard to check is method used for File Uploading */ | ||
declare function isMediaUpload<T extends keyof APIMethods>(method: T, params: NonNullable<APIMethodParams<T>>): boolean; | ||
/** | ||
* @module | ||
* Helper to convert JSON to FormData that can accept Telegram Bot API. | ||
* if File is not top-level property it will be `“attach://<file_attach_name>”` | ||
* | ||
* Set of utils for work with files and Telegram Bot API | ||
* [Documentation](https://core.telegram.org/bots/api#inputfile) | ||
*/ | ||
declare function convertJsonToFormData<T extends keyof APIMethods>(method: T, params: NonNullable<APIMethodParams<T>>): Promise<FormData>; | ||
/** Helper for convert Readable stream to buffer */ | ||
declare function convertStreamToBuffer(stream: Readable): Promise<Buffer>; | ||
type Extractor = { | ||
name: string; | ||
type: "array" | "union"; | ||
property: string; | ||
}; | ||
type MethodsWithMediaUpload = { | ||
[Method in keyof APIMethods]?: [ | ||
(params: NonNullable<APIMethodParams<Method>>) => boolean, | ||
Extractor[] | null | ||
]; | ||
}; | ||
/** Guard for check is it {@link Blob} or {@link Promise} */ | ||
declare function isBlob(blob?: TelegramInputFile | object | string): boolean; | ||
/** | ||
* A set of methods with the function of checking whether a {@link File} has been passed in the parameters | ||
* | ||
* [Documentation](https://gramio.dev/files/overview.html) | ||
* @codegenerated | ||
* */ | ||
declare const MEDIA_METHODS: MethodsWithMediaUpload; | ||
/** | ||
* Class-helper with static methods that represents the content of a media message to be sent. | ||
* | ||
* @example | ||
* ```typescript | ||
* import { MediaInput, MediaUpload } from "@gramio/files"; | ||
* [Documentation](https://gramio.dev/files/media-input.html) | ||
*/ | ||
declare class MediaInput { | ||
/** | ||
* Represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent. | ||
* | ||
* [Documentation](https://core.telegram.org/bots/api/#inputmediaanimation) | ||
*/ | ||
static animation(media: TelegramInputMediaAnimation["media"], options?: Omit<TelegramInputMediaAnimation, "media" | "type">): TelegramInputMediaAnimation; | ||
/** | ||
* Represents a general file to be sent. | ||
* | ||
* [Documentation](https://core.telegram.org/bots/api/#inputmediadocument) | ||
*/ | ||
static document(media: TelegramInputMediaDocument["media"], options?: Omit<TelegramInputMediaDocument, "media" | "type">): TelegramInputMediaDocument; | ||
/** | ||
* Represents an audio file to be treated as music to be sent. | ||
* | ||
* [Documentation](https://core.telegram.org/bots/api/#inputmediaaudio) | ||
*/ | ||
static audio(media: TelegramInputMediaAudio["media"], options?: Omit<TelegramInputMediaAudio, "media" | "type">): TelegramInputMediaAudio; | ||
/** | ||
* Represents a photo to be sent. | ||
* | ||
* [Documentation](https://core.telegram.org/bots/api/#inputmediaphoto) | ||
*/ | ||
static photo(media: TelegramInputMediaPhoto["media"], options?: Omit<TelegramInputMediaPhoto, "media" | "type">): TelegramInputMediaPhoto; | ||
/** | ||
* Represents a video to be sent. | ||
* | ||
* [Documentation](https://core.telegram.org/bots/api/#inputmediavideo) | ||
*/ | ||
static video(media: TelegramInputMediaVideo["media"], options?: Omit<TelegramInputMediaVideo, "media" | "type">): TelegramInputMediaVideo; | ||
} | ||
/** | ||
* Class-helper with static methods for file uploading. | ||
* | ||
* // method for sendMediaGroup | ||
* context.sendMediaGroup([ | ||
* MediaInput.document( | ||
* MediaUpload.url( | ||
* "https://raw.githubusercontent.com/gramiojs/types/main/README.md" | ||
* ) | ||
* ), | ||
* MediaInput.document(MediaUpload.path("./package.json")), | ||
* ]); | ||
* ``` | ||
* [Documentation](https://gramio.dev/files/media-upload.html) | ||
*/ | ||
export * from "./utils"; | ||
export { isBlob, MEDIA_METHODS } from "./media-methods-helper"; | ||
export * from "./media-input"; | ||
export * from "./media-upload"; | ||
declare class MediaUpload { | ||
/** | ||
* Method for uploading Media File by local path. | ||
*/ | ||
static path(path: string, filename?: string): Promise<File>; | ||
/** | ||
* Method for uploading Media File by Readable stream. | ||
*/ | ||
static stream(stream: Readable, filename?: string): Promise<File>; | ||
/** | ||
* Method for uploading Media File by Buffer or ArrayBuffer. | ||
*/ | ||
static buffer(buffer: Buffer | ArrayBuffer, filename?: string): File; | ||
/** | ||
* Method for uploading Media File by URL (also with fetch options). | ||
*/ | ||
static url(url: URL | string, filename?: string, options?: RequestInit): Promise<File>; | ||
/** | ||
* Method for uploading Media File by text content. | ||
*/ | ||
static text(text: string, filename?: string): File; | ||
} | ||
export { MEDIA_METHODS, MediaInput, MediaUpload, convertJsonToFormData, convertStreamToBuffer, isBlob, isMediaUpload }; |
@@ -1,45 +0,253 @@ | ||
"use strict"; | ||
/** | ||
* @module | ||
* | ||
* Set of utils for work with files and Telegram Bot API | ||
* | ||
* [Documentation](https://gramio.dev/files/overview.html) | ||
* | ||
* @example | ||
* ```typescript | ||
* import { MediaInput, MediaUpload } from "@gramio/files"; | ||
* | ||
* // method for sendMediaGroup | ||
* context.sendMediaGroup([ | ||
* MediaInput.document( | ||
* MediaUpload.url( | ||
* "https://raw.githubusercontent.com/gramiojs/types/main/README.md" | ||
* ) | ||
* ), | ||
* MediaInput.document(MediaUpload.path("./package.json")), | ||
* ]); | ||
* ``` | ||
*/ | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
import fs from 'node:fs/promises'; | ||
import { basename } from 'node:path'; | ||
function isBlob(blob) { | ||
if (!blob || typeof blob !== "object") | ||
return false; | ||
return blob instanceof Blob || blob instanceof Promise; | ||
} | ||
const MEDIA_METHODS = { | ||
setWebhook: [(params) => isBlob(params.certificate), null], | ||
sendPhoto: [(params) => 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), | ||
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)), | ||
[ | ||
{ | ||
name: "media", | ||
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)), | ||
[ | ||
{ | ||
name: "media", | ||
property: "media", | ||
type: "array" | ||
}, | ||
{ | ||
name: "thumbnail", | ||
property: "media", | ||
type: "array" | ||
} | ||
] | ||
], | ||
setChatPhoto: [(params) => isBlob(params.photo), null], | ||
editMessageMedia: [ | ||
(params) => "media" in params.media && isBlob(params.media.media) || "thumbnail" in params.media && isBlob(params.media.thumbnail), | ||
[ | ||
{ | ||
name: "media", | ||
property: "media", | ||
type: "union" | ||
}, | ||
{ | ||
name: "thumbnail", | ||
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}`; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.MEDIA_METHODS = exports.isBlob = void 0; | ||
__exportStar(require("./utils"), exports); | ||
var media_methods_helper_1 = require("./media-methods-helper"); | ||
Object.defineProperty(exports, "isBlob", { enumerable: true, get: function () { return media_methods_helper_1.isBlob; } }); | ||
Object.defineProperty(exports, "MEDIA_METHODS", { enumerable: true, get: function () { return media_methods_helper_1.MEDIA_METHODS; } }); | ||
__exportStar(require("./media-input"), exports); | ||
__exportStar(require("./media-upload"), exports); | ||
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 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; | ||
} | ||
function convertStreamToBuffer(stream) { | ||
return new Promise((resolve) => { | ||
const chunks = []; | ||
stream.on("data", (chunk) => chunks.push(chunk)); | ||
stream.on("end", () => resolve(Buffer.concat(chunks))); | ||
}); | ||
} | ||
class MediaInput { | ||
/** | ||
* Represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent. | ||
* | ||
* [Documentation](https://core.telegram.org/bots/api/#inputmediaanimation) | ||
*/ | ||
static animation(media, options = {}) { | ||
return { | ||
type: "animation", | ||
media, | ||
...options | ||
}; | ||
} | ||
/** | ||
* Represents a general file to be sent. | ||
* | ||
* [Documentation](https://core.telegram.org/bots/api/#inputmediadocument) | ||
*/ | ||
static document(media, options = {}) { | ||
return { | ||
type: "document", | ||
media, | ||
...options | ||
}; | ||
} | ||
/** | ||
* Represents an audio file to be treated as music to be sent. | ||
* | ||
* [Documentation](https://core.telegram.org/bots/api/#inputmediaaudio) | ||
*/ | ||
static audio(media, options = {}) { | ||
return { | ||
type: "audio", | ||
media, | ||
...options | ||
}; | ||
} | ||
/** | ||
* Represents a photo to be sent. | ||
* | ||
* [Documentation](https://core.telegram.org/bots/api/#inputmediaphoto) | ||
*/ | ||
static photo(media, options = {}) { | ||
return { | ||
type: "photo", | ||
media, | ||
...options | ||
}; | ||
} | ||
/** | ||
* Represents a video to be sent. | ||
* | ||
* [Documentation](https://core.telegram.org/bots/api/#inputmediavideo) | ||
*/ | ||
static video(media, options = {}) { | ||
return { | ||
type: "video", | ||
media, | ||
...options | ||
}; | ||
} | ||
} | ||
class MediaUpload { | ||
/** | ||
* Method for uploading Media File by local path. | ||
*/ | ||
static async path(path, filename) { | ||
const buffer = await fs.readFile(path); | ||
return new File([buffer], filename ?? basename(path)); | ||
} | ||
/** | ||
* Method for uploading Media File by Readable stream. | ||
*/ | ||
static async stream(stream, filename = "file.stream") { | ||
const buffer = await convertStreamToBuffer(stream); | ||
return new File([buffer], filename); | ||
} | ||
/** | ||
* Method for uploading Media File by Buffer or ArrayBuffer. | ||
*/ | ||
static buffer(buffer, filename = "file.buffer") { | ||
return new File([new Blob([buffer])], filename); | ||
} | ||
/** | ||
* Method for uploading Media File by URL (also with fetch options). | ||
*/ | ||
static async url(url, filename, options) { | ||
const res = await fetch(url, options); | ||
const buffer = await res.arrayBuffer(); | ||
return new File( | ||
[new Blob([buffer])], | ||
filename ?? (typeof url === "string" ? basename(url) : basename(url.pathname)) | ||
); | ||
} | ||
/** | ||
* Method for uploading Media File by text content. | ||
*/ | ||
static text(text, filename = "text.txt") { | ||
return new File([text], filename); | ||
} | ||
} | ||
export { MEDIA_METHODS, MediaInput, MediaUpload, convertJsonToFormData, convertStreamToBuffer, isBlob, isMediaUpload }; |
{ | ||
"name": "@gramio/files", | ||
"main": "./dist/index.js", | ||
"version": "0.0.11", | ||
"type": "commonjs", | ||
"main": "./dist/index.cjs", | ||
"module": "./dist/index.js", | ||
"types": "./dist/index.d.ts", | ||
"exports": { | ||
"import": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
}, | ||
"require": { | ||
"types": "./dist/index.d.cts", | ||
"default": "./dist/index.cjs" | ||
} | ||
}, | ||
"version": "0.0.12", | ||
"type": "module", | ||
"description": "Set of utils for work with files and Telegram Bot API", | ||
@@ -16,3 +28,3 @@ "keywords": [ | ||
"generate": "bun scripts/generate.ts", | ||
"prepublishOnly": "tsc", | ||
"prepublishOnly": "bunx pkgroll", | ||
"lint": "bunx @biomejs/biome check ./src", | ||
@@ -26,2 +38,4 @@ "lint:fix": "bun lint --apply", | ||
"@types/node": "^20.14.10", | ||
"mitata": "^0.1.11", | ||
"pkgroll": "^2.1.1", | ||
"prettier": "^3.3.2", | ||
@@ -31,7 +45,8 @@ "typescript": "^5.5.3" | ||
"dependencies": { | ||
"@gramio/types": "^7.7.0" | ||
"@gramio/types": "^7.7.1" | ||
}, | ||
"files": [ | ||
"dist" | ||
] | ||
], | ||
"license": "MIT" | ||
} |
@@ -11,2 +11,2 @@ # @gramio/files | ||
Currently, support Telegram Bot API v7.6+ | ||
Currently, support Telegram Bot API v7.7+ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
25970
0
600
Yes
7
7
3
Updated@gramio/types@^7.7.1