1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
package tasks
import (
"fmt"
"metachan/entities"
"metachan/repositories"
"metachan/utils/api/jikan"
"metachan/utils/logger"
"time"
)
func ResumeCharacterEnrichment() {
go CharacterSync()
}
func CharacterSync() error {
stubs, err := repositories.GetAllCharacterStubs()
if err != nil {
return fmt.Errorf("failed to load character stubs: %w", err)
}
sevenDaysAgo := time.Now().Add(-7 * 24 * time.Hour)
hasWork := false
for _, s := range stubs {
if s.EnrichedAt == nil || !s.EnrichedAt.After(sevenDaysAgo) {
hasWork = true
break
}
}
if !hasWork {
return nil
}
total := len(stubs)
startTime := time.Now()
enriched := 0
for i, s := range stubs {
if s.EnrichedAt != nil && s.EnrichedAt.After(sevenDaysAgo) {
continue
}
resp, err := jikan.GetCharacterByMALID(s.MALID)
if err != nil {
logger.Warnf("CharacterSync", "Failed to fetch character %d: %v", s.MALID, err)
continue
}
d := resp.Data
var voiceActors []entities.CharacterVoiceActor
for _, v := range d.Voices {
voiceActors = append(voiceActors, entities.CharacterVoiceActor{
Language: v.Language,
Person: &entities.Person{},
})
}
var animeAppearances []entities.CharacterAnimeAppearance
for _, a := range d.Anime {
animeAppearances = append(animeAppearances, entities.CharacterAnimeAppearance{
AnimeMALID: a.Anime.MALID,
Title: a.Anime.Title,
URL: a.Anime.URL,
ImageURL: a.Anime.Images.JPG.ImageURL,
Role: a.Role,
})
}
if err := repositories.UpdateCharacterDetails(
d.MALID, d.Name, d.NameKanji, d.URL, d.Images.JPG.ImageURL,
d.About, d.Nicknames, d.Favorites, voiceActors, animeAppearances,
); err != nil {
logger.Warnf("CharacterSync", "Failed to update character %d: %v", s.MALID, err)
continue
}
if err := repositories.SetCharacterEnriched(d.MALID); err != nil {
logger.Warnf("CharacterSync", "Failed to stamp enriched_at for character %d: %v", d.MALID, err)
}
enriched++
if (i+1)%50 == 0 || (i+1) == total {
progress, eta := calculateProgress(i+1, total, startTime)
logger.Infof("CharacterSync", "Enriching: %d/%d (%.1f%%) | ETA: %v", i+1, total, progress, eta)
}
}
logger.Successf("CharacterSync", "Background enrichment complete. Enriched %d characters", enriched)
return nil
}
|