refactor: domain anime type

This commit is contained in:
2026-05-26 22:45:16 +02:00
parent 5a054d250e
commit e9576d7584
6 changed files with 62 additions and 37 deletions

View File

@@ -22,6 +22,14 @@ type AnimeHandler struct {
watchlistSvc domain.WatchlistService
}
func wrapAnimes(in []jikan.Anime) []domain.Anime {
out := make([]domain.Anime, 0, len(in))
for _, a := range in {
out = append(out, domain.Anime{Anime: a})
}
return out
}
func NewAnimeHandler(svc domain.AnimeService, watchlistSvc domain.WatchlistService) *AnimeHandler {
return &AnimeHandler{
svc: svc,
@@ -405,7 +413,8 @@ func (h *AnimeHandler) HandleBrowse(c *gin.Context) {
if u, ok := user.(*domain.User); ok {
userID = u.ID
}
watchlistMap := h.watchlistMapForAnimes(c.Request.Context(), userID, res.Animes)
animes := wrapAnimes(res.Animes)
watchlistMap := h.watchlistMapForAnimes(c.Request.Context(), userID, animes)
studioName := ""
if studioID > 0 {
@@ -417,10 +426,10 @@ func (h *AnimeHandler) HandleBrowse(c *gin.Context) {
if c.GetHeader("HX-Request") == "true" && page > 1 {
c.HTML(http.StatusOK, "browse.gohtml", gin.H{
"_fragment": "anime_card_scroll",
"Animes": res.Animes,
"NextPage": page + 1,
"HasNextPage": res.HasNextPage,
"_fragment": "anime_card_scroll",
"Animes": animes,
"NextPage": page + 1,
"HasNextPage": res.HasNextPage,
"Query": q,
"Type": animeType,
"Status": status,
@@ -450,9 +459,9 @@ func (h *AnimeHandler) HandleBrowse(c *gin.Context) {
"Studio": studioID,
"StudioName": studioName,
"SFW": sfw,
"GenresList": genresList,
"Animes": res.Animes,
"HasNextPage": res.HasNextPage,
"GenresList": genresList,
"Animes": animes,
"HasNextPage": res.HasNextPage,
"NextPage": page + 1,
"User": user,
"WatchlistMap": watchlistMap,
@@ -472,8 +481,8 @@ func (h *AnimeHandler) HandleBrowse(c *gin.Context) {
"StudioName": studioName,
"SFW": sfw,
"GenresList": genresList,
"Animes": res.Animes,
"HasNextPage": res.HasNextPage,
"Animes": animes,
"HasNextPage": res.HasNextPage,
"NextPage": page + 1,
"User": user,
"WatchlistMap": watchlistMap,
@@ -634,7 +643,8 @@ func (h *AnimeHandler) HandleQuickSearch(c *gin.Context) {
if u, ok := user.(*domain.User); ok {
userID = u.ID
}
watchlistMap := h.watchlistMapForAnimes(c.Request.Context(), userID, res.Animes)
animes := wrapAnimes(res.Animes)
watchlistMap := h.watchlistMapForAnimes(c.Request.Context(), userID, animes)
type quickSearchResult struct {
ID int `json:"id"`
@@ -645,8 +655,8 @@ func (h *AnimeHandler) HandleQuickSearch(c *gin.Context) {
InWatchlist bool `json:"in_watchlist"`
}
output := make([]quickSearchResult, len(res.Animes))
for i, anime := range res.Animes {
output := make([]quickSearchResult, len(animes))
for i, anime := range animes {
output[i] = quickSearchResult{
ID: anime.MalID,
Title: anime.DisplayTitle(),
@@ -736,8 +746,9 @@ func (h *AnimeHandler) commandPaletteAnimeResults(c *gin.Context, query string)
return nil
}
items := make([]commandPaletteItem, 0, len(res.Animes))
for _, anime := range res.Animes {
animes := wrapAnimes(res.Animes)
items := make([]commandPaletteItem, 0, len(animes))
for _, anime := range animes {
items = append(items, commandPaletteItem{
ID: fmt.Sprintf("anime:%d", anime.MalID),
Type: "anime",

View File

@@ -21,6 +21,14 @@ type animeService struct {
repo domain.AnimeRepository
}
func wrapAnimes(in []jikan.Anime) []domain.Anime {
out := make([]domain.Anime, 0, len(in))
for _, a := range in {
out = append(out, domain.Anime{Anime: a})
}
return out
}
func NewAnimeService(jikan *jikan.Client, repo domain.AnimeRepository) domain.AnimeService {
return &animeService{jikan: jikan, repo: repo}
}
@@ -56,7 +64,7 @@ func (s *animeService) GetCatalogSection(ctx context.Context, userID string, sec
return domain.CatalogSectionData{}, err
}
animes := res.Animes
animes := wrapAnimes(res.Animes)
if len(animes) > 6 {
animes = animes[:6]
}
@@ -89,7 +97,7 @@ func (s *animeService) GetDiscoverSection(ctx context.Context, userID string, se
return domain.DiscoverSectionData{}, err
}
animes := res.Animes
animes := wrapAnimes(res.Animes)
if len(animes) > 8 {
animes = animes[:8]
}
@@ -197,7 +205,7 @@ func (s *animeService) GetDiscoverForYou(ctx context.Context, userID string) (do
)
continue
}
animes = append(animes, anime)
animes = append(animes, domain.Anime{Anime: anime})
}
return domain.DiscoverSectionData{Animes: animes}, nil
@@ -247,7 +255,7 @@ func (s *animeService) GetAiringSchedule(ctx context.Context, userID string) ([]
return fetchErr
}
mu.Lock()
animes = append(animes, anime)
animes = append(animes, domain.Anime{Anime: anime})
mu.Unlock()
return nil
})
@@ -271,7 +279,11 @@ func (s *animeService) GetAiringSchedule(ctx context.Context, userID string) ([]
}
func (s *animeService) GetAnimeByID(ctx context.Context, id int) (domain.Anime, error) {
return s.jikan.GetAnimeByID(ctx, id)
anime, err := s.jikan.GetAnimeByID(ctx, id)
if err != nil {
return domain.Anime{}, err
}
return domain.Anime{Anime: anime}, nil
}
func (s *animeService) SearchAdvanced(ctx context.Context, q, animeType, status, orderBy, sort string, genres []int, studioID int, sfw bool, page, limit int) (jikan.SearchResult, error) {
@@ -341,7 +353,7 @@ func (s *animeService) GetRandomAnime(ctx context.Context) (domain.Anime, error)
anime, err := s.jikan.GetRandomAnime(randomCtx)
if err == nil {
return anime, nil
return domain.Anime{Anime: anime}, nil
}
for _, fallback := range []func(context.Context, int) (jikan.TopAnimeResult, error){
@@ -350,12 +362,12 @@ func (s *animeService) GetRandomAnime(ctx context.Context) (domain.Anime, error)
s.jikan.GetSeasonsUpcoming,
} {
res, fallbackErr := fallback(ctx, 1)
if fallbackErr != nil || len(res.Animes) == 0 {
continue
if fallbackErr != nil || len(res.Animes) == 0 {
continue
}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
return domain.Anime{Anime: res.Animes[r.Intn(len(res.Animes))]}, nil
}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
return res.Animes[r.Intn(len(res.Animes))], nil
}
return domain.Anime{}, err
}

View File

@@ -6,7 +6,9 @@ import (
"mal/internal/db"
)
type Anime = jikan.Anime
type Anime struct {
jikan.Anime
}
type TopAnimeResult = jikan.TopAnimeResult
type Genre = jikan.Genre
type Character = jikan.CharacterEntry

View File

@@ -94,7 +94,7 @@ func (s *EpisodeService) RefreshTrackedDue(ctx context.Context, limit int) error
)
continue
}
if _, err := s.refresh(ctx, anime); err != nil {
if _, err := s.refresh(ctx, domain.Anime{Anime: anime}); err != nil {
observability.Warn(
"episodes_refresh_failed",
"episodes",

View File

@@ -29,7 +29,7 @@ func TestMergeEpisodesUsesUnionAndSynthesizesProviderOnlyEntries(t *testing.T) {
}
func TestNextBroadcastAfterUsesJikanTimezone(t *testing.T) {
anime := domain.Anime{MalID: 1}
anime := domain.Anime{Anime: jikan.Anime{MalID: 1}}
anime.Broadcast.Day = "Saturdays"
anime.Broadcast.Time = "23:00"
anime.Broadcast.Timezone = "Asia/Tokyo"
@@ -44,7 +44,7 @@ func TestNextBroadcastAfterUsesJikanTimezone(t *testing.T) {
}
func TestNextRetryTimeWithinAndAfterRetryWindow(t *testing.T) {
anime := domain.Anime{MalID: 1}
anime := domain.Anime{Anime: jikan.Anime{MalID: 1}}
anime.Broadcast.Day = "Saturdays"
anime.Broadcast.Time = "12:00"
anime.Broadcast.Timezone = "UTC"

View File

@@ -143,7 +143,7 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title
}
}
canonicalEpisodes, err := s.episodes.GetCanonicalEpisodes(ctx, anime, false)
canonicalEpisodes, err := s.episodes.GetCanonicalEpisodes(ctx, domain.Anime{Anime: anime}, false)
if err != nil {
return domain.WatchPageData{}, fmt.Errorf("failed to fetch episodes: %w", err)
}
@@ -289,12 +289,12 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title
Segments: segments,
}
return domain.WatchPageData{
WatchData: watchData,
Anime: anime,
Episodes: canonicalEpisodes.Episodes,
CurrentEpID: episode,
WatchlistStatus: watchlistStatus,
return domain.WatchPageData{
WatchData: watchData,
Anime: domain.Anime{Anime: anime},
Episodes: canonicalEpisodes.Episodes,
CurrentEpID: episode,
WatchlistStatus: watchlistStatus,
WatchlistIDs: watchlistIDs,
Seasons: seasons,
}, nil