Skip to content

Commit fc801f2

Browse files
authored
fix: ignore '&' tags in discovery and relation aggregation (#57)
- Add WHERE tag NOT LIKE '%&%' in getTagForDiscovery - Skip '&' tags in suggestion parsing and source picking - Exclude them from relation aggregation and updates - Early-return in processDiscoveredTag to prevent propagation - Provide SQL to delete existing '&' tag rows across related tables Closes #56 ZerGo0 Bot Co-authored-by: ZerGo0 <ZerGo0@users.noreply.github.com>
1 parent d68db92 commit fc801f2

File tree

3 files changed

+78
-68
lines changed

3 files changed

+78
-68
lines changed

backend-go/handlers/tag_handler.go

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -260,28 +260,28 @@ func (h *TagHandler) GetTags(c *fiber.Ctx) error {
260260
ChangePercent: 0,
261261
}
262262

263-
// Calculate change from previous point based on view count
264-
if i < len(history)-1 {
265-
previousPoint := history[i+1]
266-
// Calculate view count change as primary metric
267-
viewChange := point.ViewCount - previousPoint.ViewCount
268-
historyPoints[i].Change = viewChange
269-
270-
// Still track post count change for reference
271-
postChange := point.PostCount - previousPoint.PostCount
272-
historyPoints[i].PostCountChange = postChange
273-
if previousPoint.ViewCount > 0 {
274-
historyPoints[i].ChangePercent = float64(viewChange) / float64(previousPoint.ViewCount) * 100
275-
}
276-
}
277-
}
278-
279-
// Calculate total change based on view count
280-
if len(history) > 0 {
281-
newest := history[0].ViewCount
282-
oldest := history[len(history)-1].ViewCount
283-
tagWithHist.TotalChange = newest - oldest
284-
}
263+
// Calculate change from previous point based on view count
264+
if i < len(history)-1 {
265+
previousPoint := history[i+1]
266+
// Calculate view count change as primary metric
267+
viewChange := point.ViewCount - previousPoint.ViewCount
268+
historyPoints[i].Change = viewChange
269+
270+
// Still track post count change for reference
271+
postChange := point.PostCount - previousPoint.PostCount
272+
historyPoints[i].PostCountChange = postChange
273+
if previousPoint.ViewCount > 0 {
274+
historyPoints[i].ChangePercent = float64(viewChange) / float64(previousPoint.ViewCount) * 100
275+
}
276+
}
277+
}
278+
279+
// Calculate total change based on view count
280+
if len(history) > 0 {
281+
newest := history[0].ViewCount
282+
oldest := history[len(history)-1].ViewCount
283+
tagWithHist.TotalChange = newest - oldest
284+
}
285285

286286
if includeHistory {
287287
tagWithHist.History = historyPoints

backend-go/workers/statistics_calculator.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ func (w *StatisticsCalculatorWorker) calculateTagStatistics(ctx context.Context)
7676
return fmt.Errorf("failed to fetch previous statistics: %w", err)
7777
}
7878

79-
// Calculate 24-hour changes based on view count
80-
var change24h int64
81-
var changePercent24h float64
82-
if previousStats.ID != 0 {
83-
change24h = totalViewCount - previousStats.TotalViewCount
84-
if previousStats.TotalViewCount > 0 {
85-
changePercent24h = (float64(change24h) / float64(previousStats.TotalViewCount)) * 100
86-
}
87-
}
79+
// Calculate 24-hour changes based on view count
80+
var change24h int64
81+
var changePercent24h float64
82+
if previousStats.ID != 0 {
83+
change24h = totalViewCount - previousStats.TotalViewCount
84+
if previousStats.TotalViewCount > 0 {
85+
changePercent24h = (float64(change24h) / float64(previousStats.TotalViewCount)) * 100
86+
}
87+
}
8888

8989
// Create new statistics record
9090
newStats := models.TagStatistics{

backend-go/workers/tag_discovery.go

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -150,19 +150,20 @@ func (w *TagDiscoveryWorker) Run(ctx context.Context) error {
150150
}
151151

152152
func (w *TagDiscoveryWorker) getTagForDiscovery() (string, error) {
153-
// First, try to get a tag from the database that hasn't been used recently
154-
hoursAgo := time.Now().Add(-3 * time.Hour)
155-
156-
var tags []models.Tag
157-
// Get multiple tags that haven't been used recently and aren't deleted, ordered by rank
158-
if err := w.db.Where("(last_used_for_discovery IS NULL OR last_used_for_discovery < ?) AND is_deleted = ?", hoursAgo, false).
159-
Order("rank ASC").
160-
Limit(10).
161-
Find(&tags).Error; err == nil && len(tags) > 0 {
162-
// Select a random tag from the top 10 to avoid always picking the same one
163-
idx := time.Now().Unix() % int64(len(tags))
164-
return tags[idx].Tag, nil
165-
}
153+
// First, try to get a tag from the database that hasn't been used recently
154+
hoursAgo := time.Now().Add(-3 * time.Hour)
155+
156+
var tags []models.Tag
157+
// Get multiple tags that haven't been used recently and aren't deleted, ordered by rank
158+
if err := w.db.Where("(last_used_for_discovery IS NULL OR last_used_for_discovery < ?) AND is_deleted = ?", hoursAgo, false).
159+
Where("tag NOT LIKE ?", "%&%").
160+
Order("rank ASC").
161+
Limit(10).
162+
Find(&tags).Error; err == nil && len(tags) > 0 {
163+
// Select a random tag from the top 10 to avoid always picking the same one
164+
idx := time.Now().Unix() % int64(len(tags))
165+
return tags[idx].Tag, nil
166+
}
166167

167168
// If no suitable database tag, use a random seed tag
168169
if len(w.seedTags) > 0 {
@@ -176,17 +177,18 @@ func (w *TagDiscoveryWorker) getTagForDiscovery() (string, error) {
176177

177178
// extractTagsFromSuggestions extracts unique tags from media offer suggestions
178179
func (w *TagDiscoveryWorker) extractTagsFromSuggestions(suggestions []fansly.MediaOfferSuggestion) []fansly.FanslyTag {
179-
tagMap := make(map[string]fansly.FanslyTag)
180-
181-
for _, suggestion := range suggestions {
182-
for _, tag := range suggestion.PostTags {
183-
// Use the tag name as key to ensure uniqueness
184-
tagName := strings.ToLower(strings.TrimSpace(tag.Tag))
185-
if tagName != "" {
186-
tagMap[tagName] = tag
187-
}
188-
}
189-
}
180+
tagMap := make(map[string]fansly.FanslyTag)
181+
182+
for _, suggestion := range suggestions {
183+
for _, tag := range suggestion.PostTags {
184+
// Use the tag name as key to ensure uniqueness
185+
tagName := strings.ToLower(strings.TrimSpace(tag.Tag))
186+
// Ignore tags that contain '&' as Fansly truncates them before '&'
187+
if tagName != "" && !strings.Contains(tagName, "&") {
188+
tagMap[tagName] = tag
189+
}
190+
}
191+
}
190192

191193
// Convert map to slice
192194
tags := make([]fansly.FanslyTag, 0, len(tagMap))
@@ -198,11 +200,15 @@ func (w *TagDiscoveryWorker) extractTagsFromSuggestions(suggestions []fansly.Med
198200
}
199201

200202
func (w *TagDiscoveryWorker) processDiscoveredTag(tag fansly.FanslyTag) error {
201-
// Check if tag already exists
202-
var existingTag models.Tag
203-
if err := w.db.Where("tag = ?", tag.Tag).First(&existingTag).Error; err == nil {
204-
// Tag already exists
205-
return nil
203+
// Ignore tags that contain '&' as Fansly truncates them before '&'
204+
if strings.Contains(tag.Tag, "&") {
205+
return nil
206+
}
207+
// Check if tag already exists
208+
var existingTag models.Tag
209+
if err := w.db.Where("tag = ?", tag.Tag).First(&existingTag).Error; err == nil {
210+
// Tag already exists
211+
return nil
206212
}
207213

208214
// Create new tag using the data we already have
@@ -243,14 +249,18 @@ func (w *TagDiscoveryWorker) updateTagRelationsFromSuggestions(ctx context.Conte
243249
counts := make(map[key]int64)
244250

245251
for _, s := range suggestions {
246-
// Build a unique set of tag IDs observed in this suggestion
247-
seen := make(map[string]struct{})
248-
for _, t := range s.PostTags {
249-
id := strings.TrimSpace(t.ID)
250-
if id == "" {
251-
continue
252-
}
253-
seen[id] = struct{}{}
252+
// Build a unique set of tag IDs observed in this suggestion
253+
seen := make(map[string]struct{})
254+
for _, t := range s.PostTags {
255+
// Skip tags that contain '&' to avoid polluted relations
256+
if strings.Contains(strings.ToLower(strings.TrimSpace(t.Tag)), "&") {
257+
continue
258+
}
259+
id := strings.TrimSpace(t.ID)
260+
if id == "" {
261+
continue
262+
}
263+
seen[id] = struct{}{}
254264
}
255265
// For all unique tags on this suggestion, generate directed pairs A->B (A != B)
256266
if len(seen) == 0 {

0 commit comments

Comments
 (0)