stuff
This commit is contained in:
parent
46317e8ddb
commit
707e317e16
5 changed files with 222 additions and 14 deletions
|
@ -263,6 +263,20 @@ export namespace BotKeyboard {
|
||||||
return { _: 'keyboardButtonGame', text }
|
return { _: 'keyboardButtonGame', text }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Button to pay for a product.
|
||||||
|
*
|
||||||
|
* Used for inline keyboards, not reply!
|
||||||
|
*
|
||||||
|
* **Note**: This type of button must always be
|
||||||
|
* the first button in the first row. Related
|
||||||
|
* invoice is inferred from {@link InputMedia.invoice},
|
||||||
|
* thus this button should only be used with it.
|
||||||
|
*/
|
||||||
|
export function pay(text: string): tl.RawKeyboardButtonBuy {
|
||||||
|
return { _: 'keyboardButtonBuy', text }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Button to authorize a user
|
* Button to authorize a user
|
||||||
*
|
*
|
||||||
|
@ -309,6 +323,34 @@ export namespace BotKeyboard {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a button in the keyboard by its text or by predicate
|
||||||
|
*
|
||||||
|
* @param buttons Two-dimensional array of buttons
|
||||||
|
* @param predicate Button text or predicate function
|
||||||
|
*/
|
||||||
|
export function findButton(
|
||||||
|
buttons: tl.TypeKeyboardButton[][],
|
||||||
|
predicate: string | ((btn: tl.TypeKeyboardButton) => boolean)
|
||||||
|
): tl.TypeKeyboardButton | null {
|
||||||
|
if (typeof predicate === 'string') {
|
||||||
|
const text = predicate
|
||||||
|
predicate = (btn) => {
|
||||||
|
return 'text' in btn && btn.text === text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const row of buttons) {
|
||||||
|
for (const btn of row) {
|
||||||
|
if (predicate(btn)) {
|
||||||
|
return btn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
export function _rowsTo2d(
|
export function _rowsTo2d(
|
||||||
rows: tl.RawKeyboardButtonRow[]
|
rows: tl.RawKeyboardButtonRow[]
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { MtCuteArgumentError, MtCuteTypeAssertionError } from '../errors'
|
||||||
import { makeInspectable } from '../utils'
|
import { makeInspectable } from '../utils'
|
||||||
import { ChatsIndex, InputPeerLike, User, UsersIndex } from './index'
|
import { ChatsIndex, InputPeerLike, User, UsersIndex } from './index'
|
||||||
import { ChatLocation } from './chat-location'
|
import { ChatLocation } from './chat-location'
|
||||||
|
import { InputMediaLike } from '../media'
|
||||||
|
|
||||||
export namespace Chat {
|
export namespace Chat {
|
||||||
/**
|
/**
|
||||||
|
@ -559,6 +560,32 @@ export class Chat {
|
||||||
async readHistory(message = 0, clearMentions = false): Promise<void> {
|
async readHistory(message = 0, clearMentions = false): Promise<void> {
|
||||||
return this.client.readHistory(this.inputPeer, message, clearMentions)
|
return this.client.readHistory(this.inputPeer, message, clearMentions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a text message in this chat.
|
||||||
|
*
|
||||||
|
* @param text Text of the message
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
sendText(
|
||||||
|
text: string,
|
||||||
|
params?: Parameters<TelegramClient['sendText']>[2]
|
||||||
|
): ReturnType<TelegramClient['sendText']> {
|
||||||
|
return this.client.sendText(this.inputPeer, text, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a media in this chat.
|
||||||
|
*
|
||||||
|
* @param media Media to send
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
sendMedia(
|
||||||
|
media: InputMediaLike,
|
||||||
|
params?: Parameters<TelegramClient['sendText']>[2]
|
||||||
|
): ReturnType<TelegramClient['sendText']> {
|
||||||
|
return this.client.sendMedia(this.inputPeer, media, params)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeInspectable(Chat, [], ['user'])
|
makeInspectable(Chat, [], ['user'])
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { ChatPhoto } from './chat-photo'
|
||||||
import { MtCuteArgumentError } from '../errors'
|
import { MtCuteArgumentError } from '../errors'
|
||||||
import { makeInspectable } from '../utils'
|
import { makeInspectable } from '../utils'
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
|
import { InputMediaLike } from '../media'
|
||||||
|
|
||||||
export namespace User {
|
export namespace User {
|
||||||
/**
|
/**
|
||||||
|
@ -356,6 +357,32 @@ export class User {
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a text message to this user.
|
||||||
|
*
|
||||||
|
* @param text Text of the message
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
sendText(
|
||||||
|
text: string,
|
||||||
|
params?: Parameters<TelegramClient['sendText']>[2]
|
||||||
|
): ReturnType<TelegramClient['sendText']> {
|
||||||
|
return this.client.sendText(this.inputPeer, text, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a media to this user.
|
||||||
|
*
|
||||||
|
* @param media Media to send
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
sendMedia(
|
||||||
|
media: InputMediaLike,
|
||||||
|
params?: Parameters<TelegramClient['sendText']>[2]
|
||||||
|
): ReturnType<TelegramClient['sendText']> {
|
||||||
|
return this.client.sendMedia(this.inputPeer, media, params)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeInspectable(User)
|
makeInspectable(User)
|
||||||
|
|
|
@ -27,6 +27,9 @@ import { ChatMemberUpdate } from './updates'
|
||||||
import { ChosenInlineResult } from './updates/chosen-inline-result'
|
import { ChosenInlineResult } from './updates/chosen-inline-result'
|
||||||
import { MessageAction } from '@mtcute/client/src/types/messages/message-action'
|
import { MessageAction } from '@mtcute/client/src/types/messages/message-action'
|
||||||
import { UpdateState } from './state'
|
import { UpdateState } from './state'
|
||||||
|
import { UserStatusUpdate } from './updates/user-status-update'
|
||||||
|
import { PollVoteUpdate } from './updates/poll-vote'
|
||||||
|
import { UserTypingUpdate } from './updates/user-typing-update'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type describing a primitive filter, which is a function taking some `Base`
|
* Type describing a primitive filter, which is a function taking some `Base`
|
||||||
|
@ -332,19 +335,97 @@ export namespace filters {
|
||||||
*/
|
*/
|
||||||
export const chat = <T extends Chat.Type>(
|
export const chat = <T extends Chat.Type>(
|
||||||
type: T
|
type: T
|
||||||
): UpdateFilter<Message, {
|
): UpdateFilter<
|
||||||
chat: Modify<Chat, { type: T }>
|
Message,
|
||||||
sender: T extends 'private' | 'bot' | 'group' ? User : User | Chat
|
{
|
||||||
}> => (msg) =>
|
chat: Modify<Chat, { type: T }>
|
||||||
msg.chat.type === type
|
sender: T extends 'private' | 'bot' | 'group' ? User : User | Chat
|
||||||
|
}
|
||||||
|
> => (msg) => msg.chat.type === type
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter messages by chat ID
|
* Filter updates by chat ID(s)
|
||||||
*/
|
*/
|
||||||
export const chatId = (
|
export const chatId = (id: MaybeArray<number>): UpdateFilter<Message> => {
|
||||||
id: number
|
if (Array.isArray(id)) {
|
||||||
): UpdateFilter<Message> => (msg) =>
|
const index: Record<number, true> = {}
|
||||||
msg.chat.id === id
|
id.forEach((id) => (index[id] = true))
|
||||||
|
|
||||||
|
return (msg) => msg.chat.id in index
|
||||||
|
}
|
||||||
|
|
||||||
|
return (msg) => msg.chat.id === id
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter updates by user ID(s)
|
||||||
|
*
|
||||||
|
* For chat member updates, uses `user.id`
|
||||||
|
*/
|
||||||
|
export const userId = (
|
||||||
|
id: MaybeArray<number>
|
||||||
|
): UpdateFilter<
|
||||||
|
| Message
|
||||||
|
| InlineQuery
|
||||||
|
| ChatMemberUpdate
|
||||||
|
| ChosenInlineResult
|
||||||
|
| CallbackQuery
|
||||||
|
| PollVoteUpdate
|
||||||
|
| UserStatusUpdate
|
||||||
|
| UserTypingUpdate
|
||||||
|
> => {
|
||||||
|
if (Array.isArray(id)) {
|
||||||
|
const index: Record<number, true> = {}
|
||||||
|
id.forEach((id) => (index[id] = true))
|
||||||
|
|
||||||
|
return (upd) => {
|
||||||
|
const ctor = upd.constructor
|
||||||
|
|
||||||
|
if (ctor === Message) {
|
||||||
|
return (upd as Message).sender.id in index
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
ctor === UserStatusUpdate ||
|
||||||
|
ctor === UserTypingUpdate
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
(upd as UserStatusUpdate | UserTypingUpdate)
|
||||||
|
.userId in index
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
(upd as Exclude<
|
||||||
|
typeof upd,
|
||||||
|
Message | UserStatusUpdate | UserTypingUpdate
|
||||||
|
>).user.id in index
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (upd) => {
|
||||||
|
const ctor = upd.constructor
|
||||||
|
|
||||||
|
if (ctor === Message) {
|
||||||
|
return (upd as Message).sender.id === id
|
||||||
|
} else {
|
||||||
|
if (ctor === UserStatusUpdate || ctor === UserTypingUpdate) {
|
||||||
|
return (
|
||||||
|
(upd as UserStatusUpdate | UserTypingUpdate).userId ===
|
||||||
|
id
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
(upd as Exclude<
|
||||||
|
typeof upd,
|
||||||
|
Message | UserStatusUpdate | UserTypingUpdate
|
||||||
|
>).user.id === id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter incoming messages.
|
* Filter incoming messages.
|
||||||
|
@ -702,6 +783,36 @@ export namespace filters {
|
||||||
return (upd) => upd.type === types
|
return (upd) => upd.type === types
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a filter for {@link UserStatusUpdate} by new user status
|
||||||
|
*
|
||||||
|
* @param statuses Update type(s)
|
||||||
|
* @link User.Status
|
||||||
|
*/
|
||||||
|
export const userStatus: {
|
||||||
|
<T extends User.Status>(status: T): UpdateFilter<
|
||||||
|
UserStatusUpdate,
|
||||||
|
{
|
||||||
|
type: T
|
||||||
|
lastOnline: T extends 'offline' ? Date : null
|
||||||
|
nextOffline: T extends 'online' ? Date : null
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<T extends User.Status[]>(statuses: T): UpdateFilter<
|
||||||
|
UserStatusUpdate,
|
||||||
|
{ type: T[number] }
|
||||||
|
>
|
||||||
|
} = (statuses: MaybeArray<User.Status>): UpdateFilter<UserStatusUpdate> => {
|
||||||
|
if (Array.isArray(statuses)) {
|
||||||
|
const index: Partial<Record<User.Status, true>> = {}
|
||||||
|
statuses.forEach((typ) => (index[typ] = true))
|
||||||
|
|
||||||
|
return (upd) => upd.status in index
|
||||||
|
}
|
||||||
|
|
||||||
|
return (upd) => upd.status === statuses
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a filter for {@link ChatMemberUpdate} for updates
|
* Create a filter for {@link ChatMemberUpdate} for updates
|
||||||
* regarding current user
|
* regarding current user
|
||||||
|
|
|
@ -27,7 +27,8 @@ export const ContinuePropagation: unique symbol = _sym.for(
|
||||||
'mtcute:ContinuePropagation'
|
'mtcute:ContinuePropagation'
|
||||||
)
|
)
|
||||||
|
|
||||||
export type PropagationSymbol =
|
export type PropagationSymbol = symbol
|
||||||
| typeof StopPropagation
|
// this seems to cause issues after publishing
|
||||||
| typeof ContinuePropagation
|
// | typeof StopPropagation
|
||||||
| typeof StopChildrenPropagation
|
// | typeof ContinuePropagation
|
||||||
|
// | typeof StopChildrenPropagation
|
||||||
|
|
Loading…
Reference in a new issue