feat(client): sendCopy method
This commit is contained in:
parent
cb01d8250e
commit
b845864663
5 changed files with 268 additions and 91 deletions
|
@ -73,10 +73,11 @@ import { _parseEntities } from './methods/messages/parse-entities'
|
||||||
import { pinMessage } from './methods/messages/pin-message'
|
import { pinMessage } from './methods/messages/pin-message'
|
||||||
import { searchGlobal } from './methods/messages/search-global'
|
import { searchGlobal } from './methods/messages/search-global'
|
||||||
import { searchMessages } from './methods/messages/search-messages'
|
import { searchMessages } from './methods/messages/search-messages'
|
||||||
import { sendTyping } from './methods/messages/send-chat-action'
|
import { sendCopy } from './methods/messages/send-copy'
|
||||||
import { sendMediaGroup } from './methods/messages/send-media-group'
|
import { sendMediaGroup } from './methods/messages/send-media-group'
|
||||||
import { sendMedia } from './methods/messages/send-media'
|
import { sendMedia } from './methods/messages/send-media'
|
||||||
import { sendText } from './methods/messages/send-text'
|
import { sendText } from './methods/messages/send-text'
|
||||||
|
import { sendTyping } from './methods/messages/send-typing'
|
||||||
import { sendVote } from './methods/messages/send-vote'
|
import { sendVote } from './methods/messages/send-vote'
|
||||||
import { unpinMessage } from './methods/messages/unpin-message'
|
import { unpinMessage } from './methods/messages/unpin-message'
|
||||||
import { initTakeoutSession } from './methods/misc/init-takeout-session'
|
import { initTakeoutSession } from './methods/misc/init-takeout-session'
|
||||||
|
@ -131,6 +132,7 @@ import {
|
||||||
StickerSet,
|
StickerSet,
|
||||||
TakeoutSession,
|
TakeoutSession,
|
||||||
TermsOfService,
|
TermsOfService,
|
||||||
|
TypingStatus,
|
||||||
UploadFileLike,
|
UploadFileLike,
|
||||||
UploadedFile,
|
UploadedFile,
|
||||||
User,
|
User,
|
||||||
|
@ -1676,49 +1678,79 @@ export interface TelegramClient extends BaseTelegramClient {
|
||||||
}
|
}
|
||||||
): AsyncIterableIterator<Message>
|
): AsyncIterableIterator<Message>
|
||||||
/**
|
/**
|
||||||
* Sends a current user/bot typing event
|
* Copy a message (i.e. send the same message,
|
||||||
* to a conversation partner or group.
|
* but do not forward it).
|
||||||
*
|
*
|
||||||
* This status is set for 6 seconds, and is
|
* Note that if the message contains a webpage,
|
||||||
* automatically cancelled if you send a
|
* it will be copied simply as a text message,
|
||||||
* message.
|
* and if the message contains an invoice,
|
||||||
|
* it can't be copied.
|
||||||
*
|
*
|
||||||
* @param chatId Chat ID
|
* > **Note**: if you already have {@link Message} object,
|
||||||
* @param action
|
* > use {@link Message.sendCopy} instead, since that is
|
||||||
* (default: `'typing'`)
|
* > much more efficient, and that is what this method wraps.
|
||||||
* Chat action:
|
|
||||||
* - `typing` - user is typing
|
|
||||||
* - `cancel` to cancel previously sent event
|
|
||||||
* - `record_video` - user is recording a video
|
|
||||||
* - `upload_video` - user is uploading a video
|
|
||||||
* - `record_voice` - user is recording a voice note
|
|
||||||
* - `upload_voice` - user is uploading a voice note
|
|
||||||
* - `upload_photo` - user is uploading a photo
|
|
||||||
* - `upload_document` - user is sending a document
|
|
||||||
*
|
*
|
||||||
* @param progress For `upload_*` actions, progress of the upload (optional)
|
* @param toChatId Source chat ID
|
||||||
|
* @param fromChatId Target chat ID
|
||||||
|
* @param message Message ID to forward
|
||||||
|
* @param params
|
||||||
*/
|
*/
|
||||||
sendChatAction(
|
sendCopy(
|
||||||
chatId: InputPeerLike,
|
toChatId: InputPeerLike,
|
||||||
action?:
|
fromChatId: InputPeerLike,
|
||||||
| 'typing'
|
message: number,
|
||||||
| 'cancel'
|
params?: {
|
||||||
| 'record_video'
|
/**
|
||||||
| 'upload_video'
|
* Whether to send this message silently.
|
||||||
| 'record_voice'
|
*/
|
||||||
| 'upload_voice'
|
silent?: boolean
|
||||||
| 'upload_photo'
|
|
||||||
| 'upload_document'
|
/**
|
||||||
| 'geo'
|
* If set, the message will be scheduled to this date.
|
||||||
| 'contact'
|
* When passing a number, a UNIX time in ms is expected.
|
||||||
| 'game'
|
*/
|
||||||
| 'record_round'
|
schedule?: Date | number
|
||||||
| 'upload_round'
|
|
||||||
| 'group_call'
|
/**
|
||||||
| 'history_import'
|
* New message caption (only used for media)
|
||||||
| tl.TypeSendMessageAction,
|
*/
|
||||||
progress?: number
|
caption?: string
|
||||||
): Promise<void>
|
|
||||||
|
/**
|
||||||
|
* Parse mode to use to parse `text` entities before sending
|
||||||
|
* the message. Defaults to current default parse mode (if any).
|
||||||
|
*
|
||||||
|
* Passing `null` will explicitly disable formatting.
|
||||||
|
*/
|
||||||
|
parseMode?: string | null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message to reply to. Either a message object or message ID.
|
||||||
|
*/
|
||||||
|
replyTo?: number | Message
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of formatting entities to use instead of parsing via a
|
||||||
|
* parse mode.
|
||||||
|
*
|
||||||
|
* **Note:** Passing this makes the method ignore {@link parseMode}
|
||||||
|
*/
|
||||||
|
entities?: tl.TypeMessageEntity[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For bots: inline or reply markup or an instruction
|
||||||
|
* to hide a reply keyboard or to force a reply.
|
||||||
|
*/
|
||||||
|
replyMarkup?: ReplyMarkup
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to clear draft after sending this message.
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
clearDraft?: boolean
|
||||||
|
}
|
||||||
|
): Promise<Message>
|
||||||
/**
|
/**
|
||||||
* Send a group of media.
|
* Send a group of media.
|
||||||
*
|
*
|
||||||
|
@ -1909,6 +1941,23 @@ export interface TelegramClient extends BaseTelegramClient {
|
||||||
clearDraft?: boolean
|
clearDraft?: boolean
|
||||||
}
|
}
|
||||||
): Promise<Message>
|
): Promise<Message>
|
||||||
|
/**
|
||||||
|
* Sends a current user/bot typing event
|
||||||
|
* to a conversation partner or group.
|
||||||
|
*
|
||||||
|
* This status is set for 6 seconds, and is
|
||||||
|
* automatically cancelled if you send a
|
||||||
|
* message.
|
||||||
|
*
|
||||||
|
* @param chatId Chat ID
|
||||||
|
* @param status (default: `'typing'`) Typing status
|
||||||
|
* @param progress (default: `0`) For `upload_*` and history import actions, progress of the upload
|
||||||
|
*/
|
||||||
|
sendTyping(
|
||||||
|
chatId: InputPeerLike,
|
||||||
|
status?: TypingStatus | tl.TypeSendMessageAction,
|
||||||
|
progress?: number
|
||||||
|
): Promise<void>
|
||||||
/**
|
/**
|
||||||
* Send or retract a vote in a poll.
|
* Send or retract a vote in a poll.
|
||||||
*
|
*
|
||||||
|
@ -2325,10 +2374,11 @@ export class TelegramClient extends BaseTelegramClient {
|
||||||
pinMessage = pinMessage
|
pinMessage = pinMessage
|
||||||
searchGlobal = searchGlobal
|
searchGlobal = searchGlobal
|
||||||
searchMessages = searchMessages
|
searchMessages = searchMessages
|
||||||
sendChatAction = sendTyping
|
sendCopy = sendCopy
|
||||||
sendMediaGroup = sendMediaGroup
|
sendMediaGroup = sendMediaGroup
|
||||||
sendMedia = sendMedia
|
sendMedia = sendMedia
|
||||||
sendText = sendText
|
sendText = sendText
|
||||||
|
sendTyping = sendTyping
|
||||||
sendVote = sendVote
|
sendVote = sendVote
|
||||||
unpinMessage = unpinMessage
|
unpinMessage = unpinMessage
|
||||||
initTakeoutSession = initTakeoutSession
|
initTakeoutSession = initTakeoutSession
|
||||||
|
|
|
@ -31,7 +31,8 @@ import {
|
||||||
InputStickerSetItem,
|
InputStickerSetItem,
|
||||||
TakeoutSession,
|
TakeoutSession,
|
||||||
StickerSet,
|
StickerSet,
|
||||||
Poll
|
Poll,
|
||||||
|
TypingStatus
|
||||||
} from '../types'
|
} from '../types'
|
||||||
|
|
||||||
// @copy
|
// @copy
|
||||||
|
|
86
packages/client/src/methods/messages/send-copy.ts
Normal file
86
packages/client/src/methods/messages/send-copy.ts
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
import { TelegramClient } from '../../client'
|
||||||
|
import { InputPeerLike, Message, ReplyMarkup } from '../../types'
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
import { normalizeToInputPeer } from '../../utils/peer-utils'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a message (i.e. send the same message,
|
||||||
|
* but do not forward it).
|
||||||
|
*
|
||||||
|
* Note that if the message contains a webpage,
|
||||||
|
* it will be copied simply as a text message,
|
||||||
|
* and if the message contains an invoice,
|
||||||
|
* it can't be copied.
|
||||||
|
*
|
||||||
|
* > **Note**: if you already have {@link Message} object,
|
||||||
|
* > use {@link Message.sendCopy} instead, since that is
|
||||||
|
* > much more efficient, and that is what this method wraps.
|
||||||
|
*
|
||||||
|
* @param toChatId Source chat ID
|
||||||
|
* @param fromChatId Target chat ID
|
||||||
|
* @param message Message ID to forward
|
||||||
|
* @param params
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export async function sendCopy(
|
||||||
|
this: TelegramClient,
|
||||||
|
toChatId: InputPeerLike,
|
||||||
|
fromChatId: InputPeerLike,
|
||||||
|
message: number,
|
||||||
|
params?: {
|
||||||
|
/**
|
||||||
|
* Whether to send this message silently.
|
||||||
|
*/
|
||||||
|
silent?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, the message will be scheduled to this date.
|
||||||
|
* When passing a number, a UNIX time in ms is expected.
|
||||||
|
*/
|
||||||
|
schedule?: Date | number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New message caption (only used for media)
|
||||||
|
*/
|
||||||
|
caption?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse mode to use to parse `text` entities before sending
|
||||||
|
* the message. Defaults to current default parse mode (if any).
|
||||||
|
*
|
||||||
|
* Passing `null` will explicitly disable formatting.
|
||||||
|
*/
|
||||||
|
parseMode?: string | null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message to reply to. Either a message object or message ID.
|
||||||
|
*/
|
||||||
|
replyTo?: number | Message
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of formatting entities to use instead of parsing via a
|
||||||
|
* parse mode.
|
||||||
|
*
|
||||||
|
* **Note:** Passing this makes the method ignore {@link parseMode}
|
||||||
|
*/
|
||||||
|
entities?: tl.TypeMessageEntity[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For bots: inline or reply markup or an instruction
|
||||||
|
* to hide a reply keyboard or to force a reply.
|
||||||
|
*/
|
||||||
|
replyMarkup?: ReplyMarkup
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to clear draft after sending this message.
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
clearDraft?: boolean
|
||||||
|
}
|
||||||
|
): Promise<Message> {
|
||||||
|
const fromPeer = normalizeToInputPeer(await this.resolvePeer(fromChatId))
|
||||||
|
|
||||||
|
const msg = await this.getMessages(fromPeer, message)
|
||||||
|
return msg.sendCopy(toChatId, params)
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { InputPeerLike } from '../../types'
|
import { InputPeerLike, TypingStatus } from '../../types'
|
||||||
import { TypingStatus } from '../../types/peers/typing-status'
|
|
||||||
import { normalizeToInputPeer } from '../../utils/peer-utils'
|
import { normalizeToInputPeer } from '../../utils/peer-utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,7 +13,7 @@ import { normalizeToInputPeer } from '../../utils/peer-utils'
|
||||||
*
|
*
|
||||||
* @param chatId Chat ID
|
* @param chatId Chat ID
|
||||||
* @param status Typing status
|
* @param status Typing status
|
||||||
* @param progress For `upload_*` and actions, progress of the upload
|
* @param progress For `upload_*` and history import actions, progress of the upload
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export async function sendTyping(
|
export async function sendTyping(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { User, Chat } from '../peers'
|
import { User, Chat, InputPeerLike } from '../peers'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { BotKeyboard, ReplyMarkup } from '../bots'
|
import { BotKeyboard, ReplyMarkup } from '../bots'
|
||||||
import { MAX_CHANNEL_ID } from '@mtcute/core'
|
import { MAX_CHANNEL_ID } from '@mtcute/core'
|
||||||
|
@ -26,7 +26,7 @@ import {
|
||||||
Poll,
|
Poll,
|
||||||
Invoice,
|
Invoice,
|
||||||
Game,
|
Game,
|
||||||
WebPage
|
WebPage,
|
||||||
} from '../media'
|
} from '../media'
|
||||||
import { parseDocument } from '../media/document-utils'
|
import { parseDocument } from '../media/document-utils'
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ export class Message {
|
||||||
raw: tl.TypeMessage,
|
raw: tl.TypeMessage,
|
||||||
users: Record<number, tl.TypeUser>,
|
users: Record<number, tl.TypeUser>,
|
||||||
chats: Record<number, tl.TypeChat>,
|
chats: Record<number, tl.TypeChat>,
|
||||||
isScheduled = false
|
isScheduled = false,
|
||||||
) {
|
) {
|
||||||
this.client = client
|
this.client = client
|
||||||
this._users = users
|
this._users = users
|
||||||
|
@ -352,18 +352,18 @@ export class Message {
|
||||||
// forwarded channel post
|
// forwarded channel post
|
||||||
this._sender = new Chat(
|
this._sender = new Chat(
|
||||||
this.client,
|
this.client,
|
||||||
this._chats[from.channelId]
|
this._chats[from.channelId],
|
||||||
)
|
)
|
||||||
} else if (from._ === 'peerUser') {
|
} else if (from._ === 'peerUser') {
|
||||||
this._sender = new User(
|
this._sender = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[from.userId]
|
this._users[from.userId],
|
||||||
)
|
)
|
||||||
} else
|
} else
|
||||||
throw new MtCuteTypeAssertionError(
|
throw new MtCuteTypeAssertionError(
|
||||||
'Message#sender (@ raw.fromId)',
|
'Message#sender (@ raw.fromId)',
|
||||||
'peerUser | peerChannel',
|
'peerUser | peerChannel',
|
||||||
from._
|
from._,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,7 +383,7 @@ export class Message {
|
||||||
this.client,
|
this.client,
|
||||||
this.raw,
|
this.raw,
|
||||||
this._users,
|
this._users,
|
||||||
this._chats
|
this._chats,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,18 +420,18 @@ export class Message {
|
||||||
if (fwd.fromId._ === 'peerChannel') {
|
if (fwd.fromId._ === 'peerChannel') {
|
||||||
sender = new Chat(
|
sender = new Chat(
|
||||||
this.client,
|
this.client,
|
||||||
this._chats[fwd.fromId.channelId]
|
this._chats[fwd.fromId.channelId],
|
||||||
)
|
)
|
||||||
} else if (fwd.fromId._ === 'peerUser') {
|
} else if (fwd.fromId._ === 'peerUser') {
|
||||||
sender = new User(
|
sender = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[fwd.fromId.userId]
|
this._users[fwd.fromId.userId],
|
||||||
)
|
)
|
||||||
} else
|
} else
|
||||||
throw new MtCuteTypeAssertionError(
|
throw new MtCuteTypeAssertionError(
|
||||||
'Message#forward (@ raw.fwdFrom.fromId)',
|
'Message#forward (@ raw.fwdFrom.fromId)',
|
||||||
'peerUser | peerChannel',
|
'peerUser | peerChannel',
|
||||||
fwd.fromId._
|
fwd.fromId._,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
this._forward = null
|
this._forward = null
|
||||||
|
@ -483,7 +483,7 @@ export class Message {
|
||||||
} else {
|
} else {
|
||||||
this._viaBot = new User(
|
this._viaBot = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[this.raw.viaBotId]
|
this._users[this.raw.viaBotId],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -751,7 +751,7 @@ export class Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new MtCuteArgumentError(
|
throw new MtCuteArgumentError(
|
||||||
`Cannot generate message link for ${this.chat.type}`
|
`Cannot generate message link for ${this.chat.type}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,11 +793,13 @@ export class Message {
|
||||||
replyText (
|
replyText (
|
||||||
text: string,
|
text: string,
|
||||||
visible = false,
|
visible = false,
|
||||||
params?: Parameters<TelegramClient['sendText']>[2]
|
params?: Parameters<TelegramClient['sendText']>[2],
|
||||||
): ReturnType<TelegramClient['sendText']> {
|
): ReturnType<TelegramClient['sendText']> {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
return this.client.sendText(this.chat.inputPeer, text, {
|
return this.client.sendText(this.chat.inputPeer, text, {
|
||||||
...(params || {}),
|
...(
|
||||||
|
params || {}
|
||||||
|
),
|
||||||
replyTo: this.id,
|
replyTo: this.id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -817,11 +819,13 @@ export class Message {
|
||||||
replyMedia (
|
replyMedia (
|
||||||
media: InputMediaLike,
|
media: InputMediaLike,
|
||||||
visible = false,
|
visible = false,
|
||||||
params?: Parameters<TelegramClient['sendMedia']>[2]
|
params?: Parameters<TelegramClient['sendMedia']>[2],
|
||||||
): ReturnType<TelegramClient['sendMedia']> {
|
): ReturnType<TelegramClient['sendMedia']> {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
return this.client.sendMedia(this.chat.inputPeer, media, {
|
return this.client.sendMedia(this.chat.inputPeer, media, {
|
||||||
...(params || {}),
|
...(
|
||||||
|
params || {}
|
||||||
|
),
|
||||||
replyTo: this.id,
|
replyTo: this.id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -860,7 +864,7 @@ export class Message {
|
||||||
* @link TelegramClient.editMessage
|
* @link TelegramClient.editMessage
|
||||||
*/
|
*/
|
||||||
edit (
|
edit (
|
||||||
params: Parameters<TelegramClient['editMessage']>[2]
|
params: Parameters<TelegramClient['editMessage']>[2],
|
||||||
): Promise<Message> {
|
): Promise<Message> {
|
||||||
return this.client.editMessage(this.chat.inputPeer, this.id, params)
|
return this.client.editMessage(this.chat.inputPeer, this.id, params)
|
||||||
}
|
}
|
||||||
|
@ -877,13 +881,50 @@ export class Message {
|
||||||
*/
|
*/
|
||||||
editText (
|
editText (
|
||||||
text: string,
|
text: string,
|
||||||
params?: Omit<Parameters<TelegramClient['editMessage']>[2], 'text'>
|
params?: Omit<Parameters<TelegramClient['editMessage']>[2], 'text'>,
|
||||||
): Promise<Message> {
|
): Promise<Message> {
|
||||||
return this.edit({
|
return this.edit({
|
||||||
text,
|
text,
|
||||||
...(params || {}),
|
...(
|
||||||
|
params || {}
|
||||||
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send this message as a copy (i.e. send the same message,
|
||||||
|
* but do not forward it).
|
||||||
|
*
|
||||||
|
* Note that if the message contains a webpage,
|
||||||
|
* it will be copied simply as a text message,
|
||||||
|
* and if the message contains an invoice,
|
||||||
|
* it can't be copied.
|
||||||
|
*
|
||||||
|
* @param toChatId Target chat ID
|
||||||
|
* @param params Copy parameters
|
||||||
|
*/
|
||||||
|
sendCopy (toChatId: InputPeerLike, params: Parameters<TelegramClient['sendCopy']>[3]): Promise<Message> {
|
||||||
|
if (!params) params = {}
|
||||||
|
|
||||||
|
if (this.raw._ === 'messageService') {
|
||||||
|
throw new MtCuteArgumentError('Service messages can\'t be copied')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.media && !(
|
||||||
|
this.media instanceof WebPage
|
||||||
|
)) {
|
||||||
|
return this.client.sendMedia(toChatId, {
|
||||||
|
type: 'auto',
|
||||||
|
file: this.media.inputMedia,
|
||||||
|
caption: params.caption ?? this.raw.message,
|
||||||
|
// we shouldn't use original entities if the user wants custom text
|
||||||
|
entities: params.entities ?? params.caption ? undefined : this.raw.entities,
|
||||||
|
}, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.client.sendText(toChatId, this.raw.message, params)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
makeInspectable(Message, ['empty', 'isScheduled'], ['link'])
|
makeInspectable(Message, ['empty', 'isScheduled'], ['link'])
|
||||||
|
|
Loading…
Reference in a new issue