Chg - Adjusted HTTP Client to allow the usage of VPN split tunneling https://github.com/Crunchy-DL/Crunchy-Downloader/issues/57

Chg - Adjusted some debug messages
This commit is contained in:
Elwador 2024-08-12 17:10:08 +02:00
parent 3914e98dbb
commit 52369e84dc
5 changed files with 97 additions and 36 deletions

View File

@ -79,7 +79,11 @@ public class CrAuth{
if (response.IsOk){ if (response.IsOk){
JsonTokenToFileAndVariable(response.ResponseContent); JsonTokenToFileAndVariable(response.ResponseContent);
} else{ } else{
MessageBus.Current.SendMessage(new ToastMessage($"Failed to login - {response.ResponseContent.Substring(0,response.ResponseContent.Length < 200 ? response.ResponseContent.Length : 200)}", ToastType.Error, 10)); 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));
}
} }
if (crunInstance.Token?.refresh_token != null){ if (crunInstance.Token?.refresh_token != null){

View File

@ -899,7 +899,7 @@ public class CrunchyrollManager{
tsFile = videoDownloadResult.tsFile; tsFile = videoDownloadResult.tsFile;
if (!videoDownloadResult.Ok){ if (!videoDownloadResult.Ok){
Console.Error.WriteLine($"DL Stats: {JsonConvert.SerializeObject(videoDownloadResult.Parts)}"); Console.Error.WriteLine($"Faild to download video - DL Stats: {JsonConvert.SerializeObject(videoDownloadResult.Parts)}");
dlFailed = true; dlFailed = true;
} }
@ -918,7 +918,7 @@ public class CrunchyrollManager{
tsFile = audioDownloadResult.tsFile; tsFile = audioDownloadResult.tsFile;
if (!audioDownloadResult.Ok){ if (!audioDownloadResult.Ok){
Console.Error.WriteLine($"DL Stats: {JsonConvert.SerializeObject(audioDownloadResult.Parts)}"); Console.Error.WriteLine($"Faild to download audio - DL Stats: {JsonConvert.SerializeObject(audioDownloadResult.Parts)}");
dlFailed = true; dlFailed = true;
} }

View File

@ -3,8 +3,10 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using CRD.Downloader.Crunchyroll; using CRD.Downloader.Crunchyroll;
using CRD.Utils;
using CRD.Utils.CustomList; using CRD.Utils.CustomList;
using CRD.Utils.Structs; using CRD.Utils.Structs;
using CRD.Utils.Structs.History; using CRD.Utils.Structs.History;
@ -142,12 +144,17 @@ public class QueueManager{
} }
selected.DownloadSubs = historyEpisode.sublist.Count > 0 ? historyEpisode.sublist : CrunchyrollManager.Instance.CrunOptions.DlSubs; selected.DownloadSubs = historyEpisode.sublist.Count > 0 ? historyEpisode.sublist : CrunchyrollManager.Instance.CrunOptions.DlSubs;
Queue.Add(selected);
Queue.Add(selected);
if (selected.Data.Count < dubLang.Count){ if (selected.Data.Count < dubLang.Count){
Console.WriteLine("Added Episode to Queue but couldn't find all selected dubs"); Console.WriteLine("Added Episode to Queue but couldn't find all selected dubs");
Console.Error.WriteLine("Added Episode to Queue but couldn't find all selected dubs - Available dubs/subs: ");
var languages = sList.EpisodeAndLanguages.Items.Select((a, index) =>
$"{(a.IsPremiumOnly ? "+ " : "")}{sList.EpisodeAndLanguages.Langs.ElementAtOrDefault(index).CrLocale ?? "Unknown"}").ToArray();
Console.Error.WriteLine($"{selected.SeasonTitle} - Season {selected.Season} - {selected.EpisodeTitle} dubs - [{string.Join(", ", languages)}] subs - [{string.Join(", ", selected.AvailableSubs ?? [])}]");
MessageBus.Current.SendMessage(new ToastMessage($"Added episode to the queue but couldn't find all selected dubs", ToastType.Warning, 2)); MessageBus.Current.SendMessage(new ToastMessage($"Added episode to the queue but couldn't find all selected dubs", ToastType.Warning, 2));
} else{ } else{
Console.WriteLine("Added Episode to Queue"); Console.WriteLine("Added Episode to Queue");
@ -211,9 +218,9 @@ public class QueueManager{
var selected = CrunchyrollManager.Instance.CrSeries.ItemSelectMultiDub(list.Data, data.DubLang, data.But, data.AllEpisodes, data.E); var selected = CrunchyrollManager.Instance.CrSeries.ItemSelectMultiDub(list.Data, data.DubLang, data.But, data.AllEpisodes, data.E);
bool failed = false; bool failed = false;
foreach (var crunchyEpMeta in selected.Values.ToList()){ foreach (var crunchyEpMeta in selected.Values.ToList()){
if (crunchyEpMeta.Data?.First().Playback != null){ if (crunchyEpMeta.Data?.First() != null){
if (CrunchyrollManager.Instance.CrunOptions.History){ if (CrunchyrollManager.Instance.CrunOptions.History){
var historyEpisode = CrunchyrollManager.Instance.History.GetHistoryEpisodeWithDownloadDir(crunchyEpMeta.ShowId, crunchyEpMeta.SeasonId, crunchyEpMeta.Data.First().MediaId); var historyEpisode = CrunchyrollManager.Instance.History.GetHistoryEpisodeWithDownloadDir(crunchyEpMeta.ShowId, crunchyEpMeta.SeasonId, crunchyEpMeta.Data.First().MediaId);
if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties is{ SonarrEnabled: true, UseSonarrNumbering: true }){ if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties is{ SonarrEnabled: true, UseSonarrNumbering: true }){
@ -243,8 +250,8 @@ public class QueueManager{
var subLangList = CrunchyrollManager.Instance.History.GetSubList(crunchyEpMeta.ShowId, crunchyEpMeta.SeasonId); var subLangList = CrunchyrollManager.Instance.History.GetSubList(crunchyEpMeta.ShowId, crunchyEpMeta.SeasonId);
crunchyEpMeta.DownloadSubs = subLangList.Count > 0 ? subLangList : CrunchyrollManager.Instance.CrunOptions.DlSubs; crunchyEpMeta.DownloadSubs = subLangList.Count > 0 ? subLangList : CrunchyrollManager.Instance.CrunOptions.DlSubs;
Queue.Add(crunchyEpMeta); Queue.Add(crunchyEpMeta);
} else{ } else{
failed = true; failed = true;

View File

@ -4,6 +4,8 @@ using System.Net.Http;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using CRD.Downloader; using CRD.Downloader;
using CRD.Downloader.Crunchyroll; using CRD.Downloader.Crunchyroll;
@ -34,49 +36,75 @@ public class HttpClientReq{
private HttpClient client; private HttpClient client;
private HttpClientHandler handler; private Dictionary<string, CookieCollection> cookieStore;
public HttpClientReq(){ public HttpClientReq(){
// Initialize the HttpClientHandler cookieStore = new Dictionary<string, CookieCollection>();
handler = new HttpClientHandler();
handler.CookieContainer = new CookieContainer(); client = new HttpClient(CreateHttpClientHandler());
handler.UseCookies = true;
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli;
// Initialize the HttpClient with the handler
client = new HttpClient(handler);
// client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0"); // client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0");
client.DefaultRequestHeaders.UserAgent.ParseAdd("Crunchyroll/1.9.0 Nintendo Switch/18.1.0.0 UE4/4.27"); client.DefaultRequestHeaders.UserAgent.ParseAdd("Crunchyroll/1.9.0 Nintendo Switch/18.1.0.0 UE4/4.27");
// client.DefaultRequestHeaders.UserAgent.ParseAdd("Crunchyroll/3.60.0 Android/9 okhttp/4.12.0"); // client.DefaultRequestHeaders.UserAgent.ParseAdd("Crunchyroll/3.60.0 Android/9 okhttp/4.12.0");
} }
public void SetETPCookie(string refresh_token){ private HttpMessageHandler CreateHttpClientHandler(){
var cookie = new Cookie("etp_rt", refresh_token){ return new SocketsHttpHandler(){
Domain = "crunchyroll.com", AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli,
Path = "/", ConnectCallback = async (context, cancellationToken) => {
}; // Resolve IPv4 addresses only
var entry = await Dns.GetHostEntryAsync(context.DnsEndPoint.Host, AddressFamily.InterNetwork, cancellationToken).ConfigureAwait(false);
var cookie2 = new Cookie("c_locale", "en-US"){
Domain = "crunchyroll.com",
Path = "/",
};
handler.CookieContainer.Add(cookie); // Create an IPv4 socket
handler.CookieContainer.Add(cookie2); var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.NoDelay = true;
try{
await socket.ConnectAsync(entry.AddressList, context.DnsEndPoint.Port, cancellationToken).ConfigureAwait(false);
return new NetworkStream(socket, ownsSocket: true);
} catch{
socket.Dispose();
throw;
}
}
};
}
public void SetETPCookie(string refresh_token){
// var cookie = new Cookie("etp_rt", refresh_token){
// Domain = "crunchyroll.com",
// Path = "/",
// };
//
// var cookie2 = new Cookie("c_locale", "en-US"){
// Domain = "crunchyroll.com",
// Path = "/",
// };
AddCookie("crunchyroll.com", new Cookie("etp_rt", refresh_token));
AddCookie("crunchyroll.com", new Cookie("c_locale", "en-US"));
}
private void AddCookie(string domain, Cookie cookie){
if (!cookieStore.ContainsKey(domain)){
cookieStore[domain] = new CookieCollection();
}
cookieStore[domain].Add(cookie);
} }
public async Task<(bool IsOk, string ResponseContent)> SendHttpRequest(HttpRequestMessage request){ public async Task<(bool IsOk, string ResponseContent)> SendHttpRequest(HttpRequestMessage request){
string content = string.Empty; string content = string.Empty;
try{ try{
AttachCookies(request);
HttpResponseMessage response = await client.SendAsync(request); HttpResponseMessage response = await client.SendAsync(request);
content = await response.Content.ReadAsStringAsync(); content = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
return (IsOk: true, ResponseContent: content); return (IsOk: true, ResponseContent: content);
} catch (Exception e){ } catch (Exception e){
// Console.Error.WriteLine($"Error: {e} \n Response: {(content.Length < 500 ? content : "error to long")}"); // Console.Error.WriteLine($"Error: {e} \n Response: {(content.Length < 500 ? content : "error to long")}");
@ -85,6 +113,23 @@ public class HttpClientReq{
} }
} }
private void AttachCookies(HttpRequestMessage request){
if (cookieStore.TryGetValue(request.RequestUri.Host, out CookieCollection cookies)){
var cookieHeader = new StringBuilder();
foreach (Cookie cookie in cookies){
if (cookieHeader.Length > 0){
cookieHeader.Append("; ");
}
cookieHeader.Append($"{cookie.Name}={cookie.Value}");
}
if (cookieHeader.Length > 0){
request.Headers.Add("Cookie", cookieHeader.ToString());
}
}
}
public static HttpRequestMessage CreateRequestMessage(string uri, HttpMethod requestMethod, bool authHeader, bool disableDrmHeader, NameValueCollection? query){ public static HttpRequestMessage CreateRequestMessage(string uri, HttpMethod requestMethod, bool authHeader, bool disableDrmHeader, NameValueCollection? query){
UriBuilder uriBuilder = new UriBuilder(uri); UriBuilder uriBuilder = new UriBuilder(uri);
@ -99,7 +144,6 @@ public class HttpClientReq{
} }
if (disableDrmHeader){ if (disableDrmHeader){
} }
@ -114,7 +158,6 @@ public class HttpClientReq{
public HttpClient GetHttpClient(){ public HttpClient GetHttpClient(){
return client; return client;
} }
} }
public static class Api{ public static class Api{

View File

@ -88,6 +88,13 @@ public partial class AddDownloadPageViewModel : ViewModelBase{
} }
private async Task UpdateSearch(string value){ private async Task UpdateSearch(string value){
if (string.IsNullOrEmpty(value)){
SearchPopupVisible = false;
RaisePropertyChanged(nameof(SearchVisible));
SearchItems.Clear();
return;
}
var searchResults = await CrunchyrollManager.Instance.CrSeries.Search(value, CrunchyrollManager.Instance.CrunOptions.HistoryLang); var searchResults = await CrunchyrollManager.Instance.CrSeries.Search(value, CrunchyrollManager.Instance.CrunOptions.HistoryLang);
var searchItems = searchResults?.Data?.First().Items; var searchItems = searchResults?.Data?.First().Items;