mirror of
https://github.com/Crunchy-DL/Crunchy-Downloader.git
synced 2026-05-17 15:32:05 +00:00
- Added retry delay for rate limit handling - Added toggle to control whether auto refresh also adds missing episodes to the queue - Added configurable delay after each dub download - Changed encoding preset dialog to show a preview of the FFmpeg command - Changed play sound on queue empty and execute file on completion to be handled by the notification service - Changed shutdown PC option to disable once triggered - Fixed crash with queue persistence - Fixed crash with audio player - Fixed subscription countdown on the account page
187 lines
6.7 KiB
C#
187 lines
6.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Avalonia.Media.Imaging;
|
|
using CRD.Downloader;
|
|
using CRD.Downloader.Crunchyroll;
|
|
using CRD.Utils.Files;
|
|
using CRD.Utils.Sonarr.Models;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace CRD.Utils.Structs.History;
|
|
|
|
public class HistoryEpisode : INotifyPropertyChanged{
|
|
[JsonProperty("episode_title")]
|
|
public string? EpisodeTitle{ get; set; }
|
|
|
|
[JsonProperty("episode_id")]
|
|
public string? EpisodeId{ get; set; }
|
|
|
|
[JsonProperty("episode_cr_episode_number")]
|
|
public string? Episode{ get; set; }
|
|
|
|
[JsonProperty("episode_cr_episode_description")]
|
|
public string? EpisodeDescription{ get; set; }
|
|
|
|
[JsonProperty("episode_cr_season_number")]
|
|
public string? EpisodeSeasonNum{ get; set; }
|
|
|
|
[JsonProperty("episode_cr_premium_air_date")]
|
|
public DateTime? EpisodeCrPremiumAirDate{ get; set; }
|
|
|
|
[JsonProperty("episode_was_downloaded")]
|
|
public bool WasDownloaded{ get; set; }
|
|
|
|
[JsonProperty("episode_tracked_series_release_notified")]
|
|
public bool TrackedSeriesReleaseNotified{ get; set; }
|
|
|
|
[JsonProperty("episode_special_episode")]
|
|
public bool SpecialEpisode{ get; set; }
|
|
|
|
[JsonProperty("episode_available_on_streaming_service")]
|
|
public bool IsEpisodeAvailableOnStreamingService{ get; set; }
|
|
|
|
[JsonProperty("episode_type")]
|
|
public EpisodeType EpisodeType{ get; set; } = EpisodeType.Unknown;
|
|
|
|
[JsonProperty("episode_series_type")]
|
|
public SeriesType EpisodeSeriesType{ get; set; } = SeriesType.Unknown;
|
|
|
|
[JsonProperty("episode_thumbnail_url")]
|
|
public string? ThumbnailImageUrl{ get; set; }
|
|
|
|
[JsonProperty("sonarr_episode_id")]
|
|
public string? SonarrEpisodeId{ get; set; }
|
|
|
|
[JsonProperty("sonarr_has_file")]
|
|
public bool SonarrHasFile{ get; set; }
|
|
|
|
[JsonProperty("sonarr_is_monitored")]
|
|
public bool SonarrIsMonitored{ get; set; }
|
|
|
|
[JsonProperty("sonarr_episode_number")]
|
|
public string? SonarrEpisodeNumber{ get; set; }
|
|
|
|
[JsonProperty("sonarr_season_number")]
|
|
public string? SonarrSeasonNumber{ get; set; }
|
|
|
|
[JsonProperty("sonarr_absolut_number")]
|
|
public string? SonarrAbsolutNumber{ get; set; }
|
|
|
|
[JsonIgnore]
|
|
public string SonarrSeasonEpisodeText{
|
|
get{
|
|
if (int.TryParse(SonarrSeasonNumber, out int season) &&
|
|
int.TryParse(SonarrEpisodeNumber, out int episode)){
|
|
return $"S{season:D2}E{episode:D2}";
|
|
}
|
|
|
|
return $"S{SonarrSeasonNumber}E{SonarrEpisodeNumber}";
|
|
}
|
|
}
|
|
|
|
[JsonProperty("history_episode_available_soft_subs")]
|
|
public List<string> HistoryEpisodeAvailableSoftSubs{ get; set; } =[];
|
|
|
|
[JsonProperty("history_episode_available_dub_lang")]
|
|
public List<string> HistoryEpisodeAvailableDubLang{ get; set; } =[];
|
|
|
|
[JsonIgnore]
|
|
public Bitmap? ThumbnailImage{ get; set; }
|
|
|
|
[JsonIgnore]
|
|
public bool IsImageLoaded{ get; private set; }
|
|
|
|
public async Task LoadImage(){
|
|
if (IsImageLoaded || string.IsNullOrEmpty(ThumbnailImageUrl))
|
|
return;
|
|
|
|
try{
|
|
ThumbnailImage = await Helpers.LoadImage(ThumbnailImageUrl);
|
|
IsImageLoaded = true;
|
|
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ThumbnailImage)));
|
|
} catch (Exception ex){
|
|
Console.Error.WriteLine("Failed to load image: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
[JsonIgnore]
|
|
public string ReleaseDateFormated{
|
|
get{
|
|
if (!EpisodeCrPremiumAirDate.HasValue ||
|
|
EpisodeCrPremiumAirDate.Value == DateTime.MinValue ||
|
|
EpisodeCrPremiumAirDate.Value.Date == new DateTime(1970, 1, 1))
|
|
return string.Empty;
|
|
|
|
|
|
var cultureInfo = System.Globalization.CultureInfo.InvariantCulture;
|
|
string monthAbbreviation = cultureInfo.DateTimeFormat.GetAbbreviatedMonthName(EpisodeCrPremiumAirDate.Value.Month);
|
|
|
|
return string.Format("{0:00}.{1}.{2}", EpisodeCrPremiumAirDate.Value.Day, monthAbbreviation, EpisodeCrPremiumAirDate.Value.Year);
|
|
}
|
|
}
|
|
|
|
public event PropertyChangedEventHandler? PropertyChanged;
|
|
|
|
public void ToggleWasDownloaded(){
|
|
WasDownloaded = !WasDownloaded;
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(WasDownloaded)));
|
|
}
|
|
|
|
public void ToggleWasDownloadedSeries(HistorySeries? series){
|
|
WasDownloaded = !WasDownloaded;
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(WasDownloaded)));
|
|
|
|
if (series?.Seasons != null){
|
|
foreach (var historySeason in series.Seasons){
|
|
historySeason.UpdateDownloadedSilent();
|
|
}
|
|
|
|
series.UpdateNewEpisodes();
|
|
}
|
|
|
|
CfgManager.UpdateHistoryFile();
|
|
}
|
|
|
|
public async Task DownloadEpisodeDefault(){
|
|
await DownloadEpisode(EpisodeDownloadMode.Default,"",false);
|
|
}
|
|
|
|
public async Task DownloadEpisode(EpisodeDownloadMode episodeDownloadMode, string overrideDownloadPath,bool chekQueueForId){
|
|
|
|
if (chekQueueForId && QueueManager.Instance.Queue.Any(item => item.Data.Any(epmeta => epmeta.MediaId == EpisodeId))){
|
|
Console.Error.WriteLine($"Episode already in queue! E{EpisodeSeasonNum}-{EpisodeTitle}");
|
|
return;
|
|
}
|
|
|
|
switch (EpisodeType){
|
|
case EpisodeType.MusicVideo:
|
|
await CrunchyrollManager.Instance.CrQueue.CrAddMusicVideoToQueue(EpisodeId ?? string.Empty, overrideDownloadPath);
|
|
break;
|
|
case EpisodeType.Concert:
|
|
await CrunchyrollManager.Instance.CrQueue.CrAddConcertToQueue(EpisodeId ?? string.Empty, overrideDownloadPath);
|
|
break;
|
|
case EpisodeType.Episode:
|
|
case EpisodeType.Unknown:
|
|
default:
|
|
await CrunchyrollManager.Instance.CrQueue.CrAddEpisodeToQueue(EpisodeId ?? string.Empty,
|
|
string.IsNullOrEmpty(CrunchyrollManager.Instance.CrunOptions.HistoryLang) ? CrunchyrollManager.Instance.DefaultLocale : CrunchyrollManager.Instance.CrunOptions.HistoryLang,
|
|
CrunchyrollManager.Instance.CrunOptions.DubLang, false, episodeDownloadMode);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void AssignSonarrEpisodeData(SonarrEpisode episode){
|
|
SonarrEpisodeId = episode.Id.ToString();
|
|
SonarrEpisodeNumber = episode.EpisodeNumber.ToString();
|
|
SonarrHasFile = episode.HasFile;
|
|
SonarrIsMonitored = episode.Monitored;
|
|
SonarrAbsolutNumber = episode.AbsoluteEpisodeNumber.ToString();
|
|
SonarrSeasonNumber = episode.SeasonNumber.ToString();
|
|
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SonarrSeasonEpisodeText)));
|
|
}
|
|
}
|