Ctrl K
ComunidadGuías…

internal/domain/sticker_search.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package domain

import (
	"sort"
	"strings"
)

// SearchStickerSets returns a stable public catalog projection. It never
// mutates the shared catalog or includes archived, deleted, or system sets.
func SearchStickerSets(sets []StickerSet, kind StickerSetKind, query string) []StickerSet {
	tokens := strings.Fields(stickerSearchText(query))
	result := make([]StickerSet, 0)
	for _, set := range sets {
		if set.ID == 0 || set.Deleted || set.Archived || set.Kind != kind {
			continue
		}
		if stickerSearchMatches(stickerSearchText(set.Title+" "+set.ShortName), tokens) {
			result = append(result, set)
		}
	}
	sort.Slice(result, func(i, j int) bool {
		if result[i].SortOrder != result[j].SortOrder {
			return result[i].SortOrder < result[j].SortOrder
		}
		return result[i].ID < result[j].ID
	})
	return result
}

// SearchStickerDocuments searches metadata before materializing only the
// requested page of document payloads. Keywords remain specific to each item.
func SearchStickerDocuments(sets []StickerSet, kind StickerSetKind, query, emojis string, offset, limit int) []int64 {
	result := make([]int64, 0, limit)
	if limit == 0 {
		return result
	}
	tokens := strings.Fields(stickerSearchText(query))
	emojiTokens := strings.Fields(stickerSearchText(emojis))
	seen := make(map[int64]bool)
	matched := 0
	for _, set := range SearchStickerSets(sets, kind, "") {
		words := make(map[int64]string)
		emojiByID := make(map[int64]string)
		for _, pack := range set.Packs {
			for _, id := range pack.DocumentIDs {
				emojiByID[id] += " " + stickerSearchText(pack.Emoticon)
			}
		}
		for _, entry := range set.Keywords {
			words[entry.DocumentID] += " " + stickerSearchText(strings.Join(entry.Keywords, " "))
		}
		title := stickerSearchText(set.Title + " " + set.ShortName)
		for _, id := range set.DocumentIDs {
			if id == 0 || seen[id] {
				continue
			}
			text := title + " " + words[id] + " " + emojiByID[id]
			if !stickerSearchMatches(text, tokens) {
				continue
			}
			emojiMatches := len(emojiTokens) == 0
			for _, emoji := range emojiTokens {
				for _, candidate := range strings.Fields(emojiByID[id]) {
					if candidate == emoji {
						emojiMatches = true
					}
				}
			}
			if !emojiMatches {
				continue
			}
			seen[id] = true
			if matched >= offset {
				result = append(result, id)
			}
			matched++
			if len(result) == limit {
				return result
			}
		}
	}
	return result
}

func stickerSearchText(value string) string {
	return strings.ToLower(strings.NewReplacer("\ufe0f", "", "\ufe0e", "").Replace(value))
}

func stickerSearchMatches(text string, tokens []string) bool {
	for _, token := range tokens {
		if !strings.Contains(text, token) {
			return false
		}
	}
	return true
}