diff --git a/src/Downkyi.Core/Bili/BiliLocator.cs b/src/Downkyi.Core/Bili/BiliLocator.cs index 4464eae..ae784b5 100644 --- a/src/Downkyi.Core/Bili/BiliLocator.cs +++ b/src/Downkyi.Core/Bili/BiliLocator.cs @@ -2,7 +2,7 @@ public static class BiliLocator { - private static ILogin _login; + private static ILogin? _login; public static ILogin Login { get @@ -12,7 +12,7 @@ public static class BiliLocator } } - private static IUser _user; + private static IUser? _user; public static IUser User { get @@ -21,4 +21,18 @@ public static class BiliLocator return _user; } } + + private static IVideo? _video; + public static IVideo Video(string input) + { + _video ??= new Web.Video(input); + + if (_video.Input() != input) + { + _video = new Web.Video(input); + } + + return _video; + } + } \ No newline at end of file diff --git a/src/Downkyi.Core/Bili/Cookies.cs b/src/Downkyi.Core/Bili/Cookies.cs index 42f46b2..e8b6083 100644 --- a/src/Downkyi.Core/Bili/Cookies.cs +++ b/src/Downkyi.Core/Bili/Cookies.cs @@ -23,9 +23,9 @@ public static class Cookies /// /// /// - public static CookieContainer ReadCookiesFromDisk(string file) + public static CookieContainer? ReadCookiesFromDisk(string file) { - return (CookieContainer)ObjectHelper.ReadObjectFromDisk(file); + return (CookieContainer?)ObjectHelper.ReadObjectFromDisk(file); } /// @@ -37,16 +37,16 @@ public static class Cookies { var lstCookies = new List(); - Hashtable table = (Hashtable)cc.GetType().InvokeMember("m_domainTable", + var table = (Hashtable?)cc.GetType().InvokeMember("m_domainTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, cc, Array.Empty()); - foreach (object pathList in table.Values) + foreach (object pathList in table!.Values) { - SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list", + var lstCookieCol = (SortedList?)pathList.GetType().InvokeMember("m_list", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, pathList, Array.Empty()); - foreach (CookieCollection colCookies in lstCookieCol.Values) + foreach (CookieCollection colCookies in lstCookieCol!.Values) { foreach (Cookie c in colCookies.Cast()) { @@ -92,7 +92,7 @@ public static class Cookies if (strList2.Length == 0) { return cookieContainer; } // 获取expires - string expires = strList2.FirstOrDefault(it => it.Contains("Expires")).Split('=')[1]; + string expires = strList2.FirstOrDefault(it => it.Contains("Expires"))!.Split('=')[1]; DateTime dateTime = DateTime.Now; dateTime = dateTime.AddSeconds(int.Parse(expires)); diff --git a/src/Downkyi.Core/Bili/ILogin.cs b/src/Downkyi.Core/Bili/ILogin.cs index 7cf6a6a..2d78c42 100644 --- a/src/Downkyi.Core/Bili/ILogin.cs +++ b/src/Downkyi.Core/Bili/ILogin.cs @@ -8,18 +8,18 @@ public interface ILogin /// 申请二维码 /// /// (url, key) - Tuple GetQRCodeUrl(); + Tuple? GetQRCodeUrl(); /// /// 扫码登录 /// /// /// - QRCodeStatus PollQRCode(string qrcodeKey); + QRCodeStatus? PollQRCode(string qrcodeKey); /// /// 导航栏用户信息 /// /// - NavigationInfo GetNavigationInfo(); + NavigationInfo? GetNavigationInfo(); } \ No newline at end of file diff --git a/src/Downkyi.Core/Bili/IVideo.cs b/src/Downkyi.Core/Bili/IVideo.cs new file mode 100644 index 0000000..61867ce --- /dev/null +++ b/src/Downkyi.Core/Bili/IVideo.cs @@ -0,0 +1,10 @@ +using Downkyi.Core.Bili.Models; + +namespace Downkyi.Core.Bili; + +public interface IVideo +{ + string Input(); + + VideoInfo? GetVideoInfo(string? bvid = null, long aid = -1); +} \ No newline at end of file diff --git a/src/Downkyi.Core/Bili/Models/NavigationInfo.cs b/src/Downkyi.Core/Bili/Models/NavigationInfo.cs index 927ebc2..a4fb87c 100644 --- a/src/Downkyi.Core/Bili/Models/NavigationInfo.cs +++ b/src/Downkyi.Core/Bili/Models/NavigationInfo.cs @@ -3,8 +3,8 @@ public class NavigationInfo { public long Mid { get; set; } - public string Name { get; set; } - public string Header { get; set; } + public string Name { get; set; } = string.Empty; + public string Header { get; set; } = string.Empty; public int VipStatus { get; set; } // 会员开通状态 // 0:无;1:有 public bool IsLogin { get; set; } } \ No newline at end of file diff --git a/src/Downkyi.Core/Bili/Models/QRCodeStatus.cs b/src/Downkyi.Core/Bili/Models/QRCodeStatus.cs index 05f4e27..23fba07 100644 --- a/src/Downkyi.Core/Bili/Models/QRCodeStatus.cs +++ b/src/Downkyi.Core/Bili/Models/QRCodeStatus.cs @@ -2,8 +2,8 @@ public class QRCodeStatus { - public string Url { get; set; } - public string Token { get; set; } + public string Url { get; set; } = string.Empty; + public string Token { get; set; } = string.Empty; public long Timestamp { get; set; } /// @@ -13,5 +13,5 @@ public class QRCodeStatus /// 86101:未扫码 /// public long Code { get; set; } - public string Message { get; set; } + public string Message { get; set; } = string.Empty; } \ No newline at end of file diff --git a/src/Downkyi.Core/Bili/Models/Quality.cs b/src/Downkyi.Core/Bili/Models/Quality.cs index aad41c6..e9a6c50 100644 --- a/src/Downkyi.Core/Bili/Models/Quality.cs +++ b/src/Downkyi.Core/Bili/Models/Quality.cs @@ -2,6 +2,6 @@ public class Quality { - public string Name { get; set; } + public string Name { get; set; } = string.Empty; public int Id { get; set; } } \ No newline at end of file diff --git a/src/Downkyi.Core/Bili/Models/VideoInfo.cs b/src/Downkyi.Core/Bili/Models/VideoInfo.cs new file mode 100644 index 0000000..275ffd8 --- /dev/null +++ b/src/Downkyi.Core/Bili/Models/VideoInfo.cs @@ -0,0 +1,11 @@ +namespace Downkyi.Core.Bili.Models; + +public class VideoInfo +{ + public long Aid { get; set; } + public string Bvid { get; set; } = string.Empty; + public long Cid { get; set; } + public string Title { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public string PublishTime { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/src/Downkyi.Core/Bili/Utils/ParseEntrance.cs b/src/Downkyi.Core/Bili/Utils/ParseEntrance.cs index 4ad1f93..fece1a1 100644 --- a/src/Downkyi.Core/Bili/Utils/ParseEntrance.cs +++ b/src/Downkyi.Core/Bili/Utils/ParseEntrance.cs @@ -459,7 +459,7 @@ public static class ParseEntrance /// private static string EnableHttps(string url) { - if (!IsUrl(url)) { return null; } + if (!IsUrl(url)) { return string.Empty; } return url.Replace("http://", "https://"); } diff --git a/src/Downkyi.Core/Bili/Web/Login.cs b/src/Downkyi.Core/Bili/Web/Login.cs index c445cff..682302b 100644 --- a/src/Downkyi.Core/Bili/Web/Login.cs +++ b/src/Downkyi.Core/Bili/Web/Login.cs @@ -1,17 +1,17 @@ -using BiliSharp; -using BiliSharp.Api.Login; +using Downkyi.BiliSharp; +using Downkyi.BiliSharp.Api.Login; using Downkyi.Core.Bili.Models; using Downkyi.Core.Settings; namespace Downkyi.Core.Bili.Web; -public class Login : ILogin +internal class Login : ILogin { /// /// 申请二维码(web端) /// /// (url, key) - public Tuple GetQRCodeUrl() + public Tuple? GetQRCodeUrl() { string userAgent = SettingsManager.GetInstance().GetUserAgent(); BiliManager.Instance().SetUserAgent(userAgent); @@ -26,7 +26,7 @@ public class Login : ILogin /// 扫码登录(web端) /// /// - public QRCodeStatus PollQRCode(string qrcodeKey) + public QRCodeStatus? PollQRCode(string qrcodeKey) { string userAgent = SettingsManager.GetInstance().GetUserAgent(); BiliManager.Instance().SetUserAgent(userAgent); @@ -48,7 +48,7 @@ public class Login : ILogin /// 导航栏用户信息 /// /// - public NavigationInfo GetNavigationInfo() + public NavigationInfo? GetNavigationInfo() { string userAgent = SettingsManager.GetInstance().GetUserAgent(); BiliManager.Instance().SetUserAgent(userAgent); diff --git a/src/Downkyi.Core/Bili/Web/LoginHelper.cs b/src/Downkyi.Core/Bili/Web/LoginHelper.cs index c0d8943..300e4bd 100644 --- a/src/Downkyi.Core/Bili/Web/LoginHelper.cs +++ b/src/Downkyi.Core/Bili/Web/LoginHelper.cs @@ -58,7 +58,7 @@ public static class LoginHelper /// 获得登录的cookies /// /// - public static CookieContainer GetLoginInfoCookies() + public static CookieContainer? GetLoginInfoCookies() { string tempFile = LOCAL_LOGIN_INFO + "-" + Guid.NewGuid().ToString("N"); @@ -80,7 +80,7 @@ public static class LoginHelper } else { return null; } - CookieContainer cookies = Cookies.ReadCookiesFromDisk(tempFile); + var cookies = Cookies.ReadCookiesFromDisk(tempFile); if (File.Exists(tempFile)) { diff --git a/src/Downkyi.Core/Bili/Web/User.cs b/src/Downkyi.Core/Bili/Web/User.cs index be10494..9c64af0 100644 --- a/src/Downkyi.Core/Bili/Web/User.cs +++ b/src/Downkyi.Core/Bili/Web/User.cs @@ -1,5 +1,5 @@ namespace Downkyi.Core.Bili.Web; -public class User : IUser +internal class User : IUser { } \ No newline at end of file diff --git a/src/Downkyi.Core/Bili/Web/Video.cs b/src/Downkyi.Core/Bili/Web/Video.cs new file mode 100644 index 0000000..7354de8 --- /dev/null +++ b/src/Downkyi.Core/Bili/Web/Video.cs @@ -0,0 +1,71 @@ +using Downkyi.BiliSharp.Api.Models.Video; +using Downkyi.Core.Bili.Models; +using Downkyi.Core.Bili.Utils; + +namespace Downkyi.Core.Bili.Web; + +internal class Video : IVideo +{ + private readonly VideoView? videoView; + + private readonly string _input = string.Empty; + + internal Video(string input) + { + if (input == null) + { + return; + } + + _input = input; + + if (ParseEntrance.IsAvId(input) || ParseEntrance.IsAvUrl(input)) + { + long avid = ParseEntrance.GetAvId(input); + videoView = BiliSharp.Api.Video.VideoInfo.GetVideoViewInfo(null, avid); + } + + if (ParseEntrance.IsBvId(input) || ParseEntrance.IsBvUrl(input)) + { + string bvid = ParseEntrance.GetBvId(input); + videoView = BiliSharp.Api.Video.VideoInfo.GetVideoViewInfo(bvid); + } + } + + public string Input() + { + return _input; + } + + /// + /// 获取视频详情页信息 + /// + /// + /// + /// + public VideoInfo? GetVideoInfo(string? bvid = null, long aid = -1) + { + if (videoView == null) { return null; } + if (videoView.Data == null) { return null; } + if (videoView.Data.View == null) { return null; } + + /* 视频发布时间 */ + // 当地时区 + DateTime startTime = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1), TimeZoneInfo.Local); + DateTime dateTime = startTime.AddSeconds(videoView.Data.View.Pubdate); + string publishTime = dateTime.ToString("yyyy-MM-dd HH:mm:ss"); + + VideoInfo videoInfo = new() + { + Aid = videoView.Data.View.Aid, + Bvid = videoView.Data.View.Bvid, + Cid = videoView.Data.View.Cid, + Title = videoView.Data.View.Title, + Description = videoView.Data.View.Desc, + PublishTime = publishTime, + }; + + return videoInfo; + } + +} \ No newline at end of file diff --git a/src/Downkyi.Core/Downkyi.Core.csproj b/src/Downkyi.Core/Downkyi.Core.csproj index 8d92908..af33c39 100644 --- a/src/Downkyi.Core/Downkyi.Core.csproj +++ b/src/Downkyi.Core/Downkyi.Core.csproj @@ -1,6 +1,6 @@  - net7.0 + net8.0 enable enable @@ -10,14 +10,10 @@ - - + + - - - - - + diff --git a/src/Downkyi.Core/Downloader/MultiThreadDownloader.cs b/src/Downkyi.Core/Downloader/MultiThreadDownloader.cs index 4eaf589..29bdee5 100644 --- a/src/Downkyi.Core/Downloader/MultiThreadDownloader.cs +++ b/src/Downkyi.Core/Downloader/MultiThreadDownloader.cs @@ -3,6 +3,13 @@ using System.Net; namespace Downkyi.Core.Downloader; +#pragma warning disable CS8601 // 引用类型赋值可能为 null。 +#pragma warning disable CS8602 // 解引用可能出现空引用。 +#pragma warning disable CS8604 // 引用类型参数可能为 null。 +#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 +#pragma warning disable CS8622 // 参数类型中引用类型的为 Null 性与目标委托不匹配(可能是由于为 Null 性特性)。 +#pragma warning disable CS8625 // 无法将 null 字面量转换为非 null 的引用类型。 + /// /// 文件合并改变事件 /// @@ -170,7 +177,7 @@ public class MultiThreadDownloader /// /// /// - public MultiThreadDownloader(string sourceUrl, int numOfParts) : this(sourceUrl, null, numOfParts) + public MultiThreadDownloader(string sourceUrl, int numOfParts) : this(sourceUrl, null, numOfParts) { } @@ -361,6 +368,7 @@ public class MultiThreadDownloader public long GetContentLength(ref bool rangeAllowed, ref string redirectedUrl) { _request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36"; + _request.ServicePoint.ConnectionLimit = 4; _requestConfigure(_request); @@ -438,4 +446,11 @@ public class MultiThreadDownloader } #endregion 公共方法 -} \ No newline at end of file +} + +#pragma warning restore CS8625 // 无法将 null 字面量转换为非 null 的引用类型。 +#pragma warning restore CS8622 // 参数类型中引用类型的为 Null 性与目标委托不匹配(可能是由于为 Null 性特性)。 +#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 +#pragma warning restore CS8604 // 引用类型参数可能为 null。 +#pragma warning restore CS8602 // 解引用可能出现空引用。 +#pragma warning restore CS8601 // 引用类型赋值可能为 null。 \ No newline at end of file diff --git a/src/Downkyi.Core/Downloader/PartialDownloader.cs b/src/Downkyi.Core/Downloader/PartialDownloader.cs index a832f6a..8a687f9 100644 --- a/src/Downkyi.Core/Downloader/PartialDownloader.cs +++ b/src/Downkyi.Core/Downloader/PartialDownloader.cs @@ -4,6 +4,8 @@ using System.Net; namespace Downkyi.Core.Downloader; +#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 + /// /// 部分下载器 /// @@ -259,4 +261,6 @@ public class PartialDownloader { _wait = false; } -} \ No newline at end of file +} + +#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 \ No newline at end of file diff --git a/src/Downkyi.Core/FFmpeg/FFmpegHelper.cs b/src/Downkyi.Core/FFmpeg/FFmpegHelper.cs index ac6a878..0ec2b13 100644 --- a/src/Downkyi.Core/FFmpeg/FFmpegHelper.cs +++ b/src/Downkyi.Core/FFmpeg/FFmpegHelper.cs @@ -210,7 +210,7 @@ public static class FFmpegHelper /// 参数 /// 工作路径 /// 输出重定向 - private static void ExcuteProcess(string exe, string arg, string workingDirectory, DataReceivedEventHandler output) + private static void ExcuteProcess(string exe, string arg, string? workingDirectory, DataReceivedEventHandler output) { using var p = new Process(); p.StartInfo.FileName = exe; diff --git a/src/Downkyi.Core/Settings/Models/DanmakuSettings.cs b/src/Downkyi.Core/Settings/Models/DanmakuSettings.cs index 841aa6c..acb789f 100644 --- a/src/Downkyi.Core/Settings/Models/DanmakuSettings.cs +++ b/src/Downkyi.Core/Settings/Models/DanmakuSettings.cs @@ -13,7 +13,7 @@ public class DanmakuSettings public AllowStatus IsCustomDanmakuResolution { get; set; } = AllowStatus.NONE; public int DanmakuScreenWidth { get; set; } = -1; public int DanmakuScreenHeight { get; set; } = -1; - public string DanmakuFontName { get; set; } = null; + public string? DanmakuFontName { get; set; } = null; public int DanmakuFontSize { get; set; } = -1; public int DanmakuLineCount { get; set; } = -1; public DanmakuLayoutAlgorithm DanmakuLayoutAlgorithm { get; set; } = DanmakuLayoutAlgorithm.NONE; diff --git a/src/Downkyi.Core/Settings/Models/NetworkSettings.cs b/src/Downkyi.Core/Settings/Models/NetworkSettings.cs index 239926a..7493fed 100644 --- a/src/Downkyi.Core/Settings/Models/NetworkSettings.cs +++ b/src/Downkyi.Core/Settings/Models/NetworkSettings.cs @@ -19,13 +19,13 @@ public class NetworkSettings #region built-in public int Split { get; set; } = -1; public AllowStatus IsHttpProxy { get; set; } = AllowStatus.NONE; - public string HttpProxy { get; set; } = null; + public string? HttpProxy { get; set; } = null; public int HttpProxyListenPort { get; set; } = -1; #endregion #region Aria - public string AriaToken { get; set; } = null; - public string AriaHost { get; set; } = null; + 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; @@ -34,7 +34,7 @@ public class NetworkSettings public AriaConfigFileAllocation AriaFileAllocation { get; set; } = AriaConfigFileAllocation.NOT_SET; public AllowStatus IsAriaHttpProxy { get; set; } = AllowStatus.NONE; - public string AriaHttpProxy { get; set; } = null; + public string? AriaHttpProxy { get; set; } = null; public int AriaHttpProxyListenPort { get; set; } = -1; #endregion } \ No newline at end of file diff --git a/src/Downkyi.Core/Settings/Models/UserInfoSettings.cs b/src/Downkyi.Core/Settings/Models/UserInfoSettings.cs index c00bfce..ddfc187 100644 --- a/src/Downkyi.Core/Settings/Models/UserInfoSettings.cs +++ b/src/Downkyi.Core/Settings/Models/UserInfoSettings.cs @@ -3,7 +3,7 @@ public class UserInfoSettings { public long Mid { get; set; } - public string Name { get; set; } + public string Name { get; set; } = string.Empty; public bool IsLogin { get; set; } // 是否登录 public bool IsVip { get; set; } // 是否为大会员,未登录时为false } \ No newline at end of file diff --git a/src/Downkyi.Core/Settings/Models/VideoSettings.cs b/src/Downkyi.Core/Settings/Models/VideoSettings.cs index 984981d..be48f0f 100644 --- a/src/Downkyi.Core/Settings/Models/VideoSettings.cs +++ b/src/Downkyi.Core/Settings/Models/VideoSettings.cs @@ -12,11 +12,11 @@ public class VideoSettings public int Quality { get; set; } = -1; // 画质 public int AudioQuality { get; set; } = -1; // 音质 public AllowStatus IsTranscodingFlvToMp4 { get; set; } = AllowStatus.NONE; // 是否将flv转为mp4 - public string SaveVideoRootPath { get; set; } = null; // 视频保存路径 - public List HistoryVideoRootPaths { get; set; } = null; // 历史视频保存路径 + public string? SaveVideoRootPath { get; set; } = null; // 视频保存路径 + public List? HistoryVideoRootPaths { get; set; } = null; // 历史视频保存路径 public AllowStatus IsUseSaveVideoRootPath { get; set; } = AllowStatus.NONE; // 是否使用默认视频保存路径 - public VideoContentSettings VideoContent { get; set; } = null; // 下载内容 - public List FileNameParts { get; set; } = null; // 文件命名格式 - public string FileNamePartTimeFormat { get; set; } = null; // 文件命名中的时间格式 + public VideoContentSettings? VideoContent { get; set; } = null; // 下载内容 + public List? FileNameParts { get; set; } = null; // 文件命名格式 + public string? FileNamePartTimeFormat { get; set; } = null; // 文件命名中的时间格式 public OrderFormat OrderFormat { get; set; } = OrderFormat.NOT_SET; // 文件命名中的序号格式 } \ No newline at end of file diff --git a/src/Downkyi.Core/Settings/SettingsManager.Video.cs b/src/Downkyi.Core/Settings/SettingsManager.Video.cs index f543ca2..3ca19e6 100644 --- a/src/Downkyi.Core/Settings/SettingsManager.Video.cs +++ b/src/Downkyi.Core/Settings/SettingsManager.Video.cs @@ -289,7 +289,7 @@ public partial class SettingsManager /// /// /// - public bool SetFileNameParts(List fileNameParts) + public bool SetFileNameParts(List? fileNameParts) { appSettings.Video.FileNameParts = fileNameParts; return SetSettings(); diff --git a/src/Downkyi.Core/Settings/SettingsManager.cs b/src/Downkyi.Core/Settings/SettingsManager.cs index 510c88f..229c5f7 100644 --- a/src/Downkyi.Core/Settings/SettingsManager.cs +++ b/src/Downkyi.Core/Settings/SettingsManager.cs @@ -10,7 +10,7 @@ namespace Downkyi.Core.Settings; public partial class SettingsManager { - private static SettingsManager instance; + private static SettingsManager? instance; // 内存中保存一份配置 private AppSettings appSettings; @@ -41,7 +41,7 @@ public partial class SettingsManager /// private SettingsManager() { - appSettings = GetSettings(); + appSettings = GetSettings() ?? new AppSettings(); } /// @@ -67,7 +67,7 @@ public partial class SettingsManager jsonWordTemplate = Encryptor.DecryptString(jsonWordTemplate, password); #endif - return JsonConvert.DeserializeObject(jsonWordTemplate); + return JsonConvert.DeserializeObject(jsonWordTemplate) ?? new AppSettings(); } catch (Exception e) { diff --git a/src/Downkyi.Core/Utils/Encryptor/Hash.cs b/src/Downkyi.Core/Utils/Encryptor/Hash.cs index daa7bc4..c8ab211 100644 --- a/src/Downkyi.Core/Utils/Encryptor/Hash.cs +++ b/src/Downkyi.Core/Utils/Encryptor/Hash.cs @@ -10,7 +10,7 @@ public static class Hash /// /// /// - public static string GetMd5Hash(string input) + public static string? GetMd5Hash(string input) { if (input == null) { diff --git a/src/Downkyi.Core/Utils/LinkStack.cs b/src/Downkyi.Core/Utils/LinkStack.cs index a0b9494..15eeffa 100644 --- a/src/Downkyi.Core/Utils/LinkStack.cs +++ b/src/Downkyi.Core/Utils/LinkStack.cs @@ -4,7 +4,7 @@ public class LinkStack { //栈顶指示器 - public Node Top { get; set; } + public Node? Top { get; set; } //栈中结点的个数 public int NCount { get; set; } @@ -49,36 +49,36 @@ public class LinkStack } //出栈 - public T Pop() + public T? Pop() { if (IsEmpty()) { return default; } - Node p = Top; - Top = Top.Next; + Node? p = Top; + Top = Top!.Next; --NCount; - return p.Data; + return p!.Data; } // - public T Peek() + public T? Peek() { if (IsEmpty()) { return default; } - return Top.Data; + return Top!.Data; } } //结点定义 public class Node { - public T Data; + public T? Data; - public Node Next; + public Node? Next; public Node(T item) { diff --git a/src/Downkyi.Core/Utils/ListHelper.cs b/src/Downkyi.Core/Utils/ListHelper.cs index 078cd3b..098ccfe 100644 --- a/src/Downkyi.Core/Utils/ListHelper.cs +++ b/src/Downkyi.Core/Utils/ListHelper.cs @@ -27,7 +27,7 @@ public static class ListHelper /// public static void AddUnique(List list, T item) { - if (!list.Exists(t => t.Equals(item))) + if (!list.Exists(t => t!.Equals(item))) { list.Add(item); } @@ -42,7 +42,7 @@ public static class ListHelper /// public static void InsertUnique(List list, T item, int index) { - if (!list.Exists(t => t.Equals(item))) + if (!list.Exists(t => t!.Equals(item))) { list.Insert(index, item); } diff --git a/src/Downkyi.Core/Utils/ObjectHelper.cs b/src/Downkyi.Core/Utils/ObjectHelper.cs index 846d3a4..740ef90 100644 --- a/src/Downkyi.Core/Utils/ObjectHelper.cs +++ b/src/Downkyi.Core/Utils/ObjectHelper.cs @@ -15,8 +15,8 @@ public static class ObjectHelper try { using Stream stream = File.Create(file); - var formatter = new BinaryFormatter(); #pragma warning disable SYSLIB0011 // 类型或成员已过时 + var formatter = new BinaryFormatter(); formatter.Serialize(stream, obj); #pragma warning restore SYSLIB0011 // 类型或成员已过时 @@ -39,13 +39,13 @@ public static class ObjectHelper /// /// /// - public static object ReadObjectFromDisk(string file) + public static object? ReadObjectFromDisk(string file) { try { using Stream stream = File.Open(file, FileMode.Open); - var formatter = new BinaryFormatter(); #pragma warning disable SYSLIB0011 // 类型或成员已过时 + var formatter = new BinaryFormatter(); return formatter.Deserialize(stream); #pragma warning restore SYSLIB0011 // 类型或成员已过时 } diff --git a/src/Downkyi.Core/Utils/Stack.cs b/src/Downkyi.Core/Utils/Stack.cs index cf133a3..d6427f2 100644 --- a/src/Downkyi.Core/Utils/Stack.cs +++ b/src/Downkyi.Core/Utils/Stack.cs @@ -25,7 +25,7 @@ public class Stack _data[++_top] = value; } - public T Pop() + public T? Pop() { if (IsEmpty) { @@ -35,7 +35,7 @@ public class Stack return _data[_top--]; } - public T Peek() + public T? Peek() { if (IsEmpty) { diff --git a/src/Downkyi.UI/Downkyi.UI.csproj b/src/Downkyi.UI/Downkyi.UI.csproj index e1f6181..3243c3a 100644 --- a/src/Downkyi.UI/Downkyi.UI.csproj +++ b/src/Downkyi.UI/Downkyi.UI.csproj @@ -1,6 +1,6 @@  - net7.0 + net8.0 enable enable diff --git a/src/Downkyi.UI/Models/VideoInfoView.cs b/src/Downkyi.UI/Models/VideoInfoView.cs new file mode 100644 index 0000000..3340166 --- /dev/null +++ b/src/Downkyi.UI/Models/VideoInfoView.cs @@ -0,0 +1,54 @@ +using CommunityToolkit.Mvvm.ComponentModel; + +namespace Downkyi.UI.Models +{ + public partial class VideoInfoView : ObservableObject + { + public string CoverUrl { get; set; } = string.Empty; + public long UpperMid { get; set; } + public int TypeId { get; set; } + + [ObservableProperty] + private string _cover = string.Empty; + + [ObservableProperty] + private string _title = string.Empty; + + [ObservableProperty] + private string _videoZone = string.Empty; + + [ObservableProperty] + private string _createTime = string.Empty; + + [ObservableProperty] + private string _playNumber = string.Empty; + + [ObservableProperty] + private string _danmakuNumber = string.Empty; + + [ObservableProperty] + private string _likeNumber = string.Empty; + + [ObservableProperty] + private string _coinNumber = string.Empty; + + [ObservableProperty] + private string _favoriteNumber = string.Empty; + + [ObservableProperty] + private string _shareNumber = string.Empty; + + [ObservableProperty] + private string _replyNumber = string.Empty; + + [ObservableProperty] + private string _description = string.Empty; + + [ObservableProperty] + private string _upName = string.Empty; + + [ObservableProperty] + private string _upHeader = string.Empty; + + } +} diff --git a/src/Downkyi.UI/Services/IVideoInfoService.cs b/src/Downkyi.UI/Services/IVideoInfoService.cs new file mode 100644 index 0000000..c7c1051 --- /dev/null +++ b/src/Downkyi.UI/Services/IVideoInfoService.cs @@ -0,0 +1,8 @@ +using Downkyi.UI.Models; + +namespace Downkyi.UI.Services; + +public interface IVideoInfoService +{ + VideoInfoView? GetVideoView(string input); +} \ No newline at end of file diff --git a/src/Downkyi.UI/Services/MainSearchService.cs b/src/Downkyi.UI/Services/MainSearchService.cs index 35f4fa4..8a9ca3c 100644 --- a/src/Downkyi.UI/Services/MainSearchService.cs +++ b/src/Downkyi.UI/Services/MainSearchService.cs @@ -19,7 +19,7 @@ public class MainSearchService : IMainSearchService { // 移除剪贴板id //string validId = input.Replace(AppConstant.ClipboardId, ""); - + string validId = input; // 参数 diff --git a/src/Downkyi.UI/Services/VideoInfoService.cs b/src/Downkyi.UI/Services/VideoInfoService.cs new file mode 100644 index 0000000..d839b34 --- /dev/null +++ b/src/Downkyi.UI/Services/VideoInfoService.cs @@ -0,0 +1,21 @@ +using Downkyi.Core.Bili; +using Downkyi.UI.Models; + +namespace Downkyi.UI.Services; + +public class VideoInfoService : IVideoInfoService +{ + + public VideoInfoView? GetVideoView(string input) + { + if (input == null) { return null; } + + var video = BiliLocator.Video(input); + var videoInfo = video.GetVideoInfo(); + + + + throw new NotImplementedException(); + } + +} \ No newline at end of file diff --git a/src/Downkyi.UI/ViewModels/IndexViewModel.cs b/src/Downkyi.UI/ViewModels/IndexViewModel.cs index 854b3c3..ca7c9c5 100644 --- a/src/Downkyi.UI/ViewModels/IndexViewModel.cs +++ b/src/Downkyi.UI/ViewModels/IndexViewModel.cs @@ -6,7 +6,6 @@ using Downkyi.Core.Settings; using Downkyi.Core.Settings.Models; using Downkyi.Core.Storage; using Downkyi.UI.Mvvm; -using Downkyi.UI.Services; using Downkyi.UI.ViewModels.DownloadManager; using Downkyi.UI.ViewModels.Login; using Downkyi.UI.ViewModels.Settings; diff --git a/src/Downkyi.UI/ViewModels/Settings/BaseSettingsViewModel.cs b/src/Downkyi.UI/ViewModels/Settings/BaseSettingsViewModel.cs index 7caea0d..0f590ed 100644 --- a/src/Downkyi.UI/ViewModels/Settings/BaseSettingsViewModel.cs +++ b/src/Downkyi.UI/ViewModels/Settings/BaseSettingsViewModel.cs @@ -28,12 +28,12 @@ public class BaseSettingsViewModel : ViewModelBase // 发送通知 if (isSucceed) { - NotificationEvent.Publish(TipSettingUpdated); + //NotificationEvent.Publish(TipSettingUpdated); Log.Logger.Info($"{key}: {TipSettingUpdated}"); } else { - NotificationEvent.Publish(TipSettingFailed); + //NotificationEvent.Publish(TipSettingFailed); Log.Logger.Info($"{key}: {TipSettingFailed}"); } } diff --git a/src/Downkyi.UI/ViewModels/Video/VideoDetailViewModel.cs b/src/Downkyi.UI/ViewModels/Video/VideoDetailViewModel.cs index f664035..fc5585a 100644 --- a/src/Downkyi.UI/ViewModels/Video/VideoDetailViewModel.cs +++ b/src/Downkyi.UI/ViewModels/Video/VideoDetailViewModel.cs @@ -1,5 +1,8 @@ -using CommunityToolkit.Mvvm.Input; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Downkyi.UI.Models; using Downkyi.UI.Mvvm; +using Downkyi.UI.ViewModels.DownloadManager; namespace Downkyi.UI.ViewModels.Video; @@ -7,8 +10,42 @@ public partial class VideoDetailViewModel : ViewModelBase { public const string Key = "VideoDetail"; + // 保存输入字符串,避免被用户修改 + private string? input = null; + + #region 页面属性申明 + + [ObservableProperty] + private string _inputText = string.Empty; + + [ObservableProperty] + private bool _loadingVisibility; + + [ObservableProperty] + private bool _contentVisibility; + + [ObservableProperty] + private VideoInfoView _videoInfoView = new(); + + #endregion + public VideoDetailViewModel(BaseServices baseServices) : base(baseServices) { + #region 属性初始化 + + ContentVisibility = true; + + VideoInfoView.Title = "video name"; + + VideoInfoView.CoinNumber = "10"; + VideoInfoView.DanmakuNumber = "1"; + VideoInfoView.FavoriteNumber = "1"; + VideoInfoView.LikeNumber = "10"; + VideoInfoView.PlayNumber = "0"; + VideoInfoView.ReplyNumber = "1"; + VideoInfoView.ShareNumber = "1"; + + #endregion } #region 命令申明 @@ -24,6 +61,30 @@ public partial class VideoDetailViewModel : ViewModelBase await NavigationService.BackwardAsync(parameter); } + [RelayCommand] + private void Input() { } + + [RelayCommand(FlowExceptionsToTaskScheduler = true)] + private async Task DownloadManager() + { + await NavigationService.ForwardAsync(DownloadManagerViewModel.Key); + } + + [RelayCommand] + private void CopyCover() { } + + [RelayCommand] + private void CopyCoverUrl() { } + + [RelayCommand] + private void Upper() { } + #endregion + public override void OnNavigatedTo(Dictionary? parameter) + { + base.OnNavigatedTo(parameter); + + } + } \ No newline at end of file diff --git a/src/Downkyi/Assets/bili/loading/loading.gif b/src/Downkyi/Assets/bili/loading/loading.gif new file mode 100644 index 0000000..31f8504 Binary files /dev/null and b/src/Downkyi/Assets/bili/loading/loading.gif differ diff --git a/src/Downkyi/Assets/gradient.png b/src/Downkyi/Assets/gradient.png new file mode 100644 index 0000000..2f4b24e Binary files /dev/null and b/src/Downkyi/Assets/gradient.png differ diff --git a/src/Downkyi/Downkyi.csproj b/src/Downkyi/Downkyi.csproj index c56c79f..705e1b8 100644 --- a/src/Downkyi/Downkyi.csproj +++ b/src/Downkyi/Downkyi.csproj @@ -1,7 +1,7 @@  WinExe - net7.0 + net8.0 enable true Downkyi @@ -12,7 +12,7 @@ DownKyi DownKyi DownKyi - Copyright © Downkyi 2020-2023 + Copyright © Downkyi 2020-2024 2.0.0 2.0.0 2.0.0 @@ -32,21 +32,21 @@ - - - - - + + + + + + - - - - - + + + + + - diff --git a/src/Downkyi/Languages/Default.axaml b/src/Downkyi/Languages/Default.axaml index d04c36b..cbce6e8 100644 --- a/src/Downkyi/Languages/Default.axaml +++ b/src/Downkyi/Languages/Default.axaml @@ -19,8 +19,8 @@ 登录 - 请输入B站网址链接或av、BV号等…… - 请输入B站视频播放地址…… + 请输入B站网址链接或av、BV号等...... + 请输入B站视频播放地址...... 设置 下载管理 工具箱 @@ -120,6 +120,7 @@ 悄悄关注 + 请输入B站视频播放地址...... 复制封面图片 复制封面URL 播放 diff --git a/src/Downkyi/Models/AppInfo.cs b/src/Downkyi/Models/AppInfo.cs index 372ac7d..a42a194 100644 --- a/src/Downkyi/Models/AppInfo.cs +++ b/src/Downkyi/Models/AppInfo.cs @@ -1,5 +1,4 @@ using CommunityToolkit.Mvvm.DependencyInjection; -using Downkyi.Services; using Downkyi.UI.Services; using System; using System.Text.RegularExpressions; diff --git a/src/Downkyi/ServiceLocator.cs b/src/Downkyi/ServiceLocator.cs index 2e798b4..378fe45 100644 --- a/src/Downkyi/ServiceLocator.cs +++ b/src/Downkyi/ServiceLocator.cs @@ -46,6 +46,12 @@ public static class ServiceLocator public static UserSpaceViewModel UserSpaceViewModel => Ioc.Default.GetRequiredService(); + // 视频页面 + public static PublicFavoritesViewModel PublicFavoritesViewModel => + Ioc.Default.GetRequiredService(); + public static VideoDetailViewModel VideoDetailViewModel => + Ioc.Default.GetRequiredService(); + // 设置 public static SettingsViewModel SettingsViewModel => Ioc.Default.GetRequiredService(); @@ -126,8 +132,8 @@ public static class ServiceLocator .AddSingleton() .AddSingleton() // - .AddSingleton() .AddSingleton() + .AddSingleton() .BuildServiceProvider()); } } diff --git a/src/Downkyi/Themes/Default/Styles/TextBox.axaml b/src/Downkyi/Themes/Default/Styles/TextBox.axaml index cae2c41..173a0cc 100644 --- a/src/Downkyi/Themes/Default/Styles/TextBox.axaml +++ b/src/Downkyi/Themes/Default/Styles/TextBox.axaml @@ -2,6 +2,7 @@ + + + + +