From 3643ab25cdd113af7348ffe6d850fe5fcbcc7678 Mon Sep 17 00:00:00 2001 From: mkelvers Date: Mon, 6 Apr 2026 19:20:37 +0200 Subject: [PATCH] feat: expand anime struct with rating, duration, genres, studios, producers --- internal/jikan/types.go | 100 ++++++++++++++++++++++++++++++++++------ 1 file changed, 86 insertions(+), 14 deletions(-) diff --git a/internal/jikan/types.go b/internal/jikan/types.go index 9eacbcb..1e95e7c 100644 --- a/internal/jikan/types.go +++ b/internal/jikan/types.go @@ -1,26 +1,98 @@ package jikan +import "fmt" + +// NamedEntity represents genres, studios, producers, etc. +type NamedEntity struct { + MalID int `json:"mal_id"` + Name string `json:"name"` +} + +// Aired represents the airing date range +type Aired struct { + From string `json:"from"` + To string `json:"to"` + String string `json:"string"` +} + // Anime struct matching the Jikan v4 API structure type Anime struct { - MalID int `json:"mal_id"` - Title string `json:"title"` - TitleEnglish string `json:"title_english"` - TitleJapanese string `json:"title_japanese"` + MalID int `json:"mal_id"` + Title string `json:"title"` + TitleEnglish string `json:"title_english"` + TitleJapanese string `json:"title_japanese"` + TitleSynonyms []string `json:"title_synonyms"` Images struct { + Jpg struct { + LargeImageURL string `json:"large_image_url"` + } `json:"jpg"` Webp struct { LargeImageURL string `json:"large_image_url"` } `json:"webp"` } `json:"images"` - Synopsis string `json:"synopsis"` - Score float64 `json:"score"` - ScoredBy int `json:"scored_by"` - Rank int `json:"rank"` - Popularity int `json:"popularity"` - Status string `json:"status"` - Episodes int `json:"episodes"` - Season string `json:"season"` - Year int `json:"year"` - Type string `json:"type"` + Synopsis string `json:"synopsis"` + Score float64 `json:"score"` + ScoredBy int `json:"scored_by"` + Rank int `json:"rank"` + Popularity int `json:"popularity"` + Status string `json:"status"` + Episodes int `json:"episodes"` + Season string `json:"season"` + Year int `json:"year"` + Type string `json:"type"` + Rating string `json:"rating"` + Duration string `json:"duration"` + Aired Aired `json:"aired"` + Genres []NamedEntity `json:"genres"` + Studios []NamedEntity `json:"studios"` + Producers []NamedEntity `json:"producers"` +} + +// ImageURL returns the webp large image URL +func (a Anime) ImageURL() string { + return a.Images.Webp.LargeImageURL +} + +// ShortRating returns abbreviated rating (e.g., "PG-13" from "PG-13 - Teens 13 or older") +func (a Anime) ShortRating() string { + if a.Rating == "" { + return "" + } + // Rating format: "PG-13 - Teens 13 or older" + for i, c := range a.Rating { + if c == ' ' && i > 0 { + return a.Rating[:i] + } + } + return a.Rating +} + +// ShortDuration returns abbreviated duration (e.g., "23m" from "23 min per ep") +func (a Anime) ShortDuration() string { + if a.Duration == "" { + return "" + } + // Duration format: "23 min per ep" or "1 hr 30 min" + var num string + for _, c := range a.Duration { + if c >= '0' && c <= '9' { + num += string(c) + } else if c == ' ' && num != "" { + break + } + } + if num != "" { + return num + "m" + } + return a.Duration +} + +// Premiered returns season + year (e.g., "Fall 2002") +func (a Anime) Premiered() string { + if a.Season != "" && a.Year > 0 { + return fmt.Sprintf("%s %d", a.Season, a.Year) + } + return "" } type AnimeResponse struct {