chore: refresh gramsrv public release
This commit is contained in:
parent
75cebe8dbf
commit
70b6820474
1274 changed files with 378751 additions and 59919 deletions
353
internal/rpc/messages_reactions_lists.go
Normal file
353
internal/rpc/messages_reactions_lists.go
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/gotd/td/tg"
|
||||
"github.com/gotd/td/tgerr"
|
||||
"telesrv/internal/domain"
|
||||
)
|
||||
|
||||
func (r *Router) onMessagesDeleteParticipantReaction(ctx context.Context, req *tg.MessagesDeleteParticipantReactionRequest) (tg.UpdatesClass, error) {
|
||||
if req.MsgID <= 0 || req.MsgID > domain.MaxMessageBoxID {
|
||||
return nil, messageIDInvalidErr()
|
||||
}
|
||||
userID, peer, err := r.reactionPeer(ctx, req.Peer, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
participant, err := r.checkedDomainPeerFromInputPeer(ctx, userID, req.Participant)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if participant.Type != domain.PeerTypeUser || participant.ID == 0 {
|
||||
return nil, userIDInvalidErr()
|
||||
}
|
||||
if peer.Type != domain.PeerTypeChannel || r.deps.Channels == nil {
|
||||
return tgEmptyUpdates(int(r.clock.Now().Unix())), nil
|
||||
}
|
||||
moderator, ok := r.deps.Channels.(channelParticipantReactionModerator)
|
||||
if !ok {
|
||||
return nil, channelInvalidErr(domain.ErrChannelInvalid)
|
||||
}
|
||||
res, err := moderator.DeleteParticipantReaction(ctx, userID, domain.DeleteChannelParticipantReactionRequest{
|
||||
UserID: userID,
|
||||
ChannelID: peer.ID,
|
||||
MessageID: req.MsgID,
|
||||
ParticipantUserID: participant.ID,
|
||||
Date: int(r.clock.Now().Unix()),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, channelInvalidErr(err)
|
||||
}
|
||||
updates := r.channelMessageReactionsUpdates(ctx, userID, res)
|
||||
moderationIDs := []int{res.Message.ID}
|
||||
r.pushChannelViewerUpdates(ctx, userID, res.Channel.ID, res.Recipients, func(viewerUserID int64) *tg.Updates {
|
||||
return r.channelReactionsViewerUpdates(ctx, userID, viewerUserID, res, moderationIDs)
|
||||
})
|
||||
return updates, nil
|
||||
}
|
||||
|
||||
func (r *Router) onMessagesDeleteParticipantReactions(ctx context.Context, req *tg.MessagesDeleteParticipantReactionsRequest) (bool, error) {
|
||||
userID, peer, err := r.reactionPeer(ctx, req.Peer, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
participant, err := r.checkedDomainPeerFromInputPeer(ctx, userID, req.Participant)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if participant.Type != domain.PeerTypeUser || participant.ID == 0 {
|
||||
return false, userIDInvalidErr()
|
||||
}
|
||||
if peer.Type != domain.PeerTypeChannel || r.deps.Channels == nil {
|
||||
return true, nil
|
||||
}
|
||||
moderator, ok := r.deps.Channels.(channelParticipantReactionModerator)
|
||||
if !ok {
|
||||
return false, channelInvalidErr(domain.ErrChannelInvalid)
|
||||
}
|
||||
res, err := moderator.DeleteParticipantReactions(ctx, userID, domain.DeleteChannelParticipantReactionsRequest{
|
||||
UserID: userID,
|
||||
ChannelID: peer.ID,
|
||||
ParticipantUserID: participant.ID,
|
||||
Limit: domain.MaxDeleteParticipantReactionsBatch,
|
||||
Date: int(r.clock.Now().Unix()),
|
||||
})
|
||||
if err != nil {
|
||||
return false, channelInvalidErr(err)
|
||||
}
|
||||
if len(res.Messages) > 0 {
|
||||
reactionRes := domain.ChannelMessageReactionsResult{
|
||||
Channel: res.Channel,
|
||||
Messages: res.Messages,
|
||||
Recipients: res.Recipients,
|
||||
}
|
||||
ids := make([]int, 0, len(res.Messages))
|
||||
for _, msg := range res.Messages {
|
||||
if msg.ID > 0 {
|
||||
ids = append(ids, msg.ID)
|
||||
}
|
||||
}
|
||||
r.pushChannelViewerUpdates(ctx, userID, res.Channel.ID, res.Recipients, func(viewerUserID int64) *tg.Updates {
|
||||
return r.channelReactionsViewerUpdates(ctx, userID, viewerUserID, reactionRes, ids)
|
||||
})
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (r *Router) onMessagesGetMessagesReactions(ctx context.Context, req *tg.MessagesGetMessagesReactionsRequest) (tg.UpdatesClass, error) {
|
||||
if len(req.ID) > maxGetMessagesIDs {
|
||||
return nil, limitInvalidErr()
|
||||
}
|
||||
userID, peer, err := r.reactionPeer(ctx, req.Peer, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if peer.Type == domain.PeerTypeChannel && r.deps.Channels != nil {
|
||||
res, err := r.deps.Channels.GetMessageReactions(ctx, userID, domain.ChannelMessageReactionsRequest{
|
||||
UserID: userID,
|
||||
ChannelID: peer.ID,
|
||||
IDs: append([]int(nil), req.ID...),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, channelInvalidErr(err)
|
||||
}
|
||||
return r.channelMessagesReactionsUpdates(ctx, userID, res, req.ID), nil
|
||||
}
|
||||
if peer.Type == domain.PeerTypeUser && r.deps.Messages != nil {
|
||||
res, err := r.deps.Messages.GetMessageReactions(ctx, userID, domain.PrivateMessageReactionsRequest{
|
||||
OwnerUserID: userID,
|
||||
Peer: peer,
|
||||
IDs: append([]int(nil), req.ID...),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, messageReactionErr(err)
|
||||
}
|
||||
return r.privateMessagesReactionsUpdates(ctx, userID, peer, res, req.ID), nil
|
||||
}
|
||||
updates := make([]tg.UpdateClass, 0, len(req.ID))
|
||||
tgPeer := tgPeer(peer)
|
||||
for _, msgID := range req.ID {
|
||||
if msgID <= 0 || msgID > domain.MaxMessageBoxID {
|
||||
return nil, messageIDInvalidErr()
|
||||
}
|
||||
updates = append(updates, &tg.UpdateMessageReactions{
|
||||
Peer: tgPeer,
|
||||
MsgID: msgID,
|
||||
Reactions: tg.MessageReactions{
|
||||
Results: []tg.ReactionCount{},
|
||||
},
|
||||
})
|
||||
}
|
||||
return &tg.Updates{
|
||||
Updates: updates,
|
||||
Users: []tg.UserClass{},
|
||||
Chats: []tg.ChatClass{},
|
||||
Date: int(r.clock.Now().Unix()),
|
||||
Seq: 0,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Router) onMessagesGetMessageReactionsList(ctx context.Context, req *tg.MessagesGetMessageReactionsListRequest) (*tg.MessagesMessageReactionsList, error) {
|
||||
if req.ID <= 0 || req.ID > domain.MaxMessageBoxID {
|
||||
return nil, messageIDInvalidErr()
|
||||
}
|
||||
if req.Limit < 0 || req.Limit > maxSearchResultsLimit {
|
||||
return nil, limitInvalidErr()
|
||||
}
|
||||
if offset, ok := req.GetOffset(); ok && len(offset) > maxReactionListOffset {
|
||||
return nil, limitInvalidErr()
|
||||
}
|
||||
userID, peer, err := r.reactionPeer(ctx, req.Peer, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if peer.Type == domain.PeerTypeChannel && r.deps.Channels != nil {
|
||||
filter, err := optionalDomainMessageReaction(req.Reaction)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := r.deps.Channels.ListMessageReactions(ctx, userID, domain.ChannelMessageReactionsListRequest{
|
||||
UserID: userID,
|
||||
ChannelID: peer.ID,
|
||||
MessageID: req.ID,
|
||||
Reaction: filter,
|
||||
Offset: optionalString(req.GetOffset),
|
||||
Limit: req.Limit,
|
||||
})
|
||||
if errors.Is(err, domain.ErrChannelRightForbidden) {
|
||||
return nil, tgerr.New(403, "BROADCAST_FORBIDDEN")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, channelInvalidErr(err)
|
||||
}
|
||||
userIDs := make([]int64, 0, len(res.Reactions))
|
||||
reactions := make([]tg.MessagePeerReaction, 0, len(res.Reactions))
|
||||
for _, item := range res.Reactions {
|
||||
if item.UserID != 0 {
|
||||
userIDs = append(userIDs, item.UserID)
|
||||
}
|
||||
if converted := tgMessagePeerReaction(userID, item); converted != nil {
|
||||
reactions = append(reactions, *converted)
|
||||
}
|
||||
}
|
||||
out := &tg.MessagesMessageReactionsList{
|
||||
Count: res.Count,
|
||||
Reactions: reactions,
|
||||
Chats: tgChannels(userID, []domain.Channel{res.Channel}),
|
||||
Users: r.tgUsersForIDs(ctx, userID, userIDs),
|
||||
}
|
||||
if res.NextOffset != "" {
|
||||
out.SetNextOffset(res.NextOffset)
|
||||
}
|
||||
return r.applyStoryMaxIDsToMessageReactionsList(ctx, userID, out), nil
|
||||
}
|
||||
if peer.Type == domain.PeerTypeUser && r.deps.Messages != nil {
|
||||
filter, err := optionalDomainMessageReaction(req.Reaction)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := r.deps.Messages.GetMessageReactions(ctx, userID, domain.PrivateMessageReactionsRequest{
|
||||
OwnerUserID: userID,
|
||||
Peer: peer,
|
||||
IDs: []int{req.ID},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, messageReactionErr(err)
|
||||
}
|
||||
var source domain.ChannelMessageReactions
|
||||
if len(res.Messages) > 0 && res.Messages[0].Reactions != nil {
|
||||
source = *res.Messages[0].Reactions
|
||||
} else {
|
||||
source = res.Reactions
|
||||
}
|
||||
limit := req.Limit
|
||||
if limit <= 0 || limit > len(source.Recent) {
|
||||
limit = len(source.Recent)
|
||||
}
|
||||
userIDs := []int64{userID, peer.ID}
|
||||
reactions := make([]tg.MessagePeerReaction, 0, limit)
|
||||
count := 0
|
||||
for _, item := range source.Recent {
|
||||
if filter != nil && item.Reaction.Key() != filter.Key() {
|
||||
continue
|
||||
}
|
||||
count++
|
||||
if len(reactions) >= limit {
|
||||
continue
|
||||
}
|
||||
if item.UserID != 0 {
|
||||
userIDs = append(userIDs, item.UserID)
|
||||
}
|
||||
if converted := tgMessagePeerReaction(userID, item); converted != nil {
|
||||
reactions = append(reactions, *converted)
|
||||
}
|
||||
}
|
||||
return r.applyStoryMaxIDsToMessageReactionsList(ctx, userID, &tg.MessagesMessageReactionsList{
|
||||
Count: count,
|
||||
Reactions: reactions,
|
||||
Chats: r.chatsForInputPeer(ctx, userID, req.Peer),
|
||||
Users: r.tgUsersForIDs(ctx, userID, userIDs),
|
||||
}), nil
|
||||
}
|
||||
return r.applyStoryMaxIDsToMessageReactionsList(ctx, userID, &tg.MessagesMessageReactionsList{
|
||||
Count: 0,
|
||||
Reactions: []tg.MessagePeerReaction{},
|
||||
Chats: r.chatsForInputPeer(ctx, userID, req.Peer),
|
||||
Users: []tg.UserClass{},
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (r *Router) onMessagesGetUnreadReactions(ctx context.Context, req *tg.MessagesGetUnreadReactionsRequest) (tg.MessagesMessagesClass, error) {
|
||||
if err := validateHistoryBounds(req.OffsetID, req.AddOffset, req.Limit, req.MaxID, req.MinID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userID, peer, err := r.reactionPeer(ctx, req.Peer, req.GetSavedPeerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if topMsgID, ok := req.GetTopMsgID(); ok && (topMsgID < 0 || topMsgID > domain.MaxMessageBoxID) {
|
||||
return nil, messageIDInvalidErr()
|
||||
}
|
||||
if peer.Type == domain.PeerTypeChannel && r.deps.Channels != nil {
|
||||
history, err := r.deps.Channels.GetUnreadReactions(ctx, userID, domain.ChannelUnreadReactionsFilter{
|
||||
ChannelID: peer.ID,
|
||||
TopMsgID: req.TopMsgID,
|
||||
OffsetID: req.OffsetID,
|
||||
AddOffset: req.AddOffset,
|
||||
Limit: req.Limit,
|
||||
MaxID: req.MaxID,
|
||||
MinID: req.MinID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, channelInvalidErr(err)
|
||||
}
|
||||
return r.tgChannelHistoryMessages(ctx, userID, r.enrichChannelHistory(ctx, userID, history)), nil
|
||||
}
|
||||
if peer.Type == domain.PeerTypeUser && r.deps.Messages != nil {
|
||||
messages, err := r.deps.Messages.ListUnreadReactionMessages(ctx, userID, peer, req.Limit)
|
||||
if err != nil {
|
||||
return nil, internalErr()
|
||||
}
|
||||
out := &tg.MessagesMessages{
|
||||
Messages: make([]tg.MessageClass, 0, len(messages)),
|
||||
Topics: []tg.ForumTopicClass{},
|
||||
Chats: r.chatsForInputPeer(ctx, userID, req.Peer),
|
||||
Users: r.usersForMessageUpdates(ctx, userID, messages),
|
||||
}
|
||||
for _, msg := range messages {
|
||||
if item := tgMessage(msg); item != nil {
|
||||
out.Messages = append(out.Messages, item)
|
||||
}
|
||||
}
|
||||
r.applyStoryMaxIDsToMessages(ctx, userID, out)
|
||||
return out, nil
|
||||
}
|
||||
out := &tg.MessagesMessages{
|
||||
Messages: []tg.MessageClass{},
|
||||
Topics: []tg.ForumTopicClass{},
|
||||
Chats: r.chatsForInputPeer(ctx, userID, req.Peer),
|
||||
Users: []tg.UserClass{},
|
||||
}
|
||||
r.applyStoryMaxIDsToMessages(ctx, userID, out)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (r *Router) onMessagesReadReactions(ctx context.Context, req *tg.MessagesReadReactionsRequest) (*tg.MessagesAffectedHistory, error) {
|
||||
authKeyID, _ := AuthKeyIDFrom(ctx)
|
||||
userID, _, err := r.currentUserID(ctx)
|
||||
if err != nil {
|
||||
return nil, internalErr()
|
||||
}
|
||||
peer, err := r.checkedDomainPeerFromInputPeer(ctx, userID, req.Peer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if savedPeer, ok := req.GetSavedPeerID(); ok && savedPeer != nil {
|
||||
if _, err := r.checkedDomainPeerFromInputPeer(ctx, userID, savedPeer); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if topMsgID, ok := req.GetTopMsgID(); ok && (topMsgID < 0 || topMsgID > domain.MaxMessageBoxID) {
|
||||
return nil, messageIDInvalidErr()
|
||||
}
|
||||
if peer.Type == domain.PeerTypeChannel && r.deps.Channels != nil {
|
||||
res, err := r.deps.Channels.ReadReactions(ctx, userID, domain.ReadChannelReactionsRequest{
|
||||
UserID: userID,
|
||||
ChannelID: peer.ID,
|
||||
TopMsgID: req.TopMsgID,
|
||||
Limit: domain.MaxChannelReadReactionsBatch,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, channelInvalidErr(err)
|
||||
}
|
||||
return &tg.MessagesAffectedHistory{Pts: res.ChannelPts, PtsCount: 0, Offset: res.Offset}, nil
|
||||
}
|
||||
if peer.Type == domain.PeerTypeUser && r.deps.Messages != nil {
|
||||
if _, err := r.deps.Messages.ReadPeerReactions(ctx, userID, peer); err != nil {
|
||||
return nil, internalErr()
|
||||
}
|
||||
}
|
||||
return r.affectedHistory(ctx, authKeyID, userID, 0)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue