完善下载服务中,20211221暂存

croire 3 years ago
parent 966b707165
commit 7c43873e87

@ -18,5 +18,19 @@ namespace DownKyi.Core.BiliApi.Bangumi
{ 10, "Unknown" } { 10, "Unknown" }
}; };
public static Dictionary<int, int> TypeId = new Dictionary<int, int>()
{
{ 1, 13 },
{ 2, 23 },
{ 3, 177 },
{ 4, 167 },
{ 5, 11 },
{ 6, -1 },
{ 7, -1 },
{ 8, -1 },
{ 9, -1 },
{ 10, -1 }
};
} }
} }

@ -14,5 +14,15 @@ namespace DownKyi.Core.BiliApi.BiliUtils
{ 30280, "192K" } { 30280, "192K" }
}; };
/// <summary>
/// 音质id及含义
/// </summary>
public static Dictionary<string, int> AudioQualityId { get; } = new Dictionary<string, int>()
{
{ "64K", 30216 },
{ "132K", 30232 },
{ "192K", 30280 }
};
} }
} }

@ -21,5 +21,7 @@ namespace DownKyi.Core.BiliApi.Video.Models
public string Weblink { get; set; } public string Weblink { get; set; }
[JsonProperty("dimension")] [JsonProperty("dimension")]
public Dimension Dimension { get; set; } public Dimension Dimension { get; set; }
[JsonProperty("first_frame")]
public string FirstFrame { get; set; }
} }
} }

@ -37,7 +37,8 @@ namespace DownKyi.Core.BiliApi.VideoStream
} }
/// <summary> /// <summary>
/// 获取所有字幕 /// 获取所有字幕<br/>
/// 若视频没有字幕返回null
/// </summary> /// </summary>
/// <param name="avid"></param> /// <param name="avid"></param>
/// <param name="bvid"></param> /// <param name="bvid"></param>
@ -48,8 +49,12 @@ namespace DownKyi.Core.BiliApi.VideoStream
List<SubRipText> subRipTexts = new List<SubRipText>(); List<SubRipText> subRipTexts = new List<SubRipText>();
// 获取播放器信息 // 获取播放器信息
var player = PlayerV2(avid, bvid, cid); PlayerV2 player = PlayerV2(avid, bvid, cid);
if (player == null) { return subRipTexts; } if (player == null) { return subRipTexts; }
if (player.Subtitle != null && player.Subtitle.Subtitles != null && player.Subtitle.Subtitles.Count == 0)
{
return null;
}
foreach (var subtitle in player.Subtitle.Subtitles) foreach (var subtitle in player.Subtitle.Subtitles)
{ {

@ -34,6 +34,9 @@
{ {
switch (tid) switch (tid)
{ {
// 课堂
case -10:
return "Zone.cheeseDrawingImage";
case 1: case 1:
return "Zone.dougaDrawingImage"; return "Zone.dougaDrawingImage";
case 13: case 13:

@ -46,6 +46,21 @@
</DrawingImage.Drawing> </DrawingImage.Drawing>
</DrawingImage> </DrawingImage>
<DrawingImage x:Key="Zone.cheeseDrawingImage">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V128 H128 V0 H0 Z">
<GeometryDrawing Brush="#FFFBC92A" Geometry="F1 M128,128z M0,0z M105.8,0C109.2,0 112.3,0.9 115.2,2.6 118.1,4.3 120.3,6.6 122,9.5 123.7,12.4 124.5,15.5 124.5,19L124.5,108.9C124.5,112.4 123.7,115.6 122,118.4 120.3,121.3 118,123.6 115.2,125.3 112.4,127 109.2,127.9 105.8,127.9L61.6,127.9C61.6,126.6 60.6,125.4 58.7,124.4 56.8,123.4 54.5,122.9 51.9,122.9 49.3,122.9 47,123.4 45.1,124.4 43.2,125.4 42.2,126.6 42.2,127.9L22.2,127.9C18.8,127.9 15.7,127 12.8,125.3 9.9,123.6 7.7,121.3 6,118.4 4.3,115.5 3.5,112.4 3.5,108.9L3.5,19.1C3.6,15.6 4.5,12.4 6.1,9.6 7.7,6.8 10,4.4 12.8,2.7 15.7,1 18.8,0.100000000000001 22.2,0.100000000000001L105.8,0.100000000000001 105.8,0z" />
<GeometryDrawing Brush="#FFFFEA85" Geometry="F1 M128,128z M0,0z M105.8,0C109.2,0 112.3,0.9 115.2,2.6 118.1,4.3 120.3,6.6 122,9.5 123.7,12.4 124.5,15.5 124.5,19L124.5,54.2C120.2,54.7 116.7,55.5 114,56.9 111.3,58.3 110,59.8 110,61.5 110,63.2 111.3,64.7 114,66.1 116.7,67.4 120.2,68.3 124.5,68.6L124.5,74.5C124.5,78 123.7,81.2 122,84 120.3,86.9 118,89.1 115.2,90.8 112.4,92.5 109.2,93.3 105.8,93.3L22.2,93.3C18.8,93.3 15.7,92.5 12.8,90.8 9.9,89.1 7.7,86.8 6,84 4.3,81.1 3.5,78 3.5,74.5L3.5,19.1C3.6,15.6 4.5,12.4 6.1,9.6 7.7,6.8 10,4.4 12.8,2.7 15.7,1 18.8,0.100000000000001 22.2,0.100000000000001L105.8,0 105.8,0z" />
<GeometryDrawing Brush="#FFFBC92A" Geometry="F1 M128,128z M0,0z M32.6,93.4C32.6,95.2 33.4,96.9 35.1,98.4 36.8,99.9 39.1,101.1 42.1,102 45.1,102.9 48.3,103.3 51.9,103.3 55.4,103.3 58.7,102.9 61.6,102 64.5,101.1 66.9,99.9 68.6,98.4 70.3,96.9 71.2,95.3 71.2,93.5 71.2,91.8 70.3,90.1 68.6,88.6 66.9,87.1 64.5,85.9 61.6,85 58.7,84.1 55.4,83.7 51.9,83.7 48.4,83.7 45.1,84.1 42.1,85 39.1,85.9 36.8,87.1 35.1,88.6 33.5,90.1 32.6,91.7 32.6,93.4L32.6,93.4z" />
<GeometryDrawing Brush="#FFF4B828" Geometry="F1 M128,128z M0,0z M18.1,113.2C18.1,115.2 18.8,116.9 20.2,118.3 21.6,119.6 23.3,120.3 25.3,120.3 27.3,120.3 29,119.6 30.4,118.3 31.9,117 32.6,115.3 32.6,113.3 32.6,111.3 31.9,109.6 30.4,108.2 28.9,106.8 27.2,106.1 25.3,106.1 23.4,106.1 21.6,106.8 20.2,108.2 18.8,109.6 18.1,111.2 18.1,113.2L18.1,113.2z" />
<GeometryDrawing Brush="#FFF4B828" Geometry="F1 M128,128z M0,0z M56.7,113.2C56.7,115.2 57.9,116.9 60.2,118.3 62.5,119.7 65.4,120.3 68.7,120.3 72,120.3 74.9,119.6 77.3,118.3 79.7,117 80.9,115.3 80.9,113.3 80.9,111.3 79.7,109.6 77.3,108.2 74.9,106.8 72,106.1 68.7,106.1 65.4,106.1 62.5,106.8 60.2,108.2 57.9,109.6 56.7,111.2 56.7,113.2L56.7,113.2z" />
<GeometryDrawing Brush="#FFF0BF4C" Geometry="F1 M128,128z M0,0z M87.9,58.2C88.8,57.3 89.9,56.9 91.2,56.9 92.5,57 93.6,57.5 94.4,58.4 95.2,59.3 95.7,60.5 95.7,61.8 95.7,63.1 95.2,64.2 94.2,65.1 89.1,70 83.2,73.4 76.5,75.1 69.8,76.8 63,76.8 56.3,75.1 49.6,73.4 43.6,70 38.4,65.1 37.5,64.2 37,63.1 37,61.8 36.9,60.5 37.4,59.4 38.3,58.4 39.2,57.4 40.3,56.9 41.6,56.9 42.9,56.8 44,57.3 44.9,58.2 48.8,62 53.4,64.6 58.6,66 63.8,67.3 69,67.3 74.2,66 79.4,64.7 83.9,62 87.9,58.2L87.9,58.2z" />
<GeometryDrawing Brush="#FFF0BF4C" Geometry="F1 M128,128z M0,0z M98.1,23.8L98.9,23.8C100.8,23.8 102.5,24.5 103.9,25.9 105.3,27.3 106,29 105.8,30.9L105.8,40.3C105.8,42.3 105.1,44 103.8,45.4 102.5,46.8 100.8,47.5 98.9,47.5L98.1,47.5C96.1,47.4 94.4,46.7 93,45.3 91.6,43.9 91,42.3 91,40.2L91,30.8C91,28.9 91.7,27.2 93.1,25.8 94.5,24.5 96.2,23.8 98.1,23.8z" />
<GeometryDrawing Brush="#FFF0BF4C" Geometry="F1 M128,128z M0,0z M33.8,23.8L34.6,23.8C36.5,23.8 38.2,24.5 39.6,25.9 41,27.3 41.7,29 41.5,30.9L41.5,40.3C41.5,42.3 40.8,44 39.5,45.4 38.2,46.8 36.5,47.5 34.6,47.5L33.8,47.5C31.8,47.4 30.1,46.7 28.7,45.3 27.4,44 26.7,42.3 26.7,40.2L26.7,30.8C26.7,28.9 27.4,27.2 28.8,25.8 30.2,24.5 31.9,23.8 33.8,23.8z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="Zone.cinephileDrawingImage"> <DrawingImage x:Key="Zone.cinephileDrawingImage">
<DrawingImage.Drawing> <DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z"> <DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">

@ -1,4 +1,6 @@
namespace DownKyi.Core.Utils using System.Text.RegularExpressions;
namespace DownKyi.Core.Utils
{ {
public static class Format public static class Format
{ {
@ -164,5 +166,39 @@
return formatFileSize; return formatFileSize;
} }
/// <summary>
/// 去除非法字符
/// </summary>
/// <param name="originName"></param>
/// <returns></returns>
public static string FormatFileName(string originName)
{
string destName = originName;
// Windows中不能作为文件名的字符
destName = destName.Replace("\\", " ");
destName = destName.Replace("/", " ");
destName = destName.Replace(":", " ");
destName = destName.Replace("*", " ");
destName = destName.Replace("?", " ");
destName = destName.Replace("\"", " ");
destName = destName.Replace("<", " ");
destName = destName.Replace(">", " ");
destName = destName.Replace("|", " ");
// 转义字符
destName = destName.Replace("\a", "");
destName = destName.Replace("\b", "");
destName = destName.Replace("\f", "");
destName = destName.Replace("\n", "");
destName = destName.Replace("\r", "");
destName = destName.Replace("\t", "");
destName = destName.Replace("\v", "");
// 控制字符
destName = Regex.Replace(destName, @"\p{C}+", string.Empty);
return destName.Trim();
}
} }
} }

@ -43,76 +43,6 @@ namespace DownKyi
DownloadingList = new ObservableCollection<DownloadingItem>(); DownloadingList = new ObservableCollection<DownloadingItem>();
DownloadedList = new ObservableCollection<DownloadedItem>(); DownloadedList = new ObservableCollection<DownloadedItem>();
// test DownloadingList data
DownloadingList.Add(new DownloadingItem
{
MainTitle = "Test1",
Name = "name1=name1=name1=name1=name1=name1=name1=name1=name1=name1=name1",
ZoneImage = (System.Windows.Media.DrawingImage)Current.Resources[Core.BiliApi.Zone.VideoZoneIcon.Instance().GetZoneImageKey(4)],
Resolution = new Resolution
{
Name = "1080P",
Id = 64
},
AudioCodecName = "194K",
});
DownloadingList.Add(new DownloadingItem
{
MainTitle = "Test2",
Name = "name2",
ZoneImage = (System.Windows.Media.DrawingImage)Current.Resources[Core.BiliApi.Zone.VideoZoneIcon.Instance().GetZoneImageKey(3)],
Resolution = new Resolution
{
Name = "1080P",
Id = 64
},
Duration = "1h23m50s",
VideoCodecName = "HEVC",
AudioCodecName = "194K",
});
DownloadingList.Add(new DownloadingItem
{
MainTitle = "Test3",
Name = "name3",
ZoneImage = (System.Windows.Media.DrawingImage)Current.Resources[Core.BiliApi.Zone.VideoZoneIcon.Instance().GetZoneImageKey(3)],
Resolution = new Resolution
{
Name = "720P",
Id = 64
},
Duration = "23m50s",
VideoCodecName = "AVC",
AudioCodecName = "194K",
});
DownloadingList.Add(new DownloadingItem
{
MainTitle = "Test4",
Name = "name4",
ZoneImage = (System.Windows.Media.DrawingImage)Current.Resources[Core.BiliApi.Zone.VideoZoneIcon.Instance().GetZoneImageKey(3)],
Resolution = new Resolution
{
Name = "720P",
Id = 64
},
Duration = "23m50s",
VideoCodecName = "AVC",
AudioCodecName = "194K",
});
DownloadingList.Add(new DownloadingItem
{
MainTitle = "Test5",
Name = "name5",
ZoneImage = (System.Windows.Media.DrawingImage)Current.Resources[Core.BiliApi.Zone.VideoZoneIcon.Instance().GetZoneImageKey(5)],
Resolution = new Resolution
{
Name = "720P",
Id = 64
},
Duration = "23m50s",
VideoCodecName = "AVC",
AudioCodecName = "194K",
});
// TODO 从数据库读取 // TODO 从数据库读取
// 启动下载服务 // 启动下载服务

@ -87,6 +87,7 @@
<Compile Include="Images\LogoIcon.cs" /> <Compile Include="Images\LogoIcon.cs" />
<Compile Include="Images\NavigationIcon.cs" /> <Compile Include="Images\NavigationIcon.cs" />
<Compile Include="Images\NormalIcon.cs" /> <Compile Include="Images\NormalIcon.cs" />
<Compile Include="Models\DownloadBaseItem.cs" />
<Compile Include="Models\DownloadedItem.cs" /> <Compile Include="Models\DownloadedItem.cs" />
<Compile Include="Models\DownloadingItem.cs" /> <Compile Include="Models\DownloadingItem.cs" />
<Compile Include="Models\DownloadStatus.cs" /> <Compile Include="Models\DownloadStatus.cs" />

@ -64,6 +64,12 @@
<system:String x:Key="DownloadSelected">下载选中项</system:String> <system:String x:Key="DownloadSelected">下载选中项</system:String>
<system:String x:Key="AddAllToDownload">下载全部</system:String> <system:String x:Key="AddAllToDownload">下载全部</system:String>
<system:String x:Key="TipAlreadyToAddDownloading">已经添加到下载列表~</system:String>
<system:String x:Key="TipAlreadyToAddDownloaded">已经下载完成~</system:String>
<system:String x:Key="TipAddDownloadingZero">没有选中项符合下载要求!</system:String>
<system:String x:Key="TipAddDownloadingFinished1">成功添加了</system:String>
<system:String x:Key="TipAddDownloadingFinished2">项~</system:String>
<!-- DownloadManager --> <!-- DownloadManager -->
<system:String x:Key="Downloading">正在下载</system:String> <system:String x:Key="Downloading">正在下载</system:String>
<system:String x:Key="DownloadFinished">已下载</system:String> <system:String x:Key="DownloadFinished">已下载</system:String>

@ -0,0 +1,122 @@
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Windows.Media;
namespace DownKyi.Models
{
public class DownloadBaseItem : BindableBase
{
public DownloadBaseItem()
{
// 唯一id
Uuid = Guid.NewGuid().ToString("N");
// 初始化需要下载的内容
NeedDownloadContent = new Dictionary<string, bool>
{
{ "downloadAudio", true },
{ "downloadVideo", true },
{ "downloadDanmaku", true },
{ "downloadSubtitle", true },
{ "downloadCover", true }
};
}
// 此条下载项的id
public string Uuid { get; }
// 需要下载的内容
public Dictionary<string, bool> NeedDownloadContent { get; private set; }
// 视频的id
public string Bvid { get; set; }
public long Avid { get; set; }
public long Cid { get; set; }
public long EpisodeId { get; set; }
// 视频封面的url
public string CoverUrl { get; set; }
private DrawingImage zoneImage;
public DrawingImage ZoneImage
{
get => zoneImage;
set => SetProperty(ref zoneImage, value);
}
// 视频序号
private int order;
public int Order
{
get => order;
set => SetProperty(ref order, value);
}
// 视频主标题
private string mainTitle;
public string MainTitle
{
get => mainTitle;
set => SetProperty(ref mainTitle, value);
}
// 视频标题
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
// 时长
private string duration;
public string Duration
{
get => duration;
set => SetProperty(ref duration, value);
}
// 音频编码
public int AudioCodecId { get; set; }
private string audioCodecName;
public string AudioCodecName
{
get => audioCodecName;
set => SetProperty(ref audioCodecName, value);
}
// 视频编码
// "hev1.2.4.L156.90"
// "avc1.640034"
//public string VideoCodecId { get; set; }
// 视频编码名称AVC、HEVC
private string videoCodecName;
public string VideoCodecName
{
get => videoCodecName;
set => SetProperty(ref videoCodecName, value);
}
// 视频画质
private Resolution resolution;
public Resolution Resolution
{
get => resolution;
set => SetProperty(ref resolution, value);
}
// 文件路径,不包含扩展名,所有内容均以此路径下载
public string FilePath { get; set; }
// 文件大小
private string fileSize;
public string FileSize
{
get => fileSize;
set => SetProperty(ref fileSize, value);
}
}
}

@ -1,13 +1,9 @@
using Prism.Mvvm; namespace DownKyi.Models
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DownKyi.Models
{ {
public class DownloadedItem : BindableBase public class DownloadedItem : DownloadBaseItem
{ {
public DownloadedItem() : base()
{
}
} }
} }

@ -1,34 +1,19 @@
using DownKyi.Core.BiliApi.VideoStream.Models; using DownKyi.Core.Aria2cNet.Client;
using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Images; using DownKyi.Images;
using DownKyi.Utils; using DownKyi.Utils;
using Prism.Commands; using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Media;
namespace DownKyi.Models namespace DownKyi.Models
{ {
public class DownloadingItem : BindableBase public class DownloadingItem : DownloadBaseItem
{ {
public DownloadingItem() public DownloadingItem() : base()
{ {
// 唯一id
Uuid = Guid.NewGuid().ToString("N");
// 初始化下载的文件列表 // 初始化下载的文件列表
DownloadFiles = new List<string>(); DownloadFiles = new List<string>();
// 初始化需要下载的内容
NeedDownloadContent = new Dictionary<string, bool>
{
{ "downloadAudio", true },
{ "downloadVideo", true },
{ "downloadDanmaku", true },
{ "downloadSubtitle", true },
{ "downloadCover", true }
};
// 暂停继续按钮 // 暂停继续按钮
StartOrPause = ButtonIcon.Instance().Pause; StartOrPause = ButtonIcon.Instance().Pause;
StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary"); StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
@ -40,109 +25,15 @@ namespace DownKyi.Models
public PlayUrl PlayUrl { get; set; } public PlayUrl PlayUrl { get; set; }
// 此条下载项的id
public string Uuid { get; }
// Aria相关 // Aria相关
public string Gid { get; set; } public string Gid { get; set; }
// 文件路径,不包含扩展名,所有内容均以此路径下载
public string FilePath { get; set; }
// 下载的文件 // 下载的文件
public List<string> DownloadFiles { get; private set; } public List<string> DownloadFiles { get; private set; }
// 文件大小
private string fileSize;
public string FileSize
{
get => fileSize;
set => SetProperty(ref fileSize, value);
}
// 视频类别 // 视频类别
public PlayStreamType PlayStreamType { get; set; } public PlayStreamType PlayStreamType { get; set; }
// 视频的id
public string Bvid { get; set; }
public long Avid { get; set; }
public long Cid { get; set; }
public long EpisodeId { get; set; }
// 视频封面的url
public string CoverUrl { get; set; }
private DrawingImage zoneImage;
public DrawingImage ZoneImage
{
get => zoneImage;
set => SetProperty(ref zoneImage, value);
}
// 视频序号
private int order;
public int Order
{
get => order;
set => SetProperty(ref order, value);
}
// 视频主标题
private string mainTitle;
public string MainTitle
{
get => mainTitle;
set => SetProperty(ref mainTitle, value);
}
// 视频标题
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
// 时长
private string duration;
public string Duration
{
get => duration;
set => SetProperty(ref duration, value);
}
// 音频编码
public int AudioCodecId { get; set; }
private string audioCodecName;
public string AudioCodecName
{
get => audioCodecName;
set => SetProperty(ref audioCodecName, value);
}
// 视频编码
// "hev1.2.4.L156.90"
// "avc1.640034"
public string VideoCodecId { get; set; }
// 视频编码名称AVC、HEVC
private string videoCodecName;
public string VideoCodecName
{
get => videoCodecName;
set => SetProperty(ref videoCodecName, value);
}
// 视频画质
private Resolution resolution;
public Resolution Resolution
{
get => resolution;
set => SetProperty(ref resolution, value);
}
// 需要下载的内容
public Dictionary<string, bool> NeedDownloadContent { get; private set; }
// 正在下载内容(音频、视频、弹幕、字幕、封面) // 正在下载内容(音频、视频、弹幕、字幕、封面)
private string downloadContent; private string downloadContent;

@ -9,103 +9,104 @@ namespace DownKyi.Models
{ {
public string CoverUrl { get; set; } public string CoverUrl { get; set; }
public long UpperMid { get; set; } public long UpperMid { get; set; }
public int TypeId { get; set; }
private BitmapImage cover; private BitmapImage cover;
public BitmapImage Cover public BitmapImage Cover
{ {
get { return cover; } get => cover;
set { SetProperty(ref cover, value); } set => SetProperty(ref cover, value);
} }
private string title; private string title;
public string Title public string Title
{ {
get { return title; } get => title;
set { SetProperty(ref title, value); } set => SetProperty(ref title, value);
} }
private string videoZone; private string videoZone;
public string VideoZone public string VideoZone
{ {
get { return videoZone; } get => videoZone;
set { SetProperty(ref videoZone, value); } set => SetProperty(ref videoZone, value);
} }
private string createTime; private string createTime;
public string CreateTime public string CreateTime
{ {
get { return createTime; } get => createTime;
set { SetProperty(ref createTime, value); } set => SetProperty(ref createTime, value);
} }
private string playNumber; private string playNumber;
public string PlayNumber public string PlayNumber
{ {
get { return playNumber; } get => playNumber;
set { SetProperty(ref playNumber, value); } set => SetProperty(ref playNumber, value);
} }
private string danmakuNumber; private string danmakuNumber;
public string DanmakuNumber public string DanmakuNumber
{ {
get { return danmakuNumber; } get => danmakuNumber;
set { SetProperty(ref danmakuNumber, value); } set => SetProperty(ref danmakuNumber, value);
} }
private string likeNumber; private string likeNumber;
public string LikeNumber public string LikeNumber
{ {
get { return likeNumber; } get => likeNumber;
set { SetProperty(ref likeNumber, value); } set => SetProperty(ref likeNumber, value);
} }
private string coinNumber; private string coinNumber;
public string CoinNumber public string CoinNumber
{ {
get { return coinNumber; } get => coinNumber;
set { SetProperty(ref coinNumber, value); } set => SetProperty(ref coinNumber, value);
} }
private string favoriteNumber; private string favoriteNumber;
public string FavoriteNumber public string FavoriteNumber
{ {
get { return favoriteNumber; } get => favoriteNumber;
set { SetProperty(ref favoriteNumber, value); } set => SetProperty(ref favoriteNumber, value);
} }
private string shareNumber; private string shareNumber;
public string ShareNumber public string ShareNumber
{ {
get { return shareNumber; } get => shareNumber;
set { SetProperty(ref shareNumber, value); } set => SetProperty(ref shareNumber, value);
} }
private string replyNumber; private string replyNumber;
public string ReplyNumber public string ReplyNumber
{ {
get { return replyNumber; } get => replyNumber;
set { SetProperty(ref replyNumber, value); } set => SetProperty(ref replyNumber, value);
} }
private string description; private string description;
public string Description public string Description
{ {
get { return description; } get => description;
set { SetProperty(ref description, value); } set => SetProperty(ref description, value);
} }
private string upName; private string upName;
public string UpName public string UpName
{ {
get { return upName; } get => upName;
set { SetProperty(ref upName, value); } set => SetProperty(ref upName, value);
} }
private BitmapImage upHeader; private BitmapImage upHeader;
public BitmapImage UpHeader public BitmapImage UpHeader
{ {
get { return upHeader; } get => upHeader;
set { SetProperty(ref upHeader, value); } set => SetProperty(ref upHeader, value);
} }
} }

@ -13,60 +13,62 @@ namespace DownKyi.Models
public long Cid { get; set; } public long Cid { get; set; }
public long EpisodeId { get; set; } public long EpisodeId { get; set; }
public string FirstFrame { get; set; }
private bool isSelected; private bool isSelected;
public bool IsSelected public bool IsSelected
{ {
get { return isSelected; } get => isSelected;
set { SetProperty(ref isSelected, value); } set => SetProperty(ref isSelected, value);
} }
private int order; private int order;
public int Order public int Order
{ {
get { return order; } get => order;
set { SetProperty(ref order, value); } set => SetProperty(ref order, value);
} }
private string name; private string name;
public string Name public string Name
{ {
get { return name; } get => name;
set { SetProperty(ref name, value); } set => SetProperty(ref name, value);
} }
private string duration; private string duration;
public string Duration public string Duration
{ {
get { return duration; } get => duration;
set { SetProperty(ref duration, value); } set => SetProperty(ref duration, value);
} }
private List<string> audioQualityFormatList; private List<string> audioQualityFormatList;
public List<string> AudioQualityFormatList public List<string> AudioQualityFormatList
{ {
get { return audioQualityFormatList; } get => audioQualityFormatList;
set { SetProperty(ref audioQualityFormatList, value); } set => SetProperty(ref audioQualityFormatList, value);
} }
private string audioQualityFormat; private string audioQualityFormat;
public string AudioQualityFormat public string AudioQualityFormat
{ {
get { return audioQualityFormat; } get => audioQualityFormat;
set { SetProperty(ref audioQualityFormat, value); } set => SetProperty(ref audioQualityFormat, value);
} }
private List<VideoQuality> videoQualityList; private List<VideoQuality> videoQualityList;
public List<VideoQuality> VideoQualityList public List<VideoQuality> VideoQualityList
{ {
get { return videoQualityList; } get => videoQualityList;
set { SetProperty(ref videoQualityList, value); } set => SetProperty(ref videoQualityList, value);
} }
private VideoQuality videoQuality; private VideoQuality videoQuality;
public VideoQuality VideoQuality public VideoQuality VideoQuality
{ {
get { return videoQuality; } get => videoQuality;
set { SetProperty(ref videoQuality, value); } set => SetProperty(ref videoQuality, value);
} }
} }

@ -8,30 +8,29 @@ namespace DownKyi.Models
private int quality; private int quality;
public int Quality public int Quality
{ {
get { return quality; } get => quality;
set { SetProperty(ref quality, value); } set => SetProperty(ref quality, value);
} }
private string qualityFormat; private string qualityFormat;
public string QualityFormat public string QualityFormat
{ {
get { return qualityFormat; } get => qualityFormat;
set { SetProperty(ref qualityFormat, value); } set => SetProperty(ref qualityFormat, value);
} }
private List<string> videoCodecList; private List<string> videoCodecList;
public List<string> VideoCodecList public List<string> VideoCodecList
{ {
get { return videoCodecList; } get => videoCodecList;
set { SetProperty(ref videoCodecList, value); } set => SetProperty(ref videoCodecList, value);
} }
private string selectedVideoCodec; private string selectedVideoCodec;
public string SelectedVideoCodec public string SelectedVideoCodec
{ {
get { return selectedVideoCodec; } get => selectedVideoCodec;
set { SetProperty(ref selectedVideoCodec, value); } set => SetProperty(ref selectedVideoCodec, value);
} }
} }
} }

@ -93,6 +93,7 @@ namespace DownKyi.Services
Bvid = episode.Bvid, Bvid = episode.Bvid,
Cid = episode.Cid, Cid = episode.Cid,
EpisodeId = -1, EpisodeId = -1,
FirstFrame = episode.Cover,
Order = order, Order = order,
Name = name, Name = name,
Duration = "N/A" Duration = "N/A"
@ -149,6 +150,7 @@ namespace DownKyi.Services
Bvid = episode.Bvid, Bvid = episode.Bvid,
Cid = episode.Cid, Cid = episode.Cid,
EpisodeId = -1, EpisodeId = -1,
FirstFrame = episode.Cover,
Order = order, Order = order,
Name = name, Name = name,
Duration = "N/A" Duration = "N/A"
@ -218,6 +220,9 @@ namespace DownKyi.Services
videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover)); videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover));
videoInfoView.Title = bangumiSeason.Title; videoInfoView.Title = bangumiSeason.Title;
// 分区id
videoInfoView.TypeId = BangumiType.TypeId[bangumiSeason.Type];
videoInfoView.VideoZone = DictionaryResource.GetString(BangumiType.Type[bangumiSeason.Type]); videoInfoView.VideoZone = DictionaryResource.GetString(BangumiType.Type[bangumiSeason.Type]);
videoInfoView.PlayNumber = Format.FormatNumber(bangumiSeason.Stat.Views); videoInfoView.PlayNumber = Format.FormatNumber(bangumiSeason.Stat.Views);

@ -61,6 +61,7 @@ namespace DownKyi.Services
Bvid = null, Bvid = null,
Cid = episode.Cid, Cid = episode.Cid,
EpisodeId = episode.Id, EpisodeId = episode.Id,
FirstFrame = episode.Cover,
Order = order, Order = order,
Name = name, Name = name,
Duration = "N/A" Duration = "N/A"
@ -129,6 +130,10 @@ namespace DownKyi.Services
videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover)); videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover));
videoInfoView.Title = cheeseView.Title; videoInfoView.Title = cheeseView.Title;
// 分区id
// 课堂的type id B站没有定义这里自定义为-10
videoInfoView.TypeId = -10;
videoInfoView.VideoZone = DictionaryResource.GetString("Cheese"); videoInfoView.VideoZone = DictionaryResource.GetString("Cheese");
videoInfoView.CreateTime = ""; videoInfoView.CreateTime = "";

@ -67,38 +67,6 @@ namespace DownKyi.Services.Download
} }
return DownloadVideo(downloading, downloadAudio); return DownloadVideo(downloading, downloadAudio);
//// 如果音频为空,说明没有匹配到可下载的音频
//if (downloadAudio == null) { return null; }
//// 下载链接
//List<string> audioUrls = new List<string>();
//if (downloadAudio.BaseUrl != null) { audioUrls.Add(downloadAudio.BaseUrl); }
//if (downloadAudio.BackupUrl != null) { audioUrls.AddRange(downloadAudio.BackupUrl); }
//// 路径
//string[] temp = downloading.FilePath.Split('/');
//string path = downloading.FilePath.Replace(temp[temp.Length - 1], "");
//// 下载文件名
//string fileName = Guid.NewGuid().ToString("N");
//fileName = Path.Combine(path, fileName);
//// 记录本次下载的文件
//downloading.DownloadFiles.Add(fileName);
//// 开始下载
//DownloadResult downloadStatus = DownloadByAria(downloading, audioUrls, path, fileName);
//switch (downloadStatus)
//{
// case DownloadResult.SUCCESS:
// return fileName;
// case DownloadResult.FAILED:
// return null;
// case DownloadResult.ABORT:
// return null;
// default:
// return null;
//}
} }
/// <summary> /// <summary>
@ -123,7 +91,7 @@ namespace DownKyi.Services.Download
PlayUrlDashVideo downloadVideo = null; PlayUrlDashVideo downloadVideo = null;
foreach (PlayUrlDashVideo video in downloading.PlayUrl.Dash.Video) foreach (PlayUrlDashVideo video in downloading.PlayUrl.Dash.Video)
{ {
if (video.Id == downloading.Resolution.Id && video.Codecs == downloading.VideoCodecId) if (video.Id == downloading.Resolution.Id && Utils.GetVideoCodecName(video.Codecs) == downloading.VideoCodecName)
{ {
downloadVideo = video; downloadVideo = video;
break; break;
@ -155,7 +123,6 @@ namespace DownKyi.Services.Download
// 下载文件名 // 下载文件名
string fileName = Guid.NewGuid().ToString("N"); string fileName = Guid.NewGuid().ToString("N");
fileName = Path.Combine(path, fileName);
// 记录本次下载的文件 // 记录本次下载的文件
downloading.DownloadFiles.Add(fileName); downloading.DownloadFiles.Add(fileName);
@ -165,7 +132,7 @@ namespace DownKyi.Services.Download
switch (downloadStatus) switch (downloadStatus)
{ {
case DownloadResult.SUCCESS: case DownloadResult.SUCCESS:
return fileName; return Path.Combine(path, fileName);
case DownloadResult.FAILED: case DownloadResult.FAILED:
return null; return null;
case DownloadResult.ABORT: case DownloadResult.ABORT:
@ -287,6 +254,11 @@ namespace DownKyi.Services.Download
List<string> srtFiles = new List<string>(); List<string> srtFiles = new List<string>();
var subRipTexts = VideoStream.GetSubtitle(downloading.Avid, downloading.Bvid, downloading.Cid); var subRipTexts = VideoStream.GetSubtitle(downloading.Avid, downloading.Bvid, downloading.Cid);
if (subRipTexts == null)
{
return null;
}
foreach (var subRip in subRipTexts) foreach (var subRip in subRipTexts)
{ {
string srtFile = $"{downloading.FilePath}_{subRip.LanDoc}.srt"; string srtFile = $"{downloading.FilePath}_{subRip.LanDoc}.srt";
@ -546,6 +518,12 @@ namespace DownKyi.Services.Download
// 检测字幕是否下载成功 // 检测字幕是否下载成功
if (downloading.NeedDownloadContent["downloadSubtitle"]) if (downloading.NeedDownloadContent["downloadSubtitle"])
{
if (outputSubtitles == null)
{
// 为null时表示不存在字幕
}
else
{ {
foreach (string subtitle in outputSubtitles) foreach (string subtitle in outputSubtitles)
{ {
@ -555,6 +533,7 @@ namespace DownKyi.Services.Download
} }
} }
} }
}
// 检测封面是否下载成功 // 检测封面是否下载成功
if (downloading.NeedDownloadContent["downloadCover"] && File.Exists(outputCover)) if (downloading.NeedDownloadContent["downloadCover"] && File.Exists(outputCover))
@ -692,7 +671,7 @@ namespace DownKyi.Services.Download
} }
// 添加一个下载 // 添加一个下载
var ariaAddUri = AriaClient.AddUriAsync(urls, option); Task<AriaAddUri> ariaAddUri = AriaClient.AddUriAsync(urls, option);
if (ariaAddUri == null || ariaAddUri.Result == null || ariaAddUri.Result.Result == null) if (ariaAddUri == null || ariaAddUri.Result == null || ariaAddUri.Result.Result == null)
{ {
return DownloadResult.FAILED; return DownloadResult.FAILED;
@ -711,12 +690,10 @@ namespace DownKyi.Services.Download
switch (downloading.DownloadStatus) switch (downloading.DownloadStatus)
{ {
case DownloadStatus.PAUSE: case DownloadStatus.PAUSE:
var ariaPause = AriaClient.PauseAsync(downloading.Gid); Task<AriaPause> ariaPause = AriaClient.PauseAsync(downloading.Gid);
// TODO
break; break;
case DownloadStatus.DOWNLOADING: case DownloadStatus.DOWNLOADING:
var ariaUnpause = AriaClient.UnpauseAsync(downloading.Gid); Task<AriaPause> ariaUnpause = AriaClient.UnpauseAsync(downloading.Gid);
// TODO
break; break;
} }
})); }));
@ -726,6 +703,7 @@ namespace DownKyi.Services.Download
{ {
// 当前的下载视频 // 当前的下载视频
DownloadingItem video = downloadingList.FirstOrDefault(it => it.Gid == gid); DownloadingItem video = downloadingList.FirstOrDefault(it => it.Gid == gid);
if (video == null) { return; }
float percent = 0; float percent = 0;
if (totalLength != 0) if (totalLength != 0)

@ -26,9 +26,9 @@ namespace DownKyi.Services
page.PlayUrl = playUrl; page.PlayUrl = playUrl;
// 获取设置 // 获取设置
var userInfo = SettingsManager.GetInstance().GetUserInfo(); UserInfoSettings userInfo = SettingsManager.GetInstance().GetUserInfo();
int defaultQuality = SettingsManager.GetInstance().GetQuality(); int defaultQuality = SettingsManager.GetInstance().GetQuality();
var videoCodecs = SettingsManager.GetInstance().GetVideoCodecs(); VideoCodecs videoCodecs = SettingsManager.GetInstance().GetVideoCodecs();
int defaultAudioQuality = SettingsManager.GetInstance().GetAudioQuality(); int defaultAudioQuality = SettingsManager.GetInstance().GetAudioQuality();
// 未登录时最高仅720P // 未登录时最高仅720P
@ -201,7 +201,7 @@ namespace DownKyi.Services
/// </summary> /// </summary>
/// <param name="origin"></param> /// <param name="origin"></param>
/// <returns></returns> /// <returns></returns>
private static string GetVideoCodecName(string origin) internal static string GetVideoCodecName(string origin)
{ {
return origin.Contains("avc") ? "H.264/AVC" : origin.Contains("hev") ? "H.265/HEVC" : ""; return origin.Contains("avc") ? "H.264/AVC" : origin.Contains("hev") ? "H.265/HEVC" : "";
} }

@ -78,6 +78,7 @@ namespace DownKyi.Services
Bvid = videoView.Bvid, Bvid = videoView.Bvid,
Cid = page.Cid, Cid = page.Cid,
EpisodeId = -1, EpisodeId = -1,
FirstFrame = page.FirstFrame,
Order = order, Order = order,
Name = name, Name = name,
Duration = "N/A" Duration = "N/A"
@ -114,6 +115,7 @@ namespace DownKyi.Services
Bvid = episode.Bvid, Bvid = episode.Bvid,
Cid = episode.Cid, Cid = episode.Cid,
EpisodeId = -1, EpisodeId = -1,
FirstFrame = episode.Page.FirstFrame,
Order = order, Order = order,
Name = episode.Title, Name = episode.Title,
Duration = "N/A" Duration = "N/A"
@ -203,6 +205,9 @@ namespace DownKyi.Services
videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover)); videoInfoView.Cover = cover == null ? null : new BitmapImage(new Uri(cover));
videoInfoView.Title = videoView.Title; videoInfoView.Title = videoView.Title;
// 分区id
videoInfoView.TypeId = videoView.Tid;
videoInfoView.VideoZone = videoZone; videoInfoView.VideoZone = videoZone;
DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区 DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区

@ -1,12 +1,9 @@
using DownKyi.Models; using DownKyi.Images;
using DownKyi.Models;
using DownKyi.Utils;
using Prism.Commands; using Prism.Commands;
using Prism.Events; using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
namespace DownKyi.ViewModels.DownloadManager namespace DownKyi.ViewModels.DownloadManager
{ {
@ -29,15 +26,6 @@ namespace DownKyi.ViewModels.DownloadManager
{ {
// 初始化DownloadingList // 初始化DownloadingList
DownloadingList = App.DownloadingList; DownloadingList = App.DownloadingList;
//// 下载列表发生变化时执行的任务
//DownloadingList.CollectionChanged += new NotifyCollectionChangedEventHandler((object sender, NotifyCollectionChangedEventArgs e) =>
//{
// // save the downloading list and finished list.
// //SaveHistory();
//});
} }
#region 命令申明 #region 命令申明
@ -51,6 +39,34 @@ namespace DownKyi.ViewModels.DownloadManager
/// </summary> /// </summary>
private void ExecutePauseAllDownloadingCommand() private void ExecutePauseAllDownloadingCommand()
{ {
foreach (DownloadingItem downloading in downloadingList)
{
switch (downloading.DownloadStatus)
{
case DownloadStatus.NOT_STARTED:
case DownloadStatus.WAIT_FOR_DOWNLOAD:
downloading.DownloadStatus = DownloadStatus.PAUSE_STARTED;
break;
case DownloadStatus.PAUSE_STARTED:
break;
case DownloadStatus.PAUSE:
break;
case DownloadStatus.DOWNLOADING:
downloading.DownloadStatus = DownloadStatus.PAUSE;
break;
case DownloadStatus.DOWNLOAD_SUCCEED:
// 下载成功后会从下载列表中删除
// 不会出现此分支
break;
case DownloadStatus.DOWNLOAD_FAILED:
break;
default:
break;
}
downloading.StartOrPause = ButtonIcon.Instance().Start;
downloading.StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
}
} }
// 继续所有下载事件 // 继续所有下载事件
@ -62,6 +78,35 @@ namespace DownKyi.ViewModels.DownloadManager
/// </summary> /// </summary>
private void ExecuteContinueAllDownloadingCommand() private void ExecuteContinueAllDownloadingCommand()
{ {
foreach (DownloadingItem downloading in downloadingList)
{
switch (downloading.DownloadStatus)
{
case DownloadStatus.NOT_STARTED:
case DownloadStatus.WAIT_FOR_DOWNLOAD:
break;
case DownloadStatus.PAUSE_STARTED:
downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD;
break;
case DownloadStatus.PAUSE:
downloading.DownloadStatus = DownloadStatus.DOWNLOADING;
break;
case DownloadStatus.DOWNLOADING:
break;
case DownloadStatus.DOWNLOAD_SUCCEED:
// 下载成功后会从下载列表中删除
// 不会出现此分支
break;
case DownloadStatus.DOWNLOAD_FAILED:
downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD;
break;
default:
break;
}
downloading.StartOrPause = ButtonIcon.Instance().Pause;
downloading.StartOrPause.Fill = DictionaryResource.GetColor("ColorPrimary");
}
} }
// 删除所有下载事件 // 删除所有下载事件
@ -73,6 +118,7 @@ namespace DownKyi.ViewModels.DownloadManager
/// </summary> /// </summary>
private void ExecuteDeleteAllDownloadingCommand() private void ExecuteDeleteAllDownloadingCommand()
{ {
DownloadingList.Clear();
} }
#endregion #endregion

@ -1,6 +1,9 @@
using DownKyi.Core.BiliApi.BiliUtils; using DownKyi.Core.BiliApi.BiliUtils;
using DownKyi.Core.BiliApi.Zone;
using DownKyi.Core.FileName;
using DownKyi.Core.Logging; using DownKyi.Core.Logging;
using DownKyi.Core.Settings; using DownKyi.Core.Settings;
using DownKyi.Core.Utils;
using DownKyi.CustomControl; using DownKyi.CustomControl;
using DownKyi.Events; using DownKyi.Events;
using DownKyi.Images; using DownKyi.Images;
@ -13,11 +16,13 @@ using Prism.Events;
using Prism.Regions; using Prism.Regions;
using Prism.Services.Dialogs; using Prism.Services.Dialogs;
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Media;
namespace DownKyi.ViewModels namespace DownKyi.ViewModels
{ {
@ -32,76 +37,75 @@ namespace DownKyi.ViewModels
private VectorImage arrowBack; private VectorImage arrowBack;
public VectorImage ArrowBack public VectorImage ArrowBack
{ {
get { return arrowBack; } get => arrowBack;
set { SetProperty(ref arrowBack, value); } set => SetProperty(ref arrowBack, value);
} }
private string inputText; private string inputText;
public string InputText public string InputText
{ {
get { return inputText; } get => inputText;
set { SetProperty(ref inputText, value); } set => SetProperty(ref inputText, value);
} }
private GifImage loading; private GifImage loading;
public GifImage Loading public GifImage Loading
{ {
get { return loading; } get => loading;
set { SetProperty(ref loading, value); } set => SetProperty(ref loading, value);
} }
private Visibility loadingVisibility; private Visibility loadingVisibility;
public Visibility LoadingVisibility public Visibility LoadingVisibility
{ {
get { return loadingVisibility; } get => loadingVisibility;
set { SetProperty(ref loadingVisibility, value); } set => SetProperty(ref loadingVisibility, value);
} }
private VectorImage downloadManage; private VectorImage downloadManage;
public VectorImage DownloadManage public VectorImage DownloadManage
{ {
get { return downloadManage; } get => downloadManage;
set { SetProperty(ref downloadManage, value); } set => SetProperty(ref downloadManage, value);
} }
private VideoInfoView videoInfoView; private VideoInfoView videoInfoView;
public VideoInfoView VideoInfoView public VideoInfoView VideoInfoView
{ {
get { return videoInfoView; } get => videoInfoView;
set { SetProperty(ref videoInfoView, value); } set => SetProperty(ref videoInfoView, value);
} }
private ObservableCollection<VideoSection> videoSections; private ObservableCollection<VideoSection> videoSections;
public ObservableCollection<VideoSection> VideoSections public ObservableCollection<VideoSection> VideoSections
{ {
get { return videoSections; } get => videoSections;
set { SetProperty(ref videoSections, value); } set => SetProperty(ref videoSections, value);
} }
private bool isSelectAll; private bool isSelectAll;
public bool IsSelectAll public bool IsSelectAll
{ {
get { return isSelectAll; } get => isSelectAll;
set { SetProperty(ref isSelectAll, value); } set => SetProperty(ref isSelectAll, value);
} }
private Visibility contentVisibility; private Visibility contentVisibility;
public Visibility ContentVisibility public Visibility ContentVisibility
{ {
get { return contentVisibility; } get => contentVisibility;
set { SetProperty(ref contentVisibility, value); } set => SetProperty(ref contentVisibility, value);
} }
private Visibility noDataVisibility; private Visibility noDataVisibility;
public Visibility NoDataVisibility public Visibility NoDataVisibility
{ {
get { return noDataVisibility; } get => noDataVisibility;
set { SetProperty(ref noDataVisibility, value); } set => SetProperty(ref noDataVisibility, value);
} }
#endregion #endregion
public ViewVideoDetailViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator) public ViewVideoDetailViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator)
{ {
this.dialogService = dialogService; this.dialogService = dialogService;
@ -265,7 +269,7 @@ namespace DownKyi.ViewModels
if (!(parameter is VideoSection section)) { return; } if (!(parameter is VideoSection section)) { return; }
bool isSelectAll = true; bool isSelectAll = true;
foreach (var page in section.VideoPages) foreach (VideoPage page in section.VideoPages)
{ {
if (!page.IsSelected) if (!page.IsSelected)
{ {
@ -304,7 +308,7 @@ namespace DownKyi.ViewModels
private void ExecuteKeySelectAllCommand(object parameter) private void ExecuteKeySelectAllCommand(object parameter)
{ {
if (!(parameter is VideoSection section)) { return; } if (!(parameter is VideoSection section)) { return; }
foreach (var page in section.VideoPages) foreach (VideoPage page in section.VideoPages)
{ {
page.IsSelected = true; page.IsSelected = true;
} }
@ -323,14 +327,14 @@ namespace DownKyi.ViewModels
if (!(parameter is VideoSection section)) { return; } if (!(parameter is VideoSection section)) { return; }
if (IsSelectAll) if (IsSelectAll)
{ {
foreach (var page in section.VideoPages) foreach (VideoPage page in section.VideoPages)
{ {
page.IsSelected = true; page.IsSelected = true;
} }
} }
else else
{ {
foreach (var page in section.VideoPages) foreach (VideoPage page in section.VideoPages)
{ {
page.IsSelected = false; page.IsSelected = false;
} }
@ -424,11 +428,11 @@ namespace DownKyi.ViewModels
case ParseScope.NONE: case ParseScope.NONE:
break; break;
case ParseScope.SELECTED_ITEM: case ParseScope.SELECTED_ITEM:
foreach (var section in VideoSections) foreach (VideoSection section in VideoSections)
{ {
foreach (var page in section.VideoPages) foreach (VideoPage page in section.VideoPages)
{ {
var videoPage = section.VideoPages.FirstOrDefault(t => t == page); VideoPage videoPage = section.VideoPages.FirstOrDefault(t => t == page);
if (videoPage.IsSelected) if (videoPage.IsSelected)
{ {
@ -439,13 +443,13 @@ namespace DownKyi.ViewModels
} }
break; break;
case ParseScope.CURRENT_SECTION: case ParseScope.CURRENT_SECTION:
foreach (var section in VideoSections) foreach (VideoSection section in VideoSections)
{ {
if (section.IsSelected) if (section.IsSelected)
{ {
foreach (var page in section.VideoPages) foreach (VideoPage page in section.VideoPages)
{ {
var videoPage = section.VideoPages.FirstOrDefault(t => t == page); VideoPage videoPage = section.VideoPages.FirstOrDefault(t => t == page);
// 执行解析任务 // 执行解析任务
UnityUpdateView(ParseVideo, null, videoPage); UnityUpdateView(ParseVideo, null, videoPage);
@ -454,11 +458,11 @@ namespace DownKyi.ViewModels
} }
break; break;
case ParseScope.ALL: case ParseScope.ALL:
foreach (var section in VideoSections) foreach (VideoSection section in VideoSections)
{ {
foreach (var page in section.VideoPages) foreach (VideoPage page in section.VideoPages)
{ {
var videoPage = section.VideoPages.FirstOrDefault(t => t == page); VideoPage videoPage = section.VideoPages.FirstOrDefault(t => t == page);
// 执行解析任务 // 执行解析任务
UnityUpdateView(ParseVideo, null, videoPage); UnityUpdateView(ParseVideo, null, videoPage);
@ -530,12 +534,6 @@ namespace DownKyi.ViewModels
downloadDanmaku = result.Parameters.GetValue<bool>("downloadDanmaku"); downloadDanmaku = result.Parameters.GetValue<bool>("downloadDanmaku");
downloadSubtitle = result.Parameters.GetValue<bool>("downloadSubtitle"); downloadSubtitle = result.Parameters.GetValue<bool>("downloadSubtitle");
downloadCover = result.Parameters.GetValue<bool>("downloadCover"); downloadCover = result.Parameters.GetValue<bool>("downloadCover");
// 文件夹不存在则创建
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
} }
}); });
} }
@ -545,8 +543,144 @@ namespace DownKyi.ViewModels
// 这时直接退出 // 这时直接退出
if (directory == string.Empty) { return; } if (directory == string.Empty) { return; }
// 文件夹不存在则创建
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
// 添加视频计数
int i = 0;
// 添加到下载 // 添加到下载
eventAggregator.GetEvent<MessageEvent>().Publish(directory); foreach (VideoSection section in VideoSections)
{
foreach (VideoPage page in section.VideoPages)
{
// 只下载选中项,跳过未选中项
if (!page.IsSelected) { continue; }
// 没有解析的也跳过
if (page.PlayUrl == null) { continue; }
// 判断是否同一个视频需要cid、画质、音质、视频编码都相同
// 如果存在正在下载列表,则跳过,并提示
foreach (DownloadingItem item in App.DownloadingList)
{
if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodecName == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec)
{
eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloading")}");
continue;
}
}
// 如果存在下载完成列表,弹出选择框是否再次下载
foreach (DownloadedItem item in App.DownloadedList)
{
if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodecName == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec)
{
eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloaded")}");
continue;
}
}
// 文件路径
List<FileNamePart> fileNameParts = SettingsManager.GetInstance().GetFileNameParts();
FileName fileName = FileName.Builder(fileNameParts)
.SetOrder(page.Order)
.SetSection(Format.FormatFileName(section.Title))
.SetMainTitle(Format.FormatFileName(VideoInfoView.Title))
.SetPageTitle(Format.FormatFileName(page.Name))
.SetVideoZone(VideoInfoView.VideoZone.Split('>')[0])
.SetAudioQuality(page.AudioQualityFormat)
.SetVideoQuality(page.VideoQuality.QualityFormat)
.SetVideoCodec(page.VideoQuality.SelectedVideoCodec.Contains("AVC") ? "AVC" : page.VideoQuality.SelectedVideoCodec.Contains("HEVC") ? "HEVC" : "");
string filePath = Path.Combine(directory, fileName.RelativePath());
// 视频类别
PlayStreamType playStreamType;
switch (VideoInfoView.TypeId)
{
case -10:
playStreamType = PlayStreamType.CHEESE;
break;
case 13:
case 23:
case 177:
case 167:
case 11:
playStreamType = PlayStreamType.BANGUMI;
break;
case 1:
case 3:
case 129:
case 4:
case 36:
case 188:
case 234:
case 223:
case 160:
case 211:
case 217:
case 119:
case 155:
case 202:
case 5:
case 181:
default:
playStreamType = PlayStreamType.VIDEO;
break;
}
// 如果不存在,直接添加到下载列表
DownloadingItem downloading = new DownloadingItem
{
PlayUrl = page.PlayUrl,
Bvid = page.Bvid,
Avid = page.Avid,
Cid = page.Cid,
EpisodeId = page.EpisodeId,
CoverUrl = page.FirstFrame,
ZoneImage = (DrawingImage)Application.Current.Resources[VideoZoneIcon.Instance().GetZoneImageKey(VideoInfoView.TypeId)],
Order = page.Order,
MainTitle = VideoInfoView.Title,
Name = page.Name,
Duration = page.Duration,
AudioCodecId = Constant.AudioQualityId[page.AudioQualityFormat],
AudioCodecName = page.AudioQualityFormat,
VideoCodecName = page.VideoQuality.SelectedVideoCodec,
Resolution = new Resolution { Name = page.VideoQuality.QualityFormat, Id = page.VideoQuality.Quality },
FilePath = filePath,
PlayStreamType = playStreamType,
DownloadStatus = DownloadStatus.NOT_STARTED,
};
// 需要下载的内容
downloading.NeedDownloadContent["downloadAudio"] = downloadAudio;
downloading.NeedDownloadContent["downloadVideo"] = downloadVideo;
downloading.NeedDownloadContent["downloadDanmaku"] = downloadDanmaku;
downloading.NeedDownloadContent["downloadSubtitle"] = downloadSubtitle;
downloading.NeedDownloadContent["downloadCover"] = downloadCover;
// 添加到下载列表
App.DownloadingList.Add(downloading);
i++;
}
}
// 通知用户添加到下载列表的结果
if (i == 0)
{
eventAggregator.GetEvent<MessageEvent>().Publish(DictionaryResource.GetString("TipAddDownloadingZero"));
}
else
{
eventAggregator.GetEvent<MessageEvent>().Publish($"{DictionaryResource.GetString("TipAddDownloadingFinished1")}{i}{DictionaryResource.GetString("TipAddDownloadingFinished2")}");
}
} }
/// <summary> /// <summary>
@ -627,12 +761,12 @@ namespace DownKyi.ViewModels
NoDataVisibility = Visibility.Collapsed; NoDataVisibility = Visibility.Collapsed;
} }
var videoSections = videoInfoService.GetVideoSections(); List<VideoSection> videoSections = videoInfoService.GetVideoSections();
if (videoSections == null) if (videoSections == null)
{ {
LogManager.Debug(Tag, "videoSections is not exist."); LogManager.Debug(Tag, "videoSections is not exist.");
var pages = videoInfoService.GetVideoPages(); List<VideoPage> pages = videoInfoService.GetVideoPages();
PropertyChangeAsync(new Action(() => PropertyChangeAsync(new Action(() =>
{ {

@ -88,7 +88,7 @@
<Grid Grid.Row="0" VerticalAlignment="Bottom"> <Grid Grid.Row="0" VerticalAlignment="Bottom">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition /> <ColumnDefinition Width="100" />
<ColumnDefinition /> <ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>

@ -558,6 +558,7 @@
<ListBox <ListBox
x:Name="nameVideoSections" x:Name="nameVideoSections"
Grid.Row="0" Grid.Row="0"
ItemContainerStyle="{StaticResource TagItemStyle}"
ItemsSource="{Binding VideoSections, Mode=TwoWay}" ItemsSource="{Binding VideoSections, Mode=TwoWay}"
SelectionMode="Single"> SelectionMode="Single">
<i:Interaction.Triggers> <i:Interaction.Triggers>
@ -566,7 +567,7 @@
</i:EventTrigger> </i:EventTrigger>
</i:Interaction.Triggers> </i:Interaction.Triggers>
<ListBox.Style> <ListBox.Style>
<Style TargetType="{x:Type ListBox}"> <Style BasedOn="{StaticResource TagStyle}" TargetType="{x:Type ListBox}">
<Style.Triggers> <Style.Triggers>
<DataTrigger Binding="{Binding VideoSections.Count}" Value="0"> <DataTrigger Binding="{Binding VideoSections.Count}" Value="0">
<Setter Property="Height" Value="0" /> <Setter Property="Height" Value="0" />
@ -577,56 +578,6 @@
</Style.Triggers> </Style.Triggers>
</Style> </Style>
</ListBox.Style> </ListBox.Style>
<ListBox.Template>
<ControlTemplate TargetType="{x:Type ListBox}">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled">
<WrapPanel
IsItemsHost="True"
Orientation="Horizontal"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border
Name="Border"
Margin="5,3"
Padding="8,2"
Background="{DynamicResource BrushPrimary}"
CornerRadius="10"
Cursor="Hand">
<ContentPresenter
Name="content"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding Title}" />
</Border>
<ControlTemplate.Triggers>
<!-- 顺序很重要,不能修改 -->
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushBackgroundGrey}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushPrimaryTranslucent}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushPrimary}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox> </ListBox>
<!-- 视频分P --> <!-- 视频分P -->

Loading…
Cancel
Save