feat(client): support reactions
This commit is contained in:
parent
96300a795e
commit
9039830572
9 changed files with 512 additions and 6 deletions
|
@ -33,9 +33,11 @@ import {
|
|||
MaybeDynamic,
|
||||
Message,
|
||||
MessageMedia,
|
||||
MessageReactions,
|
||||
ParsedUpdate,
|
||||
PartialExcept,
|
||||
PartialOnly,
|
||||
PeerReaction,
|
||||
PeersIndex,
|
||||
Photo,
|
||||
Poll,
|
||||
|
@ -172,19 +174,23 @@ import {
|
|||
} from './methods/messages/get-discussion-message'
|
||||
import { getHistory } from './methods/messages/get-history'
|
||||
import { getMessageGroup } from './methods/messages/get-message-group'
|
||||
import { getMessageReactions } from './methods/messages/get-message-reactions'
|
||||
import { getMessagesUnsafe } from './methods/messages/get-messages-unsafe'
|
||||
import { getMessages } from './methods/messages/get-messages'
|
||||
import { getReactionUsers } from './methods/messages/get-reaction-users'
|
||||
import { getScheduledMessages } from './methods/messages/get-scheduled-messages'
|
||||
import { iterHistory } from './methods/messages/iter-history'
|
||||
import { _normalizeInline } from './methods/messages/normalize-inline'
|
||||
import { _parseEntities } from './methods/messages/parse-entities'
|
||||
import { pinMessage } from './methods/messages/pin-message'
|
||||
import { readHistory } from './methods/messages/read-history'
|
||||
import { readReactions } from './methods/messages/read-reactions'
|
||||
import { searchGlobal } from './methods/messages/search-global'
|
||||
import { searchMessages } from './methods/messages/search-messages'
|
||||
import { sendCopy } from './methods/messages/send-copy'
|
||||
import { sendMediaGroup } from './methods/messages/send-media-group'
|
||||
import { sendMedia } from './methods/messages/send-media'
|
||||
import { sendReaction } from './methods/messages/send-reaction'
|
||||
import { sendScheduled } from './methods/messages/send-scheduled'
|
||||
import { sendText } from './methods/messages/send-text'
|
||||
import { sendTyping } from './methods/messages/send-typing'
|
||||
|
@ -2430,6 +2436,36 @@ export interface TelegramClient extends BaseTelegramClient {
|
|||
* @param message ID of one of the messages in the group
|
||||
*/
|
||||
getMessageGroup(chatId: InputPeerLike, message: number): Promise<Message[]>
|
||||
/**
|
||||
* Get reactions to a message.
|
||||
*
|
||||
* > Apps should short-poll reactions for visible messages
|
||||
* > (that weren't sent by the user) once every 15-30 seconds,
|
||||
* > but only if `message.reactions` is set
|
||||
*
|
||||
* @param chatId ID of the chat with the message
|
||||
* @param messages Message ID
|
||||
* @returns Reactions to the corresponding message, or `null` if there are none
|
||||
*/
|
||||
getMessageReactions(
|
||||
chatId: InputPeerLike,
|
||||
messages: number
|
||||
): Promise<MessageReactions | null>
|
||||
/**
|
||||
* Get reactions to messages.
|
||||
*
|
||||
* > Apps should short-poll reactions for visible messages
|
||||
* > (that weren't sent by the user) once every 15-30 seconds,
|
||||
* > but only if `message.reactions` is set
|
||||
*
|
||||
* @param chatId ID of the chat with messages
|
||||
* @param messages Message IDs
|
||||
* @returns Reactions to corresponding messages, or `null` if there are none
|
||||
*/
|
||||
getMessageReactions(
|
||||
chatId: InputPeerLike,
|
||||
messages: number[]
|
||||
): Promise<(MessageReactions | null)[]>
|
||||
/**
|
||||
* Get a single message from PM or legacy group by its ID.
|
||||
* For channels, use {@link getMessages}.
|
||||
|
@ -2496,6 +2532,37 @@ export interface TelegramClient extends BaseTelegramClient {
|
|||
messageIds: number[],
|
||||
fromReply?: boolean
|
||||
): Promise<(Message | null)[]>
|
||||
/**
|
||||
* Get users who have reacted to the message.
|
||||
*
|
||||
* @param chatId Chat ID
|
||||
* @param messageId Message ID
|
||||
* @param params
|
||||
*/
|
||||
getReactionUsers(
|
||||
chatId: InputPeerLike,
|
||||
messageId: number,
|
||||
params?: {
|
||||
/**
|
||||
* Get only reactions with the specified emoji
|
||||
*/
|
||||
emoji?: string
|
||||
|
||||
/**
|
||||
* Limit the number of events returned.
|
||||
*
|
||||
* Defaults to `Infinity`, i.e. all events are returned
|
||||
*/
|
||||
limit?: number
|
||||
|
||||
/**
|
||||
* Chunk size, usually not needed.
|
||||
*
|
||||
* Defaults to `100`
|
||||
*/
|
||||
chunkSize?: number
|
||||
}
|
||||
): AsyncIterableIterator<PeerReaction>
|
||||
/**
|
||||
* Get a single scheduled message in chat by its ID
|
||||
*
|
||||
|
@ -2603,6 +2670,12 @@ export interface TelegramClient extends BaseTelegramClient {
|
|||
message?: number,
|
||||
clearMentions?: boolean
|
||||
): Promise<void>
|
||||
/**
|
||||
* Mark all reactions in chat as read.
|
||||
*
|
||||
* @param chatId Chat ID
|
||||
*/
|
||||
readReactions(chatId: InputPeerLike): Promise<void>
|
||||
/**
|
||||
* Search for messages globally from all of your chats
|
||||
*
|
||||
|
@ -2979,6 +3052,21 @@ export interface TelegramClient extends BaseTelegramClient {
|
|||
clearDraft?: boolean
|
||||
}
|
||||
): Promise<Message>
|
||||
/**
|
||||
* Send or remove a reaction.
|
||||
*
|
||||
* @param chatId Chat ID with the message to react to
|
||||
* @param message Message ID to react to
|
||||
* @param emoji Reaction emoji (or `null` to remove)
|
||||
* @param big (default: `false`) Whether to use a big reaction
|
||||
* @returns Message to which the reaction was sent
|
||||
*/
|
||||
sendReaction(
|
||||
chatId: InputPeerLike,
|
||||
message: number,
|
||||
emoji: string | null,
|
||||
big?: boolean
|
||||
): Promise<Message>
|
||||
/**
|
||||
* Send s previously scheduled message.
|
||||
*
|
||||
|
@ -3891,19 +3979,23 @@ export class TelegramClient extends BaseTelegramClient {
|
|||
getDiscussionMessage = getDiscussionMessage
|
||||
getHistory = getHistory
|
||||
getMessageGroup = getMessageGroup
|
||||
getMessageReactions = getMessageReactions
|
||||
getMessagesUnsafe = getMessagesUnsafe
|
||||
getMessages = getMessages
|
||||
getReactionUsers = getReactionUsers
|
||||
getScheduledMessages = getScheduledMessages
|
||||
iterHistory = iterHistory
|
||||
protected _normalizeInline = _normalizeInline
|
||||
protected _parseEntities = _parseEntities
|
||||
pinMessage = pinMessage
|
||||
readHistory = readHistory
|
||||
readReactions = readReactions
|
||||
searchGlobal = searchGlobal
|
||||
searchMessages = searchMessages
|
||||
sendCopy = sendCopy
|
||||
sendMediaGroup = sendMediaGroup
|
||||
sendMedia = sendMedia
|
||||
sendReaction = sendReaction
|
||||
sendScheduled = sendScheduled
|
||||
sendText = sendText
|
||||
sendTyping = sendTyping
|
||||
|
|
|
@ -55,6 +55,8 @@ import {
|
|||
BotStoppedUpdate,
|
||||
BotChatJoinRequestUpdate,
|
||||
ChatJoinRequestUpdate,
|
||||
PeerReaction,
|
||||
MessageReactions,
|
||||
} from '../types'
|
||||
|
||||
// @copy
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
import { TelegramClient } from '../../client'
|
||||
import { InputPeerLike, PeersIndex, MessageReactions } from '../../types'
|
||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||
import { getMarkedPeerId, MaybeArray } from '@mtcute/core'
|
||||
import { assertTypeIs } from '../../utils/type-assertion'
|
||||
|
||||
/**
|
||||
* Get reactions to a message.
|
||||
*
|
||||
* > Apps should short-poll reactions for visible messages
|
||||
* > (that weren't sent by the user) once every 15-30 seconds,
|
||||
* > but only if `message.reactions` is set
|
||||
*
|
||||
* @param chatId ID of the chat with the message
|
||||
* @param messages Message ID
|
||||
* @returns Reactions to the corresponding message, or `null` if there are none
|
||||
* @internal
|
||||
*/
|
||||
export async function getMessageReactions(
|
||||
this: TelegramClient,
|
||||
chatId: InputPeerLike,
|
||||
messages: number
|
||||
): Promise<MessageReactions | null>
|
||||
|
||||
/**
|
||||
* Get reactions to messages.
|
||||
*
|
||||
* > Apps should short-poll reactions for visible messages
|
||||
* > (that weren't sent by the user) once every 15-30 seconds,
|
||||
* > but only if `message.reactions` is set
|
||||
*
|
||||
* @param chatId ID of the chat with messages
|
||||
* @param messages Message IDs
|
||||
* @returns Reactions to corresponding messages, or `null` if there are none
|
||||
* @internal
|
||||
*/
|
||||
export async function getMessageReactions(
|
||||
this: TelegramClient,
|
||||
chatId: InputPeerLike,
|
||||
messages: number[]
|
||||
): Promise<(MessageReactions | null)[]>
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export async function getMessageReactions(
|
||||
this: TelegramClient,
|
||||
chatId: InputPeerLike,
|
||||
messages: MaybeArray<number>
|
||||
): Promise<MaybeArray<MessageReactions | null>> {
|
||||
const single = !Array.isArray(messages)
|
||||
if (!Array.isArray(messages)) {
|
||||
messages = [messages]
|
||||
}
|
||||
|
||||
const res = await this.call({
|
||||
_: 'messages.getMessagesReactions',
|
||||
peer: await this.resolvePeer(chatId),
|
||||
id: messages,
|
||||
})
|
||||
|
||||
assertIsUpdatesGroup('messages.getMessagesReactions', res)
|
||||
|
||||
// normally the group contains updateMessageReactions
|
||||
// for each message requested that has reactions
|
||||
//
|
||||
// these updates are not ordered in any way, so
|
||||
// we don't need to pass them to updates engine
|
||||
|
||||
const index: Record<number, MessageReactions> = {}
|
||||
|
||||
const peers = PeersIndex.from(res)
|
||||
|
||||
for (const update of res.updates) {
|
||||
assertTypeIs(
|
||||
'messages.getMessagesReactions',
|
||||
update,
|
||||
'updateMessageReactions'
|
||||
)
|
||||
|
||||
index[update.msgId] = new MessageReactions(
|
||||
this,
|
||||
update.msgId,
|
||||
getMarkedPeerId(update.peer),
|
||||
update.reactions,
|
||||
peers
|
||||
)
|
||||
}
|
||||
|
||||
if (single) {
|
||||
return index[messages[0]] ?? null
|
||||
}
|
||||
|
||||
return messages.map((messageId) => index[messageId] ?? null)
|
||||
}
|
77
packages/client/src/methods/messages/get-reaction-users.ts
Normal file
77
packages/client/src/methods/messages/get-reaction-users.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
import { TelegramClient } from '../../client'
|
||||
import {
|
||||
InputPeerLike,
|
||||
PeerReaction,
|
||||
PeersIndex,
|
||||
} from '../../types'
|
||||
import { tl } from '@mtcute/tl'
|
||||
|
||||
/**
|
||||
* Get users who have reacted to the message.
|
||||
*
|
||||
* @param chatId Chat ID
|
||||
* @param messageId Message ID
|
||||
* @param params
|
||||
* @internal
|
||||
*/
|
||||
export async function* getReactionUsers(
|
||||
this: TelegramClient,
|
||||
chatId: InputPeerLike,
|
||||
messageId: number,
|
||||
params?: {
|
||||
/**
|
||||
* Get only reactions with the specified emoji
|
||||
*/
|
||||
emoji?: string
|
||||
|
||||
/**
|
||||
* Limit the number of events returned.
|
||||
*
|
||||
* Defaults to `Infinity`, i.e. all events are returned
|
||||
*/
|
||||
limit?: number
|
||||
|
||||
/**
|
||||
* Chunk size, usually not needed.
|
||||
*
|
||||
* Defaults to `100`
|
||||
*/
|
||||
chunkSize?: number
|
||||
}
|
||||
): AsyncIterableIterator<PeerReaction> {
|
||||
if (!params) params = {}
|
||||
|
||||
const peer = await this.resolvePeer(chatId)
|
||||
|
||||
let current = 0
|
||||
let offset: string | undefined = undefined
|
||||
const total = params.limit || Infinity
|
||||
const chunkSize = Math.min(params.chunkSize ?? 100, total)
|
||||
|
||||
for (;;) {
|
||||
const res: tl.RpcCallReturn['messages.getMessageReactionsList'] =
|
||||
await this.call({
|
||||
_: 'messages.getMessageReactionsList',
|
||||
peer,
|
||||
id: messageId,
|
||||
reaction: params.emoji,
|
||||
limit: Math.min(chunkSize, total - current),
|
||||
offset,
|
||||
})
|
||||
|
||||
if (!res.reactions.length) break
|
||||
|
||||
offset = res.nextOffset
|
||||
|
||||
const peers = PeersIndex.from(res)
|
||||
|
||||
for (const reaction of res.reactions) {
|
||||
const parsed = new PeerReaction(this, reaction, peers)
|
||||
|
||||
current += 1
|
||||
yield parsed
|
||||
|
||||
if (current >= total) break
|
||||
}
|
||||
}
|
||||
}
|
20
packages/client/src/methods/messages/read-reactions.ts
Normal file
20
packages/client/src/methods/messages/read-reactions.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { TelegramClient } from '../../client'
|
||||
import { InputPeerLike } from '../../types'
|
||||
import { createDummyUpdate } from '../../utils/updates-utils'
|
||||
|
||||
/**
|
||||
* Mark all reactions in chat as read.
|
||||
*
|
||||
* @param chatId Chat ID
|
||||
* @internal
|
||||
*/
|
||||
export async function readReactions(
|
||||
this: TelegramClient,
|
||||
chatId: InputPeerLike,
|
||||
): Promise<void> {
|
||||
const res = await this.call({
|
||||
_: 'messages.readReactions',
|
||||
peer: await this.resolvePeer(chatId)
|
||||
})
|
||||
this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount))
|
||||
}
|
60
packages/client/src/methods/messages/send-reaction.ts
Normal file
60
packages/client/src/methods/messages/send-reaction.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import { TelegramClient } from '../../client'
|
||||
import {
|
||||
InputPeerLike,
|
||||
Message,
|
||||
MtTypeAssertionError,
|
||||
PeersIndex,
|
||||
} from '../../types'
|
||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||
import { tl } from '@mtcute/tl'
|
||||
|
||||
/**
|
||||
* Send or remove a reaction.
|
||||
*
|
||||
* @param chatId Chat ID with the message to react to
|
||||
* @param message Message ID to react to
|
||||
* @param emoji Reaction emoji (or `null` to remove)
|
||||
* @param big Whether to use a big reaction
|
||||
* @returns Message to which the reaction was sent
|
||||
* @internal
|
||||
*/
|
||||
export async function sendReaction(
|
||||
this: TelegramClient,
|
||||
chatId: InputPeerLike,
|
||||
message: number,
|
||||
emoji: string | null,
|
||||
big = false
|
||||
): Promise<Message> {
|
||||
const res = await this.call({
|
||||
_: 'messages.sendReaction',
|
||||
peer: await this.resolvePeer(chatId),
|
||||
msgId: message,
|
||||
reaction: emoji ?? undefined,
|
||||
big,
|
||||
})
|
||||
|
||||
assertIsUpdatesGroup('messages.sendReaction', res)
|
||||
|
||||
// normally the group contains 2 updates:
|
||||
// updateEditChannelMessage
|
||||
// updateMessageReactions
|
||||
// idk why, they contain literally the same data
|
||||
// so we can just return the message from the first one
|
||||
|
||||
this._handleUpdate(res, true)
|
||||
|
||||
const upd = res.updates.find(
|
||||
(it) => it._ === 'updateEditChannelMessage'
|
||||
) as tl.RawUpdateEditChannelMessage | undefined
|
||||
if (!upd) {
|
||||
throw new MtTypeAssertionError(
|
||||
'messages.sendReaction (@ .updates[*])',
|
||||
'updateEditChannelMessage',
|
||||
'undefined'
|
||||
)
|
||||
}
|
||||
|
||||
const peers = PeersIndex.from(res)
|
||||
|
||||
return new Message(this, upd.message, peers)
|
||||
}
|
|
@ -5,3 +5,4 @@ export * from './message'
|
|||
export * from './search-filters'
|
||||
export * from './draft-message'
|
||||
export * from './dialog'
|
||||
export * from './reactions'
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
import { User, Chat, InputPeerLike, PeersIndex } from '../peers'
|
||||
import { tl } from '@mtcute/tl'
|
||||
import { BotKeyboard, ReplyMarkup } from '../bots'
|
||||
import { assertNever, getMarkedPeerId, toggleChannelIdMark } from "@mtcute/core";
|
||||
import {
|
||||
MtArgumentError,
|
||||
MtTypeAssertionError,
|
||||
} from '../errors'
|
||||
import { assertNever, getMarkedPeerId, toggleChannelIdMark } from '@mtcute/core'
|
||||
import { MtArgumentError, MtTypeAssertionError } from '../errors'
|
||||
import { TelegramClient } from '../../client'
|
||||
import { MessageEntity } from './message-entity'
|
||||
import { makeInspectable } from '../utils'
|
||||
|
@ -13,6 +10,7 @@ import { InputMediaLike, WebPage } from '../media'
|
|||
import { _messageActionFromTl, MessageAction } from './message-action'
|
||||
import { _messageMediaFromTl, MessageMedia } from './message-media'
|
||||
import { FormattedString } from '../parser'
|
||||
import { MessageReactions } from './reactions'
|
||||
|
||||
/**
|
||||
* A message or a service message
|
||||
|
@ -314,7 +312,7 @@ export class Message {
|
|||
}
|
||||
|
||||
if (r.comments) {
|
||||
const o = (obj as unknown) as Message.MessageCommentsInfo
|
||||
const o = obj as unknown as Message.MessageCommentsInfo
|
||||
o.discussion = getMarkedPeerId(r.channelId!, 'channel')
|
||||
o.repliers =
|
||||
r.recentRepliers?.map((it) => getMarkedPeerId(it)) ?? []
|
||||
|
@ -490,6 +488,34 @@ export class Message {
|
|||
return this._markup
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this message can be forwarded
|
||||
*
|
||||
* `false` for service mesasges and private restricted chats/chanenls
|
||||
*/
|
||||
get canBeForwarded(): boolean {
|
||||
return this.raw._ === 'message' && !this.raw.noforwards
|
||||
}
|
||||
|
||||
private _reactions?: MessageReactions | null
|
||||
get reactions(): MessageReactions | null {
|
||||
if (this._reactions === undefined) {
|
||||
if (this.raw._ === 'messageService' || !this.raw.reactions) {
|
||||
this._reactions = null
|
||||
} else {
|
||||
this._reactions = new MessageReactions(
|
||||
this.client,
|
||||
this.raw.id,
|
||||
getMarkedPeerId(this.raw.peerId),
|
||||
this.raw.reactions,
|
||||
this._peers
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return this._reactions
|
||||
}
|
||||
|
||||
/**
|
||||
* Generated permalink to this message, only for groups and channels
|
||||
*
|
||||
|
@ -892,6 +918,21 @@ export class Message {
|
|||
clearMentions
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* React to this message
|
||||
*
|
||||
* @param emoji Reaction emoji
|
||||
* @param big Whether to use a big reaction
|
||||
*/
|
||||
async react(emoji: string | null, big?: boolean): Promise<Message> {
|
||||
return this.client.sendReaction(
|
||||
this.chat.inputPeer,
|
||||
this.raw.id,
|
||||
emoji,
|
||||
big
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
makeInspectable(Message, ['isScheduled'], ['link'])
|
||||
|
|
118
packages/client/src/types/messages/reactions.ts
Normal file
118
packages/client/src/types/messages/reactions.ts
Normal file
|
@ -0,0 +1,118 @@
|
|||
import { TelegramClient } from '../../client'
|
||||
import { tl } from '@mtcute/tl'
|
||||
import { makeInspectable } from '../utils'
|
||||
import { getMarkedPeerId } from '@mtcute/core'
|
||||
import { PeersIndex, User } from '../peers'
|
||||
import { assertTypeIs } from '../../utils/type-assertion'
|
||||
|
||||
export class PeerReaction {
|
||||
constructor(
|
||||
readonly client: TelegramClient,
|
||||
readonly raw: tl.RawMessagePeerReaction,
|
||||
readonly _peers: PeersIndex
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Emoji representing the reaction
|
||||
*/
|
||||
get emoji(): string {
|
||||
return this.raw.reaction!
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this is a big reaction
|
||||
*/
|
||||
get big(): boolean {
|
||||
return this.raw.big!
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this reaction is unread by the current user
|
||||
*/
|
||||
get unread(): boolean {
|
||||
return this.raw.unread!
|
||||
}
|
||||
|
||||
/**
|
||||
* ID of the user who has reacted
|
||||
*/
|
||||
get userId(): number {
|
||||
return getMarkedPeerId(this.raw.peerId)
|
||||
}
|
||||
|
||||
private _user?: User
|
||||
|
||||
/**
|
||||
* User who has reacted
|
||||
*/
|
||||
get user(): User {
|
||||
if (!this._user) {
|
||||
assertTypeIs('PeerReaction#user', this.raw.peerId, 'peerUser')
|
||||
|
||||
this._user = new User(
|
||||
this.client,
|
||||
this._peers.user(this.raw.peerId.userId)
|
||||
)
|
||||
}
|
||||
|
||||
return this._user
|
||||
}
|
||||
}
|
||||
|
||||
makeInspectable(PeerReaction)
|
||||
|
||||
export class MessageReactions {
|
||||
constructor(
|
||||
readonly client: TelegramClient,
|
||||
readonly messageId: number,
|
||||
readonly chatId: number,
|
||||
readonly raw: tl.RawMessageReactions,
|
||||
readonly _peers: PeersIndex
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Whether you can use {@link getUsers}
|
||||
* (or {@link TelegramClient.getReactionUsers})
|
||||
* to get the users who reacted to this message
|
||||
*/
|
||||
get usersVisible(): boolean {
|
||||
return this.raw.canSeeList!
|
||||
}
|
||||
|
||||
/**
|
||||
* Reactions on the message, along with their counts
|
||||
*/
|
||||
get reactions(): tl.TypeReactionCount[] {
|
||||
return this.raw.results
|
||||
}
|
||||
|
||||
private _recentReactions?: PeerReaction[]
|
||||
|
||||
/**
|
||||
* Recently reacted users.
|
||||
* To get a full list of users, use {@link getUsers}
|
||||
*/
|
||||
get recentReactions(): PeerReaction[] {
|
||||
if (!this.raw.recentReactions) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (!this._recentReactions) {
|
||||
this._recentReactions = this.raw.recentReactions.map(
|
||||
(reaction) =>
|
||||
new PeerReaction(this.client, reaction, this._peers)
|
||||
)
|
||||
}
|
||||
|
||||
return this._recentReactions
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the users who reacted to this message
|
||||
*/
|
||||
getUsers(params?: Parameters<TelegramClient['getReactionUsers']>[2]): AsyncIterableIterator<PeerReaction> {
|
||||
return this.client.getReactionUsers(this.messageId, this.chatId, params)
|
||||
}
|
||||
}
|
||||
|
||||
makeInspectable(MessageReactions)
|
Loading…
Reference in a new issue