refactor: decouple domain types from jikan

This commit is contained in:
2026-05-28 12:14:10 +02:00
committed by Milas Holsting
parent 4a4ed6ef02
commit 86586ed344
2 changed files with 262 additions and 19 deletions

View File

@@ -308,15 +308,74 @@ func (s *animeService) GetProducers(ctx context.Context, query string, page int,
}
func (s *animeService) GetGenres(ctx context.Context) ([]domain.Genre, error) {
return s.jikan.GetAnimeGenres(ctx)
genres, err := s.jikan.GetAnimeGenres(ctx)
if err != nil {
return nil, err
}
out := make([]domain.Genre, 0, len(genres))
for _, g := range genres {
if g.MalID <= 0 || strings.TrimSpace(g.Name) == "" {
continue
}
out = append(out, domain.Genre{MalID: g.MalID, Name: g.Name})
}
return out, nil
}
func (s *animeService) GetCharacters(ctx context.Context, id int) ([]domain.Character, error) {
return s.jikan.GetAnimeCharacters(ctx, id)
func (s *animeService) GetCharacters(ctx context.Context, id int) ([]domain.CharacterEntry, error) {
items, err := s.jikan.GetAnimeCharacters(ctx, id)
if err != nil {
return nil, err
}
func (s *animeService) GetRecommendations(ctx context.Context, id int) ([]domain.Recommendation, error) {
return s.jikan.GetAnimeRecommendations(ctx, id)
out := make([]domain.CharacterEntry, 0, len(items))
for _, it := range items {
var mapped domain.CharacterEntry
mapped.Character.MalID = it.Character.MalID
mapped.Character.URL = it.Character.URL
mapped.Character.Name = it.Character.Name
mapped.Character.Images.Jpg.ImageURL = it.Character.Images.Jpg.ImageURL
mapped.Character.Images.Webp.ImageURL = it.Character.Images.Webp.ImageURL
mapped.Character.Images.Webp.SmallImageURL = it.Character.Images.Webp.SmallImageURL
mapped.Role = it.Role
if len(it.VoiceActors) > 0 {
mapped.VoiceActors = make([]domain.CharacterVoiceActor, 0, len(it.VoiceActors))
for _, va := range it.VoiceActors {
var mappedVA domain.CharacterVoiceActor
mappedVA.Language = va.Language
mappedVA.Person.MalID = va.Person.MalID
mappedVA.Person.URL = va.Person.URL
mappedVA.Person.Name = va.Person.Name
mappedVA.Person.Images.Jpg.ImageURL = va.Person.Images.Jpg.ImageURL
mapped.VoiceActors = append(mapped.VoiceActors, mappedVA)
}
}
out = append(out, mapped)
}
return out, nil
}
func (s *animeService) GetRecommendations(ctx context.Context, id int) ([]domain.RecommendationEntry, error) {
items, err := s.jikan.GetAnimeRecommendations(ctx, id)
if err != nil {
return nil, err
}
out := make([]domain.RecommendationEntry, 0, len(items))
for _, it := range items {
var mapped domain.RecommendationEntry
mapped.Entry.MalID = it.Entry.MalID
mapped.Entry.URL = it.Entry.URL
mapped.Entry.Title = it.Entry.Title
mapped.Entry.Images.Webp.LargeImageURL = it.Entry.Images.Webp.LargeImageURL
mapped.URL = it.URL
mapped.Votes = it.Votes
out = append(out, mapped)
}
return out, nil
}
func (s *animeService) GetRelations(ctx context.Context, id int) ([]jikan.RelationEntry, error) {
@@ -328,15 +387,56 @@ func (s *animeService) GetEpisodes(ctx context.Context, id int, page int) (jikan
}
func (s *animeService) GetStaff(ctx context.Context, id int) ([]domain.StaffEntry, error) {
return s.jikan.GetAnimeStaff(ctx, id)
items, err := s.jikan.GetAnimeStaff(ctx, id)
if err != nil {
return nil, err
}
out := make([]domain.StaffEntry, 0, len(items))
for _, it := range items {
var mapped domain.StaffEntry
mapped.Person.MalID = it.Person.MalID
mapped.Person.URL = it.Person.URL
mapped.Person.Name = it.Person.Name
mapped.Person.Images.Jpg.ImageURL = it.Person.Images.Jpg.ImageURL
mapped.Positions = append([]string(nil), it.Positions...)
out = append(out, mapped)
}
return out, nil
}
func (s *animeService) GetStatistics(ctx context.Context, id int) (domain.Statistics, error) {
return s.jikan.GetAnimeStatistics(ctx, id)
stats, err := s.jikan.GetAnimeStatistics(ctx, id)
if err != nil {
return domain.Statistics{}, err
}
out := domain.Statistics{
Watching: stats.Watching,
Completed: stats.Completed,
OnHold: stats.OnHold,
Dropped: stats.Dropped,
PlanToWatch: stats.PlanToWatch,
Total: stats.Total,
}
if len(stats.Scores) > 0 {
out.Scores = make([]domain.StatisticsScore, 0, len(stats.Scores))
for _, s := range stats.Scores {
out.Scores = append(out.Scores, domain.StatisticsScore{Score: s.Score, Votes: s.Votes, Percentage: s.Percentage})
}
}
return out, nil
}
func (s *animeService) GetThemes(ctx context.Context, id int) (domain.ThemesData, error) {
return s.jikan.GetAnimeThemes(ctx, id)
themes, err := s.jikan.GetAnimeThemes(ctx, id)
if err != nil {
return domain.ThemesData{}, err
}
return domain.ThemesData{
Openings: append([]string(nil), themes.Openings...),
Endings: append([]string(nil), themes.Endings...),
}, nil
}
func (s *animeService) GetReviews(ctx context.Context, id int, page int) ([]domain.ReviewEntry, bool, error) {
@@ -344,7 +444,38 @@ func (s *animeService) GetReviews(ctx context.Context, id int, page int) ([]doma
if err != nil {
return nil, false, err
}
return data, pag.HasNextPage, nil
out := make([]domain.ReviewEntry, 0, len(data))
for _, it := range data {
mapped := domain.ReviewEntry{
MalID: it.MalID,
URL: it.URL,
Type: it.Type,
Date: it.Date,
Review: it.Review,
Score: it.Score,
Tags: append([]string(nil), it.Tags...),
IsSpoiler: it.IsSpoiler,
IsPreliminary: it.IsPreliminary,
EpisodesSeen: it.EpisodesSeen,
Reactions: domain.ReviewReactions{
Overall: it.Reactions.Overall,
Nice: it.Reactions.Nice,
LoveIt: it.Reactions.LoveIt,
Funny: it.Reactions.Funny,
Confusing: it.Reactions.Confusing,
Informative: it.Reactions.Informative,
WellWritten: it.Reactions.WellWritten,
Creative: it.Reactions.Creative,
},
}
mapped.User.URL = it.User.URL
mapped.User.Username = it.User.Username
mapped.User.Images.Jpg.ImageURL = it.User.Images.Jpg.ImageURL
mapped.User.Images.Webp.ImageURL = it.User.Images.Webp.ImageURL
out = append(out, mapped)
}
return out, pag.HasNextPage, nil
}
func (s *animeService) GetRandomAnime(ctx context.Context) (domain.Anime, error) {

View File

@@ -9,14 +9,126 @@ import (
type Anime struct {
jikan.Anime
}
type TopAnimeResult = jikan.TopAnimeResult
type Genre = jikan.Genre
type Character = jikan.CharacterEntry
type Recommendation = jikan.RecommendationEntry
type StaffEntry = jikan.StaffEntry
type Statistics = jikan.Statistics
type ThemesData = jikan.ThemesData
type ReviewEntry = jikan.ReviewEntry
type Genre struct {
MalID int
Name string
}
type CharacterPerson struct {
MalID int
URL string
Name string
Images struct {
Jpg struct {
ImageURL string
}
}
}
type CharacterVoiceActor struct {
Person CharacterPerson
Language string
}
type CharacterEntry struct {
Character struct {
MalID int
URL string
Name string
Images struct {
Jpg struct {
ImageURL string
}
Webp struct {
ImageURL string
SmallImageURL string
}
}
}
Role string
VoiceActors []CharacterVoiceActor
}
type RecommendationEntry struct {
Entry struct {
MalID int
URL string
Title string
Images struct {
Webp struct {
LargeImageURL string
}
}
}
URL string
Votes int
}
type StaffEntry struct {
Person CharacterPerson
Positions []string
}
type StatisticsScore struct {
Score int
Votes int
Percentage float64
}
type Statistics struct {
Watching int
Completed int
OnHold int
Dropped int
PlanToWatch int
Total int
Scores []StatisticsScore
}
type ThemesData struct {
Openings []string
Endings []string
}
type ReviewReactions struct {
Overall int
Nice int
LoveIt int
Funny int
Confusing int
Informative int
WellWritten int
Creative int
}
type ReviewUser struct {
URL string
Username string
Images struct {
Jpg struct {
ImageURL string
}
Webp struct {
ImageURL string
}
}
}
type ReviewEntry struct {
MalID int
URL string
Type string
Reactions ReviewReactions
Date string
Review string
Score int
Tags []string
IsSpoiler bool
IsPreliminary bool
EpisodesSeen int
User ReviewUser
}
type AnimeCatalogService interface {
GetCatalogSection(ctx context.Context, userID string, section string) (CatalogSectionData, error)
@@ -37,8 +149,8 @@ type AnimeSearchService interface {
type AnimeDetailsService interface {
GetAnimeByID(ctx context.Context, id int) (Anime, error)
GetCharacters(ctx context.Context, id int) ([]Character, error)
GetRecommendations(ctx context.Context, id int) ([]Recommendation, error)
GetCharacters(ctx context.Context, id int) ([]CharacterEntry, error)
GetRecommendations(ctx context.Context, id int) ([]RecommendationEntry, error)
GetRelations(ctx context.Context, id int) ([]jikan.RelationEntry, error)
GetEpisodes(ctx context.Context, id int, page int) (jikan.EpisodesResponse, error)
GetAllEpisodes(ctx context.Context, id int) ([]EpisodeData, error)