Add - Downloader remembers the Window Size and Position https://github.com/Crunchy-DL/Crunchy-Downloader/discussions/78
Chg - Adjusted the subscription check if the end date has passed but crunchyroll still thinks it's active https://github.com/Crunchy-DL/Crunchy-Downloader/issues/80
This commit is contained in:
parent
6aa10cb2c2
commit
9c6ad2d7e8
|
@ -44,7 +44,6 @@ public class CrAuth{
|
|||
PreferredContentAudioLanguage = "ja-JP",
|
||||
PreferredContentSubtitleLanguage = "de-DE"
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
private void JsonTokenToFileAndVariable(string content){
|
||||
|
@ -52,7 +51,7 @@ public class CrAuth{
|
|||
|
||||
|
||||
if (crunInstance.Token != null && crunInstance.Token.expires_in != null){
|
||||
crunInstance.Token.expires = DateTime.Now.AddMilliseconds((double)crunInstance.Token.expires_in);
|
||||
crunInstance.Token.expires = DateTime.Now.AddSeconds((double)crunInstance.Token.expires_in);
|
||||
|
||||
CfgManager.WriteTokenToYamlFile(crunInstance.Token, CfgManager.PathCrToken);
|
||||
}
|
||||
|
@ -82,7 +81,8 @@ public class CrAuth{
|
|||
if (response.ResponseContent.Contains("invalid_credentials")){
|
||||
MessageBus.Current.SendMessage(new ToastMessage($"Failed to login - because of invalid login credentials", ToastType.Error, 10));
|
||||
} else{
|
||||
MessageBus.Current.SendMessage(new ToastMessage($"Failed to login - {response.ResponseContent.Substring(0,response.ResponseContent.Length < 200 ? response.ResponseContent.Length : 200)}", ToastType.Error, 10));
|
||||
MessageBus.Current.SendMessage(new ToastMessage($"Failed to login - {response.ResponseContent.Substring(0, response.ResponseContent.Length < 200 ? response.ResponseContent.Length : 200)}",
|
||||
ToastType.Error, 10));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,20 +119,27 @@ public class CrAuth{
|
|||
if (subsc is{ SubscriptionProducts:{ Count: 0 }, ThirdPartySubscriptionProducts.Count: > 0 }){
|
||||
var thirdPartySub = subsc.ThirdPartySubscriptionProducts.First();
|
||||
var expiration = thirdPartySub.InGrace ? thirdPartySub.InGraceExpirationDate : thirdPartySub.ExpirationDate;
|
||||
var remaining = expiration - DateTime.UtcNow;
|
||||
crunInstance.Profile.HasPremium = remaining > TimeSpan.Zero;
|
||||
var remaining = expiration - DateTime.Now;
|
||||
crunInstance.Profile.HasPremium = true;
|
||||
if (crunInstance.Profile.Subscription != null){
|
||||
crunInstance.Profile.Subscription.IsActive = remaining > TimeSpan.Zero;
|
||||
crunInstance.Profile.Subscription.NextRenewalDate = expiration;
|
||||
}
|
||||
} else if (subsc is{ SubscriptionProducts:{ Count: 0 }, NonrecurringSubscriptionProducts.Count: > 0 }){
|
||||
var nonRecurringSub = subsc.NonrecurringSubscriptionProducts.First();
|
||||
var remaining = nonRecurringSub.EndDate - DateTime.UtcNow;
|
||||
crunInstance.Profile.HasPremium = remaining > TimeSpan.Zero;
|
||||
var remaining = nonRecurringSub.EndDate - DateTime.Now;
|
||||
crunInstance.Profile.HasPremium = true;
|
||||
if (crunInstance.Profile.Subscription != null){
|
||||
crunInstance.Profile.Subscription.IsActive = remaining > TimeSpan.Zero;
|
||||
crunInstance.Profile.Subscription.NextRenewalDate = nonRecurringSub.EndDate;
|
||||
}
|
||||
} else if (subsc is{ SubscriptionProducts:{ Count: 0 }, FunimationSubscriptions.Count: > 0 }){
|
||||
crunInstance.Profile.HasPremium = true;
|
||||
} else if (subsc is{ SubscriptionProducts.Count: > 0 }){
|
||||
crunInstance.Profile.HasPremium = true;
|
||||
} else{
|
||||
crunInstance.Profile.HasPremium = subsc.IsActive;
|
||||
crunInstance.Profile.HasPremium = false;
|
||||
Console.Error.WriteLine($"No subscription available:\n {JsonConvert.SerializeObject(subsc, Formatting.Indented)} ");
|
||||
}
|
||||
} else{
|
||||
crunInstance.Profile.HasPremium = false;
|
||||
|
@ -175,7 +182,6 @@ public class CrAuth{
|
|||
|
||||
await GetProfile();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async Task RefreshToken(bool needsToken){
|
||||
|
@ -213,7 +219,5 @@ public class CrAuth{
|
|||
} else{
|
||||
Console.Error.WriteLine("Refresh Token Auth Failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -59,7 +59,7 @@ public class CrEpisode(){
|
|||
CrunchyRollEpisodeData episode = new CrunchyRollEpisodeData();
|
||||
|
||||
if (crunInstance.CrunOptions.History && updateHistory){
|
||||
await crunInstance.History.UpdateWithEpisode(dlEpisode);
|
||||
await crunInstance.History.UpdateWithSeasonData(new List<CrunchyEpisode>(){dlEpisode});
|
||||
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == dlEpisode.SeriesId);
|
||||
if (historySeries != null){
|
||||
CrunchyrollManager.Instance.History.MatchHistorySeriesWithSonarr(false);
|
||||
|
|
|
@ -16,26 +16,6 @@ namespace CRD.Downloader.Crunchyroll;
|
|||
public class CrSeries(){
|
||||
private readonly CrunchyrollManager crunInstance = CrunchyrollManager.Instance;
|
||||
|
||||
public async Task<List<CrunchyEpMeta>> DownloadFromSeriesId(string id, CrunchyMultiDownload data){
|
||||
var series = await ListSeriesId(id, "", data);
|
||||
|
||||
if (series != null){
|
||||
var selected = ItemSelectMultiDub(series.Value.Data, data.DubLang, data.But, data.AllEpisodes, data.E);
|
||||
|
||||
foreach (var crunchyEpMeta in selected.Values){
|
||||
if (crunchyEpMeta.Data == null) continue;
|
||||
var languages = crunchyEpMeta.Data.Select((a) =>
|
||||
$" {a.Lang?.Name ?? "Unknown Language"}");
|
||||
|
||||
Console.WriteLine($"[S{crunchyEpMeta.Season}E{crunchyEpMeta.EpisodeNumber} - {crunchyEpMeta.EpisodeTitle} [{string.Join(", ", languages)}]");
|
||||
}
|
||||
|
||||
return selected.Values.ToList();
|
||||
}
|
||||
|
||||
return new List<CrunchyEpMeta>();
|
||||
}
|
||||
|
||||
public Dictionary<string, CrunchyEpMeta> ItemSelectMultiDub(Dictionary<string, EpisodeAndLanguage> eps, List<string> dubLang, bool? but, bool? all, List<string>? e){
|
||||
var ret = new Dictionary<string, CrunchyEpMeta>();
|
||||
|
||||
|
@ -143,26 +123,32 @@ public class CrSeries(){
|
|||
|
||||
CrSeriesSearch? parsedSeries = await ParseSeriesById(id, crLocale); // one piece - GRMG8ZQZR
|
||||
|
||||
if (parsedSeries == null){
|
||||
if (parsedSeries == null || parsedSeries.Data == null){
|
||||
Console.Error.WriteLine("Parse Data Invalid");
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = ParseSeriesResult(parsedSeries);
|
||||
// var result = ParseSeriesResult(parsedSeries);
|
||||
Dictionary<string, EpisodeAndLanguage> episodes = new Dictionary<string, EpisodeAndLanguage>();
|
||||
|
||||
if (crunInstance.CrunOptions.History){
|
||||
crunInstance.History.CRUpdateSeries(id,"");
|
||||
}
|
||||
|
||||
foreach (int season in result.Keys){
|
||||
foreach (var key in result[season].Keys){
|
||||
var s = result[season][key];
|
||||
var cachedSeasonID = "";
|
||||
var seasonData = new CrunchyEpisodeList();
|
||||
|
||||
foreach (var s in parsedSeries.Data){
|
||||
if (data?.S != null && s.Id != data.Value.S) continue;
|
||||
int fallbackIndex = 0;
|
||||
var seasonData = await GetSeasonDataById(s.Id, "");
|
||||
if (seasonData.Data != null){
|
||||
if (crunInstance.CrunOptions.History){
|
||||
crunInstance.History.UpdateWithSeasonData(seasonData, false);
|
||||
if (cachedSeasonID != s.Id){
|
||||
seasonData = await GetSeasonDataById(s.Id, "");
|
||||
cachedSeasonID = s.Id;
|
||||
}
|
||||
|
||||
if (seasonData.Data != null){
|
||||
|
||||
|
||||
foreach (var episode in seasonData.Data){
|
||||
// Prepare the episode array
|
||||
EpisodeAndLanguage item;
|
||||
|
@ -205,7 +191,6 @@ public class CrSeries(){
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (crunInstance.CrunOptions.History){
|
||||
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == id);
|
||||
|
|
|
@ -22,25 +22,20 @@ public class History(){
|
|||
public async Task CRUpdateSeries(string seriesId, string? seasonId){
|
||||
await crunInstance.CrAuth.RefreshToken(true);
|
||||
|
||||
CrSeriesSearch? parsedSeries = await crunInstance.CrSeries.ParseSeriesById(seriesId, "ja-JP", true);
|
||||
CrSeriesSearch? parsedSeries = await crunInstance.CrSeries.ParseSeriesById(seriesId, "en-US", true);
|
||||
|
||||
if (parsedSeries == null){
|
||||
Console.Error.WriteLine("Parse Data Invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
var result = crunInstance.CrSeries.ParseSeriesResult(parsedSeries);
|
||||
Dictionary<string, EpisodeAndLanguage> episodes = new Dictionary<string, EpisodeAndLanguage>();
|
||||
|
||||
foreach (int season in result.Keys){
|
||||
foreach (var key in result[season].Keys){
|
||||
var s = result[season][key];
|
||||
if (parsedSeries.Data != null){
|
||||
foreach (var s in parsedSeries.Data){
|
||||
if (!string.IsNullOrEmpty(seasonId) && s.Id != seasonId) continue;
|
||||
|
||||
var sId = s.Id;
|
||||
if (s.Versions is{ Count: > 0 }){
|
||||
foreach (var sVersion in s.Versions){
|
||||
if (sVersion.Original == true){
|
||||
foreach (var sVersion in s.Versions.Where(sVersion => sVersion.Original == true)){
|
||||
if (sVersion.Guid != null){
|
||||
sId = sVersion.Guid;
|
||||
}
|
||||
|
@ -48,13 +43,12 @@ public class History(){
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var seasonData = await crunInstance.CrSeries.GetSeasonDataById(sId, string.IsNullOrEmpty(crunInstance.CrunOptions.HistoryLang) ? crunInstance.DefaultLocale : crunInstance.CrunOptions.HistoryLang, true);
|
||||
await UpdateWithSeasonData(seasonData);
|
||||
}
|
||||
if (seasonData.Data != null) await UpdateWithSeasonData(seasonData.Data);
|
||||
}
|
||||
|
||||
|
||||
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == seriesId);
|
||||
|
||||
if (historySeries != null){
|
||||
|
@ -63,6 +57,7 @@ public class History(){
|
|||
CfgManager.UpdateHistoryFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetAsDownloaded(string? seriesId, string? seasonId, string episodeId){
|
||||
|
@ -212,116 +207,43 @@ public class History(){
|
|||
}
|
||||
|
||||
|
||||
public async Task UpdateWithEpisode(CrunchyEpisode episodeParam){
|
||||
var episode = episodeParam;
|
||||
|
||||
if (episode.Versions != null){
|
||||
var version = episode.Versions.Find(a => a.Original);
|
||||
if (version.AudioLocale != episode.AudioLocale){
|
||||
var crEpisode = await crunInstance.CrEpisode.ParseEpisodeById(version.Guid, "");
|
||||
if (crEpisode != null){
|
||||
episode = crEpisode.Value;
|
||||
} else{
|
||||
MessageBus.Current.SendMessage(new ToastMessage($"Couldn't update download History", ToastType.Warning, 1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var seriesId = episode.SeriesId;
|
||||
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == seriesId);
|
||||
if (historySeries != null){
|
||||
historySeries.HistorySeriesAddDate ??= DateTime.Now;
|
||||
|
||||
var historySeason = historySeries.Seasons.FirstOrDefault(s => s.SeasonId == episode.SeasonId);
|
||||
|
||||
await RefreshSeriesData(seriesId, historySeries);
|
||||
|
||||
if (historySeason != null){
|
||||
historySeason.SeasonTitle = episode.SeasonTitle;
|
||||
historySeason.SeasonNum = Helpers.ExtractNumberAfterS(episode.Identifier) ?? episode.SeasonNumber + "";
|
||||
historySeason.SpecialSeason = CheckStringForSpecial(episode.Identifier);
|
||||
if (historySeason.EpisodesList.All(e => e.EpisodeId != episode.Id)){
|
||||
var newHistoryEpisode = new HistoryEpisode{
|
||||
EpisodeTitle = episode.Identifier.Contains("|M|") ? episode.SeasonTitle : episode.Title,
|
||||
EpisodeDescription = episode.Description,
|
||||
EpisodeId = episode.Id,
|
||||
Episode = episode.Episode,
|
||||
EpisodeSeasonNum = Helpers.ExtractNumberAfterS(episode.Identifier) ?? episode.SeasonNumber + "",
|
||||
SpecialEpisode = !int.TryParse(episode.Episode, out _),
|
||||
};
|
||||
|
||||
historySeason.EpisodesList.Add(newHistoryEpisode);
|
||||
|
||||
historySeason.EpisodesList.Sort(new NumericStringPropertyComparer());
|
||||
}
|
||||
} else{
|
||||
var newSeason = NewHistorySeason(episode);
|
||||
|
||||
historySeries.Seasons.Add(newSeason);
|
||||
newSeason.Init();
|
||||
}
|
||||
|
||||
historySeries.UpdateNewEpisodes();
|
||||
} else{
|
||||
historySeries = new HistorySeries{
|
||||
SeriesTitle = episode.SeriesTitle,
|
||||
SeriesId = episode.SeriesId,
|
||||
Seasons =[],
|
||||
HistorySeriesAddDate = DateTime.Now,
|
||||
};
|
||||
crunInstance.HistoryList.Add(historySeries);
|
||||
var newSeason = NewHistorySeason(episode);
|
||||
|
||||
await RefreshSeriesData(seriesId, historySeries);
|
||||
|
||||
historySeries.Seasons.Add(newSeason);
|
||||
historySeries.UpdateNewEpisodes();
|
||||
historySeries.Init();
|
||||
newSeason.Init();
|
||||
}
|
||||
|
||||
SortItems();
|
||||
SortSeasons(historySeries);
|
||||
}
|
||||
|
||||
public async Task UpdateWithSeasonData(CrunchyEpisodeList seasonData, bool skippVersionCheck = true){
|
||||
if (seasonData.Data != null){
|
||||
public async Task UpdateWithSeasonData(List<CrunchyEpisode>? episodeList, bool skippVersionCheck = true){
|
||||
if (episodeList != null){
|
||||
if (!skippVersionCheck){
|
||||
if (seasonData.Data.First().Versions != null){
|
||||
var version = seasonData.Data.First().Versions.Find(a => a.Original);
|
||||
if (version.AudioLocale != seasonData.Data.First().AudioLocale){
|
||||
CRUpdateSeries(seasonData.Data.First().SeriesId, version.SeasonGuid);
|
||||
var episodeVersions = episodeList.First().Versions;
|
||||
if (episodeVersions != null){
|
||||
var version = episodeVersions.Find(a => a.Original);
|
||||
if (version.AudioLocale != episodeList.First().AudioLocale){
|
||||
await CRUpdateSeries(episodeList.First().SeriesId, version.SeasonGuid);
|
||||
return;
|
||||
}
|
||||
} else{
|
||||
CRUpdateSeries(seasonData.Data.First().SeriesId, "");
|
||||
await CRUpdateSeries(episodeList.First().SeriesId, "");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var firstEpisode = seasonData.Data.First();
|
||||
var firstEpisode = episodeList.First();
|
||||
var seriesId = firstEpisode.SeriesId;
|
||||
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == seriesId);
|
||||
if (historySeries != null){
|
||||
historySeries.HistorySeriesAddDate ??= DateTime.Now;
|
||||
|
||||
var historySeason = historySeries.Seasons.FirstOrDefault(s => s.SeasonId == firstEpisode.SeasonId);
|
||||
|
||||
await RefreshSeriesData(seriesId, historySeries);
|
||||
|
||||
var historySeason = historySeries.Seasons.FirstOrDefault(s => s.SeasonId == firstEpisode.SeasonId);
|
||||
|
||||
if (historySeason != null){
|
||||
historySeason.SeasonTitle = firstEpisode.SeasonTitle;
|
||||
historySeason.SeasonNum = Helpers.ExtractNumberAfterS(firstEpisode.Identifier) ?? firstEpisode.SeasonNumber + "";
|
||||
historySeason.SpecialSeason = CheckStringForSpecial(firstEpisode.Identifier);
|
||||
foreach (var crunchyEpisode in seasonData.Data){
|
||||
foreach (var crunchyEpisode in episodeList){
|
||||
var historyEpisode = historySeason.EpisodesList.Find(e => e.EpisodeId == crunchyEpisode.Id);
|
||||
|
||||
if (historyEpisode == null){
|
||||
var newHistoryEpisode = new HistoryEpisode{
|
||||
EpisodeTitle = crunchyEpisode.Identifier.Contains("|M|") ? crunchyEpisode.SeasonTitle : crunchyEpisode.Title,
|
||||
EpisodeTitle = GetEpisodeTitle(crunchyEpisode),
|
||||
EpisodeDescription = crunchyEpisode.Description,
|
||||
EpisodeId = crunchyEpisode.Id,
|
||||
Episode = crunchyEpisode.Episode,
|
||||
|
@ -332,7 +254,7 @@ public class History(){
|
|||
historySeason.EpisodesList.Add(newHistoryEpisode);
|
||||
} else{
|
||||
//Update existing episode
|
||||
historyEpisode.EpisodeTitle = crunchyEpisode.Identifier.Contains("|M|") ? crunchyEpisode.SeasonTitle : crunchyEpisode.Title;
|
||||
historyEpisode.EpisodeTitle = GetEpisodeTitle(crunchyEpisode);
|
||||
historyEpisode.SpecialEpisode = !int.TryParse(crunchyEpisode.Episode, out _);
|
||||
historyEpisode.EpisodeDescription = crunchyEpisode.Description;
|
||||
historyEpisode.EpisodeId = crunchyEpisode.Id;
|
||||
|
@ -343,7 +265,7 @@ public class History(){
|
|||
|
||||
historySeason.EpisodesList.Sort(new NumericStringPropertyComparer());
|
||||
} else{
|
||||
var newSeason = NewHistorySeason(seasonData, firstEpisode);
|
||||
var newSeason = NewHistorySeason(episodeList, firstEpisode);
|
||||
|
||||
newSeason.EpisodesList.Sort(new NumericStringPropertyComparer());
|
||||
|
||||
|
@ -361,7 +283,7 @@ public class History(){
|
|||
};
|
||||
crunInstance.HistoryList.Add(historySeries);
|
||||
|
||||
var newSeason = NewHistorySeason(seasonData, firstEpisode);
|
||||
var newSeason = NewHistorySeason(episodeList, firstEpisode);
|
||||
|
||||
newSeason.EpisodesList.Sort(new NumericStringPropertyComparer());
|
||||
|
||||
|
@ -381,6 +303,34 @@ public class History(){
|
|||
|
||||
private CrSeriesBase? cachedSeries;
|
||||
|
||||
private string GetEpisodeTitle(CrunchyEpisode crunchyEpisode){
|
||||
if (crunchyEpisode.Identifier.Contains("|M|")){
|
||||
if (string.IsNullOrEmpty(crunchyEpisode.Title)){
|
||||
if (crunchyEpisode.SeasonTitle.StartsWith(crunchyEpisode.SeriesTitle)){
|
||||
var splitTitle = crunchyEpisode.SeasonTitle.Split(new[]{ crunchyEpisode.SeriesTitle }, StringSplitOptions.None);
|
||||
var titlePart = splitTitle.Length > 1 ? splitTitle[1] : splitTitle[0];
|
||||
var cleanedTitle = Regex.Replace(titlePart, @"^[^a-zA-Z]+", "");
|
||||
|
||||
return cleanedTitle;
|
||||
}
|
||||
|
||||
return crunchyEpisode.SeasonTitle;
|
||||
}
|
||||
|
||||
if (crunchyEpisode.Title.StartsWith(crunchyEpisode.SeriesTitle)){
|
||||
var splitTitle = crunchyEpisode.Title.Split(new[]{ crunchyEpisode.SeriesTitle }, StringSplitOptions.None);
|
||||
var titlePart = splitTitle.Length > 1 ? splitTitle[1] : splitTitle[0];
|
||||
var cleanedTitle = Regex.Replace(titlePart, @"^[^a-zA-Z]+", "");
|
||||
|
||||
return cleanedTitle;
|
||||
}
|
||||
|
||||
return crunchyEpisode.Title;
|
||||
}
|
||||
|
||||
return crunchyEpisode.Title;
|
||||
}
|
||||
|
||||
private async Task RefreshSeriesData(string seriesId, HistorySeries historySeries){
|
||||
if (cachedSeries == null || (cachedSeries.Data != null && cachedSeries.Data.First().Id != seriesId)){
|
||||
cachedSeries = await crunInstance.CrSeries.SeriesById(seriesId, string.IsNullOrEmpty(crunInstance.CrunOptions.HistoryLang) ? crunInstance.DefaultLocale : crunInstance.CrunOptions.HistoryLang, true);
|
||||
|
@ -418,7 +368,7 @@ public class History(){
|
|||
public void SortItems(){
|
||||
var currentSortingType = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties?.SelectedSorting ?? SortingType.SeriesTitle;
|
||||
var sortingDir = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null && CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
|
||||
DateTime today = DateTime.UtcNow.Date;
|
||||
DateTime today = DateTime.Now.Date;
|
||||
switch (currentSortingType){
|
||||
case SortingType.SeriesTitle:
|
||||
var sortedList = sortingDir
|
||||
|
@ -479,7 +429,7 @@ public class History(){
|
|||
}
|
||||
}
|
||||
|
||||
public static DateTime? ParseDate(string dateStr, DateTime today){
|
||||
public DateTime? ParseDate(string dateStr, DateTime today){
|
||||
if (dateStr == "Today"){
|
||||
return today;
|
||||
}
|
||||
|
@ -502,7 +452,7 @@ public class History(){
|
|||
return "";
|
||||
}
|
||||
|
||||
private static bool CheckStringForSpecial(string identifier){
|
||||
private bool CheckStringForSpecial(string identifier){
|
||||
if (string.IsNullOrEmpty(identifier)){
|
||||
return false;
|
||||
}
|
||||
|
@ -514,7 +464,7 @@ public class History(){
|
|||
return Regex.IsMatch(identifier, pattern);
|
||||
}
|
||||
|
||||
private static HistorySeason NewHistorySeason(CrunchyEpisodeList seasonData, CrunchyEpisode firstEpisode){
|
||||
private HistorySeason NewHistorySeason(List<CrunchyEpisode> seasonData, CrunchyEpisode firstEpisode){
|
||||
var newSeason = new HistorySeason{
|
||||
SeasonTitle = firstEpisode.SeasonTitle,
|
||||
SeasonId = firstEpisode.SeasonId,
|
||||
|
@ -523,9 +473,9 @@ public class History(){
|
|||
SpecialSeason = CheckStringForSpecial(firstEpisode.Identifier)
|
||||
};
|
||||
|
||||
foreach (var crunchyEpisode in seasonData.Data!){
|
||||
foreach (var crunchyEpisode in seasonData){
|
||||
var newHistoryEpisode = new HistoryEpisode{
|
||||
EpisodeTitle = crunchyEpisode.Identifier.Contains("|M|") ? crunchyEpisode.SeasonTitle : crunchyEpisode.Title,
|
||||
EpisodeTitle = GetEpisodeTitle(crunchyEpisode),
|
||||
EpisodeDescription = crunchyEpisode.Description,
|
||||
EpisodeId = crunchyEpisode.Id,
|
||||
Episode = crunchyEpisode.Episode,
|
||||
|
@ -539,30 +489,7 @@ public class History(){
|
|||
return newSeason;
|
||||
}
|
||||
|
||||
private static HistorySeason NewHistorySeason(CrunchyEpisode episode){
|
||||
var newSeason = new HistorySeason{
|
||||
SeasonTitle = episode.SeasonTitle,
|
||||
SeasonId = episode.SeasonId,
|
||||
SeasonNum = Helpers.ExtractNumberAfterS(episode.Identifier) ?? episode.SeasonNumber + "",
|
||||
EpisodesList =[],
|
||||
};
|
||||
|
||||
var newHistoryEpisode = new HistoryEpisode{
|
||||
EpisodeTitle = episode.Identifier.Contains("|M|") ? episode.SeasonTitle : episode.Title,
|
||||
EpisodeDescription = episode.Description,
|
||||
EpisodeId = episode.Id,
|
||||
Episode = episode.Episode,
|
||||
EpisodeSeasonNum = Helpers.ExtractNumberAfterS(episode.Identifier) ?? episode.SeasonNumber + "",
|
||||
SpecialEpisode = !int.TryParse(episode.Episode, out _),
|
||||
};
|
||||
|
||||
newSeason.EpisodesList.Add(newHistoryEpisode);
|
||||
|
||||
|
||||
return newSeason;
|
||||
}
|
||||
|
||||
public async void MatchHistorySeriesWithSonarr(bool updateAll){
|
||||
public void MatchHistorySeriesWithSonarr(bool updateAll){
|
||||
if (crunInstance.CrunOptions.SonarrProperties is{ SonarrEnabled: false }){
|
||||
return;
|
||||
}
|
||||
|
@ -604,7 +531,7 @@ public class History(){
|
|||
// Create a copy of the episodes list for each thread
|
||||
var episodesCopy = new List<SonarrEpisode>(episodes);
|
||||
|
||||
var episode = FindClosestMatchEpisodes(episodesCopy, historyEpisode.EpisodeTitle);
|
||||
var episode = FindClosestMatchEpisodes(episodesCopy, historyEpisode.EpisodeTitle ?? string.Empty);
|
||||
if (episode != null){
|
||||
historyEpisode.SonarrEpisodeId = episode.Id + "";
|
||||
historyEpisode.SonarrEpisodeNumber = episode.EpisodeNumber + "";
|
||||
|
|
|
@ -22,6 +22,7 @@ public class CfgManager{
|
|||
public static readonly string PathCrToken = WorkingDirectory + "/config/cr_token.yml";
|
||||
public static readonly string PathCrDownloadOptions = WorkingDirectory + "/config/settings.yml";
|
||||
public static readonly string PathCrHistory = WorkingDirectory + "/config/history.json";
|
||||
public static readonly string PathWindowSettings= WorkingDirectory + "/config/windowSettings.json";
|
||||
|
||||
public static readonly string PathFFMPEG = WorkingDirectory + "/lib/ffmpeg.exe";
|
||||
public static readonly string PathMKVMERGE = WorkingDirectory + "/lib/mkvmerge.exe";
|
||||
|
|
|
@ -322,7 +322,7 @@ public class HistorySeries : INotifyPropertyChanged{
|
|||
await CrunchyrollManager.Instance.History.CRUpdateSeries(SeriesId, seasonId);
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SeriesTitle)));
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SeriesDescription)));
|
||||
CrunchyrollManager.Instance.History.MatchHistoryEpisodesWithSonarr(false, this);
|
||||
// CrunchyrollManager.Instance.History.MatchHistoryEpisodesWithSonarr(false, this);
|
||||
UpdateNewEpisodes();
|
||||
FetchingData = false;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FetchingData)));
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CRD.Views;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CRD.Utils.Structs;
|
||||
|
@ -98,3 +100,29 @@ public class FrameData{
|
|||
public class StringItem{
|
||||
public string stringValue{ get; set; }
|
||||
}
|
||||
|
||||
public class WindowSettings{
|
||||
public double Width{ get; set; }
|
||||
public double Height{ get; set; }
|
||||
public int ScreenIndex{ get; set; }
|
||||
public int PosX{ get; set; }
|
||||
public int PosY{ get; set; }
|
||||
}
|
||||
|
||||
public class ToastMessage(string message, ToastType type, int i){
|
||||
public string? Message{ get; set; } = message;
|
||||
public int Seconds{ get; set; } = i;
|
||||
public ToastType Type{ get; set; } = type;
|
||||
}
|
||||
|
||||
public class NavigationMessage{
|
||||
public Type? ViewModelType{ get; }
|
||||
public bool Back{ get; }
|
||||
public bool Refresh{ get; }
|
||||
|
||||
public NavigationMessage(Type? viewModelType, bool back, bool refresh){
|
||||
ViewModelType = viewModelType;
|
||||
Back = back;
|
||||
Refresh = refresh;
|
||||
}
|
||||
}
|
|
@ -30,18 +30,28 @@ public partial class AccountPageViewModel : ViewModelBase{
|
|||
|
||||
private static DispatcherTimer? _timer;
|
||||
private DateTime _targetTime;
|
||||
|
||||
private bool IsCancelled = false;
|
||||
private bool UnknownEndDate = false;
|
||||
private bool EndedButMaybeActive = false;
|
||||
|
||||
public AccountPageViewModel(){
|
||||
UpdatetProfile();
|
||||
}
|
||||
|
||||
private void Timer_Tick(object sender, EventArgs e){
|
||||
var remaining = _targetTime - DateTime.UtcNow;
|
||||
var remaining = _targetTime - DateTime.Now;
|
||||
if (remaining <= TimeSpan.Zero){
|
||||
RemainingTime = "No active Subscription";
|
||||
_timer.Stop();
|
||||
if (UnknownEndDate){
|
||||
RemainingTime = "Unknown Subscription end date";
|
||||
}
|
||||
|
||||
if (EndedButMaybeActive){
|
||||
RemainingTime = "Subscription maybe ended";
|
||||
}
|
||||
|
||||
if (CrunchyrollManager.Instance.Profile.Subscription != null){
|
||||
Console.Error.WriteLine(JsonConvert.SerializeObject(CrunchyrollManager.Instance.Profile.Subscription, Formatting.Indented));
|
||||
}
|
||||
|
@ -51,25 +61,26 @@ public partial class AccountPageViewModel : ViewModelBase{
|
|||
}
|
||||
|
||||
public void UpdatetProfile(){
|
||||
ProfileName = CrunchyrollManager.Instance.Profile.Username; // Default or fetched user name
|
||||
ProfileName = CrunchyrollManager.Instance.Profile.Username ?? "???"; // Default or fetched user name
|
||||
LoginLogoutText = CrunchyrollManager.Instance.Profile.Username == "???" ? "Login" : "Logout"; // Default state
|
||||
LoadProfileImage("https://static.crunchyroll.com/assets/avatar/170x170/" + CrunchyrollManager.Instance.Profile.Avatar);
|
||||
|
||||
|
||||
if (CrunchyrollManager.Instance.Profile.Subscription != null && CrunchyrollManager.Instance.Profile.Subscription?.SubscriptionProducts != null){
|
||||
if (CrunchyrollManager.Instance.Profile.Subscription?.SubscriptionProducts.Count >= 1){
|
||||
var sub = CrunchyrollManager.Instance.Profile.Subscription?.SubscriptionProducts.First();
|
||||
if (sub != null){
|
||||
var subscriptions = CrunchyrollManager.Instance.Profile.Subscription;
|
||||
|
||||
if (subscriptions != null){
|
||||
if (subscriptions.SubscriptionProducts is{ Count: >= 1 }){
|
||||
var sub = subscriptions.SubscriptionProducts.First();
|
||||
IsCancelled = sub.IsCancelled;
|
||||
}
|
||||
}else if (CrunchyrollManager.Instance.Profile.Subscription?.ThirdPartySubscriptionProducts.Count >= 1){
|
||||
var sub = CrunchyrollManager.Instance.Profile.Subscription?.ThirdPartySubscriptionProducts.First();
|
||||
if (sub != null){
|
||||
EndedButMaybeActive = !subscriptions.IsActive;
|
||||
} else if (subscriptions.ThirdPartySubscriptionProducts is{ Count: >= 1 }){
|
||||
var sub = subscriptions.ThirdPartySubscriptionProducts.First();
|
||||
IsCancelled = !sub.AutoRenew;
|
||||
}
|
||||
}else if(CrunchyrollManager.Instance.Profile.Subscription?.NonrecurringSubscriptionProducts.Count >= 1){
|
||||
EndedButMaybeActive = !subscriptions.IsActive;
|
||||
} else if (subscriptions.NonrecurringSubscriptionProducts is{ Count: >= 1 }){
|
||||
IsCancelled = true;
|
||||
}else if(CrunchyrollManager.Instance.Profile.Subscription?.FunimationSubscriptions.Count >= 1){
|
||||
EndedButMaybeActive = !subscriptions.IsActive;
|
||||
} else if (subscriptions.FunimationSubscriptions is{ Count: >= 1 }){
|
||||
IsCancelled = true;
|
||||
UnknownEndDate = true;
|
||||
}
|
||||
|
@ -82,24 +93,27 @@ public partial class AccountPageViewModel : ViewModelBase{
|
|||
_timer.Tick += Timer_Tick;
|
||||
_timer.Start();
|
||||
}
|
||||
|
||||
} else{
|
||||
RemainingTime = "No active Subscription";
|
||||
if (_timer != null){
|
||||
_timer.Stop();
|
||||
_timer.Tick -= Timer_Tick;
|
||||
}
|
||||
|
||||
RaisePropertyChanged(nameof(RemainingTime));
|
||||
|
||||
if (CrunchyrollManager.Instance.Profile.Subscription != null){
|
||||
Console.Error.WriteLine(JsonConvert.SerializeObject(CrunchyrollManager.Instance.Profile.Subscription, Formatting.Indented));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (UnknownEndDate){
|
||||
RemainingTime = "Unknown Subscription end date";
|
||||
}
|
||||
|
||||
if (EndedButMaybeActive){
|
||||
RemainingTime = "Subscription maybe ended";
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Platform;
|
||||
using CRD.Utils;
|
||||
using CRD.Utils.Structs;
|
||||
using CRD.Utils.Updater;
|
||||
using CRD.ViewModels;
|
||||
using CRD.Views;
|
||||
using CRD.Views.Utils;
|
||||
using FluentAvalonia.Core;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using FluentAvalonia.UI.Windowing;
|
||||
using Newtonsoft.Json;
|
||||
using ReactiveUI;
|
||||
using ContentDialogUpdateViewModel = CRD.ViewModels.Utils.ContentDialogUpdateViewModel;
|
||||
|
||||
|
@ -45,6 +52,9 @@ public partial class MainWindow : AppWindow{
|
|||
AvaloniaXamlLoader.Load(this);
|
||||
InitializeComponent();
|
||||
|
||||
Opened += OnOpened;
|
||||
Closing += OnClosing;
|
||||
|
||||
TitleBar.ExtendsContentIntoTitleBar = true;
|
||||
TitleBar.TitleBarHitTestType = TitleBarHitTestType.Complex;
|
||||
|
||||
|
@ -62,6 +72,7 @@ public partial class MainWindow : AppWindow{
|
|||
if (viewModel is SeriesPageViewModel){
|
||||
((SeriesPageViewModel)viewModel).SetStorageProvider(StorageProvider);
|
||||
}
|
||||
|
||||
navigationStack.Push(viewModel);
|
||||
nv.Content = viewModel;
|
||||
} else if (!message.Back && message.ViewModelType != null){
|
||||
|
@ -69,6 +80,7 @@ public partial class MainWindow : AppWindow{
|
|||
if (viewModel is SeriesPageViewModel){
|
||||
((SeriesPageViewModel)viewModel).SetStorageProvider(StorageProvider);
|
||||
}
|
||||
|
||||
navigationStack.Push(viewModel);
|
||||
nv.Content = viewModel;
|
||||
} else{
|
||||
|
@ -117,9 +129,10 @@ public partial class MainWindow : AppWindow{
|
|||
break;
|
||||
case "History":
|
||||
navView.Content = Activator.CreateInstance(typeof(HistoryPageViewModel));
|
||||
if ( navView.Content is HistoryPageViewModel){
|
||||
if (navView.Content is HistoryPageViewModel){
|
||||
((HistoryPageViewModel)navView.Content).SetStorageProvider(StorageProvider);
|
||||
}
|
||||
|
||||
navigationStack.Clear();
|
||||
navigationStack.Push(navView.Content);
|
||||
selectedNavVieItem = selectedItem;
|
||||
|
@ -159,22 +172,55 @@ public partial class MainWindow : AppWindow{
|
|||
|
||||
_ = await dialog.ShowAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public class ToastMessage(string message, ToastType type, int i){
|
||||
public string? Message{ get; set; } = message;
|
||||
public int Seconds{ get; set; } = i;
|
||||
public ToastType Type{ get; set; } = type;
|
||||
}
|
||||
private void OnOpened(object sender, EventArgs e){
|
||||
if (File.Exists(CfgManager.PathWindowSettings)){
|
||||
var settings = JsonConvert.DeserializeObject<WindowSettings>(File.ReadAllText(CfgManager.PathWindowSettings));
|
||||
if (settings != null){
|
||||
Width = settings.Width;
|
||||
Height = settings.Height;
|
||||
|
||||
public class NavigationMessage{
|
||||
public Type? ViewModelType{ get; }
|
||||
public bool Back{ get; }
|
||||
public bool Refresh{ get; }
|
||||
var screens = Screens.All;
|
||||
if (settings.ScreenIndex >= 0 && settings.ScreenIndex < screens.Count){
|
||||
var screen = screens[settings.ScreenIndex];
|
||||
var screenBounds = screen.Bounds;
|
||||
|
||||
public NavigationMessage(Type? viewModelType, bool back, bool refresh){
|
||||
ViewModelType = viewModelType;
|
||||
Back = back;
|
||||
Refresh = refresh;
|
||||
var topLeft = screenBounds.TopLeft;
|
||||
var bottomRight = screenBounds.BottomRight;
|
||||
|
||||
if (settings.PosX >= topLeft.X && settings.PosX <= bottomRight.X - Width &&
|
||||
settings.PosY >= topLeft.Y && settings.PosY <= bottomRight.Y - Height){
|
||||
Position = new PixelPoint(settings.PosX, settings.PosY);
|
||||
} else{
|
||||
Position = new PixelPoint(topLeft.X, topLeft.Y + 31);
|
||||
}
|
||||
} else{
|
||||
var primaryScreen = screens?[0].Bounds ?? new PixelRect(0, 0, 1000, 600); // Default size if no screens
|
||||
Position = new PixelPoint(primaryScreen.TopLeft.X, primaryScreen.TopLeft.Y + 31);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e){
|
||||
var screens = Screens.All;
|
||||
int screenIndex = 0;
|
||||
|
||||
for (int i = 0; i < screens.Count; i++){
|
||||
if (screens[i].Bounds.Contains(Position)){
|
||||
screenIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var settings = new WindowSettings{
|
||||
Width = Width,
|
||||
Height = Height,
|
||||
ScreenIndex = screenIndex,
|
||||
PosX = Position.X,
|
||||
PosY = Position.Y
|
||||
};
|
||||
|
||||
File.WriteAllText(CfgManager.PathWindowSettings, JsonConvert.SerializeObject(settings, Formatting.Indented));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue