diff options
| author | Priyansh <[email protected]> | 2025-08-19 13:19:30 +0530 |
|---|---|---|
| committer | Priyansh <[email protected]> | 2025-08-19 13:19:30 +0530 |
| commit | 9fbf28c2f77ec74c75a5274cbda897217ceaf571 (patch) | |
| tree | 87dab6adda634a08b3b1cf74c0dd1e616113aa30 | |
| parent | 6a65e3927506b0e46f18c9c1b41e952418bfd78e (diff) | |
| download | metachan-9fbf28c2f77ec74c75a5274cbda897217ceaf571.tar.xz metachan-9fbf28c2f77ec74c75a5274cbda897217ceaf571.zip | |
episodes router; anilist support; general fixes
| -rw-r--r-- | controllers/anime.go | 61 | ||||
| -rw-r--r-- | database/anime.go | 9 | ||||
| -rw-r--r-- | database/anime_cache.go | 17 | ||||
| -rw-r--r-- | entities/anime.go | 4 | ||||
| -rw-r--r-- | router/router.go | 5 | ||||
| -rw-r--r-- | services/anime/helpers.go | 18 | ||||
| -rw-r--r-- | services/anime/service.go | 2 |
7 files changed, 96 insertions, 20 deletions
diff --git a/controllers/anime.go b/controllers/anime.go index 7c01768..baaf6f9 100644 --- a/controllers/anime.go +++ b/controllers/anime.go @@ -2,6 +2,7 @@ package controllers import ( "metachan/database" + "metachan/entities" animeService "metachan/services/anime" "metachan/utils/logger" "metachan/utils/mappers" @@ -22,18 +23,9 @@ func getAnimeService() *animeService.Service { // GetAnimeByMALID fetches anime details by MAL ID func GetAnimeByMALID(c *fiber.Ctx) error { - malID := c.Params("mal_id") - if malID == "" { - return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ - "error": "Query parameter MAL ID is required", - }) - } - - mapping, err := database.GetAnimeMappingViaMALID(mappers.ForceInt(malID)) + mapping, err := getAnimeMapping(c) if err != nil { - return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ - "error": "Anime not found", - }) + return err } service := getAnimeService() @@ -50,3 +42,50 @@ func GetAnimeByMALID(c *fiber.Ctx) error { return c.JSON(anime) } + +// GetAnimeEpisodesByMALID fetches anime episodes by MAL ID +func GetAnimeEpisodesByMALID(c *fiber.Ctx) error { + mapping, err := getAnimeMapping(c) + if err != nil { + return err + } + + service := getAnimeService() + anime, err := service.GetAnimeDetails(mapping) + if err != nil { + logger.Log("Failed to fetch anime episodes: "+err.Error(), logger.LogOptions{ + Level: logger.Error, + Prefix: "AnimeAPI", + }) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": "Failed to fetch anime episodes", + }) + } + + // Return only the episodes data + return c.JSON(anime.Episodes) +} + +func getAnimeMapping(c *fiber.Ctx) (*entities.AnimeMapping, error) { + isAnilist := c.Query("provider") == "anilist" + malID := c.Params("id") + if malID == "" { + return nil, c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Query parameter MAL ID is required", + }) + } + + var mapping *entities.AnimeMapping + var err error + if isAnilist { + mapping, err = database.GetAnimeMappingViaAnilistID(mappers.ForceInt(malID)) + } else { + mapping, err = database.GetAnimeMappingViaMALID(mappers.ForceInt(malID)) + } + if err != nil { + return nil, c.Status(fiber.StatusNotFound).JSON(fiber.Map{ + "error": "Anime mapping not found", + }) + } + return mapping, nil +} diff --git a/database/anime.go b/database/anime.go index 44382bf..9d2f9e5 100644 --- a/database/anime.go +++ b/database/anime.go @@ -10,6 +10,15 @@ func GetAnimeMappingViaMALID(malID int) (*entities.AnimeMapping, error) { return &mapping, nil } +// GetAnimeMappingViaAnilistID retrieves an anime mapping by AniList ID +func GetAnimeMappingViaAnilistID(anilistID int) (*entities.AnimeMapping, error) { + var mapping entities.AnimeMapping + if err := DB.Where("anilist = ?", anilistID).First(&mapping).Error; err != nil { + return nil, err + } + return &mapping, nil +} + // GetAnimeMappingsByTVDBID retrieves all anime mappings that share the same TVDB ID func GetAnimeMappingsByTVDBID(tvdbID int) ([]entities.AnimeMapping, error) { var mappings []entities.AnimeMapping diff --git a/database/anime_cache.go b/database/anime_cache.go index b2d8d81..f26dc8b 100644 --- a/database/anime_cache.go +++ b/database/anime_cache.go @@ -465,7 +465,6 @@ func ConvertToTypesAnime(cachedAnime *entities.CachedAnime) *types.Anime { if len(cachedAnime.Episodes) > 0 { anime.Episodes.Episodes = make([]types.AnimeSingleEpisode, len(cachedAnime.Episodes)) - var subCount, dubCount int for i, episode := range cachedAnime.Episodes { episodeData := types.AnimeSingleEpisode{ Description: episode.Description, @@ -489,10 +488,10 @@ func ConvertToTypesAnime(cachedAnime *entities.CachedAnime) *types.Anime { anime.Episodes.Episodes[i] = episodeData } - anime.Episodes.Total = len(cachedAnime.Episodes) - anime.Episodes.Aired = len(cachedAnime.Episodes) - anime.Episodes.Subbed = subCount - anime.Episodes.Dubbed = dubCount + anime.Episodes.Total = cachedAnime.TotalEpisodes + anime.Episodes.Aired = cachedAnime.AiredEpisodes + anime.Episodes.Subbed = cachedAnime.SubbedCount + anime.Episodes.Dubbed = cachedAnime.DubbedCount } // Convert characters @@ -620,6 +619,10 @@ func convertToCachedAnime(animeData *types.Anime) *entities.CachedAnime { Color: animeData.Color, Season: animeData.Season, Year: animeData.Year, + SubbedCount: animeData.Episodes.Subbed, + DubbedCount: animeData.Episodes.Dubbed, + TotalEpisodes: animeData.Episodes.Total, + AiredEpisodes: animeData.Episodes.Aired, LastUpdated: time.Now(), } @@ -960,6 +963,10 @@ func saveCachedAnimeWithBatching(tx *gorm.DB, cachedAnime *entities.CachedAnime) Color: cachedAnime.Color, Season: cachedAnime.Season, Year: cachedAnime.Year, + SubbedCount: cachedAnime.SubbedCount, + DubbedCount: cachedAnime.DubbedCount, + TotalEpisodes: cachedAnime.TotalEpisodes, + AiredEpisodes: cachedAnime.AiredEpisodes, LastUpdated: cachedAnime.LastUpdated, // Include small collections that won't cause variable limit issues diff --git a/entities/anime.go b/entities/anime.go index d758da6..167ae16 100644 --- a/entities/anime.go +++ b/entities/anime.go @@ -53,6 +53,10 @@ type CachedAnime struct { Color string Season string Year int + SubbedCount int + DubbedCount int + TotalEpisodes int + AiredEpisodes int LastUpdated time.Time // Relationships diff --git a/router/router.go b/router/router.go index 911ec63..b55014a 100644 --- a/router/router.go +++ b/router/router.go @@ -11,8 +11,9 @@ func Initialize(router *fiber.App) { router.Get("/health", controllers.HealthStatus) // Anime routes - animeRouter := router.Group("/anime") - animeRouter.Get("/:mal_id", controllers.GetAnimeByMALID) + animeRouter := router.Group("/a") + animeRouter.Get("/:id", controllers.GetAnimeByMALID) + animeRouter.Get("/:id/episodes", controllers.GetAnimeEpisodesByMALID) // 404 Default router.Use(func(c *fiber.Ctx) error { diff --git a/services/anime/helpers.go b/services/anime/helpers.go index 3982ba0..3231676 100644 --- a/services/anime/helpers.go +++ b/services/anime/helpers.go @@ -53,6 +53,22 @@ func getEpisodeCount(malAnime *jikan.JikanAnimeResponse, anilistAnime *anilist.A return episodes } +// getEpisodeCountWithAiredFallback determines the total episode count, using aired episodes as fallback for long-running series +func getEpisodeCountWithAiredFallback(malAnime *jikan.JikanAnimeResponse, anilistAnime *anilist.AnilistAnimeResponse, airedCount int) int { + totalFromAPIs := getEpisodeCount(malAnime, anilistAnime) + + // For long-running series, if the aired count is significantly higher than API-reported total, + // use the aired count as a more accurate total (since APIs often report season/arc counts) + if airedCount > totalFromAPIs && airedCount > 100 { + // This indicates a long-running series where APIs might be reporting seasonal data + // For ongoing series, total should be at least as high as aired episodes + return airedCount + } + + // For normal series, use the maximum from APIs + return max(totalFromAPIs, airedCount) +} + // sortSeasonsByAirDate sorts the seasons array chronologically by air date func sortSeasonsByAirDate(seasons *[]types.AnimeSeason) { // First, collect seasons with valid dates @@ -219,7 +235,7 @@ func getNextAiringEpisode(anilistAnime *anilist.AnilistAnimeResponse) types.Anim // If AniList doesn't provide a direct next episode, but we have airing schedule nodes // Find the next episode that hasn't aired yet - if anilistAnime.Data.Media.AiringSchedule.Nodes != nil && len(anilistAnime.Data.Media.AiringSchedule.Nodes) > 0 { + if len(anilistAnime.Data.Media.AiringSchedule.Nodes) > 0 { var nextAiringEpisode types.AnimeAiringEpisode for _, node := range anilistAnime.Data.Media.AiringSchedule.Nodes { diff --git a/services/anime/service.go b/services/anime/service.go index 17336d8..6f61680 100644 --- a/services/anime/service.go +++ b/services/anime/service.go @@ -375,7 +375,7 @@ func (s *Service) GetAnimeDetailsWithSource(mapping *entities.AnimeMapping, sour Licensors: generateLicensors(anime.Data.Licensors), Seasons: seasons, Episodes: types.AnimeEpisodes{ - Total: getEpisodeCount(anime, anilistAnime), + Total: getEpisodeCountWithAiredFallback(anime, anilistAnime, len(episodes.Data)), Aired: len(episodes.Data), Subbed: subbedCount, Dubbed: dubbedCount, |
