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
283 lines
8.0 KiB
3 years ago
|
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)
|
||
|
}
|