package editor import ( "sort" "github.com/animenotifier/notify.moe/utils/animediff" "github.com/aerogo/aero" "github.com/animenotifier/arn" "github.com/animenotifier/mal" "github.com/animenotifier/notify.moe/components" "github.com/animenotifier/notify.moe/utils" ) const maxCompareMALEntries = 15 // CompareMAL ... func CompareMAL(ctx *aero.Context) string { user := utils.GetUser(ctx) year := ctx.Get("year") status := ctx.Get("status") season := ctx.Get("season") typ := ctx.Get("type") if year == "any" { year = "" } if season == "any" { season = "" } if status == "any" { status = "" } if typ == "any" { typ = "" } settings := user.Settings() settings.Editor.Filter.Year = year settings.Editor.Filter.Season = season settings.Editor.Filter.Status = status settings.Editor.Filter.Type = typ settings.Save() animes := arn.FilterAnime(func(anime *arn.Anime) bool { if year != "" && (len(anime.StartDate) < 4 || anime.StartDate[:4] != year) { return false } if status != "" && anime.Status != status { return false } if season != "" && anime.Season() != season { return false } if typ != "" && anime.Type != typ { return false } return anime.GetMapping("myanimelist/anime") != "" }) sort.Slice(animes, func(i, j int) bool { a := animes[i] b := animes[j] aPop := a.Popularity.Total() bPop := b.Popularity.Total() if aPop == bPop { return a.Title.Canonical < b.Title.Canonical } return aPop > bPop }) comparisons := compare(animes) return ctx.HTML(components.CompareMAL(comparisons, year, status, typ, "/editor/mal/diff/anime", user)) } // compare builds the comparisons to MAL anime entries. func compare(animes []*arn.Anime) []*utils.MALComparison { comparisons := []*utils.MALComparison{} malAnimeCollection := arn.MAL.Collection("Anime") for _, anime := range animes { malID := anime.GetMapping("myanimelist/anime") obj, err := malAnimeCollection.Get(malID) if err != nil { continue } malAnime := obj.(*mal.Anime) differences := diff(anime, malAnime) // Add if there were any differences if len(differences) > 0 { comparisons = append(comparisons, &utils.MALComparison{ Anime: anime, MALAnime: malAnime, Differences: differences, }) if len(comparisons) >= maxCompareMALEntries { break } } } return comparisons } // diff returns all the differences between an anime and its MAL counterpart. func diff(anime *arn.Anime, malAnime *mal.Anime) []animediff.Difference { var differences []animediff.Difference // Canonical title if anime.Title.Canonical != malAnime.Title { hash := utils.HashString(malAnime.Title) if !arn.IsAnimeDifferenceIgnored(anime.ID, "mal", malAnime.ID, "CanonicalTitle", hash) { differences = append(differences, &animediff.CanonicalTitle{ TitleA: anime.Title.Canonical, TitleB: malAnime.Title, NumericHash: hash, }) } } // Japanese title if anime.Title.Japanese != malAnime.JapaneseTitle { hash := utils.HashString(malAnime.JapaneseTitle) if !arn.IsAnimeDifferenceIgnored(anime.ID, "mal", malAnime.ID, "JapaneseTitle", hash) { differences = append(differences, &animediff.JapaneseTitle{ TitleA: anime.Title.Japanese, TitleB: malAnime.JapaneseTitle, NumericHash: hash, }) } } // Romaji title if anime.Title.Romaji != malAnime.Title { hash := utils.HashString(malAnime.Title) if !arn.IsAnimeDifferenceIgnored(anime.ID, "mal", malAnime.ID, "RomajiTitle", hash) { differences = append(differences, &animediff.RomajiTitle{ TitleA: anime.Title.Romaji, TitleB: malAnime.Title, NumericHash: hash, }) } } // Airing start date if anime.StartDate != malAnime.StartDate && malAnime.StartDate != "" { hash := utils.HashString(malAnime.StartDate) if !arn.IsAnimeDifferenceIgnored(anime.ID, "mal", malAnime.ID, "StartDate", hash) { differences = append(differences, &animediff.StartDate{ DateA: anime.StartDate, DateB: malAnime.StartDate, NumericHash: hash, }) } } // Airing end date if anime.EndDate != malAnime.EndDate && malAnime.EndDate != "" { hash := utils.HashString(malAnime.EndDate) if !arn.IsAnimeDifferenceIgnored(anime.ID, "mal", malAnime.ID, "EndDate", hash) { differences = append(differences, &animediff.EndDate{ DateA: anime.EndDate, DateB: malAnime.EndDate, NumericHash: hash, }) } } // Status if anime.Status != malAnime.Status { hash := utils.HashString(malAnime.Status) if !arn.IsAnimeDifferenceIgnored(anime.ID, "mal", malAnime.ID, "Status", hash) { differences = append(differences, &animediff.Status{ StatusA: anime.Status, StatusB: malAnime.Status, NumericHash: hash, }) } } // EpisodeCount if malAnime.EpisodeCount != 0 && anime.EpisodeCount != malAnime.EpisodeCount { hash := uint64(malAnime.EpisodeCount) if !arn.IsAnimeDifferenceIgnored(anime.ID, "mal", malAnime.ID, "EpisodeCount", hash) { differences = append(differences, &animediff.EpisodeCount{ EpisodesA: anime.EpisodeCount, EpisodesB: malAnime.EpisodeCount, NumericHash: hash, }) } } // Synopsis if len(anime.Summary) < 300 && len(anime.Summary)+50 < len(malAnime.Synopsis) { hash := utils.HashString(malAnime.Synopsis) if !arn.IsAnimeDifferenceIgnored(anime.ID, "mal", malAnime.ID, "Synopsis", hash) { differences = append(differences, &animediff.Synopsis{ SynopsisA: anime.Summary, SynopsisB: malAnime.Synopsis, NumericHash: hash, }) } } // Compare genres hashA := utils.HashStringsNoOrder(anime.Genres) hashB := utils.HashStringsNoOrder(malAnime.Genres) if hashA != hashB { if !arn.IsAnimeDifferenceIgnored(anime.ID, "mal", malAnime.ID, "Genres", hashB) { differences = append(differences, &animediff.Genres{ GenresA: anime.Genres, GenresB: malAnime.Genres, NumericHash: hashB, }) } } return differences }