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 }
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
|
@ -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 */
|
||||
export function _rowsTo2d(
|
||||
rows: tl.RawKeyboardButtonRow[]
|
||||
|
|
|
@ -7,6 +7,7 @@ import { MtCuteArgumentError, MtCuteTypeAssertionError } from '../errors'
|
|||
import { makeInspectable } from '../utils'
|
||||
import { ChatsIndex, InputPeerLike, User, UsersIndex } from './index'
|
||||
import { ChatLocation } from './chat-location'
|
||||
import { InputMediaLike } from '../media'
|
||||
|
||||
export namespace Chat {
|
||||
/**
|
||||
|
@ -559,6 +560,32 @@ export class Chat {
|
|||
async readHistory(message = 0, clearMentions = false): Promise<void> {
|
||||
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'])
|
||||
|
|
|
@ -4,6 +4,7 @@ import { ChatPhoto } from './chat-photo'
|
|||
import { MtCuteArgumentError } from '../errors'
|
||||
import { makeInspectable } from '../utils'
|
||||
import { assertTypeIs } from '../../utils/type-assertion'
|
||||
import { InputMediaLike } from '../media'
|
||||
|
||||
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)
|
||||
|
|
|
@ -27,6 +27,9 @@ import { ChatMemberUpdate } from './updates'
|
|||
import { ChosenInlineResult } from './updates/chosen-inline-result'
|
||||
import { MessageAction } from '@mtcute/client/src/types/messages/message-action'
|
||||
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`
|
||||
|
@ -332,19 +335,97 @@ export namespace filters {
|
|||
*/
|
||||
export const chat = <T extends Chat.Type>(
|
||||
type: T
|
||||
): UpdateFilter<Message, {
|
||||
): UpdateFilter<
|
||||
Message,
|
||||
{
|
||||
chat: Modify<Chat, { type: T }>
|
||||
sender: T extends 'private' | 'bot' | 'group' ? User : User | Chat
|
||||
}> => (msg) =>
|
||||
msg.chat.type === type
|
||||
}
|
||||
> => (msg) => msg.chat.type === type
|
||||
|
||||
/**
|
||||
* Filter messages by chat ID
|
||||
* Filter updates by chat ID(s)
|
||||
*/
|
||||
export const chatId = (
|
||||
id: number
|
||||
): UpdateFilter<Message> => (msg) =>
|
||||
msg.chat.id === id
|
||||
export const chatId = (id: MaybeArray<number>): UpdateFilter<Message> => {
|
||||
if (Array.isArray(id)) {
|
||||
const index: Record<number, true> = {}
|
||||
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.
|
||||
|
@ -702,6 +783,36 @@ export namespace filters {
|
|||
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
|
||||
* regarding current user
|
||||
|
|
|
@ -27,7 +27,8 @@ export const ContinuePropagation: unique symbol = _sym.for(
|
|||
'mtcute:ContinuePropagation'
|
||||
)
|
||||
|
||||
export type PropagationSymbol =
|
||||
| typeof StopPropagation
|
||||
| typeof ContinuePropagation
|
||||
| typeof StopChildrenPropagation
|
||||
export type PropagationSymbol = symbol
|
||||
// this seems to cause issues after publishing
|
||||
// | typeof StopPropagation
|
||||
// | typeof ContinuePropagation
|
||||
// | typeof StopChildrenPropagation
|
||||
|
|
Loading…
Reference in a new issue