merged from gramsrv upstream

This commit is contained in:
onysd 2026-09-01 12:06:31 +03:00
parent 79c64ee916
commit 21a0856587
651 changed files with 54774 additions and 4590 deletions

View file

@ -3,6 +3,7 @@ package memory
import (
"context"
"sort"
"strings"
"telesrv/internal/domain"
)
@ -29,6 +30,38 @@ func mediaCategoryMatches(media *domain.MessageMedia, entities []domain.MessageE
return false
}
func mediaSearchCommonMatches(id, date int, body string, reply *domain.MessageReply, req domain.MediaSearchRequest) bool {
if req.Query != "" && !strings.Contains(strings.ToLower(body), strings.ToLower(req.Query)) {
return false
}
if req.MinDate > 0 && date <= req.MinDate {
return false
}
if req.MaxDate > 0 && date >= req.MaxDate {
return false
}
if req.TopMsgID != 0 && id != req.TopMsgID && (reply == nil || reply.TopMessageID != req.TopMsgID) {
return false
}
return true
}
func savedMessageHasAnyTag(tags []domain.MessageReaction, wanted []domain.MessageReaction) bool {
if len(wanted) == 0 {
return true
}
have := make(map[string]struct{}, len(tags))
for _, reaction := range tags {
have[reaction.Key()] = struct{}{}
}
for _, reaction := range wanted {
if _, ok := have[reaction.Key()]; ok {
return true
}
}
return false
}
// pageMediaIDs 把全部匹配 id 按 newest-first 分页(返回本页 id + 满足 max/min 的总数)。
func pageMediaIDs(ids []int, req domain.MediaSearchRequest) ([]int, int) {
sort.Sort(sort.Reverse(sort.IntSlice(ids)))
@ -80,7 +113,19 @@ func (s *MessageStore) SearchPrivateMedia(ctx context.Context, ownerUserID, peer
s.mu.RLock()
matched := make([]int, 0, len(s.m[ownerUserID]))
for _, msg := range s.m[ownerUserID] {
if msg.Peer.Type != domain.PeerTypeUser || msg.Peer.ID != peerID {
if msg.Deleted || msg.Peer.Type != domain.PeerTypeUser || msg.Peer.ID != peerID {
continue
}
if req.SenderUserID != 0 && (msg.From.Type != domain.PeerTypeUser || msg.From.ID != req.SenderUserID) {
continue
}
if !mediaSearchCommonMatches(msg.ID, msg.Date, msg.Body, msg.ReplyTo, req) {
continue
}
if req.SavedPeer.ID != 0 && msg.SavedPeer != req.SavedPeer {
continue
}
if !savedMessageHasAnyTag(s.savedMessageTags[ownerUserID][msg.ID], req.SavedReactions) {
continue
}
if mediaCategoryMatches(msg.Media, msg.Entities, set) {
@ -110,7 +155,7 @@ func (s *MessageStore) CountPrivateMediaCategories(_ context.Context, ownerUserI
defer s.mu.RUnlock()
out := domain.MediaCategoryCounts{}
for _, msg := range s.m[ownerUserID] {
if msg.Peer.Type != domain.PeerTypeUser || msg.Peer.ID != peerID {
if msg.Deleted || msg.Peer.Type != domain.PeerTypeUser || msg.Peer.ID != peerID {
continue
}
for _, category := range domain.ClassifyMediaCategories(msg.Media, msg.Entities) {
@ -129,7 +174,7 @@ func (s *ChannelStore) SearchChannelMedia(ctx context.Context, viewerUserID, cha
return domain.ChannelHistory{}, nil
}
s.mu.RLock()
_, member, err := s.channelAndMemberLocked(viewerUserID, channelID)
channel, member, err := s.channelAndMemberLocked(viewerUserID, channelID)
if err != nil {
s.mu.RUnlock()
return domain.ChannelHistory{}, err
@ -139,6 +184,20 @@ func (s *ChannelStore) SearchChannelMedia(ctx context.Context, viewerUserID, cha
if msg.Deleted || msg.ID <= member.AvailableMinID {
continue
}
if channel.Monoforum {
if member.CanManageDirectMessages() && msg.SavedPeer.ID != 0 {
continue
}
if !member.CanManageDirectMessages() && msg.SavedPeer != (domain.Peer{Type: domain.PeerTypeUser, ID: viewerUserID}) {
continue
}
}
if req.SenderUserID != 0 && msg.SenderUserID != req.SenderUserID {
continue
}
if !mediaSearchCommonMatches(msg.ID, msg.Date, msg.Body, msg.ReplyTo, req) {
continue
}
if mediaCategoryMatches(msg.Media, msg.Entities, set) {
matched = append(matched, msg.ID)
}
@ -165,7 +224,7 @@ func (s *ChannelStore) CountChannelMediaCategories(_ context.Context, viewerUser
}
s.mu.RLock()
defer s.mu.RUnlock()
_, member, err := s.channelAndMemberLocked(viewerUserID, channelID)
channel, member, err := s.channelAndMemberLocked(viewerUserID, channelID)
if err != nil {
return domain.MediaCategoryCounts{}, err
}
@ -174,6 +233,14 @@ func (s *ChannelStore) CountChannelMediaCategories(_ context.Context, viewerUser
if msg.Deleted || msg.ID <= member.AvailableMinID {
continue
}
if channel.Monoforum {
if member.CanManageDirectMessages() && msg.SavedPeer.ID != 0 {
continue
}
if !member.CanManageDirectMessages() && msg.SavedPeer != (domain.Peer{Type: domain.PeerTypeUser, ID: viewerUserID}) {
continue
}
}
for _, category := range domain.ClassifyMediaCategories(msg.Media, msg.Entities) {
if category != domain.MediaCategoryNone {
out[category]++