feat(client): support all possible inline results and messages

This commit is contained in:
teidesu 2021-05-04 13:08:20 +03:00
parent 03bf248658
commit d469b81a85
8 changed files with 1060 additions and 35 deletions

View file

@ -1630,7 +1630,7 @@ export interface TelegramClient extends BaseTelegramClient {
* @param chatId ID of the chat, its username, phone or `"me"` or `"self"`
* @param medias Medias contained in the message.
* @param params Additional sending parameters
* @see InputMedia
* @link InputMedia
*/
sendMediaGroup(
chatId: InputPeerLike,
@ -1698,7 +1698,7 @@ export interface TelegramClient extends BaseTelegramClient {
* and Bot API compatible File ID, which will be wrapped
* in {@link InputMedia.auto}
* @param params Additional sending parameters
* @see InputMedia
* @link InputMedia
*/
sendMedia(
chatId: InputPeerLike,

View file

@ -16,7 +16,7 @@ import { tl } from '@mtcute/tl'
* @param chatId ID of the chat, its username, phone or `"me"` or `"self"`
* @param medias Medias contained in the message.
* @param params Additional sending parameters
* @see InputMedia
* @link InputMedia
* @internal
*/
export async function sendMediaGroup(

View file

@ -18,7 +18,7 @@ import { normalizeDate, randomUlong } from '../../utils/misc-utils'
* and Bot API compatible File ID, which will be wrapped
* in {@link InputMedia.auto}
* @param params Additional sending parameters
* @see InputMedia
* @link InputMedia
* @internal
*/
export async function sendMedia(

View file

@ -2,6 +2,9 @@ import { tl } from '@mtcute/tl'
import { BotKeyboard, ReplyMarkup } from '../keyboards'
import { TelegramClient } from '../../../client'
/**
* Inline message containing only text
*/
export interface InputInlineMessageText {
type: 'text'
@ -27,8 +30,145 @@ export interface InputInlineMessageText {
disableWebPreview?: boolean
}
/**
* Inline message containing media, which is automatically
* inferred from the result itself.
*/
export interface InputInlineMessageMedia {
type: 'media'
/**
* Caption for the media
*/
text?: string
/**
* Caption markup entities.
* If passed, parse mode is ignored
*/
entities?: tl.TypeMessageEntity[]
/**
* Message reply markup
*/
replyMarkup?: ReplyMarkup
}
/**
* Inline message containing a geolocation
*/
export interface InputInlineMessageGeo {
type: 'geo'
/**
* Latitude of the geolocation
*/
latitude: number
/**
* Longitude of the geolocation
*/
longitude: number
/**
* For live locations, direction in which the location
* moves, in degrees (1-360)
*/
heading?: number
/**
* For live locations, period for which this live location
* will be updated
*/
period?: number
/**
* For live locations, a maximum distance to another
* chat member for proximity alerts, in meters (0-100000)
*/
proximityNotificationRadius?: number
/**
* Message's reply markup
*/
replyMarkup?: ReplyMarkup
}
/**
* Inline message containing a venue
*/
export interface InputInlineMessageVenue {
type: 'venue'
/**
* Latitude of the geolocation
*/
latitude: number
/**
* Longitude of the geolocation
*/
longitude: number
/**
* Venue name
*/
title: string
/**
* Venue address
*/
address: string
/**
* When available, source from where this venue was acquired
*/
source?: {
/**
* Provider name (`foursquare` or `gplaces` for Google Places)
*/
provider?: 'foursquare' | 'gplaces'
/**
* Venue ID in the provider's DB
*/
id: string
/**
* Venue type in the provider's DB
*
* - [Supported types for Foursquare](https://developer.foursquare.com/docs/build-with-foursquare/categories/)
* (use names, lowercase them, replace spaces and " & " with `_` (underscore) and remove other symbols,
* and use `/` (slash) as hierarchy separator)
* - [Supported types for Google Places](https://developers.google.com/places/web-service/supported_types)
*/
type: string
}
/**
* Message's reply markup
*/
replyMarkup?: ReplyMarkup
}
/**
* Inline message containing a game
*/
export interface InputInlineMessageGame {
type: 'game'
/**
* Message's reply markup
*/
replyMarkup?: ReplyMarkup
}
export type InputInlineMessage =
| InputInlineMessageText
| InputInlineMessageMedia
| InputInlineMessageGeo
| InputInlineMessageVenue
| InputInlineMessageGame
export namespace BotInlineMessage {
export function text (
@ -44,6 +184,52 @@ export namespace BotInlineMessage {
}
}
export function media (
text?: string,
params?: Omit<InputInlineMessageMedia, 'type' | 'text'>,
): InputInlineMessageMedia {
return {
type: 'media',
text,
...(
params || {}
),
}
}
export function geo (
latitude: number,
longitude: number,
params?: Omit<InputInlineMessageGeo, 'type' | 'latitude' | 'longitude'>,
): InputInlineMessageGeo {
return {
type: 'geo',
latitude,
longitude,
...(
params || {}
),
}
}
export function venue (
params: Omit<InputInlineMessageVenue, 'type'>,
): InputInlineMessageVenue {
return {
type: 'venue',
...params,
}
}
export function game (
params: Omit<InputInlineMessageGame, 'type'>,
): InputInlineMessageGame {
return {
type: 'game',
...params,
}
}
export async function _convertToTl (
client: TelegramClient,
obj: InputInlineMessage,
@ -60,6 +246,56 @@ export namespace BotInlineMessage {
}
}
if (obj.type === 'media') {
const [message, entities] = await client['_parseEntities'](obj.text, parseMode, obj.entities)
return {
_: 'inputBotInlineMessageMediaAuto',
message,
entities,
replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup)
}
}
if (obj.type === 'geo') {
return {
_: 'inputBotInlineMessageMediaGeo',
geoPoint: {
_: 'inputGeoPoint',
lat: obj.latitude,
long: obj.longitude
},
heading: obj.heading,
period: obj.period,
proximityNotificationRadius: obj.proximityNotificationRadius,
replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup)
}
}
if (obj.type === 'venue') {
return {
_: 'inputBotInlineMessageMediaVenue',
geoPoint: {
_: 'inputGeoPoint',
lat: obj.latitude,
long: obj.longitude
},
title: obj.title,
address: obj.address,
provider: obj.source?.provider ?? '',
venueId: obj.source?.id ?? '',
venueType: obj.source?.type ?? '',
replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup)
}
}
if (obj.type === 'game') {
return {
_: 'inputBotInlineMessageGame',
replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup)
}
}
return obj as never
}
}

View file

@ -1,6 +1,9 @@
import { tl } from '@mtcute/tl'
import { BotInlineMessage, InputInlineMessage } from './input-inline-message'
import { TelegramClient } from '../../../client'
import { fileIdToInputDocument, fileIdToInputPhoto } from '@mtcute/file-id'
import { extractFileName } from '../../../utils/file-utils'
import { MtCuteArgumentError } from '../../errors'
interface BaseInputInlineResult {
/**
@ -19,7 +22,7 @@ interface BaseInputInlineResult {
}
/**
* Represents an input article.
* Inline result containing an article.
*
* If `message` is not provided, a {@link InputInlineMessageText} is created
* with web preview enabled and text generated as follows:
@ -63,40 +66,615 @@ export interface InputInlineResultArticle extends BaseInputInlineResult {
hideUrl?: boolean
/**
* Article thumbnail URL (only jpeg).
* Article thumbnail URL (must be jpeg).
*/
thumb?: string | tl.RawInputWebDocument
}
export type InputInlineResult = InputInlineResultArticle
/**
* Inline result containing an animation (silent mp4 or gif).
*
* If `message` is not provided, {@link InputInlineMessageMedia} is used
* with empty caption
*/
export interface InputInlineResultGif extends BaseInputInlineResult {
type: 'gif'
/**
* The animation itself.
*
* Can be a URL, a TDLib and Bot API compatible File ID,
* or a TL object representing either of them.
*/
media: string | tl.RawInputWebDocument | tl.RawInputDocument
/**
* Media MIME type, defaults to `video/mp4`, only applicable
* to URLs.
*
* Usually unnecessary, since Telegram automatically infers it.
*/
mime?: string
/**
* Title of the result
*/
title?: string
/**
* Animation thumbnail URL. Defaults to `media`,
* only applicable in case `media` is a URL
*/
thumb?: string | tl.RawInputWebDocument
/**
* Thumbnail MIME type (defaults to `image/jpeg`)
*/
thumbMime?: string
/**
* Width of the animation in pixels
*/
width?: number
/**
* Height of the animation in pixels
*/
height?: number
/**
* Duration of the animation in seconds
*/
duration?: number
}
/**
* Inline result containing a video (only MP4)
*
* If `message` is not provided, {@link InputInlineMessageMedia} is used
* with empty caption for non-embed videos, {@link InputInlineMessageText}
* is used with text containing the URL for embed videos.
*/
export interface InputInlineResultVideo extends BaseInputInlineResult {
type: 'video'
/**
* The video itself, or a page containing an embedded video
*
* Can be a URL, a TDLib and Bot API compatible File ID,
* or a TL object representing either of them.
*/
media: string | tl.RawInputWebDocument | tl.RawInputDocument
/**
* In case `media` is a URL, whether that URL is a link
* to an embedded video player.
*
* In such case, thumbnail must be passed explicitly.
*/
isEmbed?: boolean
/**
* Title of the result
*/
title: string
/**
* Description of the result
*/
description?: string
/**
* Video thumbnail URL (must be jpeg). Defaults to `media`,
* only applicable in case `media` is a URL.
*
* Must be provided explicitly if this is an embed video.
*/
thumb?: string | tl.RawInputWebDocument
/**
* Width of the video in pixels
*/
width?: number
/**
* Height of the video in pixels
*/
height?: number
/**
* Duration of the video in seconds
*/
duration?: number
}
/**
* Inline result containing an audio file
*
* If `message` is not provided, {@link InputInlineMessageMedia} is used
* with empty caption.
*/
export interface InputInlineResultAudio extends BaseInputInlineResult {
type: 'audio'
/**
* The audio itself
*
* Can be a URL, a TDLib and Bot API compatible File ID,
* or a TL object representing either of them.
*/
media: string | tl.RawInputWebDocument | tl.RawInputDocument
/**
* MIME type of the audio file, defaults to `audio/mpeg`
*
* Usually unnecessary, since Telegram infers it automatically.
*/
mime?: string
/**
* Title of the audio track
*/
title: string
/**
* Performer of the audio track
*/
performer?: string
/**
* Duration of the audio in seconds
*/
duration?: number
}
/**
* Inline result containing a voice note
*
* If `message` is not provided, {@link InputInlineMessageMedia} is used
* with empty caption.
*/
export interface InputInlineResultVoice extends BaseInputInlineResult {
type: 'voice'
/**
* The voice itself (.ogg, preferably encoded with OPUS)
*
* Can be a URL, a TDLib and Bot API compatible File ID,
* or a TL object representing either of them.
*/
media: string | tl.RawInputWebDocument | tl.RawInputDocument
/**
* Title of the result
*/
title: string
/**
* Duration of the voice note in seconds
*/
duration?: number
}
/**
* Inline result containing a photo
*
* If `message` is not provided, {@link InputInlineMessageMedia} is used
* with empty caption.
*/
export interface InputInlineResultPhoto extends BaseInputInlineResult {
type: 'photo'
/**
* The photo itself
*
* Can be a URL, a TDLib and Bot API compatible File ID,
* or a TL object representing either of them.
*/
media: string | tl.RawInputWebDocument | tl.RawInputPhoto
/**
* Title of the result
*/
title?: string
/**
* Description of the result
*/
description?: string
/**
* Width of the photo in pixels
*/
width?: number
/**
* Height of the photo in pixels
*/
height?: number
/**
* Photo thumbnail URL (must be jpeg). Defaults to `media`,
* only applicable in case `media` is a URL
*/
thumb?: string | tl.RawInputWebDocument
}
/**
* Inline result containing a sticker
*
* If `message` is not provided, {@link InputInlineMessageMedia} is used.
*/
export interface InputInlineResultSticker extends BaseInputInlineResult {
type: 'sticker'
/**
* The sticker itself. Can't be a URL.
*/
media: string | tl.RawInputDocument
}
/**
* Inline result containing a document
*
* If `message` is not provided, {@link InputInlineMessageMedia} is used
* with empty caption.
*/
export interface InputInlineResultFile extends BaseInputInlineResult {
type: 'file'
/**
* The file itself
*
* Can be a URL, a TDLib and Bot API compatible File ID,
* or a TL object representing either of them.
*/
media: string | tl.RawInputWebDocument | tl.RawInputDocument
/**
* MIME type of the file.
*
* Due to some Telegram limitation, you can only send
* PDF and ZIP files (`application/pdf` and `application/zip`
* MIMEs respectively).
*
* Must be provided if `media` is a URL
*/
mime?: string
/**
* Title of the result
*/
title?: string
/**
* Description of the result
*/
description?: string
/**
* Photo thumbnail URL (must be jpeg). Defaults to `media`,
* only applicable in case `media` is a URL
*/
thumb?: string | tl.RawInputWebDocument
}
/**
* Inline result containing a geolocation.
*
* If `message` is not passed, a {@link InputInlineMessageGeo} is
* used, with the `latitude` and `longitude` parameters set
* accordingly
*/
export interface InputInlineResultGeo extends BaseInputInlineResult {
type: 'geo'
/**
* Title of the result
*/
title: string
/**
* Latitude of the geolocation
*/
latitude: number
/**
* Longitude of the geolocation
*/
longitude: number
/**
* Location thumbnail URL (must be jpeg).
*
* By default, Telegram generates one based on
* the location set by `latitude` and `longitude`
*/
thumb?: string | tl.RawInputWebDocument
}
/**
* Inline result containing a venue.
*
* If `message` is not passed, an error is thrown.
*/
export interface InputInlineResultVenue extends BaseInputInlineResult {
type: 'venue'
/**
* Title of the venue
*/
title: string
/**
* Address of the venue
*/
address: string
/**
* Venue thumbnail URL (must be jpeg).
*
* By default, Telegram generates one based on
* the location in the `message`
*/
thumb?: string | tl.RawInputWebDocument
}
/**
* Inline result containing a game.
*
* If `message` is not passed, {@link InputInlineMessageGame} is used.
*
* Note that `message` can only be {@link InputInlineMessageGame}
*/
export interface InputInlineResultGame extends BaseInputInlineResult {
type: 'game'
/**
* Short name of the game
*/
shortName: string
}
/**
* Inline result containing a contact.
*
* If `message` is not passed, {@link InputInlineMessageContact} is used.
*/
export interface InputInlineResultContact extends BaseInputInlineResult {
type: 'contact'
/**
* First name of the contact
*/
firstName: string
/**
* Last name of the contact
*/
lastName?: string
/**
* Phone number of the contact
*/
phone: string
/**
* Contact thumbnail URL (i.e. their avatar) (must be jpeg)
*/
thumb?: string | tl.RawInputWebDocument
}
export type InputInlineResult =
| InputInlineResultArticle
| InputInlineResultGif
| InputInlineResultVideo
| InputInlineResultAudio
| InputInlineResultVoice
| InputInlineResultPhoto
| InputInlineResultSticker
| InputInlineResultFile
| InputInlineResultGeo
| InputInlineResultVenue
| InputInlineResultGame
| InputInlineResultContact
export namespace BotInline {
export function article(
params: Omit<InputInlineResultArticle, 'type'>
id: string,
params: Omit<InputInlineResultArticle, 'type' | 'id'>
): InputInlineResultArticle {
return {
id,
type: 'article',
...params,
}
}
export function gif(
id: string,
media: string | tl.RawInputWebDocument | tl.RawInputDocument,
params: Omit<InputInlineResultGif, 'type' | 'id' | 'media'>
): InputInlineResultGif {
return {
id,
media,
type: 'gif',
...params,
}
}
export function video(
id: string,
media: string | tl.RawInputWebDocument | tl.RawInputDocument,
params: Omit<InputInlineResultVideo, 'type' | 'id' | 'media'>
): InputInlineResultVideo {
return {
id,
type: 'video',
media,
...params,
}
}
export function audio(
id: string,
media: string | tl.RawInputWebDocument | tl.RawInputDocument,
params: Omit<InputInlineResultAudio, 'type' | 'id' | 'media'>
): InputInlineResultAudio {
return {
id,
type: 'audio',
media,
...params,
}
}
export function voice(
id: string,
media: string | tl.RawInputWebDocument | tl.RawInputDocument,
params: Omit<InputInlineResultVoice, 'type' | 'id' | 'media'>
): InputInlineResultVoice {
return {
id,
type: 'voice',
media,
...params,
}
}
export function photo(
id: string,
media: string | tl.RawInputWebDocument | tl.RawInputPhoto,
params: Omit<InputInlineResultPhoto, 'type' | 'id' | 'media'>
): InputInlineResultPhoto {
return {
id,
type: 'photo',
media,
...params,
}
}
export function sticker(
id: string,
media: string | tl.RawInputDocument
): InputInlineResultSticker {
return {
id,
type: 'sticker',
media,
}
}
export function file(
id: string,
media: string | tl.RawInputWebDocument | tl.RawInputDocument,
params: Omit<InputInlineResultFile, 'type' | 'id' | 'media'>
): InputInlineResultFile {
return {
id,
type: 'file',
media,
...params,
}
}
export function geo(
latitude: number,
longitude: number,
params: Omit<InputInlineResultGeo, 'type' | 'latitude' | 'longitude'>
): InputInlineResultGeo {
return {
type: 'geo',
latitude,
longitude,
...params,
}
}
export function venue(
id: string,
params: Omit<InputInlineResultVenue, 'type' | 'id'>
): InputInlineResultVenue {
return {
id,
type: 'venue',
...params,
}
}
export function contact(
id: string,
params: Omit<InputInlineResultContact, 'type' | 'id'>
): InputInlineResultContact {
return {
id,
type: 'contact',
...params,
}
}
export function game(
id: string,
shortName: string,
params?: Omit<InputInlineResultGame, 'type' | 'id' | 'shortName'>
): InputInlineResultGame {
return {
id,
type: 'game',
shortName,
...(params || {})
}
}
export async function _convertToTl(
client: TelegramClient,
obj: InputInlineResult,
parseMode?: string | null
): Promise<tl.TypeInputBotInlineResult> {
const normalizeThumb = (
obj: InputInlineResult,
fallback?: string
): tl.RawInputWebDocument | undefined => {
if (obj.type !== 'voice' && obj.type !== 'audio' && obj.type !== 'sticker' && obj.type !== 'game') {
if (!obj.thumb || typeof obj.thumb === 'string') {
if (!obj.thumb && !fallback) {
return undefined
}
return {
_: 'inputWebDocument',
size: 0,
url: obj.thumb || fallback!,
mimeType:
obj.type === 'gif'
? obj.thumbMime ?? 'image/jpeg'
: 'image/jpeg',
attributes: [],
}
} else {
return obj.thumb
}
}
}
if (obj.type === 'article') {
let sendMessage: tl.TypeInputBotInlineMessage
if (obj.message) {
sendMessage = await BotInlineMessage._convertToTl(client, obj.message, parseMode)
sendMessage = await BotInlineMessage._convertToTl(
client,
obj.message,
parseMode
)
} else {
let message = obj.title
const entities: tl.TypeMessageEntity[] = [
{
_: 'messageEntityBold',
offset: 0,
length: message.length
}
length: message.length,
},
]
if (obj.url) {
@ -104,7 +682,7 @@ export namespace BotInline {
_: 'messageEntityTextUrl',
url: obj.url,
offset: 0,
length: message.length
length: message.length,
})
}
@ -115,7 +693,7 @@ export namespace BotInline {
sendMessage = {
_: 'inputBotInlineMessageText',
message,
entities
entities,
}
}
@ -126,24 +704,235 @@ export namespace BotInline {
title: obj.title,
description: obj.description,
url: obj.hideUrl ? undefined : obj.url,
content: obj.url && obj.hideUrl ? {
content:
obj.url && obj.hideUrl
? {
_: 'inputWebDocument',
url: obj.url,
mimeType: 'text/html',
size: 0,
attributes: []
} : undefined,
thumb: typeof obj.thumb === 'string' ? {
_: 'inputWebDocument',
size: 0,
url: obj.thumb,
mimeType: 'image/jpeg',
attributes: [],
} : obj.thumb,
}
: undefined,
thumb:
typeof obj.thumb === 'string'
? normalizeThumb(obj)
: obj.thumb,
sendMessage,
}
}
if (obj.type === 'game') {
let sendMessage: tl.TypeInputBotInlineMessage
if (obj.message) {
sendMessage = await BotInlineMessage._convertToTl(
client,
obj.message,
parseMode
)
if (sendMessage._ !== 'inputBotInlineMessageGame') {
throw new MtCuteArgumentError('game inline result must contain a game inline message')
}
} else {
sendMessage = {
_: 'inputBotInlineMessageGame'
}
}
return {
_: 'inputBotInlineResultGame',
id: obj.id,
shortName: obj.shortName,
sendMessage
}
}
return obj as never
let sendMessage: tl.TypeInputBotInlineMessage
if (obj.message) {
sendMessage = await BotInlineMessage._convertToTl(
client,
obj.message,
parseMode
)
} else {
if (obj.type === 'venue')
throw new MtCuteArgumentError('message bust be supplied for venue inline result')
if (
obj.type === 'video' &&
obj.isEmbed &&
typeof obj.media === 'string'
) {
sendMessage = {
_: 'inputBotInlineMessageText',
message: obj.media,
}
} else if (obj.type === 'geo') {
sendMessage = {
_: 'inputBotInlineMessageMediaGeo',
geoPoint: {
_: 'inputGeoPoint',
lat: obj.latitude,
long: obj.longitude,
},
}
} else if (obj.type === 'contact') {
sendMessage = {
_: 'inputBotInlineMessageMediaContact',
phoneNumber: obj.phone,
firstName: obj.firstName,
lastName: obj.lastName ?? '',
vcard: ''
}
} else {
sendMessage = {
_: 'inputBotInlineMessageMediaAuto',
message: '',
}
}
}
let media:
| tl.TypeInputWebDocument
| tl.TypeInputDocument
| tl.TypeInputPhoto
| undefined = undefined
if (obj.type !== 'geo' && obj.type !== 'venue' && obj.type !== 'contact') {
if (typeof obj.media === 'string') {
// file id or url
if (obj.media.match(/^https?:\/\//)) {
if (obj.type === 'sticker')
throw new MtCuteArgumentError('sticker inline result cannot contain a URL')
let mime: string
if (obj.type === 'video') mime = 'video/mp4'
else if (obj.type === 'audio')
mime = obj.mime ?? 'audio/mpeg'
else if (obj.type === 'gif') mime = obj.mime ?? 'image/jpeg'
else if (obj.type === 'voice') mime = 'audio/ogg'
else if (obj.type === 'file') {
if (!obj.mime)
throw new MtCuteArgumentError(
'MIME type must be specified for file inline result'
)
mime = obj.mime
} else mime = 'image/jpeg'
const attributes: tl.TypeDocumentAttribute[] = []
if (
(obj.type === 'video' ||
obj.type === 'gif' ||
obj.type === 'photo') &&
obj.width &&
obj.height
) {
if (obj.type !== 'photo' && obj.duration) {
attributes.push({
_: 'documentAttributeVideo',
w: obj.width,
h: obj.height,
duration: obj.duration,
})
} else {
attributes.push({
_: 'documentAttributeImageSize',
w: obj.width,
h: obj.height,
})
}
} else if (obj.type === 'audio' || obj.type === 'voice') {
attributes.push({
_: 'documentAttributeAudio',
voice: obj.type === 'voice',
duration: obj.duration ?? 0,
title: obj.type === 'audio' ? obj.title : '',
performer:
obj.type === 'audio' ? obj.performer : '',
})
}
attributes.push({
_: 'documentAttributeFilename',
fileName: extractFileName(obj.media),
})
media = {
_: 'inputWebDocument',
url: obj.media,
mimeType: mime,
size: 0,
attributes,
}
} else if (obj.type === 'photo') {
media = fileIdToInputPhoto(obj.media)
} else {
media = fileIdToInputDocument(obj.media)
}
} else {
media = obj.media
}
}
let title: string | undefined = undefined
let description: string | undefined = undefined
// incredible hacks by durov team.
// i honestly don't understand why didn't they just
// make a bunch of types, as they normally do,
// but whatever.
// ref: https://github.com/tdlib/td/blob/master/td/telegram/InlineQueriesManager.cpp
if (obj.type === 'contact') {
title = obj.lastName?.length ? `${obj.firstName} ${obj.lastName}` : obj.firstName
} else if (obj.type !== 'sticker') {
title = obj.title
}
if (obj.type === 'audio') {
description = obj.performer
} else if (obj.type === 'geo') {
description = `${obj.latitude} ${obj.longitude}`
} else if (obj.type === 'venue') {
description = obj.address
} else if (obj.type === 'contact') {
description = obj.phone
} else if (obj.type !== 'gif' && obj.type !== 'voice' && obj.type !== 'sticker') {
description = obj.description
}
if (!media || media._ === 'inputWebDocument') {
return {
_: 'inputBotInlineResult',
id: obj.id,
type: obj.type,
title,
description,
content: media,
thumb: normalizeThumb(obj, media?.url),
sendMessage,
}
}
if (media._ === 'inputPhoto') {
return {
_: 'inputBotInlineResultPhoto',
id: obj.id,
type: obj.type,
photo: media,
sendMessage,
}
}
return {
_: 'inputBotInlineResultDocument',
id: obj.id,
type: obj.type,
title,
description,
document: media,
sendMessage,
}
}
}

View file

@ -84,7 +84,7 @@ export class FileLocation {
*
* Shorthand for `client.downloadAsStream({ location: this })`
*
* @see TelegramClient.downloadAsIterable
* @link TelegramClient.downloadAsIterable
*/
downloadIterable(): AsyncIterableIterator<Buffer> {
return this.client.downloadAsIterable({ location: this })
@ -96,7 +96,7 @@ export class FileLocation {
*
* Shorthand for `client.downloadAsStream({ location: this })`
*
* @see TelegramClient.downloadAsStream
* @link TelegramClient.downloadAsStream
*/
downloadStream(): Readable {
return this.client.downloadAsStream({ location: this })
@ -107,7 +107,7 @@ export class FileLocation {
*
* Shorthand for `client.downloadAsBuffer({ location: this })`
*
* @see TelegramClient.downloadAsBuffer
* @link TelegramClient.downloadAsBuffer
*/
downloadBuffer(): Promise<Buffer> {
return this.client.downloadAsBuffer({ location: this })
@ -120,7 +120,7 @@ export class FileLocation {
* Shorthand for `client.downloadToFile(filename, { location: this })`
*
* @param filename Local file name
* @see TelegramClient.downloadToFile
* @link TelegramClient.downloadToFile
*/
downloadToFile(filename: string): Promise<void> {
return this.client.downloadToFile(filename, { location: this })

View file

@ -240,7 +240,7 @@ export interface InputMediaVideo extends BaseInputMedia {
* applicable if `file` is {@link UploadFileLike},
* otherwise they are ignored.
*
* @see InputMedia
* @link InputMedia
*/
export type InputMediaLike =
| InputMediaAudio

View file

@ -931,7 +931,7 @@ export class Message {
/**
* Edit this message's text and/or reply markup
*
* @see TelegramClient.editMessage
* @link TelegramClient.editMessage
*/
edit(
params: Parameters<TelegramClient['editMessage']>[2]
@ -947,7 +947,7 @@ export class Message {
*
* @param text New message text
* @param params Additional parameters
* @see TelegramClient.editMessage
* @link TelegramClient.editMessage
*/
editText(
text: string,