mirror of
https://github.com/Crunchy-DL/Crunchy-Downloader.git
synced 2026-01-11 20:10:26 +00:00
Add - Added **Clear Queue** button https://github.com/Crunchy-DL/Crunchy-Downloader/issues/206
Add - Added **Download Only First Available Dub** option https://github.com/Crunchy-DL/Crunchy-Downloader/issues/207 Add - Added **Mark as Watched** on Download Finish https://github.com/Crunchy-DL/Crunchy-Downloader/issues/216 Chg - Changed **copy state of settings** when an episode is added to the queue https://github.com/Crunchy-DL/Crunchy-Downloader/issues/211 Chg - Changed **updater error handling** https://github.com/Crunchy-DL/Crunchy-Downloader/issues/194 Fix - Fixed **updater on Linux** https://github.com/Crunchy-DL/Crunchy-Downloader/issues/194 Fix - Fixed **subtitle ordering** https://github.com/Crunchy-DL/Crunchy-Downloader/issues/213 Fix - Fixed **muxing passed settings** to apply configurations correctly
This commit is contained in:
parent
06864f51ae
commit
40b7b6d1de
18 changed files with 375 additions and 75 deletions
|
|
@ -18,8 +18,8 @@ public class CrAuth{
|
|||
|
||||
private readonly string authorization = ApiUrls.authBasicMob;
|
||||
private readonly string userAgent = ApiUrls.MobileUserAgent;
|
||||
private const string DeviceType = "OnePlus CPH2449";
|
||||
private const string DeviceName = "CPH2449";
|
||||
private readonly string deviceType = "OnePlus CPH2449";
|
||||
private readonly string deviceName = "CPH2449";
|
||||
|
||||
public async Task AuthAnonymous(){
|
||||
string uuid = Guid.NewGuid().ToString();
|
||||
|
|
@ -28,10 +28,13 @@ public class CrAuth{
|
|||
{ "grant_type", "client_id" },
|
||||
{ "scope", "offline_access" },
|
||||
{ "device_id", uuid },
|
||||
{ "device_name", DeviceName },
|
||||
{ "device_type", DeviceType },
|
||||
{ "device_type", deviceType },
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(deviceName)){
|
||||
formData.Add("device_name", deviceName);
|
||||
}
|
||||
|
||||
var requestContent = new FormUrlEncodedContent(formData);
|
||||
|
||||
var crunchyAuthHeaders = new Dictionary<string, string>{
|
||||
|
|
@ -78,15 +81,18 @@ public class CrAuth{
|
|||
string uuid = Guid.NewGuid().ToString();
|
||||
|
||||
var formData = new Dictionary<string, string>{
|
||||
{ "username", data.Username }, // Replace with actual data
|
||||
{ "password", data.Password }, // Replace with actual data
|
||||
{ "username", data.Username },
|
||||
{ "password", data.Password },
|
||||
{ "grant_type", "password" },
|
||||
{ "scope", "offline_access" },
|
||||
{ "device_id", uuid },
|
||||
{ "device_name", DeviceName },
|
||||
{ "device_type", DeviceType },
|
||||
{ "device_type", deviceType },
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(deviceName)){
|
||||
formData.Add("device_name", deviceName);
|
||||
}
|
||||
|
||||
var requestContent = new FormUrlEncodedContent(formData);
|
||||
|
||||
var crunchyAuthHeaders = new Dictionary<string, string>{
|
||||
|
|
@ -192,10 +198,13 @@ public class CrAuth{
|
|||
{ "scope", "offline_access" },
|
||||
{ "device_id", uuid },
|
||||
{ "grant_type", "refresh_token" },
|
||||
{ "device_name", DeviceName },
|
||||
{ "device_type", DeviceType },
|
||||
{ "device_type", deviceType },
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(deviceName)){
|
||||
formData.Add("device_name", deviceName);
|
||||
}
|
||||
|
||||
var requestContent = new FormUrlEncodedContent(formData);
|
||||
|
||||
var crunchyAuthHeaders = new Dictionary<string, string>{
|
||||
|
|
@ -250,10 +259,13 @@ public class CrAuth{
|
|||
{ "grant_type", "refresh_token" },
|
||||
{ "scope", "offline_access" },
|
||||
{ "device_id", uuid },
|
||||
{ "device_name", DeviceName },
|
||||
{ "device_type", DeviceType },
|
||||
{ "device_type", deviceType },
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(deviceName)){
|
||||
formData.Add("device_name", deviceName);
|
||||
}
|
||||
|
||||
var requestContent = new FormUrlEncodedContent(formData);
|
||||
|
||||
var crunchyAuthHeaders = new Dictionary<string, string>{
|
||||
|
|
|
|||
|
|
@ -281,4 +281,18 @@ public class CrEpisode(){
|
|||
|
||||
return complete;
|
||||
}
|
||||
|
||||
public async Task MarkAsWatched(string episodeId){
|
||||
|
||||
var request = HttpClientReq.CreateRequestMessage($"{ApiUrls.Content}/discover/{crunInstance.Token?.account_id}/mark_as_watched/{episodeId}", HttpMethod.Post, true,false,null);
|
||||
|
||||
var response = await HttpClientReq.Instance.SendHttpRequest(request);
|
||||
|
||||
if (!response.IsOk){
|
||||
Console.Error.WriteLine($"Mark as watched for {episodeId} failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -96,6 +96,7 @@ public class CrunchyrollManager{
|
|||
private CrDownloadOptions InitDownloadOptions(){
|
||||
var options = new CrDownloadOptions();
|
||||
|
||||
options.UseCrBetaApi = true;
|
||||
options.AutoDownload = false;
|
||||
options.RemoveFinishedDownload = false;
|
||||
options.Chapters = true;
|
||||
|
|
@ -146,6 +147,7 @@ public class CrunchyrollManager{
|
|||
if (Path.Exists(CfgManager.PathCrDownloadOptionsOld)){
|
||||
var optionsYaml = new CrDownloadOptionsYaml();
|
||||
|
||||
optionsYaml.UseCrBetaApi = true;
|
||||
optionsYaml.AutoDownload = false;
|
||||
optionsYaml.RemoveFinishedDownload = false;
|
||||
optionsYaml.Chapters = true;
|
||||
|
|
@ -349,6 +351,8 @@ public class CrunchyrollManager{
|
|||
foreach (var keyValue in groupByDub){
|
||||
var result = await MuxStreams(keyValue.Value,
|
||||
new CrunchyMuxOptions{
|
||||
DubLangList = options.DubLang,
|
||||
SubLangList = options.DlSubs,
|
||||
FfmpegOptions = options.FfmpegOptions,
|
||||
SkipSubMux = options.SkipSubsMux,
|
||||
Output = fileNameAndPath,
|
||||
|
|
@ -364,7 +368,11 @@ public class CrunchyrollManager{
|
|||
CcTag = options.CcTag,
|
||||
KeepAllVideos = true,
|
||||
MuxDescription = options.IncludeVideoDescription,
|
||||
DlVideoOnce = options.DlVideoOnce
|
||||
DlVideoOnce = options.DlVideoOnce,
|
||||
DefaultSubSigns = options.DefaultSubSigns,
|
||||
DefaultSubForcedDisplay = options.DefaultSubForcedDisplay,
|
||||
CcSubsMuxingFlag = options.CcSubsMuxingFlag,
|
||||
SignsSubsAsForced = options.SignsSubsAsForced,
|
||||
},
|
||||
fileNameAndPath);
|
||||
|
||||
|
|
@ -403,6 +411,8 @@ public class CrunchyrollManager{
|
|||
} else{
|
||||
var result = await MuxStreams(res.Data,
|
||||
new CrunchyMuxOptions{
|
||||
DubLangList = options.DubLang,
|
||||
SubLangList = options.DlSubs,
|
||||
FfmpegOptions = options.FfmpegOptions,
|
||||
SkipSubMux = options.SkipSubsMux,
|
||||
Output = fileNameAndPath,
|
||||
|
|
@ -418,7 +428,11 @@ public class CrunchyrollManager{
|
|||
CcTag = options.CcTag,
|
||||
KeepAllVideos = true,
|
||||
MuxDescription = options.IncludeVideoDescription,
|
||||
DlVideoOnce = options.DlVideoOnce
|
||||
DlVideoOnce = options.DlVideoOnce,
|
||||
DefaultSubSigns = options.DefaultSubSigns,
|
||||
DefaultSubForcedDisplay = options.DefaultSubForcedDisplay,
|
||||
CcSubsMuxingFlag = options.CcSubsMuxingFlag,
|
||||
SignsSubsAsForced = options.SignsSubsAsForced,
|
||||
},
|
||||
fileNameAndPath);
|
||||
|
||||
|
|
@ -497,6 +511,9 @@ public class CrunchyrollManager{
|
|||
History.SetAsDownloaded(data.SeriesId, data.SeasonId, data.Data.First().MediaId);
|
||||
}
|
||||
|
||||
if (options.MarkAsWatched && data.Data is{ Count: > 0 }){
|
||||
_ = CrEpisode.MarkAsWatched(data.Data.First().MediaId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -623,6 +640,8 @@ public class CrunchyrollManager{
|
|||
|
||||
|
||||
var merger = new Merger(new MergerOptions{
|
||||
DubLangList = options.DubLangList,
|
||||
SubLangList = options.SubLangList,
|
||||
OnlyVid = data.Where(a => a.Type == DownloadMediaType.Video).Select(a => new MergerInput{ Language = a.Lang, Path = a.Path ?? string.Empty }).ToList(),
|
||||
SkipSubMux = options.SkipSubMux,
|
||||
OnlyAudio = data.Where(a => a.Type == DownloadMediaType.Audio).Select(a => new MergerInput{ Language = a.Lang, Path = a.Path ?? string.Empty }).ToList(),
|
||||
|
|
@ -643,6 +662,10 @@ public class CrunchyrollManager{
|
|||
},
|
||||
CcTag = options.CcTag,
|
||||
mp3 = muxToMp3,
|
||||
DefaultSubSigns = options.DefaultSubSigns,
|
||||
DefaultSubForcedDisplay = options.DefaultSubForcedDisplay,
|
||||
CcSubsMuxingFlag = options.CcSubsMuxingFlag,
|
||||
SignsSubsAsForced = options.SignsSubsAsForced,
|
||||
Description = muxDesc ? data.Where(a => a.Type == DownloadMediaType.Description).Select(a => new MergerInput{ Path = a.Path ?? string.Empty }).ToList() :[],
|
||||
});
|
||||
|
||||
|
|
@ -805,7 +828,7 @@ public class CrunchyrollManager{
|
|||
|
||||
if (data.Data is{ Count: > 0 }){
|
||||
options.Partsize = options.Partsize > 0 ? options.Partsize : 1;
|
||||
|
||||
|
||||
var sortedMetaData = data.Data
|
||||
.OrderBy(metaData => options.DubLang.IndexOf(metaData.Lang?.CrLocale ?? string.Empty) != -1 ? options.DubLang.IndexOf(metaData.Lang?.CrLocale ?? string.Empty) : int.MaxValue)
|
||||
.ToList();
|
||||
|
|
@ -1332,7 +1355,7 @@ public class CrunchyrollManager{
|
|||
Data = files,
|
||||
Error = dlFailed,
|
||||
FileName = fileName.Length > 0 ? (Path.IsPathRooted(fileName) ? fileName : Path.Combine(fileDir, fileName)) : "./unknown",
|
||||
ErrorText = ""
|
||||
ErrorText = "Audio or Video download failed",
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -227,6 +227,15 @@ public partial class CrunchyrollSettingsViewModel : ViewModelBase{
|
|||
[ObservableProperty]
|
||||
private bool _searchFetchFeaturedMusic;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _useCrBetaApi;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _downloadFirstAvailableDub;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _markAsWatched;
|
||||
|
||||
private bool settingsLoaded;
|
||||
|
||||
public CrunchyrollSettingsViewModel(){
|
||||
|
|
@ -280,6 +289,9 @@ public partial class CrunchyrollSettingsViewModel : ViewModelBase{
|
|||
AddScaledBorderAndShadow = options.SubsAddScaledBorder is ScaledBorderAndShadowSelection.ScaledBorderAndShadowNo or ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes;
|
||||
SelectedScaledBorderAndShadow = GetScaledBorderAndShadowFromOptions(options);
|
||||
|
||||
MarkAsWatched = options.MarkAsWatched;
|
||||
DownloadFirstAvailableDub = options.DownloadFirstAvailableDub;
|
||||
UseCrBetaApi = options.UseCrBetaApi;
|
||||
CCSubsFont = options.CcSubsFont ?? "";
|
||||
CCSubsMuxingFlag = options.CcSubsMuxingFlag;
|
||||
SignsSubsAsForced = options.SignsSubsAsForced;
|
||||
|
|
@ -344,6 +356,9 @@ public partial class CrunchyrollSettingsViewModel : ViewModelBase{
|
|||
return;
|
||||
}
|
||||
|
||||
CrunchyrollManager.Instance.CrunOptions.MarkAsWatched = MarkAsWatched;
|
||||
CrunchyrollManager.Instance.CrunOptions.DownloadFirstAvailableDub = DownloadFirstAvailableDub;
|
||||
CrunchyrollManager.Instance.CrunOptions.UseCrBetaApi = UseCrBetaApi;
|
||||
CrunchyrollManager.Instance.CrunOptions.SignsSubsAsForced = SignsSubsAsForced;
|
||||
CrunchyrollManager.Instance.CrunOptions.CcSubsMuxingFlag = CCSubsMuxingFlag;
|
||||
CrunchyrollManager.Instance.CrunOptions.CcSubsFont = CCSubsFont;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
x:DataType="vm:CrunchyrollSettingsViewModel"
|
||||
x:Class="CRD.Downloader.Crunchyroll.Views.CrunchyrollSettingsView">
|
||||
|
||||
|
||||
|
||||
<Design.DataContext>
|
||||
<vm:CrunchyrollSettingsViewModel />
|
||||
</Design.DataContext>
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
<ScrollViewer Padding="20 20 20 0">
|
||||
<StackPanel Spacing="8">
|
||||
|
||||
|
||||
<controls:SettingsExpander Header="Dub language"
|
||||
IconSource="Speaker2"
|
||||
Description="Change the selected dub language (with multiple dubs some can be out of sync)">
|
||||
|
|
@ -203,10 +204,10 @@
|
|||
<CheckBox IsChecked="{Binding SearchFetchFeaturedMusic}"> </CheckBox>
|
||||
</controls:SettingsExpanderItem.Footer>
|
||||
</controls:SettingsExpanderItem>
|
||||
|
||||
|
||||
|
||||
|
||||
</controls:SettingsExpander>
|
||||
|
||||
|
||||
<controls:SettingsExpander Header="Download Settings"
|
||||
IconSource="Download"
|
||||
Description="Adjust download settings"
|
||||
|
|
@ -265,6 +266,12 @@
|
|||
</controls:SettingsExpanderItem.Footer>
|
||||
</controls:SettingsExpanderItem>
|
||||
|
||||
<controls:SettingsExpanderItem Content="Download First Available Dub" Description="Downloads only the first available dub from the dubs list">
|
||||
<controls:SettingsExpanderItem.Footer>
|
||||
<CheckBox IsChecked="{Binding DownloadFirstAvailableDub}"> </CheckBox>
|
||||
</controls:SettingsExpanderItem.Footer>
|
||||
</controls:SettingsExpanderItem>
|
||||
|
||||
<controls:SettingsExpanderItem Content="Audio Quality">
|
||||
<controls:SettingsExpanderItem.Footer>
|
||||
<ComboBox HorizontalContentAlignment="Center" MinWidth="210" MaxDropDownHeight="400"
|
||||
|
|
@ -279,6 +286,12 @@
|
|||
<CheckBox IsChecked="{Binding DownloadChapters}"> </CheckBox>
|
||||
</controls:SettingsExpanderItem.Footer>
|
||||
</controls:SettingsExpanderItem>
|
||||
|
||||
<controls:SettingsExpanderItem Content="Mark as watched" Description="Mark the downloaded episodes as watched on Crunchyroll">
|
||||
<controls:SettingsExpanderItem.Footer>
|
||||
<CheckBox IsChecked="{Binding MarkAsWatched}"> </CheckBox>
|
||||
</controls:SettingsExpanderItem.Footer>
|
||||
</controls:SettingsExpanderItem>
|
||||
|
||||
<controls:SettingsExpander.Footer>
|
||||
</controls:SettingsExpander.Footer>
|
||||
|
|
@ -541,6 +554,27 @@
|
|||
</controls:SettingsExpander.Footer>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<controls:SettingsExpander Header="CR Api"
|
||||
IconSource="World"
|
||||
Description="Change connection settings for the api">
|
||||
<controls:SettingsExpander.Footer>
|
||||
|
||||
</controls:SettingsExpander.Footer>
|
||||
|
||||
<controls:SettingsExpanderItem Content="CR Beta Api">
|
||||
<controls:SettingsExpanderItem.Footer>
|
||||
<CheckBox IsChecked="{Binding UseCrBetaApi}"> </CheckBox>
|
||||
</controls:SettingsExpanderItem.Footer>
|
||||
</controls:SettingsExpanderItem>
|
||||
|
||||
<!-- <controls:SettingsExpanderItem Content="CR Old Auth" Description="You have to logout and login if you change this"> -->
|
||||
<!-- <controls:SettingsExpanderItem.Footer> -->
|
||||
<!-- <CheckBox IsChecked="{Binding UseCrOldAuthHeader}"> </CheckBox> -->
|
||||
<!-- </controls:SettingsExpanderItem.Footer> -->
|
||||
<!-- </controls:SettingsExpanderItem> -->
|
||||
|
||||
</controls:SettingsExpander>
|
||||
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
|
|
@ -175,7 +176,10 @@ public partial class ProgramManager : ObservableObject{
|
|||
|
||||
|
||||
private void CleanUpOldUpdater(){
|
||||
string backupFilePath = Path.Combine(Directory.GetCurrentDirectory(), "Updater.exe.bak");
|
||||
|
||||
var executableExtension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
|
||||
|
||||
string backupFilePath = Path.Combine(Directory.GetCurrentDirectory(), $"Updater{executableExtension}.bak");
|
||||
|
||||
if (File.Exists(backupFilePath)){
|
||||
try{
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ using System.Collections.Specialized;
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CRD.Downloader.Crunchyroll;
|
||||
using CRD.Utils;
|
||||
using CRD.Utils.CustomList;
|
||||
using CRD.Utils.Structs;
|
||||
using CRD.Utils.Structs.Crunchyroll;
|
||||
using CRD.Utils.Structs.History;
|
||||
using CRD.ViewModels;
|
||||
using CRD.Views;
|
||||
|
|
@ -61,6 +63,8 @@ public class QueueManager{
|
|||
Console.Error.WriteLine("Failed to Remove Episode from list");
|
||||
}
|
||||
}
|
||||
} else if (e.Action == NotifyCollectionChangedAction.Reset && Queue.Count == 0){
|
||||
DownloadItemModels.Clear();
|
||||
}
|
||||
|
||||
UpdateDownloadListItems();
|
||||
|
|
@ -151,14 +155,41 @@ public class QueueManager{
|
|||
|
||||
selected.OnlySubs = onlySubs;
|
||||
|
||||
if (CrunchyrollManager.Instance.CrunOptions.DownloadFirstAvailableDub && selected.Data.Count > 1){
|
||||
var sortedMetaData = selected.Data
|
||||
.OrderBy(metaData => {
|
||||
var locale = metaData.Lang?.CrLocale ?? string.Empty;
|
||||
var index = dubLang.IndexOf(locale);
|
||||
return index != -1 ? index : int.MaxValue;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
if (sortedMetaData.Count != 0){
|
||||
var first = sortedMetaData.First();
|
||||
selected.Data =[first];
|
||||
selected.SelectedDubs =[first.Lang?.CrLocale ?? string.Empty];
|
||||
}
|
||||
}
|
||||
|
||||
var newOptions = Helpers.DeepCopy(CrunchyrollManager.Instance.CrunOptions);
|
||||
|
||||
if (selected.OnlySubs){
|
||||
newOptions.Novids = true;
|
||||
newOptions.Noaudio = true;
|
||||
}
|
||||
|
||||
newOptions.DubLang = dubLang;
|
||||
|
||||
selected.DownloadSettings = newOptions;
|
||||
|
||||
Queue.Add(selected);
|
||||
|
||||
if (selected.Data.Count < dubLang.Count){
|
||||
if (selected.Data.Count < dubLang.Count && !CrunchyrollManager.Instance.CrunOptions.DownloadFirstAvailableDub){
|
||||
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();
|
||||
$"{(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 ??[])}]");
|
||||
|
|
@ -172,7 +203,7 @@ public class QueueManager{
|
|||
Console.Error.WriteLine("Episode couldn't be added to Queue - Available dubs/subs: ");
|
||||
|
||||
var languages = sList.EpisodeAndLanguages.Items.Select((a, index) =>
|
||||
$"{(a.IsPremiumOnly ? "+ " : "")}{sList.EpisodeAndLanguages.Langs.ElementAtOrDefault(index).CrLocale ?? "Unknown"}").ToArray();
|
||||
$"{(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($"Couldn't add episode to the queue with current dub settings", ToastType.Error, 2));
|
||||
|
|
@ -188,6 +219,18 @@ public class QueueManager{
|
|||
if (movieMeta != null){
|
||||
movieMeta.DownloadSubs = CrunchyrollManager.Instance.CrunOptions.DlSubs;
|
||||
movieMeta.OnlySubs = onlySubs;
|
||||
|
||||
var newOptions = Helpers.DeepCopy(CrunchyrollManager.Instance.CrunOptions);
|
||||
|
||||
if (movieMeta.OnlySubs){
|
||||
newOptions.Novids = true;
|
||||
newOptions.Noaudio = true;
|
||||
}
|
||||
|
||||
newOptions.DubLang = dubLang;
|
||||
|
||||
movieMeta.DownloadSettings = newOptions;
|
||||
|
||||
Queue.Add(movieMeta);
|
||||
|
||||
Console.WriteLine("Added Movie to Queue");
|
||||
|
|
@ -199,6 +242,9 @@ public class QueueManager{
|
|||
|
||||
|
||||
public void CrAddMusicMetaToQueue(CrunchyEpMeta epMeta){
|
||||
var newOptions = Helpers.DeepCopy(CrunchyrollManager.Instance.CrunOptions);
|
||||
epMeta.DownloadSettings = newOptions;
|
||||
|
||||
Queue.Add(epMeta);
|
||||
MessageBus.Current.SendMessage(new ToastMessage($"Added episode to the queue", ToastType.Information, 1));
|
||||
}
|
||||
|
|
@ -210,15 +256,18 @@ public class QueueManager{
|
|||
|
||||
if (musicVideo != null){
|
||||
var musicVideoMeta = CrunchyrollManager.Instance.CrMusic.EpisodeMeta(musicVideo);
|
||||
|
||||
|
||||
(HistoryEpisode? historyEpisode, List<string> dublist, List<string> sublist, string downloadDirPath, string videoQuality) historyEpisode = (null, [], [], "", "");
|
||||
|
||||
if (CrunchyrollManager.Instance.CrunOptions.History){
|
||||
historyEpisode = CrunchyrollManager.Instance.History.GetHistoryEpisodeWithDubListAndDownloadDir(musicVideoMeta.SeriesId, musicVideoMeta.SeasonId, musicVideoMeta.Data.First().MediaId);
|
||||
}
|
||||
|
||||
|
||||
musicVideoMeta.VideoQuality = !string.IsNullOrEmpty(historyEpisode.videoQuality) ? historyEpisode.videoQuality : CrunchyrollManager.Instance.CrunOptions.QualityVideo;
|
||||
|
||||
|
||||
var newOptions = Helpers.DeepCopy(CrunchyrollManager.Instance.CrunOptions);
|
||||
musicVideoMeta.DownloadSettings = newOptions;
|
||||
|
||||
Queue.Add(musicVideoMeta);
|
||||
MessageBus.Current.SendMessage(new ToastMessage($"Added music video to the queue", ToastType.Information, 1));
|
||||
}
|
||||
|
|
@ -231,14 +280,18 @@ public class QueueManager{
|
|||
|
||||
if (concert != null){
|
||||
var concertMeta = CrunchyrollManager.Instance.CrMusic.EpisodeMeta(concert);
|
||||
|
||||
|
||||
(HistoryEpisode? historyEpisode, List<string> dublist, List<string> sublist, string downloadDirPath, string videoQuality) historyEpisode = (null, [], [], "", "");
|
||||
|
||||
if (CrunchyrollManager.Instance.CrunOptions.History){
|
||||
historyEpisode = CrunchyrollManager.Instance.History.GetHistoryEpisodeWithDubListAndDownloadDir(concertMeta.SeriesId, concertMeta.SeasonId, concertMeta.Data.First().MediaId);
|
||||
}
|
||||
|
||||
|
||||
concertMeta.VideoQuality = !string.IsNullOrEmpty(historyEpisode.videoQuality) ? historyEpisode.videoQuality : CrunchyrollManager.Instance.CrunOptions.QualityVideo;
|
||||
|
||||
var newOptions = Helpers.DeepCopy(CrunchyrollManager.Instance.CrunOptions);
|
||||
concertMeta.DownloadSettings = newOptions;
|
||||
|
||||
Queue.Add(concertMeta);
|
||||
MessageBus.Current.SendMessage(new ToastMessage($"Added concert to the queue", ToastType.Information, 1));
|
||||
}
|
||||
|
|
@ -285,6 +338,34 @@ public class QueueManager{
|
|||
crunchyEpMeta.DownloadSubs = subLangList.sublist.Count > 0 ? subLangList.sublist : CrunchyrollManager.Instance.CrunOptions.DlSubs;
|
||||
|
||||
|
||||
if (CrunchyrollManager.Instance.CrunOptions.DownloadFirstAvailableDub && crunchyEpMeta.Data.Count > 1){
|
||||
var sortedMetaData = crunchyEpMeta.Data
|
||||
.OrderBy(metaData => {
|
||||
var locale = metaData.Lang?.CrLocale ?? string.Empty;
|
||||
var index = data.DubLang.IndexOf(locale);
|
||||
return index != -1 ? index : int.MaxValue;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
if (sortedMetaData.Count != 0){
|
||||
var first = sortedMetaData.First();
|
||||
crunchyEpMeta.Data =[first];
|
||||
crunchyEpMeta.SelectedDubs =[first.Lang?.CrLocale ?? string.Empty];
|
||||
}
|
||||
}
|
||||
|
||||
var newOptions = Helpers.DeepCopy(CrunchyrollManager.Instance.CrunOptions);
|
||||
|
||||
if (crunchyEpMeta.OnlySubs){
|
||||
newOptions.Novids = true;
|
||||
newOptions.Noaudio = true;
|
||||
}
|
||||
|
||||
newOptions.DubLang = data.DubLang;
|
||||
|
||||
crunchyEpMeta.DownloadSettings = newOptions;
|
||||
|
||||
|
||||
Queue.Add(crunchyEpMeta);
|
||||
} else{
|
||||
failed = true;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ using CRD.Utils.Structs;
|
|||
using CRD.Utils.Structs.Crunchyroll;
|
||||
using Microsoft.Win32;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace CRD.Utils;
|
||||
|
||||
|
|
@ -39,10 +40,19 @@ public class Helpers{
|
|||
}
|
||||
|
||||
public static T DeepCopy<T>(T obj){
|
||||
var json = JsonConvert.SerializeObject(obj);
|
||||
var settings = new JsonSerializerSettings{
|
||||
ContractResolver = new DefaultContractResolver{
|
||||
IgnoreSerializableAttribute = true,
|
||||
IgnoreSerializableInterface = true
|
||||
},
|
||||
ObjectCreationHandling = ObjectCreationHandling.Replace
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(obj, settings);
|
||||
return JsonConvert.DeserializeObject<T>(json);
|
||||
}
|
||||
|
||||
|
||||
public static string ConvertTimeFormat(string time){
|
||||
var timeParts = time.Split(':', '.');
|
||||
int hours = int.Parse(timeParts[0]);
|
||||
|
|
|
|||
|
|
@ -249,21 +249,21 @@ public static class ApiUrls{
|
|||
public static readonly string ApiBeta = "https://beta-api.crunchyroll.com";
|
||||
public static readonly string ApiN = "https://www.crunchyroll.com";
|
||||
public static readonly string Anilist = "https://graphql.anilist.co";
|
||||
|
||||
public static readonly string Auth = ApiN + "/auth/v1/token";
|
||||
public static readonly string Profile = ApiN + "/accounts/v1/me/profile";
|
||||
public static readonly string CmsToken = ApiN + "/index/v2";
|
||||
public static readonly string Search = ApiN + "/content/v2/discover/search";
|
||||
public static readonly string Browse = ApiN + "/content/v2/discover/browse";
|
||||
public static readonly string Cms = ApiN + "/content/v2/cms";
|
||||
public static readonly string Content = ApiN + "/content/v2";
|
||||
|
||||
|
||||
public static string Auth => (CrunchyrollManager.Instance.CrunOptions.UseCrBetaApi ? ApiBeta : ApiN) + "/auth/v1/token";
|
||||
public static string Profile => (CrunchyrollManager.Instance.CrunOptions.UseCrBetaApi ? ApiBeta : ApiN) + "/accounts/v1/me/profile";
|
||||
public static string CmsToken => (CrunchyrollManager.Instance.CrunOptions.UseCrBetaApi ? ApiBeta : ApiN) + "/index/v2";
|
||||
public static string Search => (CrunchyrollManager.Instance.CrunOptions.UseCrBetaApi ? ApiBeta : ApiN) + "/content/v2/discover/search";
|
||||
public static string Browse => (CrunchyrollManager.Instance.CrunOptions.UseCrBetaApi ? ApiBeta : ApiN) + "/content/v2/discover/browse";
|
||||
public static string Cms => (CrunchyrollManager.Instance.CrunOptions.UseCrBetaApi ? ApiBeta : ApiN) + "/content/v2/cms";
|
||||
public static string Content => (CrunchyrollManager.Instance.CrunOptions.UseCrBetaApi ? ApiBeta : ApiN) + "/content/v2";
|
||||
|
||||
public static string Subscription => (CrunchyrollManager.Instance.CrunOptions.UseCrBetaApi ? ApiBeta : ApiN) + "/subs/v3/subscriptions/";
|
||||
|
||||
public static readonly string BetaBrowse = ApiBeta + "/content/v1/browse";
|
||||
public static readonly string BetaCms = ApiBeta + "/cms/v2";
|
||||
public static readonly string DRM = ApiBeta + "/drm/v1/auth";
|
||||
|
||||
public static readonly string Subscription = ApiN + "/subs/v3/subscriptions/";
|
||||
|
||||
public static readonly string authBasic = "Basic bm9haWhkZXZtXzZpeWcwYThsMHE6";
|
||||
|
||||
public static readonly string authBasicMob = "Basic ZG1yeWZlc2NkYm90dWJldW56NXo6NU45aThPV2cyVmtNcm1oekNfNUNXekRLOG55SXo0QU0=";
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ public class Merger{
|
|||
args.Add($"-i \"{sub.value.File}\"");
|
||||
metaData.Add($"-map {index}:s");
|
||||
if (options.Defaults.Sub.Code == sub.value.Language.Code &&
|
||||
(CrunchyrollManager.Instance.CrunOptions.DefaultSubSigns == sub.value.Signs || CrunchyrollManager.Instance.CrunOptions.DefaultSubSigns && !hasSignsSub)
|
||||
(options.DefaultSubSigns == sub.value.Signs || options.DefaultSubSigns && !hasSignsSub)
|
||||
&& sub.value.ClosedCaption == false){
|
||||
metaData.Add($"-disposition:s:{sub.i} default");
|
||||
} else{
|
||||
|
|
@ -168,9 +168,9 @@ public class Merger{
|
|||
args.Add($"\"{Helpers.AddUncPrefixIfNeeded(vid.Path)}\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var sortedAudio = options.OnlyAudio
|
||||
.OrderBy(sub => CrunchyrollManager.Instance.CrunOptions.DubLang.IndexOf(sub.Language.CrLocale) != -1 ? CrunchyrollManager.Instance.CrunOptions.DubLang.IndexOf(sub.Language.CrLocale) : int.MaxValue)
|
||||
.OrderBy(sub => options.DubLangList.IndexOf(sub.Language.CrLocale) != -1 ? options.DubLangList.IndexOf(sub.Language.CrLocale) : int.MaxValue)
|
||||
.ToList();
|
||||
|
||||
foreach (var aud in sortedAudio){
|
||||
|
|
@ -198,11 +198,12 @@ public class Merger{
|
|||
bool hasSignsSub = options.Subtitles.Any(sub => sub.Signs && options.Defaults.Sub.Code == sub.Language.Code);
|
||||
|
||||
var sortedSubtitles = options.Subtitles
|
||||
.OrderBy(sub => CrunchyrollManager.Instance.CrunOptions.DlSubs.IndexOf(sub.Language.CrLocale) != -1 ? CrunchyrollManager.Instance.CrunOptions.DlSubs.IndexOf(sub.Language.CrLocale) : int.MaxValue)
|
||||
.ThenBy(sub => sub.Signs ? 0 : 1)
|
||||
.ThenBy(sub => sub.ClosedCaption ? 0 : 1)
|
||||
.OrderBy(sub => options.SubLangList.IndexOf(sub.Language.CrLocale) != -1
|
||||
? options.SubLangList.IndexOf(sub.Language.CrLocale)
|
||||
: int.MaxValue)
|
||||
.ThenBy(sub => sub.ClosedCaption ? 2 : sub.Signs ? 1 : 0)
|
||||
.ToList();
|
||||
|
||||
|
||||
foreach (var subObj in sortedSubtitles){
|
||||
bool isForced = false;
|
||||
if (subObj.Delay.HasValue){
|
||||
|
|
@ -210,17 +211,17 @@ public class Merger{
|
|||
args.Add($"--sync 0:{delay}");
|
||||
}
|
||||
|
||||
string trackNameExtra = subObj.ClosedCaption == true ? $" {options.CcTag}" : "";
|
||||
trackNameExtra += subObj.Signs == true ? " Signs" : "";
|
||||
string trackNameExtra = subObj.ClosedCaption ? $" {options.CcTag}" : "";
|
||||
trackNameExtra += subObj.Signs ? " Signs" : "";
|
||||
|
||||
string trackName = $"0:\"{(subObj.Language.Language ?? subObj.Language.Name) + trackNameExtra}\"";
|
||||
args.Add($"--track-name {trackName}");
|
||||
args.Add($"--language 0:\"{subObj.Language.Code}\"");
|
||||
|
||||
if (options.Defaults.Sub.Code == subObj.Language.Code &&
|
||||
(CrunchyrollManager.Instance.CrunOptions.DefaultSubSigns == subObj.Signs || CrunchyrollManager.Instance.CrunOptions.DefaultSubSigns && !hasSignsSub) && subObj.ClosedCaption == false){
|
||||
(options.DefaultSubSigns == subObj.Signs || options.DefaultSubSigns && !hasSignsSub) && subObj.ClosedCaption == false){
|
||||
args.Add("--default-track 0");
|
||||
if (CrunchyrollManager.Instance.CrunOptions.DefaultSubForcedDisplay){
|
||||
if (options.DefaultSubForcedDisplay){
|
||||
args.Add("--forced-track 0:yes");
|
||||
isForced = true;
|
||||
}
|
||||
|
|
@ -228,11 +229,11 @@ public class Merger{
|
|||
args.Add("--default-track 0:0");
|
||||
}
|
||||
|
||||
if (subObj.ClosedCaption == true && CrunchyrollManager.Instance.CrunOptions.CcSubsMuxingFlag){
|
||||
if (subObj.ClosedCaption && options.CcSubsMuxingFlag){
|
||||
args.Add("--hearing-impaired-flag 0:yes");
|
||||
}
|
||||
|
||||
if (subObj.Signs && CrunchyrollManager.Instance.CrunOptions.SignsSubsAsForced && !isForced){
|
||||
if (subObj.Signs && options.SignsSubsAsForced && !isForced){
|
||||
args.Add("--forced-track 0:yes");
|
||||
}
|
||||
|
||||
|
|
@ -302,7 +303,7 @@ public class Merger{
|
|||
Console.Error.WriteLine("Failed to retrieve video durations");
|
||||
return -100;
|
||||
}
|
||||
|
||||
|
||||
var extractFramesBaseEnd = await SyncingHelper.ExtractFrames(baseVideoPath, baseFramesDirEnd, baseVideoDurationTimeSpan.Value.TotalSeconds - 360, 360);
|
||||
var extractFramesCompareEnd = await SyncingHelper.ExtractFrames(compareVideoPath, compareFramesDirEnd, compareVideoDurationTimeSpan.Value.TotalSeconds - 360, 360);
|
||||
|
||||
|
|
@ -333,21 +334,20 @@ public class Merger{
|
|||
Time = GetTimeFromFileName(fp, extractFramesCompareEnd.frameRate)
|
||||
}).ToList();
|
||||
|
||||
|
||||
|
||||
|
||||
// Calculate offsets
|
||||
var startOffset = SyncingHelper.CalculateOffset(baseFramesStart, compareFramesStart);
|
||||
var endOffset = SyncingHelper.CalculateOffset(baseFramesEnd, compareFramesEnd,true);
|
||||
var endOffset = SyncingHelper.CalculateOffset(baseFramesEnd, compareFramesEnd, true);
|
||||
|
||||
var lengthDiff = (baseVideoDurationTimeSpan.Value.TotalMicroseconds - compareVideoDurationTimeSpan.Value.TotalMicroseconds) / 1000000;
|
||||
|
||||
|
||||
endOffset += lengthDiff;
|
||||
|
||||
|
||||
Console.WriteLine($"Start offset: {startOffset} seconds");
|
||||
Console.WriteLine($"End offset: {endOffset} seconds");
|
||||
|
||||
CleanupDirectory(cleanupDir);
|
||||
|
||||
|
||||
baseFramesStart.Clear();
|
||||
baseFramesEnd.Clear();
|
||||
compareFramesStart.Clear();
|
||||
|
|
@ -378,7 +378,7 @@ public class Merger{
|
|||
private static double GetTimeFromFileName(string fileName, double frameRate){
|
||||
var match = Regex.Match(Path.GetFileName(fileName), @"frame(\d+)");
|
||||
if (match.Success){
|
||||
return int.Parse(match.Groups[1].Value) / frameRate;
|
||||
return int.Parse(match.Groups[1].Value) / frameRate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -452,6 +452,8 @@ public class ParsedFont{
|
|||
}
|
||||
|
||||
public class CrunchyMuxOptions{
|
||||
public List<string> DubLangList{ get; set; } = new List<string>();
|
||||
public List<string> SubLangList{ get; set; } = new List<string>();
|
||||
public string Output{ get; set; }
|
||||
public bool? SkipSubMux{ get; set; }
|
||||
public bool? KeepAllVideos{ get; set; }
|
||||
|
|
@ -468,9 +470,17 @@ public class CrunchyMuxOptions{
|
|||
public string CcTag{ get; set; }
|
||||
public bool SyncTiming{ get; set; }
|
||||
public bool DlVideoOnce{ get; set; }
|
||||
|
||||
public bool DefaultSubSigns{ get; set; }
|
||||
|
||||
public bool DefaultSubForcedDisplay{ get; set; }
|
||||
public bool CcSubsMuxingFlag{ get; set; }
|
||||
public bool SignsSubsAsForced{ get; set; }
|
||||
}
|
||||
|
||||
public class MergerOptions{
|
||||
public List<string> DubLangList{ get; set; } = new List<string>();
|
||||
public List<string> SubLangList{ get; set; } = new List<string>();
|
||||
public List<MergerInput> OnlyVid{ get; set; } = new List<MergerInput>();
|
||||
public List<MergerInput> OnlyAudio{ get; set; } = new List<MergerInput>();
|
||||
public List<SubtitleInput> Subtitles{ get; set; } = new List<SubtitleInput>();
|
||||
|
|
@ -484,6 +494,10 @@ public class MergerOptions{
|
|||
public MuxOptions Options{ get; set; }
|
||||
public Defaults Defaults{ get; set; }
|
||||
public bool mp3{ get; set; }
|
||||
public bool DefaultSubSigns{ get; set; }
|
||||
public bool DefaultSubForcedDisplay{ get; set; }
|
||||
public bool CcSubsMuxingFlag{ get; set; }
|
||||
public bool SignsSubsAsForced{ get; set; }
|
||||
public List<MergerInput> Description{ get; set; } = new List<MergerInput>();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public class CrDownloadOptions{
|
|||
public List<string> Override{ get; set; } =[];
|
||||
|
||||
[JsonIgnore]
|
||||
public string CcTag{ get; set; } = "";
|
||||
public string CcTag{ get; set; } = "CC";
|
||||
|
||||
[JsonIgnore]
|
||||
public bool Nocleanup{ get; set; }
|
||||
|
|
@ -115,6 +115,12 @@ public class CrDownloadOptions{
|
|||
|
||||
#region Crunchyroll Settings
|
||||
|
||||
[JsonProperty("cr_mark_as_watched")]
|
||||
public bool MarkAsWatched{ get; set; }
|
||||
|
||||
[JsonProperty("cr_beta_api")]
|
||||
public bool UseCrBetaApi{ get; set; }
|
||||
|
||||
[JsonProperty("hard_sub_lang")]
|
||||
public string Hslang{ get; set; } = "";
|
||||
|
||||
|
|
@ -208,6 +214,9 @@ public class CrDownloadOptions{
|
|||
[JsonProperty("keep_dubs_seperate")]
|
||||
public bool KeepDubsSeperate{ get; set; }
|
||||
|
||||
[JsonProperty("dl_first_available_dub")]
|
||||
public bool DownloadFirstAvailableDub{ get; set; }
|
||||
|
||||
[JsonProperty("mux_skip_muxing")]
|
||||
public bool SkipMuxing{ get; set; }
|
||||
|
||||
|
|
@ -364,6 +373,9 @@ public class CrDownloadOptionsYaml{
|
|||
|
||||
#region Crunchyroll Settings
|
||||
|
||||
[YamlIgnore]
|
||||
public bool UseCrBetaApi{ get; set; }
|
||||
|
||||
[YamlMember(Alias = "hard_sub_lang", ApplyNamingConventions = false)]
|
||||
public string Hslang{ get; set; } = "";
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using CRD.Utils.Structs.Crunchyroll;
|
||||
using CRD.Utils.Structs.History;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
|
@ -378,6 +379,9 @@ public class CrunchyEpMeta{
|
|||
public List<string> downloadedFiles{ get; set; } =[];
|
||||
|
||||
public bool OnlySubs{ get; set; }
|
||||
|
||||
public CrDownloadOptions? DownloadSettings;
|
||||
|
||||
}
|
||||
|
||||
public class DownloadProgress{
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace CRD.Utils.Updater;
|
|||
|
||||
public class Updater : INotifyPropertyChanged{
|
||||
public double progress = 0;
|
||||
public bool failed = false;
|
||||
|
||||
#region Singelton
|
||||
|
||||
|
|
@ -50,8 +51,8 @@ public class Updater : INotifyPropertyChanged{
|
|||
private readonly string apiEndpoint = "https://api.github.com/repos/Crunchy-DL/Crunchy-Downloader/releases/latest";
|
||||
|
||||
public async Task<bool> CheckForUpdatesAsync(){
|
||||
if (Directory.Exists(tempPath)){
|
||||
Directory.Delete(tempPath, true);
|
||||
if (File.Exists(tempPath)){
|
||||
File.Delete(tempPath);
|
||||
}
|
||||
|
||||
if (Directory.Exists(extractPath)){
|
||||
|
|
@ -123,6 +124,7 @@ public class Updater : INotifyPropertyChanged{
|
|||
|
||||
public async Task DownloadAndUpdateAsync(){
|
||||
try{
|
||||
failed = false;
|
||||
Helpers.EnsureDirectoriesExist(tempPath);
|
||||
|
||||
// Download the zip file
|
||||
|
|
@ -164,19 +166,54 @@ public class Updater : INotifyPropertyChanged{
|
|||
ApplyUpdate(extractPath);
|
||||
} else{
|
||||
Console.Error.WriteLine("Failed to get Update");
|
||||
failed = true;
|
||||
OnPropertyChanged(nameof(failed));
|
||||
}
|
||||
} catch (Exception e){
|
||||
Console.Error.WriteLine($"Failed to get Update: {e.Message}");
|
||||
failed = true;
|
||||
OnPropertyChanged(nameof(failed));
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyUpdate(string updateFolder){
|
||||
var ExecutableExtension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
|
||||
var currentPath = AppDomain.CurrentDomain.BaseDirectory;
|
||||
var updaterPath = Path.Combine(currentPath, "Updater" + ExecutableExtension);
|
||||
var arguments = $"\"{currentPath.Substring(0, currentPath.Length - 1)}\" \"{updateFolder}\"";
|
||||
var executableExtension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
|
||||
var currentPath = Path.GetFullPath(AppContext.BaseDirectory);
|
||||
var updaterPath = Path.Combine(currentPath, "Updater" + executableExtension);
|
||||
|
||||
System.Diagnostics.Process.Start(updaterPath, arguments);
|
||||
Environment.Exit(0);
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)){
|
||||
try{
|
||||
var chmodProcess = new System.Diagnostics.ProcessStartInfo{
|
||||
FileName = "/bin/bash",
|
||||
Arguments = $"-c \"chmod +x '{updaterPath}'\"",
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
System.Diagnostics.Process.Start(chmodProcess)?.WaitForExit();
|
||||
} catch (Exception ex){
|
||||
Console.Error.WriteLine($"Error setting execute permissions: {ex.Message}");
|
||||
failed = true;
|
||||
OnPropertyChanged(nameof(failed));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try{
|
||||
var startInfo = new System.Diagnostics.ProcessStartInfo{
|
||||
FileName = updaterPath,
|
||||
UseShellExecute = false
|
||||
};
|
||||
startInfo.ArgumentList.Add(currentPath);
|
||||
startInfo.ArgumentList.Add(updateFolder);
|
||||
|
||||
System.Diagnostics.Process.Start(startInfo);
|
||||
Environment.Exit(0);
|
||||
} catch (Exception ex){
|
||||
Console.Error.WriteLine($"Error launching updater: {ex.Message}");
|
||||
failed = true;
|
||||
OnPropertyChanged(nameof(failed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +45,26 @@ public partial class DownloadsPageViewModel : ViewModelBase{
|
|||
CrunchyrollManager.Instance.CrunOptions.RemoveFinishedDownload = value;
|
||||
CfgManager.WriteCrSettings();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public void ClearQueue(){
|
||||
var items = QueueManager.Instance.Queue;
|
||||
QueueManager.Instance.Queue.Clear();
|
||||
|
||||
foreach (var crunchyEpMeta in items){
|
||||
if (!crunchyEpMeta.DownloadProgress.Done){
|
||||
foreach (var downloadItemDownloadedFile in crunchyEpMeta.downloadedFiles){
|
||||
try{
|
||||
if (File.Exists(downloadItemDownloadedFile)){
|
||||
File.Delete(downloadItemDownloadedFile);
|
||||
}
|
||||
} catch (Exception){
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class DownloadItemModel : INotifyPropertyChanged{
|
||||
|
|
@ -210,7 +230,7 @@ public partial class DownloadItemModel : INotifyPropertyChanged{
|
|||
newOptions.Noaudio = true;
|
||||
}
|
||||
|
||||
await CrunchyrollManager.Instance.DownloadEpisode(epMeta, newOptions);
|
||||
await CrunchyrollManager.Instance.DownloadEpisode(epMeta, epMeta.DownloadSettings ?? newOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ public partial class ContentDialogUpdateViewModel : ViewModelBase{
|
|||
[ObservableProperty]
|
||||
private double _progress;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _failed;
|
||||
|
||||
private AccountPageViewModel accountPageViewModel;
|
||||
|
||||
|
|
@ -28,7 +30,11 @@ public partial class ContentDialogUpdateViewModel : ViewModelBase{
|
|||
private void Progress_PropertyChanged(object? sender, PropertyChangedEventArgs e){
|
||||
if (e.PropertyName == nameof(Updater.Instance.progress)){
|
||||
Progress = Updater.Instance.progress;
|
||||
}else if (e.PropertyName == nameof(Updater.Instance.failed)){
|
||||
Failed = Updater.Instance.failed;
|
||||
dialog.IsPrimaryButtonEnabled = !Failed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,9 +20,20 @@
|
|||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
|
||||
<ToggleSwitch HorizontalAlignment="Right" Margin="0 0 10 0 " IsChecked="{Binding RemoveFinished}" OffContent="Remove Finished" OnContent="Remove Finished"></ToggleSwitch>
|
||||
<ToggleSwitch HorizontalAlignment="Right" Margin="0 0 10 0 " IsChecked="{Binding AutoDownload}" OffContent="Auto Download" OnContent="Auto Download"></ToggleSwitch>
|
||||
<Button BorderThickness="0"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0 0 10 0 "
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding ClearQueue}">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<controls:SymbolIcon Symbol="Delete" FontSize="22" />
|
||||
<TextBlock Text="Clear Queue" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap" ></TextBlock>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -178,9 +178,11 @@ public partial class MainWindow : AppWindow{
|
|||
public async void ShowUpdateDialog(){
|
||||
var dialog = new ContentDialog(){
|
||||
Title = "Updating",
|
||||
// CloseButtonText = "Close"
|
||||
PrimaryButtonText = "Close"
|
||||
};
|
||||
|
||||
dialog.IsPrimaryButtonEnabled = false;
|
||||
|
||||
var viewModel = new ContentDialogUpdateViewModel(dialog);
|
||||
dialog.Content = new ContentDialogUpdateView(){
|
||||
DataContext = viewModel
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
x:Class="CRD.Views.Utils.ContentDialogUpdateView">
|
||||
|
||||
<StackPanel Spacing="10" MinWidth="400">
|
||||
<TextBlock Text="Please wait while the update is being downloaded..." HorizontalAlignment="Center" Margin="0,10,0,20"/>
|
||||
<TextBlock IsVisible="{Binding !Failed}" Text="Please wait while the update is being downloaded..." HorizontalAlignment="Center" Margin="0,10,0,20"/>
|
||||
<TextBlock IsVisible="{Binding Failed}" Foreground="IndianRed" Text="Update failed check the log for more information" HorizontalAlignment="Center" Margin="0,10,0,20"/>
|
||||
<ProgressBar Minimum="0" Maximum="100" Value="{Binding Progress}" HorizontalAlignment="Center" VerticalAlignment="Center" Width="350"/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
Loading…
Reference in a new issue