2024-06-19 00:16:02 +00:00
using System ;
2024-05-04 15:35:32 +00:00
using System.Collections.Generic ;
using System.Collections.Specialized ;
2024-05-26 00:27:31 +00:00
using System.Globalization ;
2024-05-04 15:35:32 +00:00
using System.Linq ;
using System.Net.Http ;
using System.Text.RegularExpressions ;
using System.Threading.Tasks ;
using System.Web ;
2024-06-21 01:49:44 +00:00
using Avalonia.Remote.Protocol.Input ;
2024-05-04 15:35:32 +00:00
using CRD.Utils ;
using CRD.Utils.Structs ;
using Newtonsoft.Json ;
namespace CRD.Downloader ;
2024-05-25 22:02:45 +00:00
public class CrEpisode ( ) {
private readonly Crunchyroll crunInstance = Crunchyroll . Instance ;
2024-06-21 01:49:44 +00:00
2024-06-27 20:52:12 +00:00
public async Task < CrunchyEpisode ? > ParseEpisodeById ( string id , string crLocale , bool forcedLang = false ) {
2024-05-04 15:35:32 +00:00
if ( crunInstance . CmsToken ? . Cms = = null ) {
2024-06-19 00:16:02 +00:00
Console . Error . WriteLine ( "Missing CMS Access Token" ) ;
2024-05-04 15:35:32 +00:00
return null ;
}
NameValueCollection query = HttpUtility . ParseQueryString ( new UriBuilder ( ) . Query ) ;
2024-06-27 20:52:12 +00:00
2024-05-04 15:35:32 +00:00
query [ "preferred_audio_language" ] = "ja-JP" ;
2024-06-27 20:52:12 +00:00
if ( ! string . IsNullOrEmpty ( crLocale ) ) {
query [ "locale" ] = crLocale ;
if ( forcedLang ) {
query [ "force_locale" ] = crLocale ;
}
}
2024-05-04 15:35:32 +00:00
var request = HttpClientReq . CreateRequestMessage ( $"{Api.Cms}/episodes/{id}" , HttpMethod . Get , true , true , query ) ;
var response = await HttpClientReq . Instance . SendHttpRequest ( request ) ;
if ( ! response . IsOk ) {
2024-06-19 00:16:02 +00:00
Console . Error . WriteLine ( "Series Request Failed" ) ;
2024-05-04 15:35:32 +00:00
return null ;
}
CrunchyEpisodeList epsidoe = Helpers . Deserialize < CrunchyEpisodeList > ( response . ResponseContent , crunInstance . SettingsJsonSerializerSettings ) ;
if ( epsidoe . Total < 1 ) {
return null ;
}
2024-06-21 01:49:44 +00:00
if ( epsidoe . Total = = 1 & & epsidoe . Data ! = null ) {
return epsidoe . Data . First ( ) ;
}
Console . Error . WriteLine ( "Multiple episodes returned with one ID?" ) ;
if ( epsidoe . Data ! = null ) return epsidoe . Data . First ( ) ;
return null ;
2024-05-04 15:35:32 +00:00
}
2024-06-28 03:28:45 +00:00
public async Task < CrunchyRollEpisodeData > EpisodeData ( CrunchyEpisode dlEpisode , bool updateHistory = false ) {
2024-05-04 15:35:32 +00:00
bool serieshasversions = true ;
2024-06-21 01:49:44 +00:00
// Dictionary<string, EpisodeAndLanguage> episodes = new Dictionary<string, EpisodeAndLanguage>();
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
CrunchyRollEpisodeData episode = new CrunchyRollEpisodeData ( ) ;
2024-06-28 03:28:45 +00:00
if ( crunInstance . CrunOptions . History & & updateHistory ) {
2024-06-21 01:49:44 +00:00
await crunInstance . CrHistory . UpdateWithEpisode ( dlEpisode ) ;
}
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
var seasonIdentifier = ! string . IsNullOrEmpty ( dlEpisode . Identifier ) ? dlEpisode . Identifier . Split ( '|' ) [ 1 ] : $"S{dlEpisode.SeasonNumber}" ;
episode . Key = $"{seasonIdentifier}E{dlEpisode.Episode ?? (dlEpisode.EpisodeNumber + "")}" ;
episode . EpisodeAndLanguages = new EpisodeAndLanguage {
Items = new List < CrunchyEpisode > ( ) ,
Langs = new List < LanguageItem > ( )
} ;
if ( dlEpisode . Versions ! = null ) {
foreach ( var version in dlEpisode . Versions ) {
// Ensure there is only one of the same language
if ( episode . EpisodeAndLanguages . Langs . All ( a = > a . CrLocale ! = version . AudioLocale ) ) {
// Push to arrays if there are no duplicates of the same language
episode . EpisodeAndLanguages . Items . Add ( dlEpisode ) ;
episode . EpisodeAndLanguages . Langs . Add ( Array . Find ( Languages . languages , a = > a . CrLocale = = version . AudioLocale ) ) ;
2024-05-04 15:35:32 +00:00
}
}
2024-06-21 01:49:44 +00:00
} else {
// Episode didn't have versions, mark it as such to be logged.
serieshasversions = false ;
// Ensure there is only one of the same language
if ( episode . EpisodeAndLanguages . Langs . All ( a = > a . CrLocale ! = dlEpisode . AudioLocale ) ) {
// Push to arrays if there are no duplicates of the same language
episode . EpisodeAndLanguages . Items . Add ( dlEpisode ) ;
episode . EpisodeAndLanguages . Langs . Add ( Array . Find ( Languages . languages , a = > a . CrLocale = = dlEpisode . AudioLocale ) ) ;
}
2024-05-04 15:35:32 +00:00
}
2024-06-21 01:49:44 +00:00
2024-05-04 15:35:32 +00:00
int specialIndex = 1 ;
int epIndex = 1 ;
2024-06-21 01:49:44 +00:00
var isSpecial = ! Regex . IsMatch ( episode . EpisodeAndLanguages . Items [ 0 ] . Episode ? ? string . Empty , @"^\d+$" ) ; // Checking if the episode is not a number (i.e., special).
string newKey ;
if ( isSpecial & & ! string . IsNullOrEmpty ( episode . EpisodeAndLanguages . Items [ 0 ] . Episode ) ) {
newKey = episode . EpisodeAndLanguages . Items [ 0 ] . Episode ? ? "SP" + ( specialIndex + " " + episode . EpisodeAndLanguages . Items [ 0 ] . Id ) ;
} else {
newKey = $"{(isSpecial ? " SP " : 'E')}{(isSpecial ? (specialIndex + " " + episode.EpisodeAndLanguages.Items[0].Id) : episode.EpisodeAndLanguages.Items[0].Episode ?? epIndex + " ")}" ;
2024-05-04 15:35:32 +00:00
}
2024-06-21 01:49:44 +00:00
episode . Key = newKey ;
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
var seasonTitle = episode . EpisodeAndLanguages . Items . FirstOrDefault ( a = > ! Regex . IsMatch ( a . SeasonTitle , @"\(\w+ Dub\)" ) ) . SeasonTitle
? ? Regex . Replace ( episode . EpisodeAndLanguages . Items [ 0 ] . SeasonTitle , @"\(\w+ Dub\)" , "" ) . TrimEnd ( ) ;
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
var title = episode . EpisodeAndLanguages . Items [ 0 ] . Title ;
var seasonNumber = Helpers . ExtractNumberAfterS ( episode . EpisodeAndLanguages . Items [ 0 ] . Identifier ) ? ? episode . EpisodeAndLanguages . Items [ 0 ] . SeasonNumber . ToString ( ) ;
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
var languages = episode . EpisodeAndLanguages . Items . Select ( ( a , index ) = >
$"{(a.IsPremiumOnly ? " + " : " ")}{episode.EpisodeAndLanguages.Langs.ElementAtOrDefault(index).Name ?? " Unknown "}" ) . ToArray ( ) ; //☆
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
Console . WriteLine ( $"[{episode.Key}] {seasonTitle} - Season {seasonNumber} - {title} [{string.Join(" , ", languages)}]" ) ;
2024-05-04 15:35:32 +00:00
if ( ! serieshasversions ) {
2024-06-21 01:49:44 +00:00
Console . WriteLine ( "Couldn\'t find versions on episode, fell back to old method." ) ;
2024-05-04 15:35:32 +00:00
}
2024-06-21 01:49:44 +00:00
// crunchySeriesList.Data = sortedEpisodes;
/ /
/ /
// var images = (episode.EpisodeAndLanguages.Items[0].Images?.Thumbnail ?? new List<List<Image>>{ new List<Image>{ new Image{ Source = "/notFound.png" } } });
// var seconds = (int)Math.Floor(episode.EpisodeAndLanguages.Items[0].DurationMs / 1000.0);
/ /
// var newEpisode = new Episode{
// E = episode.Key.StartsWith("E") ? episode.Key.Substring(1) : episode.Key,
// Lang = episode.EpisodeAndLanguages.Langs.Select(a => a.Code).ToList(),
// Name = episode.EpisodeAndLanguages.Items[0].Title,
// Season = Helpers.ExtractNumberAfterS(episode.EpisodeAndLanguages.Items[0].Identifier) ?? episode.EpisodeAndLanguages.Items[0].SeasonNumber.ToString(),
// SeriesTitle = Regex.Replace(episode.EpisodeAndLanguages.Items[0].SeriesTitle, @"\(\w+ Dub\)", "").TrimEnd(),
// SeasonTitle = Regex.Replace(episode.EpisodeAndLanguages.Items[0].SeasonTitle, @"\(\w+ Dub\)", "").TrimEnd(),
// EpisodeNum = episode.EpisodeAndLanguages.Items[0].EpisodeNumber?.ToString() ?? episode.EpisodeAndLanguages.Items[0].Episode ?? "?",
// Id = episode.EpisodeAndLanguages.Items[0].SeasonId,
// Img = images[images.Count / 2].FirstOrDefault().Source,
// Description = episode.EpisodeAndLanguages.Items[0].Description,
// Time = $"{seconds / 60}:{seconds % 60:D2}" // Ensures two digits for seconds.
// };
/ /
// CrunchySeriesList crunchySeriesList = new CrunchySeriesList();
return episode ;
2024-05-04 15:35:32 +00:00
}
2024-06-21 01:49:44 +00:00
public CrunchyEpMeta EpisodeMeta ( CrunchyRollEpisodeData episodeP , List < string > dubLang ) {
// var ret = new Dictionary<string, CrunchyEpMeta>();
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
var retMeta = new CrunchyEpMeta ( ) ;
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
for ( int index = 0 ; index < episodeP . EpisodeAndLanguages . Items . Count ; index + + ) {
var item = episodeP . EpisodeAndLanguages . Items [ index ] ;
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
if ( ! dubLang . Contains ( episodeP . EpisodeAndLanguages . Langs [ index ] . CrLocale ) )
continue ;
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
item . HideSeasonTitle = true ;
if ( string . IsNullOrEmpty ( item . SeasonTitle ) & & ! string . IsNullOrEmpty ( item . SeriesTitle ) ) {
item . SeasonTitle = item . SeriesTitle ;
item . HideSeasonTitle = false ;
item . HideSeasonNumber = true ;
}
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
if ( string . IsNullOrEmpty ( item . SeasonTitle ) & & string . IsNullOrEmpty ( item . SeriesTitle ) ) {
item . SeasonTitle = "NO_TITLE" ;
item . SeriesTitle = "NO_TITLE" ;
}
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
var epNum = episodeP . Key . StartsWith ( 'E' ) ? episodeP . Key [ 1. . ] : episodeP . Key ;
var images = ( item . Images ? . Thumbnail ? ? new List < List < Image > > { new List < Image > { new Image { Source = "/notFound.png" } } } ) ;
Regex dubPattern = new Regex ( @"\(\w+ Dub\)" ) ;
var epMeta = new CrunchyEpMeta ( ) ;
epMeta . Data = new List < CrunchyEpMetaData > { new ( ) { MediaId = item . Id , Versions = item . Versions , IsSubbed = item . IsSubbed , IsDubbed = item . IsDubbed } } ;
epMeta . SeriesTitle = episodeP . EpisodeAndLanguages . Items . FirstOrDefault ( a = > ! dubPattern . IsMatch ( a . SeriesTitle ) ) . SeriesTitle ? ? Regex . Replace ( episodeP . EpisodeAndLanguages . Items [ 0 ] . SeriesTitle , @"\(\w+ Dub\)" , "" ) . TrimEnd ( ) ;
epMeta . SeasonTitle = episodeP . EpisodeAndLanguages . Items . FirstOrDefault ( a = > ! dubPattern . IsMatch ( a . SeasonTitle ) ) . SeasonTitle ? ? Regex . Replace ( episodeP . EpisodeAndLanguages . Items [ 0 ] . SeasonTitle , @"\(\w+ Dub\)" , "" ) . TrimEnd ( ) ;
epMeta . EpisodeNumber = item . Episode ;
epMeta . EpisodeTitle = item . Title ;
epMeta . SeasonId = item . SeasonId ;
epMeta . Season = Helpers . ExtractNumberAfterS ( item . Identifier ) ? ? item . SeasonNumber + "" ;
epMeta . ShowId = item . SeriesId ;
epMeta . AbsolutEpisodeNumberE = epNum ;
epMeta . Image = images [ images . Count / 2 ] . FirstOrDefault ( ) . Source ;
epMeta . DownloadProgress = new DownloadProgress ( ) {
IsDownloading = false ,
Done = false ,
Error = false ,
Percent = 0 ,
Time = 0 ,
DownloadSpeed = 0
} ;
epMeta . AvailableSubs = item . SubtitleLocales ;
2024-06-27 20:52:12 +00:00
epMeta . Description = item . Description ;
2024-06-21 01:49:44 +00:00
if ( episodeP . EpisodeAndLanguages . Langs . Count > 0 ) {
epMeta . SelectedDubs = dubLang
. Where ( language = > episodeP . EpisodeAndLanguages . Langs . Any ( epLang = > epLang . CrLocale = = language ) )
. ToList ( ) ;
}
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
var epMetaData = epMeta . Data [ 0 ] ;
if ( ! string . IsNullOrEmpty ( item . StreamsLink ) ) {
epMetaData . Playback = item . StreamsLink ;
if ( string . IsNullOrEmpty ( item . Playback ) ) {
item . Playback = item . StreamsLink ;
2024-05-04 15:35:32 +00:00
}
2024-06-21 01:49:44 +00:00
}
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
if ( retMeta . Data ! = null ) {
epMetaData . Lang = episodeP . EpisodeAndLanguages . Langs [ index ] ;
retMeta . Data . Add ( epMetaData ) ;
} else {
epMetaData . Lang = episodeP . EpisodeAndLanguages . Langs [ index ] ;
epMeta . Data [ 0 ] = epMetaData ;
retMeta = epMeta ;
}
2024-05-04 15:35:32 +00:00
2024-06-21 01:49:44 +00:00
// show ep
item . SeqId = epNum ;
2024-05-04 15:35:32 +00:00
}
2024-06-21 01:49:44 +00:00
return retMeta ;
2024-05-04 15:35:32 +00:00
}
}