Files
seanime-docker/seanime-2.9.10/internal/api/anilist/media_helper.go
2025-09-20 14:08:38 +01:00

575 lines
14 KiB
Go

package anilist
import (
"seanime/internal/util/comparison"
"github.com/samber/lo"
)
func (m *BaseAnime) GetTitleSafe() string {
if m.GetTitle().GetEnglish() != nil {
return *m.GetTitle().GetEnglish()
}
if m.GetTitle().GetRomaji() != nil {
return *m.GetTitle().GetRomaji()
}
return ""
}
func (m *BaseAnime) GetEnglishTitleSafe() string {
if m.GetTitle().GetEnglish() != nil {
return *m.GetTitle().GetEnglish()
}
return ""
}
func (m *BaseAnime) GetRomajiTitleSafe() string {
if m.GetTitle().GetRomaji() != nil {
return *m.GetTitle().GetRomaji()
}
if m.GetTitle().GetEnglish() != nil {
return *m.GetTitle().GetEnglish()
}
return ""
}
func (m *BaseAnime) GetPreferredTitle() string {
if m.GetTitle().GetUserPreferred() != nil {
return *m.GetTitle().GetUserPreferred()
}
return m.GetTitleSafe()
}
func (m *BaseAnime) GetCoverImageSafe() string {
if m.GetCoverImage().GetExtraLarge() != nil {
return *m.GetCoverImage().GetExtraLarge()
}
if m.GetCoverImage().GetLarge() != nil {
return *m.GetCoverImage().GetLarge()
}
if m.GetBannerImage() != nil {
return *m.GetBannerImage()
}
return ""
}
func (m *BaseAnime) GetBannerImageSafe() string {
if m.GetBannerImage() != nil {
return *m.GetBannerImage()
}
return m.GetCoverImageSafe()
}
func (m *BaseAnime) IsMovieOrSingleEpisode() bool {
if m == nil {
return false
}
if m.GetTotalEpisodeCount() == 1 {
return true
}
return false
}
func (m *BaseAnime) GetSynonymsDeref() []string {
if m.Synonyms == nil {
return nil
}
return lo.Map(m.Synonyms, func(s *string, i int) string { return *s })
}
func (m *BaseAnime) GetSynonymsContainingSeason() []string {
if m.Synonyms == nil {
return nil
}
return lo.Filter(lo.Map(m.Synonyms, func(s *string, i int) string { return *s }), func(s string, i int) bool { return comparison.ValueContainsSeason(s) })
}
func (m *BaseAnime) GetStartYearSafe() int {
if m == nil || m.StartDate == nil || m.StartDate.Year == nil {
return 0
}
return *m.StartDate.Year
}
func (m *BaseAnime) IsMovie() bool {
if m == nil {
return false
}
if m.Format == nil {
return false
}
return *m.Format == MediaFormatMovie
}
func (m *BaseAnime) IsFinished() bool {
if m == nil {
return false
}
if m.Status == nil {
return false
}
return *m.Status == MediaStatusFinished
}
func (m *BaseAnime) GetAllTitles() []*string {
titles := make([]*string, 0)
if m.HasRomajiTitle() {
titles = append(titles, m.Title.Romaji)
}
if m.HasEnglishTitle() {
titles = append(titles, m.Title.English)
}
if m.HasSynonyms() && len(m.Synonyms) > 1 {
titles = append(titles, lo.Filter(m.Synonyms, func(s *string, i int) bool { return comparison.ValueContainsSeason(*s) })...)
}
return titles
}
func (m *BaseAnime) GetAllTitlesDeref() []string {
titles := make([]string, 0)
if m.HasRomajiTitle() {
titles = append(titles, *m.Title.Romaji)
}
if m.HasEnglishTitle() {
titles = append(titles, *m.Title.English)
}
if m.HasSynonyms() && len(m.Synonyms) > 1 {
syn := lo.Filter(m.Synonyms, func(s *string, i int) bool { return comparison.ValueContainsSeason(*s) })
for _, s := range syn {
titles = append(titles, *s)
}
}
return titles
}
func (m *BaseAnime) GetMainTitles() []*string {
titles := make([]*string, 0)
if m.HasRomajiTitle() {
titles = append(titles, m.Title.Romaji)
}
if m.HasEnglishTitle() {
titles = append(titles, m.Title.English)
}
return titles
}
func (m *BaseAnime) GetMainTitlesDeref() []string {
titles := make([]string, 0)
if m.HasRomajiTitle() {
titles = append(titles, *m.Title.Romaji)
}
if m.HasEnglishTitle() {
titles = append(titles, *m.Title.English)
}
return titles
}
// GetCurrentEpisodeCount returns the current episode number for that media and -1 if it doesn't have one.
// i.e. -1 is returned if the media has no episodes AND the next airing episode is not set.
func (m *BaseAnime) GetCurrentEpisodeCount() int {
ceil := -1
if m.Episodes != nil {
ceil = *m.Episodes
}
if m.NextAiringEpisode != nil {
if m.NextAiringEpisode.Episode > 0 {
ceil = m.NextAiringEpisode.Episode - 1
}
}
return ceil
}
func (m *BaseAnime) GetCurrentEpisodeCountOrNil() *int {
n := m.GetCurrentEpisodeCount()
if n == -1 {
return nil
}
return &n
}
// GetTotalEpisodeCount returns the total episode number for that media and -1 if it doesn't have one
func (m *BaseAnime) GetTotalEpisodeCount() int {
ceil := -1
if m.Episodes != nil {
ceil = *m.Episodes
}
return ceil
}
// GetTotalEpisodeCount returns the total episode number for that media and -1 if it doesn't have one
func (m *BaseAnime) GetTotalEpisodeCountOrNil() *int {
return m.Episodes
}
// GetPossibleSeasonNumber returns the possible season number for that media and -1 if it doesn't have one.
// It looks at the synonyms and returns the highest season number found.
func (m *BaseAnime) GetPossibleSeasonNumber() int {
if m == nil || m.Synonyms == nil || len(m.Synonyms) == 0 {
return -1
}
titles := lo.Filter(m.Synonyms, func(s *string, i int) bool { return comparison.ValueContainsSeason(*s) })
if m.HasEnglishTitle() {
titles = append(titles, m.Title.English)
}
if m.HasRomajiTitle() {
titles = append(titles, m.Title.Romaji)
}
seasons := lo.Map(titles, func(s *string, i int) int { return comparison.ExtractSeasonNumber(*s) })
return lo.Max(seasons)
}
func (m *BaseAnime) HasEnglishTitle() bool {
return m.Title.English != nil
}
func (m *BaseAnime) HasRomajiTitle() bool {
return m.Title.Romaji != nil
}
func (m *BaseAnime) HasSynonyms() bool {
return m.Synonyms != nil
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
func (m *CompleteAnime) GetTitleSafe() string {
if m.GetTitle().GetEnglish() != nil {
return *m.GetTitle().GetEnglish()
}
if m.GetTitle().GetRomaji() != nil {
return *m.GetTitle().GetRomaji()
}
return "N/A"
}
func (m *CompleteAnime) GetRomajiTitleSafe() string {
if m.GetTitle().GetRomaji() != nil {
return *m.GetTitle().GetRomaji()
}
if m.GetTitle().GetEnglish() != nil {
return *m.GetTitle().GetEnglish()
}
return "N/A"
}
func (m *CompleteAnime) GetPreferredTitle() string {
if m.GetTitle().GetUserPreferred() != nil {
return *m.GetTitle().GetUserPreferred()
}
return m.GetTitleSafe()
}
func (m *CompleteAnime) GetCoverImageSafe() string {
if m.GetCoverImage().GetExtraLarge() != nil {
return *m.GetCoverImage().GetExtraLarge()
}
if m.GetCoverImage().GetLarge() != nil {
return *m.GetCoverImage().GetLarge()
}
if m.GetBannerImage() != nil {
return *m.GetBannerImage()
}
return ""
}
func (m *CompleteAnime) GetBannerImageSafe() string {
if m.GetBannerImage() != nil {
return *m.GetBannerImage()
}
return m.GetCoverImageSafe()
}
func (m *CompleteAnime) IsMovieOrSingleEpisode() bool {
if m == nil {
return false
}
if m.GetTotalEpisodeCount() == 1 {
return true
}
return false
}
func (m *CompleteAnime) IsMovie() bool {
if m == nil {
return false
}
if m.Format == nil {
return false
}
return *m.Format == MediaFormatMovie
}
func (m *CompleteAnime) IsFinished() bool {
if m == nil {
return false
}
if m.Status == nil {
return false
}
return *m.Status == MediaStatusFinished
}
func (m *CompleteAnime) GetAllTitles() []*string {
titles := make([]*string, 0)
if m.HasRomajiTitle() {
titles = append(titles, m.Title.Romaji)
}
if m.HasEnglishTitle() {
titles = append(titles, m.Title.English)
}
if m.HasSynonyms() && len(m.Synonyms) > 1 {
titles = append(titles, lo.Filter(m.Synonyms, func(s *string, i int) bool { return comparison.ValueContainsSeason(*s) })...)
}
return titles
}
func (m *CompleteAnime) GetAllTitlesDeref() []string {
titles := make([]string, 0)
if m.HasRomajiTitle() {
titles = append(titles, *m.Title.Romaji)
}
if m.HasEnglishTitle() {
titles = append(titles, *m.Title.English)
}
if m.HasSynonyms() && len(m.Synonyms) > 1 {
syn := lo.Filter(m.Synonyms, func(s *string, i int) bool { return comparison.ValueContainsSeason(*s) })
for _, s := range syn {
titles = append(titles, *s)
}
}
return titles
}
// GetCurrentEpisodeCount returns the current episode number for that media and -1 if it doesn't have one.
// i.e. -1 is returned if the media has no episodes AND the next airing episode is not set.
func (m *CompleteAnime) GetCurrentEpisodeCount() int {
ceil := -1
if m.Episodes != nil {
ceil = *m.Episodes
}
if m.NextAiringEpisode != nil {
if m.NextAiringEpisode.Episode > 0 {
ceil = m.NextAiringEpisode.Episode - 1
}
}
return ceil
}
// GetTotalEpisodeCount returns the total episode number for that media and -1 if it doesn't have one
func (m *CompleteAnime) GetTotalEpisodeCount() int {
ceil := -1
if m.Episodes != nil {
ceil = *m.Episodes
}
return ceil
}
// GetPossibleSeasonNumber returns the possible season number for that media and -1 if it doesn't have one.
// It looks at the synonyms and returns the highest season number found.
func (m *CompleteAnime) GetPossibleSeasonNumber() int {
if m == nil || m.Synonyms == nil || len(m.Synonyms) == 0 {
return -1
}
titles := lo.Filter(m.Synonyms, func(s *string, i int) bool { return comparison.ValueContainsSeason(*s) })
if m.HasEnglishTitle() {
titles = append(titles, m.Title.English)
}
if m.HasRomajiTitle() {
titles = append(titles, m.Title.Romaji)
}
seasons := lo.Map(titles, func(s *string, i int) int { return comparison.ExtractSeasonNumber(*s) })
return lo.Max(seasons)
}
func (m *CompleteAnime) HasEnglishTitle() bool {
return m.Title.English != nil
}
func (m *CompleteAnime) HasRomajiTitle() bool {
return m.Title.Romaji != nil
}
func (m *CompleteAnime) HasSynonyms() bool {
return m.Synonyms != nil
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var EdgeNarrowFormats = []MediaFormat{MediaFormatTv, MediaFormatTvShort}
var EdgeBroaderFormats = []MediaFormat{MediaFormatTv, MediaFormatTvShort, MediaFormatOna, MediaFormatOva, MediaFormatMovie, MediaFormatSpecial}
func (m *CompleteAnime) FindEdge(relation string, formats []MediaFormat) (*BaseAnime, bool) {
if m.GetRelations() == nil {
return nil, false
}
edges := m.GetRelations().GetEdges()
for _, edge := range edges {
if edge.GetRelationType().String() == relation {
for _, fm := range formats {
if fm.String() == edge.GetNode().GetFormat().String() {
return edge.GetNode(), true
}
}
}
}
return nil, false
}
func (e *CompleteAnime_Relations_Edges) IsBroadRelationFormat() bool {
if e.GetNode() == nil {
return false
}
if e.GetNode().GetFormat() == nil {
return false
}
for _, fm := range EdgeBroaderFormats {
if fm.String() == e.GetNode().GetFormat().String() {
return true
}
}
return false
}
func (e *CompleteAnime_Relations_Edges) IsNarrowRelationFormat() bool {
if e.GetNode() == nil {
return false
}
if e.GetNode().GetFormat() == nil {
return false
}
for _, fm := range EdgeNarrowFormats {
if fm.String() == e.GetNode().GetFormat().String() {
return true
}
}
return false
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
func (m *CompleteAnime) ToBaseAnime() *BaseAnime {
if m == nil {
return nil
}
var trailer *BaseAnime_Trailer
if m.GetTrailer() != nil {
trailer = &BaseAnime_Trailer{
ID: m.GetTrailer().GetID(),
Site: m.GetTrailer().GetSite(),
Thumbnail: m.GetTrailer().GetThumbnail(),
}
}
var nextAiringEpisode *BaseAnime_NextAiringEpisode
if m.GetNextAiringEpisode() != nil {
nextAiringEpisode = &BaseAnime_NextAiringEpisode{
AiringAt: m.GetNextAiringEpisode().GetAiringAt(),
TimeUntilAiring: m.GetNextAiringEpisode().GetTimeUntilAiring(),
Episode: m.GetNextAiringEpisode().GetEpisode(),
}
}
var startDate *BaseAnime_StartDate
if m.GetStartDate() != nil {
startDate = &BaseAnime_StartDate{
Year: m.GetStartDate().GetYear(),
Month: m.GetStartDate().GetMonth(),
Day: m.GetStartDate().GetDay(),
}
}
var endDate *BaseAnime_EndDate
if m.GetEndDate() != nil {
endDate = &BaseAnime_EndDate{
Year: m.GetEndDate().GetYear(),
Month: m.GetEndDate().GetMonth(),
Day: m.GetEndDate().GetDay(),
}
}
return &BaseAnime{
ID: m.GetID(),
IDMal: m.GetIDMal(),
SiteURL: m.GetSiteURL(),
Format: m.GetFormat(),
Episodes: m.GetEpisodes(),
Status: m.GetStatus(),
Synonyms: m.GetSynonyms(),
BannerImage: m.GetBannerImage(),
Season: m.GetSeason(),
SeasonYear: m.GetSeasonYear(),
Type: m.GetType(),
IsAdult: m.GetIsAdult(),
CountryOfOrigin: m.GetCountryOfOrigin(),
Genres: m.GetGenres(),
Duration: m.GetDuration(),
Description: m.GetDescription(),
MeanScore: m.GetMeanScore(),
Trailer: trailer,
Title: &BaseAnime_Title{
UserPreferred: m.GetTitle().GetUserPreferred(),
Romaji: m.GetTitle().GetRomaji(),
English: m.GetTitle().GetEnglish(),
Native: m.GetTitle().GetNative(),
},
CoverImage: &BaseAnime_CoverImage{
ExtraLarge: m.GetCoverImage().GetExtraLarge(),
Large: m.GetCoverImage().GetLarge(),
Medium: m.GetCoverImage().GetMedium(),
Color: m.GetCoverImage().GetColor(),
},
StartDate: startDate,
EndDate: endDate,
NextAiringEpisode: nextAiringEpisode,
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
func (m *AnimeListEntry) GetProgressSafe() int {
if m == nil {
return 0
}
if m.Progress == nil {
return 0
}
return *m.Progress
}
func (m *AnimeListEntry) GetScoreSafe() float64 {
if m == nil {
return 0
}
if m.Score == nil {
return 0
}
return *m.Score
}
func (m *AnimeListEntry) GetRepeatSafe() int {
if m == nil {
return 0
}
if m.Repeat == nil {
return 0
}
return *m.Repeat
}
func (m *AnimeListEntry) GetStatusSafe() MediaListStatus {
if m == nil {
return ""
}
if m.Status == nil {
return ""
}
return *m.Status
}