parent
efc68b895d
commit
2cbed9b883
6 changed files with 514 additions and 14 deletions
|
@ -13,7 +13,7 @@ import type { BaseTelegramClientOptions } from './base.js'
|
||||||
import { BaseTelegramClient } from './base.js'
|
import { BaseTelegramClient } from './base.js'
|
||||||
import type { ITelegramClient } from './client.types.js'
|
import type { ITelegramClient } from './client.types.js'
|
||||||
import type { RawUpdateInfo } from './updates/types.js'
|
import type { RawUpdateInfo } from './updates/types.js'
|
||||||
import type { AllStories, ArrayPaginated, ArrayWithTotal, Boost, BoostSlot, BoostStats, BotChatJoinRequestUpdate, BotCommands, BotReactionCountUpdate, BotReactionUpdate, BotStoppedUpdate, BusinessCallbackQuery, BusinessChatLink, BusinessConnection, BusinessMessage, BusinessWorkHoursDay, CallbackQuery, Chat, ChatEvent, ChatInviteLink, ChatInviteLinkMember, ChatJoinRequestUpdate, ChatMember, ChatMemberUpdate, ChatPreview, ChatlistPreview, ChosenInlineResult, CollectibleInfo, DeleteBusinessMessageUpdate, DeleteMessageUpdate, DeleteStoryUpdate, Dialog, FactCheck, FileDownloadLocation, FileDownloadParameters, ForumTopic, FullChat, GameHighScore, HistoryReadUpdate, InlineCallbackQuery, InlineQuery, InputChatEventFilters, InputDialogFolder, InputFileLike, InputInlineResult, InputMediaLike, InputMediaSticker, InputMessageId, InputPeerLike, InputPrivacyRule, InputReaction, InputStickerSet, InputStickerSetItem, InputText, MaybeDynamic, Message, MessageEffect, MessageMedia, MessageReactions, ParametersSkip2, ParsedUpdate, PeerReaction, PeerStories, Photo, Poll, PollUpdate, PollVoteUpdate, PreCheckoutQuery, RawDocument, ReplyMarkup, SentCode, StarGift, StarsStatus, StarsTransaction, Sticker, StickerSet, StickerType, StoriesStealthMode, Story, StoryInteractions, StoryUpdate, StoryViewer, StoryViewersList, TakeoutSession, TextWithEntities, TypingStatus, UploadFileLike, UploadedFile, User, UserStarGift, UserStatusUpdate, UserTypingUpdate } from './types/index.js'
|
import type { AllStories, ArrayPaginated, ArrayWithTotal, Boost, BoostSlot, BoostStats, BotChatJoinRequestUpdate, BotCommands, BotReactionCountUpdate, BotReactionUpdate, BotStoppedUpdate, BusinessCallbackQuery, BusinessChatLink, BusinessConnection, BusinessMessage, BusinessWorkHoursDay, CallbackQuery, Chat, ChatEvent, ChatInviteLink, ChatInviteLinkMember, ChatJoinRequestUpdate, ChatMember, ChatMemberUpdate, ChatPreview, ChatlistPreview, ChosenInlineResult, CollectibleInfo, DeleteBusinessMessageUpdate, DeleteMessageUpdate, DeleteStoryUpdate, Dialog, FactCheck, FileDownloadLocation, FileDownloadParameters, ForumTopic, FullChat, GameHighScore, HistoryReadUpdate, InlineCallbackQuery, InlineQuery, InputChatEventFilters, InputDialogFolder, InputFileLike, InputInlineResult, InputMediaLike, InputMediaSticker, InputMessageId, InputPeerLike, InputPrivacyRule, InputReaction, InputStickerSet, InputStickerSetItem, InputText, InputWebview, MaybeDynamic, Message, MessageEffect, MessageMedia, MessageReactions, ParametersSkip2, ParsedUpdate, PeerReaction, PeerStories, Photo, Poll, PollUpdate, PollVoteUpdate, PreCheckoutQuery, RawDocument, ReplyMarkup, SentCode, StarGift, StarsStatus, StarsTransaction, Sticker, StickerSet, StickerType, StoriesStealthMode, Story, StoryInteractions, StoryUpdate, StoryViewer, StoryViewersList, TakeoutSession, TextWithEntities, TypingStatus, UploadFileLike, UploadedFile, User, UserStarGift, UserStatusUpdate, UserTypingUpdate, WebviewResult } from './types/index.js'
|
||||||
import type { StringSessionData } from './utils/string-session.js'
|
import type { StringSessionData } from './utils/string-session.js'
|
||||||
import type { ITelegramStorageProvider } from './storage/provider.js'
|
import type { ITelegramStorageProvider } from './storage/provider.js'
|
||||||
import { Conversation } from './types/conversation.js'
|
import { Conversation } from './types/conversation.js'
|
||||||
|
@ -43,6 +43,7 @@ import { getBotMenuButton } from './methods/bots/get-bot-menu-button.js'
|
||||||
import { getCallbackAnswer } from './methods/bots/get-callback-answer.js'
|
import { getCallbackAnswer } from './methods/bots/get-callback-answer.js'
|
||||||
import { getGameHighScores, getInlineGameHighScores } from './methods/bots/get-game-high-scores.js'
|
import { getGameHighScores, getInlineGameHighScores } from './methods/bots/get-game-high-scores.js'
|
||||||
import { getMyCommands } from './methods/bots/get-my-commands.js'
|
import { getMyCommands } from './methods/bots/get-my-commands.js'
|
||||||
|
import { closeWebview, openWebview } from './methods/bots/open-webview.js'
|
||||||
import { prepareInlineMessage } from './methods/bots/prepare-inline-message.js'
|
import { prepareInlineMessage } from './methods/bots/prepare-inline-message.js'
|
||||||
import { setBotInfo } from './methods/bots/set-bot-info.js'
|
import { setBotInfo } from './methods/bots/set-bot-info.js'
|
||||||
import { setBotMenuButton } from './methods/bots/set-bot-menu-button.js'
|
import { setBotMenuButton } from './methods/bots/set-bot-menu-button.js'
|
||||||
|
@ -280,7 +281,7 @@ import { setGlobalTtl } from './methods/users/set-global-ttl.js'
|
||||||
import { setMyBirthday } from './methods/users/set-my-birthday.js'
|
import { setMyBirthday } from './methods/users/set-my-birthday.js'
|
||||||
import { setMyProfilePhoto } from './methods/users/set-my-profile-photo.js'
|
import { setMyProfilePhoto } from './methods/users/set-my-profile-photo.js'
|
||||||
import { setMyUsername } from './methods/users/set-my-username.js'
|
import { setMyUsername } from './methods/users/set-my-username.js'
|
||||||
import { setOffline, setOnline } from './methods/users/set-online.js'
|
import { sendOnline, setOnline } from './methods/users/set-online.js'
|
||||||
import { unblockUser } from './methods/users/unblock-user.js'
|
import { unblockUser } from './methods/users/unblock-user.js'
|
||||||
import { updateProfile } from './methods/users/update-profile.js'
|
import { updateProfile } from './methods/users/update-profile.js'
|
||||||
import { withParams } from './methods/misc/with-params.js'
|
import { withParams } from './methods/misc/with-params.js'
|
||||||
|
@ -988,6 +989,92 @@ export interface TelegramClient extends ITelegramClient {
|
||||||
*/
|
*/
|
||||||
langCode?: string
|
langCode?: string
|
||||||
}): Promise<tl.RawBotCommand[]>
|
}): Promise<tl.RawBotCommand[]>
|
||||||
|
/**
|
||||||
|
* Open a webview.
|
||||||
|
* **Available**: 👤 users only
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
openWebview(
|
||||||
|
params: {
|
||||||
|
/** Information about the webview to open */
|
||||||
|
webview: InputWebview
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bot whose webview to open
|
||||||
|
*/
|
||||||
|
bot: InputPeerLike
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat to report to the server as the "currently open chat",
|
||||||
|
* also the chat to which the message will be sent in case of
|
||||||
|
* `from_inline_keyboard`, `from_bot_menu` and `from_attach_menu` webviews
|
||||||
|
*/
|
||||||
|
chat?: InputPeerLike
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Theme parameters to pass to the mini app
|
||||||
|
*
|
||||||
|
* Each value should be a string (hex-encoded RGB, no alpha)
|
||||||
|
*/
|
||||||
|
theme?: tl.TypeDataJSON | {
|
||||||
|
// https://corefork.telegram.org/api/bots/webapps#theme-parameters
|
||||||
|
/** Background color */
|
||||||
|
bg_color?: string
|
||||||
|
/** Secondary background color */
|
||||||
|
secondary_bg_color?: string
|
||||||
|
/** Text color */
|
||||||
|
text_color?: string
|
||||||
|
/** Hint text color */
|
||||||
|
hint_color?: string
|
||||||
|
/** Link color */
|
||||||
|
link_color?: string
|
||||||
|
/** Button color */
|
||||||
|
button_color?: string
|
||||||
|
/** Button text color */
|
||||||
|
button_text_color?: string
|
||||||
|
/** Header background color */
|
||||||
|
header_bg_color?: string
|
||||||
|
/** Accent text color */
|
||||||
|
accent_text_color?: string
|
||||||
|
/** Section background color */
|
||||||
|
section_bg_color?: string
|
||||||
|
/** Section header text color */
|
||||||
|
section_header_text_color?: string
|
||||||
|
/** Section separator color */
|
||||||
|
section_separator_color?: string
|
||||||
|
/** Sub title text color */
|
||||||
|
subtitle_text_color?: string
|
||||||
|
/** Text color for destructive action buttons in prompts */
|
||||||
|
destructive_text_color?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Webview platform to use in the init data
|
||||||
|
*
|
||||||
|
* Some of the known values:
|
||||||
|
* - `android` - Android clients
|
||||||
|
* - `ios` - iOS clients
|
||||||
|
* - `tdesktop` - Telegram Desktop
|
||||||
|
* - `macos` - Telegram for macOS
|
||||||
|
* - `unigram` - Unigram
|
||||||
|
*/
|
||||||
|
platform:
|
||||||
|
| 'android'
|
||||||
|
| 'ios'
|
||||||
|
| 'tdesktop'
|
||||||
|
| 'macos'
|
||||||
|
| 'unigram'
|
||||||
|
| (string & {})
|
||||||
|
}): Promise<WebviewResult>
|
||||||
|
/**
|
||||||
|
* Close a webview previously opened by {@link openWebview} method.
|
||||||
|
*
|
||||||
|
* **Available**: ✅ both users and bots
|
||||||
|
*
|
||||||
|
* @param webview Webview result returned by {@link openWebview}, or its `.queryId`
|
||||||
|
*/
|
||||||
|
closeWebview(
|
||||||
|
webview: WebviewResult | tl.Long): Promise<void>
|
||||||
/**
|
/**
|
||||||
* Prepare an inline message result to be sent later via the
|
* Prepare an inline message result to be sent later via the
|
||||||
* `shareMessage` [mini-app api method](https://core.telegram.org/bots/webapps#initializing-mini-apps).
|
* `shareMessage` [mini-app api method](https://core.telegram.org/bots/webapps#initializing-mini-apps).
|
||||||
|
@ -4206,12 +4293,13 @@ export interface TelegramClient extends ITelegramClient {
|
||||||
* automatically cancelled if you send a
|
* automatically cancelled if you send a
|
||||||
* message.
|
* message.
|
||||||
*
|
*
|
||||||
|
* If you need a continuous typing status, use {@link setTyping} instead.
|
||||||
|
*
|
||||||
* **Available**: ✅ both users and bots
|
* **Available**: ✅ both users and bots
|
||||||
*
|
*
|
||||||
* @param chatId Chat ID
|
* @param chatId Chat ID
|
||||||
* @param [status='typing'] Typing status
|
* @param [status='typing'] Typing status
|
||||||
* @param params
|
* @param params
|
||||||
* @deprecated - use {@link setTyping} instead
|
|
||||||
*/
|
*/
|
||||||
sendTyping(
|
sendTyping(
|
||||||
chatId: InputPeerLike, status?: Exclude<TypingStatus, 'interaction' | 'interaction_seen'> | tl.TypeSendMessageAction,
|
chatId: InputPeerLike, status?: Exclude<TypingStatus, 'interaction' | 'interaction_seen'> | tl.TypeSendMessageAction,
|
||||||
|
@ -4250,7 +4338,7 @@ export interface TelegramClient extends ITelegramClient {
|
||||||
* Sets whether a user is typing in a specific chat
|
* Sets whether a user is typing in a specific chat
|
||||||
*
|
*
|
||||||
* This status is automatically renewed by mtcute until a further
|
* This status is automatically renewed by mtcute until a further
|
||||||
* call with `sendMessageCancelAction` is made, or a message is sent to the chat.
|
* call with `cancel` is made, or a message is sent to the chat.
|
||||||
* **Available**: ✅ both users and bots
|
* **Available**: ✅ both users and bots
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -4258,12 +4346,13 @@ export interface TelegramClient extends ITelegramClient {
|
||||||
params: {
|
params: {
|
||||||
/** Chat ID where the user is currently typing */
|
/** Chat ID where the user is currently typing */
|
||||||
peerId: InputPeerLike
|
peerId: InputPeerLike
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Typing status to send (false is a shortcut for `{ _: 'sendMessageCancelAction' }`)
|
* Typing status to send
|
||||||
*
|
*
|
||||||
* @default `{ _: 'sendMessageTypingAction' }`
|
* @default `typing`
|
||||||
*/
|
*/
|
||||||
status?: tl.TypeSendMessageAction | false
|
status?: Exclude<TypingStatus, 'interaction' | 'interaction_seen'> | tl.TypeSendMessageAction
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For `upload_*` and history import actions, progress of the upload
|
* For `upload_*` and history import actions, progress of the upload
|
||||||
|
@ -5750,14 +5839,16 @@ export interface TelegramClient extends ITelegramClient {
|
||||||
*/
|
*/
|
||||||
setMyUsername(username: string | null): Promise<User>
|
setMyUsername(username: string | null): Promise<User>
|
||||||
/**
|
/**
|
||||||
* Change user status to offline or online
|
* Change user status to offline or online once,
|
||||||
|
* which will expire after a while (currently ~5 minutes)
|
||||||
|
*
|
||||||
|
* For continuously sending online/offline status, use {@link setOnline}
|
||||||
*
|
*
|
||||||
* **Available**: 👤 users only
|
* **Available**: 👤 users only
|
||||||
*
|
*
|
||||||
* @param [offline=true] Whether the user is currently offline
|
* @param online Whether the user is currently online
|
||||||
* @deprecated - use {@link setOnline} instead
|
|
||||||
*/
|
*/
|
||||||
setOffline(offline?: boolean): Promise<void>
|
sendOnline(online: boolean): Promise<void>
|
||||||
/**
|
/**
|
||||||
* Change user status to online or offline
|
* Change user status to online or offline
|
||||||
*
|
*
|
||||||
|
@ -6042,6 +6133,12 @@ TelegramClient.prototype.getInlineGameHighScores = function (...args) {
|
||||||
TelegramClient.prototype.getMyCommands = function (...args) {
|
TelegramClient.prototype.getMyCommands = function (...args) {
|
||||||
return getMyCommands(this._client, ...args)
|
return getMyCommands(this._client, ...args)
|
||||||
}
|
}
|
||||||
|
TelegramClient.prototype.openWebview = function (...args) {
|
||||||
|
return openWebview(this._client, ...args)
|
||||||
|
}
|
||||||
|
TelegramClient.prototype.closeWebview = function (...args) {
|
||||||
|
return closeWebview(this._client, ...args)
|
||||||
|
}
|
||||||
TelegramClient.prototype.prepareInlineMessage = function (...args) {
|
TelegramClient.prototype.prepareInlineMessage = function (...args) {
|
||||||
return prepareInlineMessage(this._client, ...args)
|
return prepareInlineMessage(this._client, ...args)
|
||||||
}
|
}
|
||||||
|
@ -6779,8 +6876,8 @@ TelegramClient.prototype.setMyProfilePhoto = function (...args) {
|
||||||
TelegramClient.prototype.setMyUsername = function (...args) {
|
TelegramClient.prototype.setMyUsername = function (...args) {
|
||||||
return setMyUsername(this._client, ...args)
|
return setMyUsername(this._client, ...args)
|
||||||
}
|
}
|
||||||
TelegramClient.prototype.setOffline = function (...args) {
|
TelegramClient.prototype.sendOnline = function (...args) {
|
||||||
return setOffline(this._client, ...args)
|
return sendOnline(this._client, ...args)
|
||||||
}
|
}
|
||||||
TelegramClient.prototype.setOnline = function (...args) {
|
TelegramClient.prototype.setOnline = function (...args) {
|
||||||
return setOnline(this._client, ...args)
|
return setOnline(this._client, ...args)
|
||||||
|
|
|
@ -24,6 +24,8 @@ export { getCallbackAnswer } from './methods/bots/get-callback-answer.js'
|
||||||
export { getGameHighScores } from './methods/bots/get-game-high-scores.js'
|
export { getGameHighScores } from './methods/bots/get-game-high-scores.js'
|
||||||
export { getInlineGameHighScores } from './methods/bots/get-game-high-scores.js'
|
export { getInlineGameHighScores } from './methods/bots/get-game-high-scores.js'
|
||||||
export { getMyCommands } from './methods/bots/get-my-commands.js'
|
export { getMyCommands } from './methods/bots/get-my-commands.js'
|
||||||
|
export { openWebview } from './methods/bots/open-webview.js'
|
||||||
|
export { closeWebview } from './methods/bots/open-webview.js'
|
||||||
export { prepareInlineMessage } from './methods/bots/prepare-inline-message.js'
|
export { prepareInlineMessage } from './methods/bots/prepare-inline-message.js'
|
||||||
export { setBotInfo } from './methods/bots/set-bot-info.js'
|
export { setBotInfo } from './methods/bots/set-bot-info.js'
|
||||||
export { setBotMenuButton } from './methods/bots/set-bot-menu-button.js'
|
export { setBotMenuButton } from './methods/bots/set-bot-menu-button.js'
|
||||||
|
@ -282,7 +284,7 @@ export { setGlobalTtl } from './methods/users/set-global-ttl.js'
|
||||||
export { setMyBirthday } from './methods/users/set-my-birthday.js'
|
export { setMyBirthday } from './methods/users/set-my-birthday.js'
|
||||||
export { setMyProfilePhoto } from './methods/users/set-my-profile-photo.js'
|
export { setMyProfilePhoto } from './methods/users/set-my-profile-photo.js'
|
||||||
export { setMyUsername } from './methods/users/set-my-username.js'
|
export { setMyUsername } from './methods/users/set-my-username.js'
|
||||||
export { setOffline } from './methods/users/set-online.js'
|
export { sendOnline } from './methods/users/set-online.js'
|
||||||
export { setOnline } from './methods/users/set-online.js'
|
export { setOnline } from './methods/users/set-online.js'
|
||||||
export { unblockUser } from './methods/users/unblock-user.js'
|
export { unblockUser } from './methods/users/unblock-user.js'
|
||||||
export { updateProfile } from './methods/users/update-profile.js'
|
export { updateProfile } from './methods/users/update-profile.js'
|
||||||
|
|
|
@ -71,6 +71,7 @@ import {
|
||||||
InputStickerSet,
|
InputStickerSet,
|
||||||
InputStickerSetItem,
|
InputStickerSetItem,
|
||||||
InputText,
|
InputText,
|
||||||
|
InputWebview,
|
||||||
MaybeDynamic,
|
MaybeDynamic,
|
||||||
Message,
|
Message,
|
||||||
MessageEffect,
|
MessageEffect,
|
||||||
|
@ -111,6 +112,7 @@ import {
|
||||||
UserStarGift,
|
UserStarGift,
|
||||||
UserStatusUpdate,
|
UserStatusUpdate,
|
||||||
UserTypingUpdate,
|
UserTypingUpdate,
|
||||||
|
WebviewResult,
|
||||||
} from '../types/index.js'
|
} from '../types/index.js'
|
||||||
// @copy
|
// @copy
|
||||||
import { StringSessionData } from '../utils/string-session.js'
|
import { StringSessionData } from '../utils/string-session.js'
|
||||||
|
|
245
packages/core/src/highlevel/methods/bots/open-webview.ts
Normal file
245
packages/core/src/highlevel/methods/bots/open-webview.ts
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
import type { tl } from '@mtcute/tl'
|
||||||
|
import { asNonNull } from '@fuman/utils'
|
||||||
|
import Long from 'long'
|
||||||
|
|
||||||
|
import type { ITelegramClient } from '../../client.types.js'
|
||||||
|
import type { InputPeerLike } from '../../types/index.js'
|
||||||
|
import { type InputWebview, WebviewResult } from '../../types/bots/webview.js'
|
||||||
|
import { resolvePeer, resolveUser } from '../users/resolve-peer.js'
|
||||||
|
import { longToFastString } from '../../../utils/long-utils.js'
|
||||||
|
import { toInputPeer } from '../../utils/peer-utils.js'
|
||||||
|
import { assertNever } from '../../../types/utils.js'
|
||||||
|
|
||||||
|
const _getWebviewTimerId = (queryId: tl.Long) => `webview:${longToFastString(queryId)}`
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a webview.
|
||||||
|
*/
|
||||||
|
export async function openWebview(
|
||||||
|
client: ITelegramClient,
|
||||||
|
params: {
|
||||||
|
/** Information about the webview to open */
|
||||||
|
webview: InputWebview
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bot whose webview to open
|
||||||
|
*/
|
||||||
|
bot: InputPeerLike
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat to report to the server as the "currently open chat",
|
||||||
|
* also the chat to which the message will be sent in case of
|
||||||
|
* `from_inline_keyboard`, `from_bot_menu` and `from_attach_menu` webviews
|
||||||
|
*/
|
||||||
|
chat?: InputPeerLike
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Theme parameters to pass to the mini app
|
||||||
|
*
|
||||||
|
* Each value should be a string (hex-encoded RGB, no alpha)
|
||||||
|
*/
|
||||||
|
theme?: tl.TypeDataJSON | {
|
||||||
|
// https://corefork.telegram.org/api/bots/webapps#theme-parameters
|
||||||
|
/** Background color */
|
||||||
|
bg_color?: string
|
||||||
|
/** Secondary background color */
|
||||||
|
secondary_bg_color?: string
|
||||||
|
/** Text color */
|
||||||
|
text_color?: string
|
||||||
|
/** Hint text color */
|
||||||
|
hint_color?: string
|
||||||
|
/** Link color */
|
||||||
|
link_color?: string
|
||||||
|
/** Button color */
|
||||||
|
button_color?: string
|
||||||
|
/** Button text color */
|
||||||
|
button_text_color?: string
|
||||||
|
/** Header background color */
|
||||||
|
header_bg_color?: string
|
||||||
|
/** Accent text color */
|
||||||
|
accent_text_color?: string
|
||||||
|
/** Section background color */
|
||||||
|
section_bg_color?: string
|
||||||
|
/** Section header text color */
|
||||||
|
section_header_text_color?: string
|
||||||
|
/** Section separator color */
|
||||||
|
section_separator_color?: string
|
||||||
|
/** Sub title text color */
|
||||||
|
subtitle_text_color?: string
|
||||||
|
/** Text color for destructive action buttons in prompts */
|
||||||
|
destructive_text_color?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Webview platform to use in the init data
|
||||||
|
*
|
||||||
|
* Some of the known values:
|
||||||
|
* - `android` - Android clients
|
||||||
|
* - `ios` - iOS clients
|
||||||
|
* - `tdesktop` - Telegram Desktop
|
||||||
|
* - `macos` - Telegram for macOS
|
||||||
|
* - `unigram` - Unigram
|
||||||
|
*/
|
||||||
|
platform:
|
||||||
|
| 'android'
|
||||||
|
| 'ios'
|
||||||
|
| 'tdesktop'
|
||||||
|
| 'macos'
|
||||||
|
| 'unigram'
|
||||||
|
| (string & {})
|
||||||
|
},
|
||||||
|
): Promise<WebviewResult> {
|
||||||
|
const {
|
||||||
|
webview,
|
||||||
|
bot,
|
||||||
|
chat,
|
||||||
|
theme,
|
||||||
|
platform,
|
||||||
|
} = params
|
||||||
|
|
||||||
|
const botPeer = await resolveUser(client, bot)
|
||||||
|
|
||||||
|
let themeObj: tl.TypeDataJSON | undefined
|
||||||
|
if (theme) {
|
||||||
|
if ('_' in theme) {
|
||||||
|
themeObj = theme
|
||||||
|
} else {
|
||||||
|
themeObj = {
|
||||||
|
_: 'dataJSON',
|
||||||
|
data: JSON.stringify(theme),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (webview.type) {
|
||||||
|
case 'main': {
|
||||||
|
const chatPeer = chat != null ? await resolvePeer(client, chat) : { _: 'inputPeerEmpty' as const }
|
||||||
|
|
||||||
|
const res = await client.call({
|
||||||
|
_: 'messages.requestMainWebView',
|
||||||
|
compact: webview.compact,
|
||||||
|
peer: chatPeer,
|
||||||
|
bot: botPeer,
|
||||||
|
startParam: webview.startParam,
|
||||||
|
themeParams: themeObj,
|
||||||
|
platform,
|
||||||
|
})
|
||||||
|
|
||||||
|
return new WebviewResult(res)
|
||||||
|
}
|
||||||
|
case 'from_reply_keyboard':
|
||||||
|
case 'from_switch_inline':
|
||||||
|
case 'from_side_menu': {
|
||||||
|
const res = await client.call({
|
||||||
|
_: 'messages.requestSimpleWebView',
|
||||||
|
bot: botPeer,
|
||||||
|
url: webview.type === 'from_side_menu' ? undefined : webview.url,
|
||||||
|
themeParams: themeObj,
|
||||||
|
platform,
|
||||||
|
})
|
||||||
|
|
||||||
|
return new WebviewResult(res)
|
||||||
|
}
|
||||||
|
case 'from_inline_keyboard':
|
||||||
|
case 'from_bot_menu':
|
||||||
|
case 'from_attach_menu': {
|
||||||
|
const chatPeer = chat != null ? await resolvePeer(client, chat) : toInputPeer(botPeer)
|
||||||
|
|
||||||
|
const tlReplyTo = typeof webview.replyTo === 'number'
|
||||||
|
? {
|
||||||
|
_: 'inputReplyToMessage' as const,
|
||||||
|
replyToMsgId: webview.replyTo,
|
||||||
|
}
|
||||||
|
: webview.replyTo
|
||||||
|
const tlSendAs = webview.sendAs !== undefined ? await resolvePeer(client, webview.sendAs) : undefined
|
||||||
|
|
||||||
|
const res = await client.call({
|
||||||
|
_: 'messages.requestWebView',
|
||||||
|
bot: botPeer,
|
||||||
|
peer: chatPeer,
|
||||||
|
url: webview.type === 'from_attach_menu' ? undefined : webview.url,
|
||||||
|
compact: webview.compact,
|
||||||
|
themeParams: themeObj,
|
||||||
|
platform,
|
||||||
|
replyTo: tlReplyTo,
|
||||||
|
sendAs: tlSendAs,
|
||||||
|
silent: webview.silent,
|
||||||
|
})
|
||||||
|
|
||||||
|
const withTimer = res.queryId != null && !webview.fireAndForget
|
||||||
|
|
||||||
|
const result = new WebviewResult(res, withTimer)
|
||||||
|
|
||||||
|
if (withTimer) {
|
||||||
|
const queryId = asNonNull(result.queryId)
|
||||||
|
const timerId = _getWebviewTimerId(queryId)
|
||||||
|
|
||||||
|
client.timers.create(timerId, async (abortSignal) => {
|
||||||
|
await client.call({
|
||||||
|
_: 'messages.prolongWebView',
|
||||||
|
silent: webview.silent,
|
||||||
|
peer: chatPeer,
|
||||||
|
bot: botPeer,
|
||||||
|
queryId,
|
||||||
|
replyTo: tlReplyTo,
|
||||||
|
sendAs: tlSendAs,
|
||||||
|
}, { abortSignal })
|
||||||
|
}, 60_000)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
case 'from_link': {
|
||||||
|
const chatPeer = chat != null ? await resolvePeer(client, chat) : toInputPeer(botPeer)
|
||||||
|
|
||||||
|
const res = await client.call({
|
||||||
|
_: 'messages.requestAppWebView',
|
||||||
|
writeAllowed: webview.allowWrite,
|
||||||
|
compact: webview.compact,
|
||||||
|
peer: chatPeer,
|
||||||
|
app: {
|
||||||
|
_: 'inputBotAppShortName',
|
||||||
|
botId: botPeer,
|
||||||
|
shortName: webview.shortName,
|
||||||
|
},
|
||||||
|
startParam: webview.startParam,
|
||||||
|
themeParams: themeObj,
|
||||||
|
platform,
|
||||||
|
})
|
||||||
|
|
||||||
|
const withTimer = res.queryId != null && !webview.fireAndForget
|
||||||
|
const result = new WebviewResult(res, withTimer)
|
||||||
|
|
||||||
|
if (withTimer) {
|
||||||
|
const queryId = asNonNull(result.queryId)
|
||||||
|
const timerId = _getWebviewTimerId(queryId)
|
||||||
|
|
||||||
|
client.timers.create(timerId, async (abortSignal) => {
|
||||||
|
await client.call({
|
||||||
|
_: 'messages.prolongWebView',
|
||||||
|
peer: chatPeer,
|
||||||
|
bot: botPeer,
|
||||||
|
queryId,
|
||||||
|
}, { abortSignal })
|
||||||
|
}, 60_000)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assertNever(webview)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close a webview previously opened by {@link openWebview} method.
|
||||||
|
*
|
||||||
|
* @param webview Webview result returned by {@link openWebview}, or its `.queryId`
|
||||||
|
*/
|
||||||
|
export async function closeWebview(
|
||||||
|
client: ITelegramClient,
|
||||||
|
webview: WebviewResult | tl.Long,
|
||||||
|
): Promise<void> {
|
||||||
|
const timerId = _getWebviewTimerId(Long.isLong(webview) ? webview : asNonNull(webview.queryId))
|
||||||
|
client.timers.cancel(timerId)
|
||||||
|
}
|
|
@ -3,3 +3,4 @@ export * from './game-high-score.js'
|
||||||
export * from './inline-message/index.js'
|
export * from './inline-message/index.js'
|
||||||
export * from './inline-result/index.js'
|
export * from './inline-result/index.js'
|
||||||
export * from './keyboards/index.js'
|
export * from './keyboards/index.js'
|
||||||
|
export * from './webview.js'
|
||||||
|
|
153
packages/core/src/highlevel/types/bots/webview.ts
Normal file
153
packages/core/src/highlevel/types/bots/webview.ts
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
import type { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
|
import type { InputPeerLike } from '../peers/peer.js'
|
||||||
|
import { makeInspectable } from '../../utils/inspectable.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about the mini app for {@link openWebview} method
|
||||||
|
*
|
||||||
|
* - `main` - the ["main"](https://corefork.telegram.org/api/bots/webapps#main-mini-apps) mini-app, configured via BotFather
|
||||||
|
* - `from_reply_keyboard` - webview button found in [reply keyboards](https://corefork.telegram.org/api/bots/webapps#keyboard-button-mini-apps)
|
||||||
|
* - `from_switch_inline` - webview button found [at the top of inline results](https://corefork.telegram.org/api/bots/webapps#inline-mode-mini-apps)
|
||||||
|
* - `from_side_menu` - webview button found in the [side menu](https://corefork.telegram.org/api/bots/webapps#side-menu-mini-apps)
|
||||||
|
* - `from_inline_keyboard` - webview button found in [inline keyboards](https://corefork.telegram.org/api/bots/webapps#inline-button-mini-apps)
|
||||||
|
* - `from_bot_menu` - webview button found in [bot menus](https://corefork.telegram.org/api/bots/webapps#menu-button-mini-apps)
|
||||||
|
* - `from_attach_menu` - webview button found in [attachment menus](https://corefork.telegram.org/api/bots/webapps#attachment-menu-mini-apps)
|
||||||
|
* - `from_link` - webview opened via [direct links](https://corefork.telegram.org/api/bots/webapps#direct-link-mini-apps)
|
||||||
|
*/
|
||||||
|
export type InputWebview =
|
||||||
|
| {
|
||||||
|
type: 'main'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, requests to open the mini app in compact mode (as opposed to fullview mode).
|
||||||
|
* Must be set if the `mode` parameter of the Main Mini App link is equal to `compact`.
|
||||||
|
*/
|
||||||
|
compact?: boolean
|
||||||
|
|
||||||
|
/** Start parameter from the deep link for the mini app */
|
||||||
|
startParam?: string
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'from_reply_keyboard' | 'from_switch_inline'
|
||||||
|
|
||||||
|
/** URL of the mini app found in the button */
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
| { type: 'from_side_menu' }
|
||||||
|
| {
|
||||||
|
type: 'from_inline_keyboard' | 'from_bot_menu'
|
||||||
|
|
||||||
|
/** URL of the mini app found in the button */
|
||||||
|
url: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, requests to open the mini app in compact mode (as opposed to fullview mode).
|
||||||
|
* Must be set if the `mode` parameter of the Main Mini App link is equal to `compact`.
|
||||||
|
*/
|
||||||
|
compact?: boolean
|
||||||
|
|
||||||
|
/** ID of the message to which we should reply if the mini app asks to do so */
|
||||||
|
replyTo?: number | tl.TypeInputReplyTo
|
||||||
|
/**
|
||||||
|
* Peer to use when sending the message.
|
||||||
|
*/
|
||||||
|
sendAs?: InputPeerLike
|
||||||
|
|
||||||
|
/** If the mini app asks to send a message, whether to send it silently */
|
||||||
|
silent?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Telegram asks us to keep sending `messages.prolongWebView` requests every minute until the webview is closed.
|
||||||
|
* If this parameter is set to `true`, the timer will not be started, and the webview will never be prolonged.
|
||||||
|
*/
|
||||||
|
fireAndForget?: boolean
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'from_attach_menu'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, requests to open the mini app in compact mode (as opposed to fullview mode).
|
||||||
|
* Must be set if the `mode` parameter of the Main Mini App link is equal to `compact`.
|
||||||
|
*/
|
||||||
|
compact?: boolean
|
||||||
|
|
||||||
|
/** ID of the message to which we should reply if the mini app asks to do so */
|
||||||
|
replyTo?: number | tl.TypeInputReplyTo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peer to use when sending the message.
|
||||||
|
*/
|
||||||
|
sendAs?: InputPeerLike
|
||||||
|
|
||||||
|
/** If the mini app asks to send a message, whether to send it silently */
|
||||||
|
silent?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Telegram asks us to keep sending `messages.prolongWebView` requests every minute until the webview is closed.
|
||||||
|
* If this parameter is set to `true`, the timer will not be started, and the webview will never be prolonged.
|
||||||
|
*/
|
||||||
|
fireAndForget?: boolean
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'from_link'
|
||||||
|
|
||||||
|
/** Short name of the app (from the link) */
|
||||||
|
shortName: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the bot is asking permission to send messages to the user,
|
||||||
|
* whether to allow it to do so
|
||||||
|
*/
|
||||||
|
allowWrite?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, requests to open the mini app in compact mode (as opposed to fullview mode).
|
||||||
|
* Must be set if the `mode` parameter of the Main Mini App link is equal to `compact`.
|
||||||
|
*/
|
||||||
|
compact?: boolean
|
||||||
|
|
||||||
|
/** Start parameter from the deep link for the mini app */
|
||||||
|
startParam?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Telegram asks us to keep sending `messages.prolongWebView` requests every minute until the webview is closed.
|
||||||
|
* If this parameter is set to `true`, the timer will not be started, and the webview will never be prolonged.
|
||||||
|
*/
|
||||||
|
fireAndForget?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result of {@link openWebview} method call
|
||||||
|
*/
|
||||||
|
export class WebviewResult {
|
||||||
|
constructor(
|
||||||
|
readonly raw: tl.RawWebViewResultUrl,
|
||||||
|
/** If true, the caller should use `closeWebview` method eventually to close the webview */
|
||||||
|
readonly shouldBeClosed: boolean = false,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/** Whether the webview should be opened as a landscape fullscreen app */
|
||||||
|
get isFullscreen(): boolean {
|
||||||
|
return this.raw.fullscreen!
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether the webview should be opened in "compact" mode */
|
||||||
|
get isCompact(): boolean {
|
||||||
|
return !this.raw.fullsize
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Webview session ID (only returned by inline button mini apps, menu button mini apps, attachment menu mini apps).
|
||||||
|
*/
|
||||||
|
get queryId(): tl.Long | null {
|
||||||
|
return this.raw.queryId ?? null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Actual URL to open */
|
||||||
|
get url(): string {
|
||||||
|
return this.raw.url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeInspectable(WebviewResult, ['shouldBeClosed'])
|
Loading…
Reference in a new issue