aboutsummaryrefslogtreecommitdiff
path: root/tasks/charactersync.task.go
blob: 762c2f397a20460ebef19df08c50afaa1299c55e (plain)
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
}