You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

283 lines
8.0 KiB

package message
import (
"context"
"io"
"github.com/go-faster/errors"
"github.com/gotd/td/internal/crypto"
"github.com/gotd/td/telegram/message/peer"
"github.com/gotd/td/telegram/uploader"
"github.com/gotd/td/tg"
)
// Sender is a message sending helper.
type Sender struct {
raw *tg.Client
rand io.Reader
uploader Uploader
resolver peer.Resolver
}
// NewSender creates a new Sender.
func NewSender(raw *tg.Client) *Sender {
return &Sender{
raw: raw,
rand: crypto.DefaultRand(),
uploader: uploader.NewUploader(raw),
resolver: peer.DefaultResolver(raw),
}
}
// WithUploader sets file uploader to use.
func (s *Sender) WithUploader(u Uploader) *Sender {
s.uploader = u
return s
}
// WithResolver sets peer resolver to use.
func (s *Sender) WithResolver(resolver peer.Resolver) *Sender {
s.resolver = resolver
return s
}
// WithRand sets random ID source.
func (s *Sender) WithRand(r io.Reader) *Sender {
s.rand = r
return s
}
// ClearAllDrafts clears all drafts in all peers.
func (s *Sender) ClearAllDrafts(ctx context.Context) error {
_, err := s.raw.MessagesClearAllDrafts(ctx)
return err
}
// sendMessage sends message to peer.
func (s *Sender) sendMessage(ctx context.Context, req *tg.MessagesSendMessageRequest) (tg.UpdatesClass, error) {
if req.RandomID == 0 {
id, err := crypto.RandInt64(s.rand)
if err != nil {
return nil, errors.Wrap(err, "generate random_id")
}
req.RandomID = id
}
return s.raw.MessagesSendMessage(ctx, req)
}
// sendMedia sends message with single media to peer.
func (s *Sender) sendMedia(ctx context.Context, req *tg.MessagesSendMediaRequest) (tg.UpdatesClass, error) {
if req.RandomID == 0 {
id, err := crypto.RandInt64(s.rand)
if err != nil {
return nil, errors.Wrap(err, "generate random_id")
}
req.RandomID = id
}
return s.raw.MessagesSendMedia(ctx, req)
}
// sendMultiMedia sends message with multiple media to peer.
func (s *Sender) sendMultiMedia(ctx context.Context, req *tg.MessagesSendMultiMediaRequest) (tg.UpdatesClass, error) {
for i := range req.MultiMedia {
id, err := crypto.RandInt64(s.rand)
if err != nil {
return nil, errors.Wrap(err, "generate random_id")
}
req.MultiMedia[i].RandomID = id
}
return s.raw.MessagesSendMultiMedia(ctx, req)
}
// editMessage edits message.
func (s *Sender) editMessage(ctx context.Context, req *tg.MessagesEditMessageRequest) (tg.UpdatesClass, error) {
return s.raw.MessagesEditMessage(ctx, req)
}
// forwardMessages forwards message to peer.
func (s *Sender) forwardMessages(ctx context.Context, req *tg.MessagesForwardMessagesRequest) (tg.UpdatesClass, error) {
req.RandomID = make([]int64, len(req.ID))
for i := range req.RandomID {
id, err := crypto.RandInt64(s.rand)
if err != nil {
return nil, errors.Wrap(err, "generate random_id")
}
req.RandomID[i] = id
}
return s.raw.MessagesForwardMessages(ctx, req)
}
// sendInlineBotResult sends inline query result message to peer.
func (s *Sender) sendInlineBotResult(
ctx context.Context,
req *tg.MessagesSendInlineBotResultRequest,
) (tg.UpdatesClass, error) {
if req.RandomID == 0 {
id, err := crypto.RandInt64(s.rand)
if err != nil {
return nil, errors.Wrap(err, "generate random_id")
}
req.RandomID = id
}
return s.raw.MessagesSendInlineBotResult(ctx, req)
}
// uploadMedia uploads file and associate it to a chat (without actually sending it to the chat).
func (s *Sender) uploadMedia(ctx context.Context, req *tg.MessagesUploadMediaRequest) (tg.MessageMediaClass, error) {
return s.raw.MessagesUploadMedia(ctx, req)
}
// getDocumentByHash finds document by hash, MIME type and size.
func (s *Sender) getDocumentByHash(
ctx context.Context,
req *tg.MessagesGetDocumentByHashRequest,
) (tg.DocumentClass, error) {
return s.raw.MessagesGetDocumentByHash(ctx, req)
}
// saveDraft saves a message draft associated to a chat.
func (s *Sender) saveDraft(ctx context.Context, req *tg.MessagesSaveDraftRequest) error {
_, err := s.raw.MessagesSaveDraft(ctx, req)
return err
}
// sendVote votes in a poll.
func (s *Sender) sendVote(ctx context.Context, req *tg.MessagesSendVoteRequest) (tg.UpdatesClass, error) {
return s.raw.MessagesSendVote(ctx, req)
}
// setTyping sends a typing event to a conversation partner or group.
func (s *Sender) setTyping(ctx context.Context, req *tg.MessagesSetTypingRequest) error {
_, err := s.raw.MessagesSetTyping(ctx, req)
return err
}
// report reports a message in a chat for violation of Telegram's Terms of Service.
func (s *Sender) report(ctx context.Context, req *tg.MessagesReportRequest) (bool, error) {
return s.raw.MessagesReport(ctx, req)
}
// reportSpam reports a new incoming chat for spam, if the peer settings of the chat allow us to do that.
func (s *Sender) reportSpam(ctx context.Context, p tg.InputPeerClass) (bool, error) {
return s.raw.MessagesReportSpam(ctx, p)
}
func (s *Sender) sendReaction(
ctx context.Context,
p tg.InputPeerClass, msgID int, reaction string,
) (tg.UpdatesClass, error) {
return s.raw.MessagesSendReaction(ctx, &tg.MessagesSendReactionRequest{
Peer: p,
MsgID: msgID,
Reaction: reaction,
})
}
// sendScreenshotNotification sends notification about screenshot to peer.
func (s *Sender) sendScreenshotNotification(
ctx context.Context,
req *tg.MessagesSendScreenshotNotificationRequest,
) (tg.UpdatesClass, error) {
if req.RandomID == 0 {
id, err := crypto.RandInt64(s.rand)
if err != nil {
return nil, errors.Wrap(err, "generate random_id")
}
req.RandomID = id
}
return s.raw.MessagesSendScreenshotNotification(ctx, req)
}
// getPeerSettings returns peer settings.
func (s *Sender) getPeerSettings(ctx context.Context, p tg.InputPeerClass) (*tg.MessagesPeerSettings, error) {
return s.raw.MessagesGetPeerSettings(ctx, p)
}
// sendScheduledMessages sends scheduled messages using given ids.
func (s *Sender) sendScheduledMessages(
ctx context.Context,
req *tg.MessagesSendScheduledMessagesRequest,
) (tg.UpdatesClass, error) {
return s.raw.MessagesSendScheduledMessages(ctx, req)
}
// deleteScheduledMessages deletes scheduled messages using given ids.
func (s *Sender) deleteScheduledMessages(
ctx context.Context,
req *tg.MessagesDeleteScheduledMessagesRequest,
) (tg.UpdatesClass, error) {
return s.raw.MessagesDeleteScheduledMessages(ctx, req)
}
// getScheduledHistory gets scheduled messages history.
func (s *Sender) getScheduledHistory(
ctx context.Context,
req *tg.MessagesGetScheduledHistoryRequest,
) (tg.MessagesMessagesClass, error) {
return s.raw.MessagesGetScheduledHistory(ctx, req)
}
// getScheduledMessages gets scheduled messages using given ids.
func (s *Sender) getScheduledMessages(
ctx context.Context,
req *tg.MessagesGetScheduledMessagesRequest,
) (tg.MessagesMessagesClass, error) {
return s.raw.MessagesGetScheduledMessages(ctx, req)
}
// importChatInvite imports a chat invite and join a private chat/supergroup/channel.
func (s *Sender) importChatInvite(
ctx context.Context,
hash string,
) (tg.UpdatesClass, error) {
return s.raw.MessagesImportChatInvite(ctx, hash)
}
// joinChannel joins a channel/supergroup.
func (s *Sender) joinChannel(
ctx context.Context,
input tg.InputChannelClass,
) (tg.UpdatesClass, error) {
return s.raw.ChannelsJoinChannel(ctx, input)
}
// leaveChannel leaves a channel/supergroup.
func (s *Sender) leaveChannel(
ctx context.Context,
input tg.InputChannelClass,
) (tg.UpdatesClass, error) {
return s.raw.ChannelsLeaveChannel(ctx, input)
}
// deleteChatUser delete user from chat.
func (s *Sender) deleteChatUser(
ctx context.Context,
req *tg.MessagesDeleteChatUserRequest,
) (tg.UpdatesClass, error) {
return s.raw.MessagesDeleteChatUser(ctx, req)
}
// deleteChannelMessages deletes messages in channel.
func (s *Sender) deleteChannelMessages(
ctx context.Context,
req *tg.ChannelsDeleteMessagesRequest,
) (*tg.MessagesAffectedMessages, error) {
return s.raw.ChannelsDeleteMessages(ctx, req)
}
// deleteMessages deletes messages in chat.
func (s *Sender) deleteMessages(
ctx context.Context,
req *tg.MessagesDeleteMessagesRequest,
) (*tg.MessagesAffectedMessages, error) {
return s.raw.MessagesDeleteMessages(ctx, req)
}