mirror of
https://github.com/leiurayer/downkyi.git
synced 2024-04-21 12:41:55 +00:00
支持自定义aria服务器,本地测试通过
This commit is contained in:
@@ -16,7 +16,10 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
public static class AriaClient
|
||||
{
|
||||
private static readonly string JSONRPC = "2.0";
|
||||
private static readonly string TOKEN = "downkyi";
|
||||
private const string LOCAL_HOST = "http://localhost";
|
||||
private const string TOKEN = "downkyi";
|
||||
private static string host = LOCAL_HOST;
|
||||
private static string token = TOKEN;
|
||||
|
||||
/// <summary>
|
||||
/// This method adds a new download.
|
||||
@@ -41,7 +44,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
uris,
|
||||
option
|
||||
};
|
||||
@@ -91,7 +94,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
torrent,
|
||||
uris,
|
||||
option
|
||||
@@ -136,7 +139,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
metalink,
|
||||
uris,
|
||||
option
|
||||
@@ -168,7 +171,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -193,7 +196,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -220,7 +223,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -242,7 +245,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
@@ -266,7 +269,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -288,7 +291,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
@@ -311,7 +314,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -333,7 +336,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
@@ -360,7 +363,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -384,7 +387,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -408,7 +411,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -433,7 +436,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -457,7 +460,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -480,7 +483,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
@@ -520,7 +523,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
offset,
|
||||
num
|
||||
};
|
||||
@@ -552,7 +555,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
offset,
|
||||
num
|
||||
};
|
||||
@@ -591,7 +594,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid,
|
||||
pos,
|
||||
how.ToString("G")
|
||||
@@ -635,7 +638,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid,
|
||||
fileIndex,
|
||||
delUris,
|
||||
@@ -669,7 +672,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
|
||||
@@ -705,7 +708,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid,
|
||||
option
|
||||
};
|
||||
@@ -735,7 +738,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -770,7 +773,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
option
|
||||
};
|
||||
|
||||
@@ -793,7 +796,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
@@ -814,7 +817,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
@@ -836,7 +839,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
"token:" + token,
|
||||
gid
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
@@ -858,7 +861,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
@@ -881,7 +884,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
@@ -902,7 +905,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
@@ -926,7 +929,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
@@ -947,7 +950,7 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN
|
||||
"token:" + token,
|
||||
};
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
@@ -1018,13 +1021,31 @@ namespace DownKyi.Core.Aria2cNet.Client
|
||||
return await GetRpcResponseAsync<SystemListNotifications>(ariaSend);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置aria token
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
public static void SetToken(string token = TOKEN)
|
||||
{
|
||||
AriaClient.token = token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置aria host
|
||||
/// </summary>
|
||||
/// <param name="host"></param>
|
||||
public static void SetHost(string host = LOCAL_HOST)
|
||||
{
|
||||
AriaClient.host = host;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取jsonrpc的地址
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static string GetRpcUri(int listenPort = 6800)
|
||||
{
|
||||
return $"http://localhost:{listenPort}/jsonrpc";
|
||||
return $"{host}:{listenPort}/jsonrpc";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
NOT_SET = 0,
|
||||
BUILT_IN,
|
||||
ARIA,
|
||||
CUSTOM_ARIA,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace DownKyi.Core.Settings.Models
|
||||
#endregion
|
||||
|
||||
#region Aria
|
||||
public string AriaToken { get; set; } = null;
|
||||
public string AriaHost { get; set; } = null;
|
||||
public int AriaListenPort { get; set; } = -1;
|
||||
public AriaConfigLogLevel AriaLogLevel { get; set; } = AriaConfigLogLevel.NOT_SET;
|
||||
public int AriaSplit { get; set; } = -1;
|
||||
|
||||
@@ -24,6 +24,12 @@ namespace DownKyi.Core.Settings
|
||||
private readonly string httpProxy = "";
|
||||
private readonly int httpProxyListenPort = 0;
|
||||
|
||||
// Aria服务器token
|
||||
private readonly string ariaToken = "downkyi";
|
||||
|
||||
// Aria服务器host
|
||||
private readonly string ariaHost = "http://localhost";
|
||||
|
||||
// Aria服务器端口号
|
||||
private readonly int ariaListenPort = 6800;
|
||||
|
||||
@@ -263,6 +269,60 @@ namespace DownKyi.Core.Settings
|
||||
return SetSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Aria服务器的token
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetAriaToken()
|
||||
{
|
||||
appSettings = GetSettings();
|
||||
if (appSettings.Network.AriaToken == null)
|
||||
{
|
||||
// 第一次获取,先设置默认值
|
||||
SetHttpProxy(ariaToken);
|
||||
return ariaToken;
|
||||
}
|
||||
return appSettings.Network.AriaToken;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置Aria服务器的token
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public bool SetAriaToken(string token)
|
||||
{
|
||||
appSettings.Network.AriaToken = token;
|
||||
return SetSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Aria服务器的host
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetAriaHost()
|
||||
{
|
||||
appSettings = GetSettings();
|
||||
if (appSettings.Network.AriaHost == null)
|
||||
{
|
||||
// 第一次获取,先设置默认值
|
||||
SetHttpProxy(ariaHost);
|
||||
return ariaHost;
|
||||
}
|
||||
return appSettings.Network.AriaHost;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置Aria服务器的host
|
||||
/// </summary>
|
||||
/// <param name="host"></param>
|
||||
/// <returns></returns>
|
||||
public bool SetAriaHost(string host)
|
||||
{
|
||||
appSettings.Network.AriaHost = host;
|
||||
return SetSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Aria服务器的端口号
|
||||
/// </summary>
|
||||
|
||||
@@ -132,6 +132,9 @@ namespace DownKyi
|
||||
case Downloader.ARIA:
|
||||
downloadService = new AriaDownloadService(DownloadingList, DownloadedList);
|
||||
break;
|
||||
case Downloader.CUSTOM_ARIA:
|
||||
downloadService = new CustomAriaDownloadService(DownloadingList, DownloadedList);
|
||||
break;
|
||||
}
|
||||
if (downloadService != null)
|
||||
{
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
<Compile Include="Models\OrderFormatDisplay.cs" />
|
||||
<Compile Include="Services\AlertService.cs" />
|
||||
<Compile Include="Services\Download\AddToDownloadService.cs" />
|
||||
<Compile Include="Services\Download\CustomAriaDownloadService.cs" />
|
||||
<Compile Include="Services\Download\BuiltinDownloadService.cs" />
|
||||
<Compile Include="Services\Download\DownloadStorageService.cs" />
|
||||
<Compile Include="Services\SearchService.cs" />
|
||||
|
||||
@@ -188,7 +188,10 @@
|
||||
<system:String x:Key="SelectDownloader">选择下载器(重启生效):</system:String>
|
||||
<system:String x:Key="BuiltinDownloader">内建下载器(测试)</system:String>
|
||||
<system:String x:Key="Aria2cDownloader">Aria2下载器</system:String>
|
||||
<system:String x:Key="CustomAria2cDownloader">自定义Aria2下载器</system:String>
|
||||
<system:String x:Key="AriaServerHost">Aria服务器地址:</system:String>
|
||||
<system:String x:Key="AriaServerPort">Aria服务器端口:</system:String>
|
||||
<system:String x:Key="AriaServerToken">Aria服务器Token:</system:String>
|
||||
<system:String x:Key="AriaLogLevel">Aria日志等级:</system:String>
|
||||
<system:String x:Key="AriaMaxConcurrentDownloads">Aria同时下载数:</system:String>
|
||||
<system:String x:Key="AriaSplit">Aria最大线程数:</system:String>
|
||||
|
||||
@@ -232,6 +232,11 @@ namespace DownKyi.Services.Download
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
// 设置aria token
|
||||
AriaClient.SetToken();
|
||||
// 设置aria host
|
||||
AriaClient.SetHost();
|
||||
|
||||
// 启动Aria服务器
|
||||
StartAriaServer();
|
||||
|
||||
|
||||
@@ -0,0 +1,440 @@
|
||||
using DownKyi.Core.Aria2cNet;
|
||||
using DownKyi.Core.Aria2cNet.Client;
|
||||
using DownKyi.Core.Aria2cNet.Client.Entity;
|
||||
using DownKyi.Core.Aria2cNet.Server;
|
||||
using DownKyi.Core.BiliApi.VideoStream.Models;
|
||||
using DownKyi.Core.Logging;
|
||||
using DownKyi.Core.Settings;
|
||||
using DownKyi.Core.Utils;
|
||||
using DownKyi.Models;
|
||||
using DownKyi.Utils;
|
||||
using DownKyi.ViewModels.DownloadManager;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DownKyi.Services.Download
|
||||
{
|
||||
/// <summary>
|
||||
/// 音视频采用Aria下载,其余采用WebClient下载
|
||||
/// </summary>
|
||||
public class CustomAriaDownloadService : DownloadService, IDownloadService
|
||||
{
|
||||
public CustomAriaDownloadService(ObservableCollection<DownloadingItem> downloadingList, ObservableCollection<DownloadedItem> downloadedList) : base(downloadingList, downloadedList)
|
||||
{
|
||||
Tag = "AriaDownloadService";
|
||||
}
|
||||
|
||||
#region 音视频
|
||||
|
||||
/// <summary>
|
||||
/// 下载音频,返回下载文件路径
|
||||
/// </summary>
|
||||
/// <param name="downloading"></param>
|
||||
/// <returns></returns>
|
||||
public override string DownloadAudio(DownloadingItem downloading)
|
||||
{
|
||||
PlayUrlDashVideo downloadAudio = BaseDownloadAudio(downloading);
|
||||
|
||||
return DownloadVideo(downloading, downloadAudio);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载视频,返回下载文件路径
|
||||
/// </summary>
|
||||
/// <param name="downloading"></param>
|
||||
/// <returns></returns>
|
||||
public override string DownloadVideo(DownloadingItem downloading)
|
||||
{
|
||||
PlayUrlDashVideo downloadVideo = BaseDownloadVideo(downloading);
|
||||
|
||||
return DownloadVideo(downloading, downloadVideo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将下载音频和视频的函数中相同代码抽象出来
|
||||
/// </summary>
|
||||
/// <param name="downloading"></param>
|
||||
/// <param name="downloadVideo"></param>
|
||||
/// <returns></returns>
|
||||
private string DownloadVideo(DownloadingItem downloading, PlayUrlDashVideo downloadVideo)
|
||||
{
|
||||
// 如果为空,说明没有匹配到可下载的音频视频
|
||||
if (downloadVideo == null) { return null; }
|
||||
|
||||
// 下载链接
|
||||
List<string> urls = new List<string>();
|
||||
if (downloadVideo.BaseUrl != null) { urls.Add(downloadVideo.BaseUrl); }
|
||||
if (downloadVideo.BackupUrl != null) { urls.AddRange(downloadVideo.BackupUrl); }
|
||||
|
||||
// 路径
|
||||
downloading.DownloadBase.FilePath = downloading.DownloadBase.FilePath.Replace("\\", "/");
|
||||
string[] temp = downloading.DownloadBase.FilePath.Split('/');
|
||||
//string path = downloading.DownloadBase.FilePath.Replace(temp[temp.Length - 1], "");
|
||||
string path = downloading.DownloadBase.FilePath.TrimEnd(temp[temp.Length - 1].ToCharArray());
|
||||
|
||||
// 下载文件名
|
||||
string fileName = Guid.NewGuid().ToString("N");
|
||||
string key = $"{downloadVideo.Id}_{downloadVideo.Codecs}";
|
||||
|
||||
// 老版本数据库没有这一项,会变成null
|
||||
if (downloading.Downloading.DownloadedFiles == null)
|
||||
{
|
||||
downloading.Downloading.DownloadedFiles = new List<string>();
|
||||
}
|
||||
|
||||
if (downloading.Downloading.DownloadFiles.ContainsKey(key))
|
||||
{
|
||||
// 如果存在,表示下载过,
|
||||
// 则继续使用上次下载的文件名
|
||||
fileName = downloading.Downloading.DownloadFiles[key];
|
||||
|
||||
// 还要检查一下文件有没有被人删掉,删掉的话重新下载
|
||||
// 如果下载视频之后音频文件被人删了。此时gid还是视频的,会下错文件
|
||||
if (downloading.Downloading.DownloadedFiles.Contains(key) && File.Exists(Path.Combine(path, fileName)))
|
||||
{
|
||||
return Path.Combine(path, fileName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 记录本次下载的文件
|
||||
try
|
||||
{
|
||||
downloading.Downloading.DownloadFiles.Add(key, fileName);
|
||||
}
|
||||
catch (ArgumentException) { }
|
||||
// Gid最好能是每个文件单独存储,现在复用有可能会混
|
||||
// 不过好消息是下载是按固定顺序的,而且下载了两个音频会混流不过
|
||||
downloading.Downloading.Gid = null;
|
||||
}
|
||||
|
||||
// 启用https
|
||||
AllowStatus useSSL = SettingsManager.GetInstance().UseSSL();
|
||||
if (useSSL == AllowStatus.YES)
|
||||
{
|
||||
for (int i = 0; i < urls.Count; i++)
|
||||
{
|
||||
string url = urls[i];
|
||||
if (url.StartsWith("http://"))
|
||||
{
|
||||
urls[i] = url.Replace("http://", "https://");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < urls.Count; i++)
|
||||
{
|
||||
string url = urls[i];
|
||||
if (url.StartsWith("https://"))
|
||||
{
|
||||
urls[i] = url.Replace("https://", "http://");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 开始下载
|
||||
DownloadResult downloadStatus = DownloadByAria(downloading, urls, path, fileName);
|
||||
switch (downloadStatus)
|
||||
{
|
||||
case DownloadResult.SUCCESS:
|
||||
downloading.Downloading.DownloadedFiles.Add(key);
|
||||
downloading.Downloading.Gid = null;
|
||||
return Path.Combine(path, fileName);
|
||||
case DownloadResult.FAILED:
|
||||
case DownloadResult.ABORT:
|
||||
default:
|
||||
return nullMark;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 下载封面
|
||||
/// </summary>
|
||||
/// <param name="downloading"></param>
|
||||
public override string DownloadCover(DownloadingItem downloading, string coverUrl, string fileName)
|
||||
{
|
||||
return BaseDownloadCover(downloading, coverUrl, fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载弹幕
|
||||
/// </summary>
|
||||
/// <param name="downloading"></param>
|
||||
public override string DownloadDanmaku(DownloadingItem downloading)
|
||||
{
|
||||
return BaseDownloadDanmaku(downloading);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载字幕
|
||||
/// </summary>
|
||||
/// <param name="downloading"></param>
|
||||
public override List<string> DownloadSubtitle(DownloadingItem downloading)
|
||||
{
|
||||
return BaseDownloadSubtitle(downloading);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 混流音频和视频
|
||||
/// </summary>
|
||||
/// <param name="downloading"></param>
|
||||
/// <param name="audioUid"></param>
|
||||
/// <param name="videoUid"></param>
|
||||
/// <returns></returns>
|
||||
public override string MixedFlow(DownloadingItem downloading, string audioUid, string videoUid)
|
||||
{
|
||||
if (videoUid == nullMark)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return BaseMixedFlow(downloading, audioUid, videoUid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析视频流的下载链接
|
||||
/// </summary>
|
||||
/// <param name="downloading"></param>
|
||||
public override void Parse(DownloadingItem downloading)
|
||||
{
|
||||
BaseParse(downloading);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止下载服务(转换await和Task.Wait两种调用形式)
|
||||
/// </summary>
|
||||
private async Task EndTask()
|
||||
{
|
||||
// 停止基本任务
|
||||
await BaseEndTask();
|
||||
|
||||
// 关闭Aria服务器
|
||||
await CloseAriaServer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止下载服务
|
||||
/// </summary>
|
||||
public void End()
|
||||
{
|
||||
Task.Run(EndTask).Wait();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动下载服务
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
// 设置aria token
|
||||
AriaClient.SetToken(SettingsManager.GetInstance().GetAriaToken());
|
||||
// 设置aria host
|
||||
AriaClient.SetHost(SettingsManager.GetInstance().GetAriaHost());
|
||||
|
||||
// 启动基本服务
|
||||
BaseStart();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 强制暂停
|
||||
/// </summary>
|
||||
/// <param name="downloading"></param>
|
||||
/// <exception cref="OperationCanceledException"></exception>
|
||||
protected override void Pause(DownloadingItem downloading)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
downloading.DownloadStatusTitle = DictionaryResource.GetString("Pausing");
|
||||
if (downloading.Downloading.DownloadStatus == DownloadStatus.PAUSE)
|
||||
{
|
||||
throw new OperationCanceledException("Stop thread by pause");
|
||||
}
|
||||
// 是否存在
|
||||
var isExist = IsExist(downloading);
|
||||
if (!isExist.Result)
|
||||
{
|
||||
throw new OperationCanceledException("Task is deleted");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在于下载列表中
|
||||
/// </summary>
|
||||
/// <param name="downloading"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<bool> IsExist(DownloadingItem downloading)
|
||||
{
|
||||
bool isExist = downloadingList.Contains(downloading);
|
||||
if (isExist)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 先恢复为waiting状态,暂停状态下Remove会导致文件重新下载,原因暂不清楚
|
||||
await AriaClient.UnpauseAsync(downloading.Downloading.Gid);
|
||||
// 移除下载项
|
||||
var ariaRemove = await AriaClient.RemoveAsync(downloading.Downloading.Gid);
|
||||
if (ariaRemove == null || ariaRemove.Result == downloading.Downloading.Gid)
|
||||
{
|
||||
// 从内存中删除下载项
|
||||
await AriaClient.RemoveDownloadResultAsync(downloading.Downloading.Gid);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭Aria服务器
|
||||
/// </summary>
|
||||
private async Task CloseAriaServer()
|
||||
{
|
||||
// 暂停所有下载
|
||||
var ariaPause = await AriaClient.PauseAllAsync();
|
||||
#if DEBUG
|
||||
Core.Utils.Debugging.Console.PrintLine(ariaPause.ToString());
|
||||
#endif
|
||||
|
||||
// 关闭服务器
|
||||
bool close = AriaServer.CloseServer();
|
||||
#if DEBUG
|
||||
Core.Utils.Debugging.Console.PrintLine(close);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 采用Aria下载文件
|
||||
/// </summary>
|
||||
/// <param name="downloading"></param>
|
||||
/// <returns></returns>
|
||||
private DownloadResult DownloadByAria(DownloadingItem downloading, List<string> urls, string path, string localFileName)
|
||||
{
|
||||
// path已斜杠结尾,去掉斜杠
|
||||
path = path.TrimEnd('/').TrimEnd('\\');
|
||||
|
||||
//检查gid对应任务,如果已创建那么直接使用
|
||||
//但是代理设置会出现不能随时更新的问题
|
||||
|
||||
if (downloading.Downloading.Gid != null)
|
||||
{
|
||||
Task<AriaTellStatus> status = AriaClient.TellStatus(downloading.Downloading.Gid);
|
||||
if (status == null || status.Result == null)
|
||||
downloading.Downloading.Gid = null;
|
||||
else if (status.Result.Result == null && status.Result.Error != null)
|
||||
{
|
||||
if (status.Result.Error.Message.Contains("is not found"))
|
||||
{
|
||||
downloading.Downloading.Gid = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (downloading.Downloading.Gid == null)
|
||||
{
|
||||
AriaSendOption option = new AriaSendOption
|
||||
{
|
||||
//HttpProxy = $"http://{Settings.GetAriaHttpProxy()}:{Settings.GetAriaHttpProxyListenPort()}",
|
||||
Dir = path,
|
||||
Out = localFileName,
|
||||
//Header = $"cookie: {LoginHelper.GetLoginInfoCookiesString()}\nreferer: https://www.bilibili.com",
|
||||
//UseHead = "true",
|
||||
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36",
|
||||
};
|
||||
|
||||
//// 如果设置了代理,则增加HttpProxy
|
||||
//if (SettingsManager.GetInstance().IsAriaHttpProxy() == AllowStatus.YES)
|
||||
//{
|
||||
// option.HttpProxy = $"http://{SettingsManager.GetInstance().GetAriaHttpProxy()}:{SettingsManager.GetInstance().GetAriaHttpProxyListenPort()}";
|
||||
//}
|
||||
|
||||
// 添加一个下载
|
||||
Task<AriaAddUri> ariaAddUri = AriaClient.AddUriAsync(urls, option);
|
||||
if (ariaAddUri == null || ariaAddUri.Result == null || ariaAddUri.Result.Result == null)
|
||||
{
|
||||
return DownloadResult.FAILED;
|
||||
}
|
||||
|
||||
// 保存gid
|
||||
string gid = ariaAddUri.Result.Result;
|
||||
downloading.Downloading.Gid = gid;
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<AriaPause> ariaUnpause = AriaClient.UnpauseAsync(downloading.Downloading.Gid);
|
||||
}
|
||||
|
||||
// 管理下载
|
||||
AriaManager ariaManager = new AriaManager();
|
||||
ariaManager.TellStatus += AriaTellStatus;
|
||||
ariaManager.DownloadFinish += AriaDownloadFinish;
|
||||
return ariaManager.GetDownloadStatus(downloading.Downloading.Gid, new Action(() =>
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
switch (downloading.Downloading.DownloadStatus)
|
||||
{
|
||||
case DownloadStatus.PAUSE:
|
||||
Task<AriaPause> ariaPause = AriaClient.PauseAsync(downloading.Downloading.Gid);
|
||||
// 通知UI,并阻塞当前线程
|
||||
Pause(downloading);
|
||||
break;
|
||||
case DownloadStatus.DOWNLOADING:
|
||||
break;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void AriaTellStatus(long totalLength, long completedLength, long speed, string gid)
|
||||
{
|
||||
// 当前的下载视频
|
||||
DownloadingItem video = null;
|
||||
try
|
||||
{
|
||||
video = downloadingList.FirstOrDefault(it => it.Downloading.Gid == gid);
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
Core.Utils.Debugging.Console.PrintLine("AriaTellStatus()发生异常: {0}", e);
|
||||
LogManager.Error("AriaTellStatus()", e);
|
||||
}
|
||||
|
||||
if (video == null) { return; }
|
||||
|
||||
// 下载进度百分比
|
||||
float percent = 0;
|
||||
if (totalLength != 0)
|
||||
{
|
||||
percent = (float)completedLength / totalLength * 100;
|
||||
}
|
||||
|
||||
// 根据进度判断本次是否需要更新UI
|
||||
if (Math.Abs(percent - video.Progress) < 0.01) { return; }
|
||||
|
||||
// 下载进度
|
||||
video.Progress = percent;
|
||||
|
||||
// 下载大小
|
||||
video.DownloadingFileSize = Format.FormatFileSize(completedLength) + "/" + Format.FormatFileSize(totalLength);
|
||||
|
||||
// 下载速度
|
||||
video.SpeedDisplay = Format.FormatSpeed(speed);
|
||||
|
||||
// 最大下载速度
|
||||
if (video.Downloading.MaxSpeed < speed)
|
||||
{
|
||||
video.Downloading.MaxSpeed = speed;
|
||||
}
|
||||
}
|
||||
|
||||
private void AriaDownloadFinish(bool isSuccess, string downloadPath, string gid, string msg)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,13 @@ namespace DownKyi.ViewModels.Settings
|
||||
set => SetProperty(ref aria2c, value);
|
||||
}
|
||||
|
||||
private bool customAria2c;
|
||||
public bool CustomAria2c
|
||||
{
|
||||
get => customAria2c;
|
||||
set => SetProperty(ref customAria2c, value);
|
||||
}
|
||||
|
||||
private List<int> maxCurrentDownloads;
|
||||
public List<int> MaxCurrentDownloads
|
||||
{
|
||||
@@ -90,6 +97,13 @@ namespace DownKyi.ViewModels.Settings
|
||||
set => SetProperty(ref httpProxyPort, value);
|
||||
}
|
||||
|
||||
private string ariaHost;
|
||||
public string AriaHost
|
||||
{
|
||||
get => ariaHost;
|
||||
set => SetProperty(ref ariaHost, value);
|
||||
}
|
||||
|
||||
private int ariaListenPort;
|
||||
public int AriaListenPort
|
||||
{
|
||||
@@ -97,6 +111,13 @@ namespace DownKyi.ViewModels.Settings
|
||||
set => SetProperty(ref ariaListenPort, value);
|
||||
}
|
||||
|
||||
private string ariaToken;
|
||||
public string AriaToken
|
||||
{
|
||||
get => ariaToken;
|
||||
set => SetProperty(ref ariaToken, value);
|
||||
}
|
||||
|
||||
private List<string> ariaLogLevels;
|
||||
public List<string> AriaLogLevels
|
||||
{
|
||||
@@ -259,6 +280,9 @@ namespace DownKyi.ViewModels.Settings
|
||||
case Downloader.ARIA:
|
||||
Aria2c = true;
|
||||
break;
|
||||
case Downloader.CUSTOM_ARIA:
|
||||
CustomAria2c = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// builtin同时下载数
|
||||
@@ -277,9 +301,15 @@ namespace DownKyi.ViewModels.Settings
|
||||
// builtin的http代理的端口
|
||||
HttpProxyPort = SettingsManager.GetInstance().GetHttpProxyListenPort();
|
||||
|
||||
// Aria服务器host
|
||||
AriaHost = SettingsManager.GetInstance().GetAriaHost();
|
||||
|
||||
// Aria服务器端口
|
||||
AriaListenPort = SettingsManager.GetInstance().GetAriaListenPort();
|
||||
|
||||
// Aria服务器Token
|
||||
AriaToken = SettingsManager.GetInstance().GetAriaToken();
|
||||
|
||||
// Aria的日志等级
|
||||
AriaConfigLogLevel ariaLogLevel = SettingsManager.GetInstance().GetAriaLogLevel();
|
||||
SelectedAriaLogLevel = ariaLogLevel.ToString("G");
|
||||
@@ -349,6 +379,9 @@ namespace DownKyi.ViewModels.Settings
|
||||
case "Aria2c":
|
||||
downloader = Downloader.ARIA;
|
||||
break;
|
||||
case "CustomAria2c":
|
||||
downloader = Downloader.CUSTOM_ARIA;
|
||||
break;
|
||||
default:
|
||||
downloader = SettingsManager.GetInstance().GetDownloader();
|
||||
break;
|
||||
@@ -444,6 +477,21 @@ namespace DownKyi.ViewModels.Settings
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria服务器host事件
|
||||
private DelegateCommand<string> ariaHostCommand;
|
||||
public DelegateCommand<string> AriaHostCommand => ariaHostCommand ?? (ariaHostCommand = new DelegateCommand<string>(ExecuteAriaHostCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria服务器host事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteAriaHostCommand(string parameter)
|
||||
{
|
||||
AriaHost = parameter;
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAriaHost(AriaHost);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria服务器端口事件
|
||||
private DelegateCommand<string> ariaListenPortCommand;
|
||||
public DelegateCommand<string> AriaListenPortCommand => ariaListenPortCommand ?? (ariaListenPortCommand = new DelegateCommand<string>(ExecuteAriaListenPortCommand));
|
||||
@@ -461,6 +509,21 @@ namespace DownKyi.ViewModels.Settings
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria服务器token事件
|
||||
private DelegateCommand<string> ariaTokenCommand;
|
||||
public DelegateCommand<string> AriaTokenCommand => ariaTokenCommand ?? (ariaTokenCommand = new DelegateCommand<string>(ExecuteAriaTokenCommand));
|
||||
|
||||
/// <summary>
|
||||
/// Aria服务器token事件
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
private void ExecuteAriaTokenCommand(string parameter)
|
||||
{
|
||||
AriaToken = parameter;
|
||||
bool isSucceed = SettingsManager.GetInstance().SetAriaToken(AriaToken);
|
||||
PublishTip(isSucceed);
|
||||
}
|
||||
|
||||
// Aria的日志等级事件
|
||||
private DelegateCommand<string> ariaLogLevelsCommand;
|
||||
public DelegateCommand<string> AriaLogLevelsCommand => ariaLogLevelsCommand ?? (ariaLogLevelsCommand = new DelegateCommand<string>(ExecuteAriaLogLevelsCommand));
|
||||
|
||||
@@ -56,6 +56,15 @@
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
IsChecked="{Binding Aria2c}"
|
||||
Style="{StaticResource RadioStyle}" />
|
||||
<RadioButton
|
||||
Margin="20,0,0,0"
|
||||
Command="{Binding SelectDownloaderCommand}"
|
||||
CommandParameter="CustomAria2c"
|
||||
Content="{DynamicResource CustomAria2cDownloader}"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
IsChecked="{Binding CustomAria2c}"
|
||||
Style="{StaticResource RadioStyle}" />
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</StackPanel>
|
||||
@@ -208,6 +217,32 @@
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
|
||||
<!--<StackPanel
|
||||
Margin="0,20,0,0"
|
||||
Orientation="Horizontal"
|
||||
ToolTip="{DynamicResource PressEnterToApplySettingTip}">
|
||||
<TextBlock
|
||||
Width="100"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource AriaServerHost}" />
|
||||
<TextBox
|
||||
Name="nameAriaLocalHost"
|
||||
Width="100"
|
||||
Height="20"
|
||||
VerticalContentAlignment="Center"
|
||||
IsReadOnly="True"
|
||||
Text="{Binding AriaHost}">
|
||||
<TextBox.InputBindings>
|
||||
<KeyBinding
|
||||
Key="Enter"
|
||||
Command="{Binding AriaHostCommand}"
|
||||
CommandParameter="{Binding ElementName=nameAriaLocalHost, Path=Text}" />
|
||||
</TextBox.InputBindings>
|
||||
</TextBox>
|
||||
</StackPanel>-->
|
||||
|
||||
<StackPanel
|
||||
Margin="0,20,0,0"
|
||||
Orientation="Horizontal"
|
||||
@@ -449,6 +484,97 @@
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel x:Name="nameCustomAria">
|
||||
<StackPanel.Style>
|
||||
<Style TargetType="{x:Type StackPanel}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding CustomAria2c}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding CustomAria2c}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
|
||||
<StackPanel
|
||||
Margin="0,20,0,0"
|
||||
Orientation="Horizontal"
|
||||
ToolTip="{DynamicResource PressEnterToApplySettingTip}">
|
||||
<TextBlock
|
||||
Width="100"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource AriaServerHost}" />
|
||||
<TextBox
|
||||
Name="nameAriaHost"
|
||||
Width="300"
|
||||
Height="20"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding AriaHost}">
|
||||
<TextBox.InputBindings>
|
||||
<KeyBinding
|
||||
Key="Enter"
|
||||
Command="{Binding AriaHostCommand}"
|
||||
CommandParameter="{Binding ElementName=nameAriaHost, Path=Text}" />
|
||||
</TextBox.InputBindings>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
Margin="0,20,0,0"
|
||||
Orientation="Horizontal"
|
||||
ToolTip="{DynamicResource PressEnterToApplySettingTip}">
|
||||
<TextBlock
|
||||
Width="100"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource AriaServerPort}" />
|
||||
<TextBox
|
||||
Name="nameAriaPort"
|
||||
Width="100"
|
||||
Height="20"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding AriaListenPort}">
|
||||
<TextBox.InputBindings>
|
||||
<KeyBinding
|
||||
Key="Enter"
|
||||
Command="{Binding AriaListenPortCommand}"
|
||||
CommandParameter="{Binding ElementName=nameAriaPort, Path=Text}" />
|
||||
</TextBox.InputBindings>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
Margin="0,20,0,0"
|
||||
Orientation="Horizontal"
|
||||
ToolTip="{DynamicResource PressEnterToApplySettingTip}">
|
||||
<TextBlock
|
||||
Width="100"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource BrushTextDark}"
|
||||
Text="{DynamicResource AriaServerToken}" />
|
||||
<TextBox
|
||||
Name="nameAriaToken"
|
||||
Width="100"
|
||||
Height="20"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding AriaToken}">
|
||||
<TextBox.InputBindings>
|
||||
<KeyBinding
|
||||
Key="Enter"
|
||||
Command="{Binding AriaTokenCommand}"
|
||||
CommandParameter="{Binding ElementName=nameAriaToken, Path=Text}" />
|
||||
</TextBox.InputBindings>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="10" />
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
Reference in New Issue
Block a user