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.
282 lines
8.0 KiB
282 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) |
|
}
|
|
|