chore: refresh gramsrv public release
This commit is contained in:
parent
75cebe8dbf
commit
70b6820474
1274 changed files with 378751 additions and 59919 deletions
198
internal/store/memory/media_search.go
Normal file
198
internal/store/memory/media_search.go
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
package memory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
)
|
||||
|
||||
// 共享媒体标签页读路径(memory 实现):直接扫内存消息按 domain.ClassifyMediaCategories 分类过滤,
|
||||
// 无需索引表(数据量小)。分类真值与 postgres 写路径/回填同源。
|
||||
|
||||
func mediaCategorySet(cats []domain.MediaCategory) map[domain.MediaCategory]bool {
|
||||
set := make(map[domain.MediaCategory]bool, len(cats))
|
||||
for _, c := range cats {
|
||||
if c != domain.MediaCategoryNone {
|
||||
set[c] = true
|
||||
}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func mediaCategoryMatches(media *domain.MessageMedia, entities []domain.MessageEntity, set map[domain.MediaCategory]bool) bool {
|
||||
for _, c := range domain.ClassifyMediaCategories(media, entities) {
|
||||
if set[c] {
|
||||
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)))
|
||||
inRange := make([]int, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
if req.MaxID != 0 && id > req.MaxID {
|
||||
continue
|
||||
}
|
||||
if req.MinID != 0 && id < req.MinID {
|
||||
continue
|
||||
}
|
||||
inRange = append(inRange, id)
|
||||
}
|
||||
count := len(inRange)
|
||||
page := make([]int, 0, len(inRange))
|
||||
for _, id := range inRange {
|
||||
if req.OffsetID != 0 && id >= req.OffsetID {
|
||||
continue
|
||||
}
|
||||
page = append(page, id)
|
||||
}
|
||||
off := req.AddOffset
|
||||
if off < 0 {
|
||||
off = 0
|
||||
}
|
||||
if off > len(page) {
|
||||
off = len(page)
|
||||
}
|
||||
page = page[off:]
|
||||
limit := req.Limit
|
||||
if limit == 0 {
|
||||
return nil, count
|
||||
}
|
||||
if limit < 0 || limit > 100 {
|
||||
limit = 100
|
||||
}
|
||||
if len(page) > limit {
|
||||
page = page[:limit]
|
||||
}
|
||||
return page, count
|
||||
}
|
||||
|
||||
// SearchPrivateMedia 实现 store.MessageStore。
|
||||
func (s *MessageStore) SearchPrivateMedia(ctx context.Context, ownerUserID, peerID int64, req domain.MediaSearchRequest) (domain.MessageList, error) {
|
||||
set := mediaCategorySet(req.Categories)
|
||||
if ownerUserID == 0 || peerID == 0 || len(set) == 0 {
|
||||
return domain.MessageList{}, nil
|
||||
}
|
||||
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 {
|
||||
continue
|
||||
}
|
||||
if mediaCategoryMatches(msg.Media, msg.Entities, set) {
|
||||
matched = append(matched, msg.ID)
|
||||
}
|
||||
}
|
||||
s.mu.RUnlock()
|
||||
|
||||
ids, count := pageMediaIDs(matched, req)
|
||||
if req.HasKnownCount {
|
||||
count = req.KnownCount
|
||||
}
|
||||
list, err := s.GetByIDs(ctx, ownerUserID, ids)
|
||||
if err != nil {
|
||||
return domain.MessageList{}, err
|
||||
}
|
||||
list.Count = count
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// CountPrivateMediaCategories 实现 store.MessageStore。
|
||||
func (s *MessageStore) CountPrivateMediaCategories(_ context.Context, ownerUserID, peerID int64) (domain.MediaCategoryCounts, error) {
|
||||
if ownerUserID == 0 || peerID == 0 {
|
||||
return domain.MediaCategoryCounts{}, nil
|
||||
}
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
out := domain.MediaCategoryCounts{}
|
||||
for _, msg := range s.m[ownerUserID] {
|
||||
if msg.Peer.Type != domain.PeerTypeUser || msg.Peer.ID != peerID {
|
||||
continue
|
||||
}
|
||||
for _, category := range domain.ClassifyMediaCategories(msg.Media, msg.Entities) {
|
||||
if category != domain.MediaCategoryNone {
|
||||
out[category]++
|
||||
}
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// SearchChannelMedia 实现 store.ChannelStore。
|
||||
func (s *ChannelStore) SearchChannelMedia(ctx context.Context, viewerUserID, channelID int64, req domain.MediaSearchRequest) (domain.ChannelHistory, error) {
|
||||
set := mediaCategorySet(req.Categories)
|
||||
if viewerUserID == 0 || channelID == 0 || len(set) == 0 {
|
||||
return domain.ChannelHistory{}, nil
|
||||
}
|
||||
s.mu.RLock()
|
||||
_, member, err := s.channelAndMemberLocked(viewerUserID, channelID)
|
||||
if err != nil {
|
||||
s.mu.RUnlock()
|
||||
return domain.ChannelHistory{}, err
|
||||
}
|
||||
matched := make([]int, 0, len(s.messages[channelID]))
|
||||
for _, msg := range s.messages[channelID] {
|
||||
if msg.Deleted || msg.ID <= member.AvailableMinID {
|
||||
continue
|
||||
}
|
||||
if mediaCategoryMatches(msg.Media, msg.Entities, set) {
|
||||
matched = append(matched, msg.ID)
|
||||
}
|
||||
}
|
||||
s.mu.RUnlock()
|
||||
|
||||
ids, count := pageMediaIDs(matched, req)
|
||||
if req.HasKnownCount {
|
||||
count = req.KnownCount
|
||||
}
|
||||
hist, err := s.GetChannelMessages(ctx, viewerUserID, channelID, ids)
|
||||
if err != nil {
|
||||
return domain.ChannelHistory{}, err
|
||||
}
|
||||
hist.Messages = reorderChannelMessagesByMediaOrder(hist.Messages, ids)
|
||||
hist.Count = count
|
||||
return hist, nil
|
||||
}
|
||||
|
||||
// CountChannelMediaCategories 实现 store.ChannelStore。
|
||||
func (s *ChannelStore) CountChannelMediaCategories(_ context.Context, viewerUserID, channelID int64) (domain.MediaCategoryCounts, error) {
|
||||
if viewerUserID == 0 || channelID == 0 {
|
||||
return domain.MediaCategoryCounts{}, nil
|
||||
}
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
_, member, err := s.channelAndMemberLocked(viewerUserID, channelID)
|
||||
if err != nil {
|
||||
return domain.MediaCategoryCounts{}, err
|
||||
}
|
||||
out := domain.MediaCategoryCounts{}
|
||||
for _, msg := range s.messages[channelID] {
|
||||
if msg.Deleted || msg.ID <= member.AvailableMinID {
|
||||
continue
|
||||
}
|
||||
for _, category := range domain.ClassifyMediaCategories(msg.Media, msg.Entities) {
|
||||
if category != domain.MediaCategoryNone {
|
||||
out[category]++
|
||||
}
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func reorderChannelMessagesByMediaOrder(msgs []domain.ChannelMessage, order []int) []domain.ChannelMessage {
|
||||
byID := make(map[int]domain.ChannelMessage, len(msgs))
|
||||
for _, m := range msgs {
|
||||
byID[m.ID] = m
|
||||
}
|
||||
out := make([]domain.ChannelMessage, 0, len(order))
|
||||
for _, id := range order {
|
||||
if m, ok := byID[id]; ok {
|
||||
out = append(out, m)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue