283 lines
8.1 KiB
Go
283 lines
8.1 KiB
Go
package rpc
|
|
|
|
import (
|
|
"context"
|
|
|
|
"telesrv/internal/domain"
|
|
)
|
|
|
|
func (r *Router) enrichUpdateEvents(ctx context.Context, viewerUserID int64, events []domain.UpdateEvent) []domain.UpdateEvent {
|
|
if len(events) == 0 {
|
|
return events
|
|
}
|
|
out := append([]domain.UpdateEvent(nil), events...)
|
|
for i := range out {
|
|
if out[i].Type == domain.UpdateEventMessageReactions {
|
|
out[i] = r.enrichMessageReactionEvent(ctx, viewerUserID, out[i])
|
|
}
|
|
userIDs := make(map[int64]struct{})
|
|
channelIDs := make(map[int64]struct{})
|
|
addDomainPeerRef(out[i].Peer, 0, userIDs, channelIDs)
|
|
for _, peer := range out[i].Peers {
|
|
addDomainPeerRef(peer, 0, userIDs, channelIDs)
|
|
}
|
|
collectMessagePeerRefs(out[i].Message, 0, userIDs, channelIDs)
|
|
out[i].Users = r.withUsersPresence(mergeDomainUsers(out[i].Users, r.domainUsersForIDs(ctx, viewerUserID, mapKeys(userIDs))...))
|
|
out[i].Channels = mergeDomainChannels(out[i].Channels, r.domainChannelsForIDs(ctx, viewerUserID, mapKeys(channelIDs))...)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (r *Router) enrichMessageReactionEvent(ctx context.Context, viewerUserID int64, event domain.UpdateEvent) domain.UpdateEvent {
|
|
if r.deps.Messages == nil || event.Message.ID <= 0 {
|
|
return event
|
|
}
|
|
peer := event.Message.Peer
|
|
if peer.Type == "" || peer.ID == 0 {
|
|
peer = event.Peer
|
|
}
|
|
if peer.Type != domain.PeerTypeUser || peer.ID == 0 {
|
|
return event
|
|
}
|
|
res, err := r.deps.Messages.GetMessageReactions(ctx, viewerUserID, domain.PrivateMessageReactionsRequest{
|
|
OwnerUserID: viewerUserID,
|
|
Peer: peer,
|
|
IDs: []int{event.Message.ID},
|
|
})
|
|
if err != nil {
|
|
return event
|
|
}
|
|
for _, msg := range res.Messages {
|
|
if msg.OwnerUserID == viewerUserID && msg.ID == event.Message.ID {
|
|
msg.Pts = event.Pts
|
|
event.Message = msg
|
|
event.Peer = msg.Peer
|
|
return event
|
|
}
|
|
}
|
|
return event
|
|
}
|
|
|
|
func (r *Router) enrichChannelDifference(ctx context.Context, viewerUserID int64, diff domain.ChannelDifference) domain.ChannelDifference {
|
|
userIDs := make(map[int64]struct{})
|
|
channelIDs := make(map[int64]struct{})
|
|
for _, event := range diff.Events {
|
|
collectChannelUpdatePeerRefs(event, diff.Channel.ID, userIDs, channelIDs)
|
|
}
|
|
for _, msg := range diff.NewMessages {
|
|
collectChannelMessagePeerRefs(msg, diff.Channel.ID, userIDs, channelIDs)
|
|
}
|
|
for _, event := range diff.OtherUpdates {
|
|
collectChannelUpdatePeerRefs(event, diff.Channel.ID, userIDs, channelIDs)
|
|
}
|
|
diff.Users = r.withUsersPresence(mergeDomainUsers(diff.Users, r.domainUsersForIDs(ctx, viewerUserID, mapKeys(userIDs))...))
|
|
diff.Channels = mergeDomainChannels(diff.Channels, r.domainChannelsForIDs(ctx, viewerUserID, mapKeys(channelIDs))...)
|
|
return diff
|
|
}
|
|
|
|
func (r *Router) enrichChannelHistory(ctx context.Context, viewerUserID int64, history domain.ChannelHistory) domain.ChannelHistory {
|
|
userIDs := make(map[int64]struct{})
|
|
channelIDs := make(map[int64]struct{})
|
|
for _, msg := range history.Messages {
|
|
collectChannelMessagePeerRefs(msg, history.Channel.ID, userIDs, channelIDs)
|
|
}
|
|
for _, topic := range history.Topics {
|
|
if topic.CreatorUserID != 0 {
|
|
userIDs[topic.CreatorUserID] = struct{}{}
|
|
}
|
|
}
|
|
history.Users = r.withUsersPresence(mergeDomainUsers(history.Users, r.domainUsersForIDs(ctx, viewerUserID, mapKeys(userIDs))...))
|
|
history.Channels = mergeDomainChannels(history.Channels, r.domainChannelsForIDs(ctx, viewerUserID, mapKeys(channelIDs))...)
|
|
return history
|
|
}
|
|
|
|
func collectMessagePeerRefs(msg domain.Message, currentChannelID int64, userIDs, channelIDs map[int64]struct{}) {
|
|
addDomainPeerRef(msg.From, currentChannelID, userIDs, channelIDs)
|
|
addDomainPeerRef(msg.Peer, currentChannelID, userIDs, channelIDs)
|
|
if msg.Forward != nil {
|
|
addDomainPeerRef(msg.Forward.From, currentChannelID, userIDs, channelIDs)
|
|
}
|
|
if msg.ReplyTo != nil {
|
|
addDomainPeerRef(msg.ReplyTo.Peer, currentChannelID, userIDs, channelIDs)
|
|
}
|
|
if msg.Reactions != nil {
|
|
for _, reaction := range msg.Reactions.Recent {
|
|
if reaction.UserID != 0 {
|
|
userIDs[reaction.UserID] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func collectChannelUpdatePeerRefs(event domain.ChannelUpdateEvent, currentChannelID int64, userIDs, channelIDs map[int64]struct{}) {
|
|
if event.SenderUserID != 0 {
|
|
userIDs[event.SenderUserID] = struct{}{}
|
|
}
|
|
for _, id := range event.UserIDs {
|
|
if id != 0 {
|
|
userIDs[id] = struct{}{}
|
|
}
|
|
}
|
|
for _, member := range []domain.ChannelMember{event.Previous, event.Participant} {
|
|
if member.UserID != 0 {
|
|
userIDs[member.UserID] = struct{}{}
|
|
}
|
|
if member.InviterUserID != 0 {
|
|
userIDs[member.InviterUserID] = struct{}{}
|
|
}
|
|
}
|
|
collectChannelMessagePeerRefs(event.Message, currentChannelID, userIDs, channelIDs)
|
|
}
|
|
|
|
func collectChannelMessagePeerRefs(msg domain.ChannelMessage, currentChannelID int64, userIDs, channelIDs map[int64]struct{}) {
|
|
if msg.SenderUserID != 0 {
|
|
userIDs[msg.SenderUserID] = struct{}{}
|
|
}
|
|
addDomainPeerRef(msg.From, currentChannelID, userIDs, channelIDs)
|
|
if msg.SendAs != nil {
|
|
addDomainPeerRef(*msg.SendAs, currentChannelID, userIDs, channelIDs)
|
|
}
|
|
if msg.Forward != nil {
|
|
addDomainPeerRef(msg.Forward.From, currentChannelID, userIDs, channelIDs)
|
|
}
|
|
if msg.ReplyTo != nil {
|
|
addDomainPeerRef(msg.ReplyTo.Peer, currentChannelID, userIDs, channelIDs)
|
|
}
|
|
if msg.Action != nil {
|
|
for _, id := range msg.Action.UserIDs {
|
|
if id != 0 {
|
|
userIDs[id] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
if msg.Reactions != nil {
|
|
for _, reaction := range msg.Reactions.Recent {
|
|
if reaction.UserID != 0 {
|
|
userIDs[reaction.UserID] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func addDomainPeerRef(peer domain.Peer, currentChannelID int64, userIDs, channelIDs map[int64]struct{}) {
|
|
switch peer.Type {
|
|
case domain.PeerTypeUser:
|
|
if peer.ID != 0 {
|
|
userIDs[peer.ID] = struct{}{}
|
|
}
|
|
case domain.PeerTypeChannel:
|
|
if peer.ID != 0 && peer.ID != currentChannelID {
|
|
channelIDs[peer.ID] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (r *Router) domainUsersForIDs(ctx context.Context, currentUserID int64, ids []int64) []domain.User {
|
|
if len(ids) == 0 {
|
|
return nil
|
|
}
|
|
out := make([]domain.User, 0, len(ids))
|
|
seen := make(map[int64]struct{}, len(ids))
|
|
for _, id := range ids {
|
|
if id == 0 {
|
|
continue
|
|
}
|
|
if _, ok := seen[id]; ok {
|
|
continue
|
|
}
|
|
seen[id] = struct{}{}
|
|
switch {
|
|
case id == domain.OfficialSystemUserID:
|
|
out = append(out, r.withUserPresence(domain.OfficialSystemUser()))
|
|
case r.deps.Users == nil:
|
|
continue
|
|
case id == currentUserID:
|
|
if u, err := r.deps.Users.Self(ctx, currentUserID); err == nil && u.ID != 0 {
|
|
out = append(out, r.withUserPresence(u))
|
|
}
|
|
default:
|
|
if u, found, err := r.deps.Users.ByID(ctx, currentUserID, id); err == nil && found {
|
|
out = append(out, r.withUserPresence(u))
|
|
}
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (r *Router) domainChannelsForIDs(ctx context.Context, currentUserID int64, ids []int64) []domain.Channel {
|
|
if r.deps.Channels == nil || len(ids) == 0 {
|
|
return nil
|
|
}
|
|
out := make([]domain.Channel, 0, len(ids))
|
|
seen := make(map[int64]struct{}, len(ids))
|
|
for _, id := range ids {
|
|
if id == 0 {
|
|
continue
|
|
}
|
|
if _, ok := seen[id]; ok {
|
|
continue
|
|
}
|
|
seen[id] = struct{}{}
|
|
view, err := r.deps.Channels.GetChannel(ctx, currentUserID, id)
|
|
if err != nil || view.Channel.ID == 0 {
|
|
continue
|
|
}
|
|
out = append(out, view.Channel)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func mergeDomainUsers(base []domain.User, extra ...domain.User) []domain.User {
|
|
out := append([]domain.User(nil), base...)
|
|
seen := make(map[int64]struct{}, len(out)+len(extra))
|
|
for _, u := range out {
|
|
if u.ID != 0 {
|
|
seen[u.ID] = struct{}{}
|
|
}
|
|
}
|
|
for _, u := range extra {
|
|
if u.ID == 0 {
|
|
continue
|
|
}
|
|
if _, ok := seen[u.ID]; ok {
|
|
continue
|
|
}
|
|
seen[u.ID] = struct{}{}
|
|
out = append(out, u)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func mergeDomainChannels(base []domain.Channel, extra ...domain.Channel) []domain.Channel {
|
|
out := append([]domain.Channel(nil), base...)
|
|
seen := make(map[int64]struct{}, len(out)+len(extra))
|
|
for _, ch := range out {
|
|
if ch.ID != 0 {
|
|
seen[ch.ID] = struct{}{}
|
|
}
|
|
}
|
|
for _, ch := range extra {
|
|
if ch.ID == 0 {
|
|
continue
|
|
}
|
|
if _, ok := seen[ch.ID]; ok {
|
|
continue
|
|
}
|
|
seen[ch.ID] = struct{}{}
|
|
out = append(out, ch)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func mapKeys(items map[int64]struct{}) []int64 {
|
|
if len(items) == 0 {
|
|
return nil
|
|
}
|
|
out := make([]int64, 0, len(items))
|
|
for id := range items {
|
|
if id != 0 {
|
|
out = append(out, id)
|
|
}
|
|
}
|
|
return out
|
|
}
|