151 lines
5.2 KiB
C#
151 lines
5.2 KiB
C#
using AnimeAnnouncer.Cache;
|
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
|
|
namespace AnimeAnnouncer.Web.Pages;
|
|
|
|
public class IndexModel : PageModel
|
|
{
|
|
private readonly ILogger<IndexModel> _logger;
|
|
private readonly TMDBCache? _tmdbCache;
|
|
|
|
public List<AiringShowViewModel> AiringShows { get; set; } = new();
|
|
|
|
public string? ErrorMessage { get; set; }
|
|
|
|
public IndexModel(ILogger<IndexModel> logger, IServiceProvider serviceProvider)
|
|
{
|
|
_logger = logger;
|
|
_tmdbCache = serviceProvider.GetService<TMDBCache>();
|
|
}
|
|
|
|
public async Task OnGetAsync()
|
|
{
|
|
if (_tmdbCache == null)
|
|
{
|
|
ErrorMessage = "Redis cache connection is not configured or unavailable.";
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
List<AiringSoonItem>? airingList = await _tmdbCache.GetAiringList();
|
|
|
|
if (airingList == null || airingList.Count == 0)
|
|
{
|
|
AiringShows = new List<AiringShowViewModel>();
|
|
return;
|
|
}
|
|
|
|
var viewModels = new List<AiringShowViewModel>();
|
|
|
|
foreach (var airingItem in airingList)
|
|
{
|
|
TMDBCacheItem? cacheItem = null;
|
|
try
|
|
{
|
|
cacheItem = await _tmdbCache.GetCacheItem<TMDBCacheItem>($"ShowCache-{airingItem.Title}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(ex, "Failed to retrieve cache item for title: {Title}", airingItem.Title);
|
|
}
|
|
|
|
viewModels.Add(new AiringShowViewModel
|
|
{
|
|
AiringSoon = airingItem,
|
|
CachedDetails = cacheItem
|
|
});
|
|
}
|
|
|
|
// Exclude placeholder/sentinel last-air-dates (e.g. DateTime.MaxValue == 12/31/9999,
|
|
// used by the announcer when an exact air date is unknown), then sort descending
|
|
// by LastAirDate (nulls last).
|
|
var displayable = viewModels.Where(x =>
|
|
{
|
|
var date = x.EffectiveLastAirDate;
|
|
// Keep items with a real, displayable date; drop the MaxValue sentinel.
|
|
return !date.HasValue || date.Value < DateTime.MaxValue.AddMonths(-1);
|
|
}).ToList();
|
|
|
|
AiringShows = displayable
|
|
.Where(x => x.EffectiveLastAirDate.HasValue && x.EffectiveLastAirDate.Value.Date >= DateTime.Now.Date)
|
|
.OrderBy(x => x.EffectiveLastAirDate)
|
|
.ThenBy(x => x.Title)
|
|
.ToList();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error loading airing soon list");
|
|
ErrorMessage = $"Unable to load airing soon list: {ex.Message}";
|
|
}
|
|
}
|
|
|
|
public class AiringShowViewModel
|
|
{
|
|
public required AiringSoonItem AiringSoon { get; set; }
|
|
public TMDBCacheItem? CachedDetails { get; set; }
|
|
|
|
public string Title => AiringSoon.Title;
|
|
public int ShowID => AiringSoon.ShowID;
|
|
public DateTime? EffectiveLastAirDate => AiringSoon.LastAirDate ?? CachedDetails?.LastAirDate;
|
|
public int LatestEpisodeNumber => AiringSoon.LatestEpisodeNumber > 0
|
|
? AiringSoon.LatestEpisodeNumber
|
|
: (CachedDetails?.LatestEpisodeNumber ?? 0);
|
|
public int? LastEpisodeNumber => CachedDetails?.LastEpisodeNumber;
|
|
public int? LatestSeasonNumber => CachedDetails?.LatestSeasonNumber;
|
|
public int? LatestOrdinalEpisodeNumber => CachedDetails?.LatestOrdinalEpisodeNumber;
|
|
public double? VoteAverage => CachedDetails?.VoteAverage;
|
|
public string? Overview => !string.IsNullOrWhiteSpace(CachedDetails?.LatestSeasonOverview)
|
|
? CachedDetails.LatestSeasonOverview
|
|
: CachedDetails?.Overview;
|
|
|
|
public string? PosterUrl
|
|
{
|
|
get
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(CachedDetails?.LatestSeasonPosterPath))
|
|
return CachedDetails.LatestSeasonPosterPath;
|
|
if (!string.IsNullOrWhiteSpace(CachedDetails?.PosterPath))
|
|
return CachedDetails.PosterPath;
|
|
//if (!string.IsNullOrWhiteSpace(CachedDetails?.AnilistPosterPath))
|
|
// return CachedDetails.AnilistPosterPath;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public string? BackdropUrl => CachedDetails?.BackdropPath;
|
|
|
|
public DateTime AirReferenceNow => DateTime.Now;
|
|
|
|
public bool IsFuture
|
|
{
|
|
get
|
|
{
|
|
var date = EffectiveLastAirDate;
|
|
return date.HasValue && date.Value > AirReferenceNow;
|
|
}
|
|
}
|
|
|
|
public int DaysUntil
|
|
{
|
|
get
|
|
{
|
|
var date = EffectiveLastAirDate;
|
|
if (!date.HasValue)
|
|
return 0;
|
|
return (int)((date.Value - AirReferenceNow).Ticks / TimeSpan.FromDays(1).Ticks);
|
|
}
|
|
}
|
|
|
|
public string AirDateFormatted
|
|
{
|
|
get
|
|
{
|
|
var date = EffectiveLastAirDate;
|
|
return date.HasValue ? date.Value.ToString("MM/dd/yyyy") : "Unknown";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|