feat(client): sending document-like media (files, audios, videos, gifs, voices)
This commit is contained in:
parent
0901f97e0d
commit
7e4142a572
8 changed files with 549 additions and 2 deletions
|
@ -27,6 +27,7 @@ import { iterHistory } from './methods/messages/iter-history'
|
||||||
import { _parseEntities } from './methods/messages/parse-entities'
|
import { _parseEntities } from './methods/messages/parse-entities'
|
||||||
import { searchGlobal } from './methods/messages/search-global'
|
import { searchGlobal } from './methods/messages/search-global'
|
||||||
import { searchMessages } from './methods/messages/search-messages'
|
import { searchMessages } from './methods/messages/search-messages'
|
||||||
|
import { sendMedia } from './methods/messages/send-media'
|
||||||
import { sendPhoto } from './methods/messages/send-photo'
|
import { sendPhoto } from './methods/messages/send-photo'
|
||||||
import { sendText } from './methods/messages/send-text'
|
import { sendText } from './methods/messages/send-text'
|
||||||
import {
|
import {
|
||||||
|
@ -54,6 +55,7 @@ import {
|
||||||
Chat,
|
Chat,
|
||||||
FileDownloadParameters,
|
FileDownloadParameters,
|
||||||
InputFileLike,
|
InputFileLike,
|
||||||
|
InputMediaLike,
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
MaybeDynamic,
|
MaybeDynamic,
|
||||||
Message,
|
Message,
|
||||||
|
@ -738,6 +740,60 @@ export class TelegramClient extends BaseTelegramClient {
|
||||||
): AsyncIterableIterator<Message> {
|
): AsyncIterableIterator<Message> {
|
||||||
return searchMessages.apply(this, arguments)
|
return searchMessages.apply(this, arguments)
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Send a single media.
|
||||||
|
*
|
||||||
|
* @param chatId ID of the chat, its username, phone or `"me"` or `"self"`
|
||||||
|
* @param media Media contained in the message
|
||||||
|
* @param params Additional sending parameters
|
||||||
|
*/
|
||||||
|
sendMedia(
|
||||||
|
chatId: InputPeerLike,
|
||||||
|
media: InputMediaLike,
|
||||||
|
params?: {
|
||||||
|
/**
|
||||||
|
* Message to reply to. Either a message object or message ID.
|
||||||
|
*/
|
||||||
|
replyTo?: number | Message
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse mode to use to parse entities before sending
|
||||||
|
* the message. Defaults to current default parse mode (if any).
|
||||||
|
*
|
||||||
|
* Passing `null` will explicitly disable formatting.
|
||||||
|
*/
|
||||||
|
parseMode?: string | null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to send this message silently.
|
||||||
|
*/
|
||||||
|
silent?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, the message will be scheduled to this date.
|
||||||
|
* When passing a number, a UNIX time in ms is expected.
|
||||||
|
*/
|
||||||
|
schedule?: Date | number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For bots: inline or reply markup or an instruction
|
||||||
|
* to hide a reply keyboard or to force a reply.
|
||||||
|
*/
|
||||||
|
replyMarkup?: ReplyMarkup
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that will be called after some part has been uploaded.
|
||||||
|
* Only used when a file that requires uploading is passed,
|
||||||
|
* and not used when uploading a thumbnail.
|
||||||
|
*
|
||||||
|
* @param uploaded Number of bytes already uploaded
|
||||||
|
* @param total Total file size
|
||||||
|
*/
|
||||||
|
progressCallback?: (uploaded: number, total: number) => void
|
||||||
|
}
|
||||||
|
): Promise<Message> {
|
||||||
|
return sendMedia.apply(this, arguments)
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Send a single photo
|
* Send a single photo
|
||||||
*
|
*
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
UpdateFilter,
|
UpdateFilter,
|
||||||
Message,
|
Message,
|
||||||
ReplyMarkup,
|
ReplyMarkup,
|
||||||
|
InputMediaLike
|
||||||
} from '../types'
|
} from '../types'
|
||||||
|
|
||||||
// @copy
|
// @copy
|
||||||
|
|
|
@ -22,6 +22,11 @@ try {
|
||||||
|
|
||||||
const debug = require('debug')('mtcute:upload')
|
const debug = require('debug')('mtcute:upload')
|
||||||
|
|
||||||
|
const OVERRIDE_MIME: Record<string, string> = {
|
||||||
|
// tg doesn't interpret `audio/opus` files as voice messages for some reason
|
||||||
|
'audio/opus': 'audio/ogg'
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upload a file to Telegram servers, without actually
|
* Upload a file to Telegram servers, without actually
|
||||||
* sending a message anywhere. Useful when an `InputFile` is required.
|
* sending a message anywhere. Useful when an `InputFile` is required.
|
||||||
|
@ -247,6 +252,8 @@ export async function uploadFile(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fileMime! in OVERRIDE_MIME) fileMime = OVERRIDE_MIME[fileMime!]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
inputFile,
|
inputFile,
|
||||||
size: fileSize,
|
size: fileSize,
|
||||||
|
|
201
packages/client/src/methods/messages/send-media.ts
Normal file
201
packages/client/src/methods/messages/send-media.ts
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
import { TelegramClient } from '../../client'
|
||||||
|
import {
|
||||||
|
BotKeyboard,
|
||||||
|
InputMediaLike,
|
||||||
|
InputPeerLike,
|
||||||
|
isUploadedFile,
|
||||||
|
Message,
|
||||||
|
MtCuteArgumentError,
|
||||||
|
ReplyMarkup,
|
||||||
|
} from '../../types'
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
import { extractFileName } from '../../utils/file-utils'
|
||||||
|
import { normalizeToInputPeer } from '../../utils/peer-utils'
|
||||||
|
import { normalizeDate, randomUlong } from '../../utils/misc-utils'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a single media.
|
||||||
|
*
|
||||||
|
* @param chatId ID of the chat, its username, phone or `"me"` or `"self"`
|
||||||
|
* @param media Media contained in the message
|
||||||
|
* @param params Additional sending parameters
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export async function sendMedia(
|
||||||
|
this: TelegramClient,
|
||||||
|
chatId: InputPeerLike,
|
||||||
|
media: InputMediaLike,
|
||||||
|
params?: {
|
||||||
|
/**
|
||||||
|
* Message to reply to. Either a message object or message ID.
|
||||||
|
*/
|
||||||
|
replyTo?: number | Message
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse mode to use to parse entities before sending
|
||||||
|
* the message. Defaults to current default parse mode (if any).
|
||||||
|
*
|
||||||
|
* Passing `null` will explicitly disable formatting.
|
||||||
|
*/
|
||||||
|
parseMode?: string | null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to send this message silently.
|
||||||
|
*/
|
||||||
|
silent?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, the message will be scheduled to this date.
|
||||||
|
* When passing a number, a UNIX time in ms is expected.
|
||||||
|
*/
|
||||||
|
schedule?: Date | number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For bots: inline or reply markup or an instruction
|
||||||
|
* to hide a reply keyboard or to force a reply.
|
||||||
|
*/
|
||||||
|
replyMarkup?: ReplyMarkup
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that will be called after some part has been uploaded.
|
||||||
|
* Only used when a file that requires uploading is passed,
|
||||||
|
* and not used when uploading a thumbnail.
|
||||||
|
*
|
||||||
|
* @param uploaded Number of bytes already uploaded
|
||||||
|
* @param total Total file size
|
||||||
|
*/
|
||||||
|
progressCallback?: (uploaded: number, total: number) => void
|
||||||
|
}
|
||||||
|
): Promise<Message> {
|
||||||
|
if (!params) params = {}
|
||||||
|
|
||||||
|
if (media.type === 'photo') {
|
||||||
|
return this.sendPhoto(chatId, media.file, {
|
||||||
|
caption: media.caption,
|
||||||
|
entities: media.entities,
|
||||||
|
...params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let inputMedia: tl.TypeInputMedia | null = null
|
||||||
|
|
||||||
|
let inputFile: tl.TypeInputFile | undefined = undefined
|
||||||
|
let thumb: tl.TypeInputFile | undefined = undefined
|
||||||
|
let mime = 'application/octet-stream'
|
||||||
|
|
||||||
|
const input = media.file
|
||||||
|
if (typeof input === 'string' && input.match(/^https?:\/\//)) {
|
||||||
|
inputMedia = {
|
||||||
|
_: 'inputMediaDocumentExternal',
|
||||||
|
url: input,
|
||||||
|
}
|
||||||
|
} else if (isUploadedFile(input)) {
|
||||||
|
inputFile = input.inputFile
|
||||||
|
mime = input.mime
|
||||||
|
} else if (typeof input === 'object' && tl.isAnyInputFile(input)) {
|
||||||
|
inputFile = input
|
||||||
|
} else {
|
||||||
|
const uploaded = await this.uploadFile({
|
||||||
|
file: input,
|
||||||
|
fileName: media.fileName,
|
||||||
|
progressCallback: params.progressCallback,
|
||||||
|
})
|
||||||
|
inputFile = uploaded.inputFile
|
||||||
|
mime = uploaded.mime
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inputMedia) {
|
||||||
|
if (!inputFile) throw new Error('should not happen')
|
||||||
|
|
||||||
|
if ('thumb' in media && media.thumb) {
|
||||||
|
const t = media.thumb
|
||||||
|
if (typeof t === 'string' && t.match(/^https?:\/\//)) {
|
||||||
|
throw new MtCuteArgumentError("Thumbnail can't be external")
|
||||||
|
} else if (isUploadedFile(t)) {
|
||||||
|
thumb = t.inputFile
|
||||||
|
} else if (typeof t === 'object' && tl.isAnyInputFile(t)) {
|
||||||
|
thumb = t
|
||||||
|
} else {
|
||||||
|
const uploaded = await this.uploadFile({
|
||||||
|
file: t,
|
||||||
|
})
|
||||||
|
thumb = uploaded.inputFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const attributes: tl.TypeDocumentAttribute[] = []
|
||||||
|
|
||||||
|
if (media.type !== 'voice') {
|
||||||
|
attributes.push({
|
||||||
|
_: 'documentAttributeFilename',
|
||||||
|
fileName:
|
||||||
|
media.fileName ||
|
||||||
|
(typeof media.file === 'string'
|
||||||
|
? extractFileName(media.file)
|
||||||
|
: 'unnamed'),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (media.type === 'video') {
|
||||||
|
attributes.push({
|
||||||
|
_: 'documentAttributeVideo',
|
||||||
|
duration: media.duration || 0,
|
||||||
|
w: media.width || 0,
|
||||||
|
h: media.height || 0,
|
||||||
|
supportsStreaming: media.supportsStreaming,
|
||||||
|
roundMessage: media.isRound
|
||||||
|
})
|
||||||
|
if (media.isAnimated) attributes.push({ _: 'documentAttributeAnimated' })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (media.type === 'audio' || media.type === 'voice') {
|
||||||
|
attributes.push({
|
||||||
|
_: 'documentAttributeAudio',
|
||||||
|
voice: media.type === 'voice',
|
||||||
|
duration: media.duration || 0,
|
||||||
|
title: media.type === 'audio' ? media.title : undefined,
|
||||||
|
performer: media.type === 'audio' ? media.performer : undefined,
|
||||||
|
waveform: media.type === 'voice' ? media.waveform : undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
inputMedia = {
|
||||||
|
_: 'inputMediaUploadedDocument',
|
||||||
|
nosoundVideo: media.type === 'video' && media.isAnimated,
|
||||||
|
forceFile: media.type === 'document',
|
||||||
|
file: inputFile,
|
||||||
|
thumb,
|
||||||
|
mimeType: mime,
|
||||||
|
attributes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [message, entities] = await this._parseEntities(
|
||||||
|
media.caption,
|
||||||
|
params.parseMode,
|
||||||
|
media.entities
|
||||||
|
)
|
||||||
|
|
||||||
|
const peer = normalizeToInputPeer(await this.resolvePeer(chatId))
|
||||||
|
const replyMarkup = BotKeyboard._convertToTl(params.replyMarkup)
|
||||||
|
|
||||||
|
|
||||||
|
const res = await this.call({
|
||||||
|
_: 'messages.sendMedia',
|
||||||
|
peer,
|
||||||
|
media: inputMedia,
|
||||||
|
silent: params.silent,
|
||||||
|
replyToMsgId: params.replyTo
|
||||||
|
? typeof params.replyTo === 'number'
|
||||||
|
? params.replyTo
|
||||||
|
: params.replyTo.id
|
||||||
|
: undefined,
|
||||||
|
randomId: randomUlong(),
|
||||||
|
scheduleDate: normalizeDate(params.schedule),
|
||||||
|
replyMarkup,
|
||||||
|
message,
|
||||||
|
entities,
|
||||||
|
})
|
||||||
|
|
||||||
|
return this._findMessageInUpdate(res)
|
||||||
|
}
|
|
@ -5,8 +5,6 @@ import {
|
||||||
BotKeyboard,
|
BotKeyboard,
|
||||||
ReplyMarkup,
|
ReplyMarkup,
|
||||||
isUploadedFile,
|
isUploadedFile,
|
||||||
filters,
|
|
||||||
Photo,
|
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
|
|
|
@ -8,3 +8,4 @@ export * from './video'
|
||||||
export * from './location'
|
export * from './location'
|
||||||
export * from './voice'
|
export * from './voice'
|
||||||
export * from './sticker'
|
export * from './sticker'
|
||||||
|
export * from './input-media'
|
||||||
|
|
275
packages/client/src/types/media/input-media.ts
Normal file
275
packages/client/src/types/media/input-media.ts
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
import { InputFileLike } from '../files'
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
|
interface BaseInputMedia {
|
||||||
|
/**
|
||||||
|
* File to be sent
|
||||||
|
*/
|
||||||
|
file: InputFileLike
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caption of the media
|
||||||
|
*/
|
||||||
|
caption?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caption entities of the media.
|
||||||
|
* If passed, {@link caption} is ignored
|
||||||
|
*/
|
||||||
|
entities?: tl.TypeMessageEntity[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override file name for the file.
|
||||||
|
*/
|
||||||
|
fileName?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically detect media type based on file contents.
|
||||||
|
*
|
||||||
|
* Only works for files that are internally documents, i.e.
|
||||||
|
* *does not* infer photos, so use {@link InputMediaPhoto} instead.
|
||||||
|
*/
|
||||||
|
export interface InputMediaAuto extends BaseInputMedia {
|
||||||
|
type: 'auto'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An audio file or voice message to be sent
|
||||||
|
*/
|
||||||
|
export interface InputMediaAudio extends BaseInputMedia {
|
||||||
|
type: 'audio'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thumbnail of the audio file album cover.
|
||||||
|
*
|
||||||
|
* The thumbnail should be in JPEG format and less than 200 KB in size.
|
||||||
|
* A thumbnail's width and height should not exceed 320 pixels.
|
||||||
|
* Thumbnails can't be reused and can be only uploaded as a new file.
|
||||||
|
*/
|
||||||
|
thumb?: InputFileLike
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duration of the audio in seconds
|
||||||
|
*/
|
||||||
|
duration?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performer of the audio
|
||||||
|
*/
|
||||||
|
performer?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Title of the audio
|
||||||
|
*/
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Voice message to be sent
|
||||||
|
*/
|
||||||
|
export interface InputMediaVoice extends BaseInputMedia {
|
||||||
|
type: 'voice'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duration of the voice message in seconds
|
||||||
|
*/
|
||||||
|
duration?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waveform of the voice message
|
||||||
|
*/
|
||||||
|
waveform?: Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic file to be sent
|
||||||
|
*/
|
||||||
|
export interface InputMediaDocument extends BaseInputMedia {
|
||||||
|
type: 'document'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thumbnail of the document.
|
||||||
|
*
|
||||||
|
* The thumbnail should be in JPEG format and less than 200 KB in size.
|
||||||
|
* A thumbnail's width and height should not exceed 320 pixels.
|
||||||
|
* Thumbnails can't be reused and can be only uploaded as a new file.
|
||||||
|
*/
|
||||||
|
thumb?: InputFileLike
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A photo to be sent
|
||||||
|
*/
|
||||||
|
export interface InputMediaPhoto extends BaseInputMedia {
|
||||||
|
type: 'photo'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A video to be sent
|
||||||
|
*/
|
||||||
|
export interface InputMediaVideo extends BaseInputMedia {
|
||||||
|
type: 'video'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thumbnail of the video.
|
||||||
|
*
|
||||||
|
* The thumbnail should be in JPEG format and less than 200 KB in size.
|
||||||
|
* A thumbnail's width and height should not exceed 320 pixels.
|
||||||
|
* Thumbnails can't be reused and can be only uploaded as a new file.
|
||||||
|
*/
|
||||||
|
thumb?: InputFileLike
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Width of the video in pixels
|
||||||
|
*/
|
||||||
|
width?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Height of the video in pixels
|
||||||
|
*/
|
||||||
|
height?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duration of the video in seconds
|
||||||
|
*/
|
||||||
|
duration?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the video is suitable for streaming
|
||||||
|
*/
|
||||||
|
supportsStreaming?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this video is an animated GIF
|
||||||
|
*/
|
||||||
|
isAnimated?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this video is a round message (aka video note)
|
||||||
|
*/
|
||||||
|
isRound?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input media that can be sent somewhere.
|
||||||
|
*
|
||||||
|
* Note that meta-fields (like `duration`) are only
|
||||||
|
* applicable if `file` is {@link UploadFileLike},
|
||||||
|
* otherwise they are ignored.
|
||||||
|
*
|
||||||
|
* @see InputMedia
|
||||||
|
*/
|
||||||
|
export type InputMediaLike =
|
||||||
|
| InputMediaAudio
|
||||||
|
| InputMediaVoice
|
||||||
|
| InputMediaDocument
|
||||||
|
| InputMediaPhoto
|
||||||
|
| InputMediaVideo
|
||||||
|
| InputMediaAuto
|
||||||
|
|
||||||
|
export namespace InputMedia {
|
||||||
|
type OmitTypeAndFile<T extends InputMediaLike> = Omit<T, 'type' | 'file'>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an animation to be sent
|
||||||
|
*/
|
||||||
|
export function animation(
|
||||||
|
file: InputFileLike,
|
||||||
|
params?: OmitTypeAndFile<InputMediaVideo>
|
||||||
|
): InputMediaVideo {
|
||||||
|
return {
|
||||||
|
type: 'video',
|
||||||
|
file,
|
||||||
|
isAnimated: true,
|
||||||
|
...(params || {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an audio to be sent
|
||||||
|
*/
|
||||||
|
export function audio(
|
||||||
|
file: InputFileLike,
|
||||||
|
params?: OmitTypeAndFile<InputMediaAudio>
|
||||||
|
): InputMediaAudio {
|
||||||
|
return {
|
||||||
|
type: 'audio',
|
||||||
|
file,
|
||||||
|
...(params || {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an document to be sent
|
||||||
|
*/
|
||||||
|
export function document(
|
||||||
|
file: InputFileLike,
|
||||||
|
params?: OmitTypeAndFile<InputMediaDocument>
|
||||||
|
): InputMediaDocument {
|
||||||
|
return {
|
||||||
|
type: 'document',
|
||||||
|
file,
|
||||||
|
...(params || {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an photo to be sent
|
||||||
|
*/
|
||||||
|
export function photo(
|
||||||
|
file: InputFileLike,
|
||||||
|
params?: OmitTypeAndFile<InputMediaPhoto>
|
||||||
|
): InputMediaPhoto {
|
||||||
|
return {
|
||||||
|
type: 'photo',
|
||||||
|
file,
|
||||||
|
...(params || {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an video to be sent
|
||||||
|
*/
|
||||||
|
export function video(
|
||||||
|
file: InputFileLike,
|
||||||
|
params?: OmitTypeAndFile<InputMediaVideo>
|
||||||
|
): InputMediaVideo {
|
||||||
|
return {
|
||||||
|
type: 'video',
|
||||||
|
file,
|
||||||
|
...(params || {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a voice message to be sent
|
||||||
|
*/
|
||||||
|
export function voice(
|
||||||
|
file: InputFileLike,
|
||||||
|
params?: OmitTypeAndFile<InputMediaVoice>
|
||||||
|
): InputMediaVoice {
|
||||||
|
return {
|
||||||
|
type: 'voice',
|
||||||
|
file,
|
||||||
|
...(params || {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
export function auto(
|
||||||
|
file: InputFileLike,
|
||||||
|
params?: OmitTypeAndFile<InputMediaAuto>
|
||||||
|
): InputMediaAuto {
|
||||||
|
return {
|
||||||
|
type: 'auto',
|
||||||
|
file,
|
||||||
|
...(params || {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -98,3 +98,11 @@ export function svgPathToFile(path: string): Buffer {
|
||||||
'</svg>'
|
'</svg>'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FILENAME_REGEX = /^(\/?.+[/\\])*(.+\..+)$/
|
||||||
|
|
||||||
|
export function extractFileName(path: string): string {
|
||||||
|
const m = path.match(FILENAME_REGEX)
|
||||||
|
if (m) return m[2]
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue