mirror of
https://github.com/leiurayer/downkyi.git
synced 2025-04-27 05:30:47 +08:00
提交已重构的部分
This commit is contained in:
parent
2c13369532
commit
8f7b9df8f9
src
Core
Common.csDownloader.csFFmpegHelper.csFileDownloadUtil.csUserSpaceOld.csUtils.cs
api
danmaku
fileDownload
FileDownloadConfig.csFileDownloadEvent.csFileDownloadHelper.csFileDownloadInfo.csFileInfo.csThreadDownloadInfo.cs
history
login
users
aria2cNet
danmaku2ass
Bilibili.csCollision.csConfig.csCreater.csDanmaku.csDictionary.csDisplay.csFilter.csProducer.csStudio.csSubtitle.csUtils.cs
entity
BangumiMedia.csBangumiSeason.csCheeseList.csCheeseSeason.csDanmu.csFavFolder.csFavResource.csLoginUrl.csMyInfo.csNav.csPlayUrl.csStat.csUserSettings.csVideoDetail.csVideoView.cs
entity2
history
users
settings
DownKyi.Core/Aria2cNet
AriaManager.cs
Client
AriaClient.cs
Entity
AriaAddMetalink.csAriaAddTorrent.csAriaAddUri.csAriaChangeOption.csAriaChangePosition.csAriaChangeUri.csAriaError.csAriaGetFiles.csAriaGetGlobalStat.csAriaGetOption.csAriaGetPeers.csAriaGetServers.csAriaGetSessionInfo.csAriaGetUris.csAriaOption.csAriaPause.csAriaRemove.csAriaSaveSession.csAriaSendData.csAriaShutdown.csAriaTellStatus.csAriaUri.csAriaVersion.csSystemListMethods.cs
@ -1,440 +0,0 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
public static class Common
|
||||
{
|
||||
// 配置文件所在路径
|
||||
public static readonly string ConfigPath = "./Config/";
|
||||
|
||||
// 日志、历史等文件所在路径
|
||||
public static readonly string RecordPath = "./Config/";
|
||||
|
||||
/// <summary>
|
||||
/// 判断字符串是否以http或https开头,且域名为bilibili.com
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsUrl(string input)
|
||||
{
|
||||
if (input.StartsWith("http://") || input.StartsWith("https://"))
|
||||
{
|
||||
if (input.Contains("www.bilibili.com")) { return true; }
|
||||
else { return false; }
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否为avid
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAvid(string input)
|
||||
{
|
||||
if (input.StartsWith("av"))
|
||||
{
|
||||
bool isInt = Regex.IsMatch(input.Remove(0, 2), @"^\d+$");
|
||||
return isInt;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否为bvid
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsBvid(string input)
|
||||
{
|
||||
if (input.StartsWith("BV") && input.Length == 12)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否是用户空间的url
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsUserSpaceUrl(string input)
|
||||
{
|
||||
if (input.StartsWith("http://") || input.StartsWith("https://"))
|
||||
{
|
||||
if (input.Contains("space.bilibili.com"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否是用户id
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsUserId(string input)
|
||||
{
|
||||
string inputLower = input.ToLower();
|
||||
if (inputLower.StartsWith("uid:"))
|
||||
{
|
||||
string uid = inputLower.TrimStart(new char[] { 'u', 'i', 'd', ':' });
|
||||
return IsInt(uid);
|
||||
}
|
||||
else if (inputLower.StartsWith("uid"))
|
||||
{
|
||||
string uid = inputLower.TrimStart(new char[] { 'u', 'i', 'd' });
|
||||
return IsInt(uid);
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户id
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public static long GetUserId(string url)
|
||||
{
|
||||
string[] strList = url.Split('?');
|
||||
string baseUrl = strList[0];
|
||||
|
||||
var match = Regex.Match(baseUrl, @"\d+");
|
||||
if (match.Success)
|
||||
{
|
||||
return GetInt(match.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从url中解析id,包括bvid和番剧的id
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetVideoId(string url)
|
||||
{
|
||||
string[] strList = url.Split('?');
|
||||
string baseUrl = strList[0];
|
||||
|
||||
string[] str2List = baseUrl.Split('/');
|
||||
string id = str2List[str2List.Length - 1];
|
||||
|
||||
if (id == "")
|
||||
{
|
||||
// 字符串末尾
|
||||
return str2List[str2List.Length - 2];
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是视频还是番剧
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public static VideoType GetVideoType(string url)
|
||||
{
|
||||
if (url.ToLower().Contains("/video/bv"))
|
||||
{
|
||||
return VideoType.VIDEO;
|
||||
}
|
||||
|
||||
if (url.ToLower().Contains("/video/av"))
|
||||
{
|
||||
return VideoType.VIDEO_AV;
|
||||
}
|
||||
|
||||
if (url.ToLower().Contains("/bangumi/play/ss"))
|
||||
{
|
||||
return VideoType.BANGUMI_SEASON;
|
||||
}
|
||||
|
||||
if (url.ToLower().Contains("/bangumi/play/ep"))
|
||||
{
|
||||
return VideoType.BANGUMI_EPISODE;
|
||||
}
|
||||
|
||||
if (url.ToLower().Contains("/bangumi/media/md"))
|
||||
{
|
||||
return VideoType.BANGUMI_MEDIA;
|
||||
}
|
||||
|
||||
if (url.ToLower().Contains("/cheese/play/ss"))
|
||||
{
|
||||
return VideoType.CHEESE_SEASON;
|
||||
}
|
||||
|
||||
if (url.ToLower().Contains("/cheese/play/ep"))
|
||||
{
|
||||
return VideoType.CHEESE_EPISODE;
|
||||
}
|
||||
|
||||
return VideoType.NONE;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化Duration时间
|
||||
/// </summary>
|
||||
/// <param name="duration"></param>
|
||||
/// <returns></returns>
|
||||
public static string FormatDuration(long duration)
|
||||
{
|
||||
string formatDuration;
|
||||
if (duration / 60 > 0)
|
||||
{
|
||||
long dur = duration / 60;
|
||||
if (dur / 60 > 0)
|
||||
{
|
||||
formatDuration = $"{dur / 60}h{dur % 60}m{duration % 60}s";
|
||||
}
|
||||
else
|
||||
{
|
||||
formatDuration = $"{duration / 60}m{duration % 60}s";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
formatDuration = $"{duration}s";
|
||||
}
|
||||
return formatDuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化Duration时间,格式为00:00:00
|
||||
/// </summary>
|
||||
/// <param name="duration"></param>
|
||||
/// <returns></returns>
|
||||
public static string FormatDuration2(long duration)
|
||||
{
|
||||
string formatDuration;
|
||||
if (duration / 60 > 0)
|
||||
{
|
||||
long dur = duration / 60;
|
||||
if (dur / 60 > 0)
|
||||
{
|
||||
formatDuration = string.Format("{0:D2}", dur / 60) + ":" + string.Format("{0:D2}", dur % 60) + ":" + string.Format("{0:D2}", duration % 60);
|
||||
}
|
||||
else
|
||||
{
|
||||
formatDuration = "00:" + string.Format("{0:D2}", duration / 60) + ":" + string.Format("{0:D2}", duration % 60);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
formatDuration = "00:00:" + string.Format("{0:D2}", duration);
|
||||
}
|
||||
return formatDuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化Duration时间,格式为00:00
|
||||
/// </summary>
|
||||
/// <param name="duration"></param>
|
||||
/// <returns></returns>
|
||||
public static string FormatDuration3(long duration)
|
||||
{
|
||||
string formatDuration;
|
||||
if (duration / 60 > 0)
|
||||
{
|
||||
long dur = duration / 60;
|
||||
if (dur / 60 > 0)
|
||||
{
|
||||
formatDuration = string.Format("{0:D2}", dur / 60) + ":" + string.Format("{0:D2}", dur % 60) + ":" + string.Format("{0:D2}", duration % 60);
|
||||
}
|
||||
else
|
||||
{
|
||||
formatDuration = string.Format("{0:D2}", duration / 60) + ":" + string.Format("{0:D2}", duration % 60);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
formatDuration = "00:" + string.Format("{0:D2}", duration);
|
||||
}
|
||||
return formatDuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化数字,超过10000的数字将单位改为万,超过100000000的数字将单位改为亿,并保留1位小数
|
||||
/// </summary>
|
||||
/// <param name="number"></param>
|
||||
/// <returns></returns>
|
||||
public static string FormatNumber(long number)
|
||||
{
|
||||
if (number > 99999999)
|
||||
{
|
||||
return (number / 100000000.0f).ToString("F1") + "亿";
|
||||
}
|
||||
|
||||
if (number > 9999)
|
||||
{
|
||||
return (number / 10000.0f).ToString("F1") + "万";
|
||||
}
|
||||
else
|
||||
{
|
||||
return number.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化网速
|
||||
/// </summary>
|
||||
/// <param name="speed"></param>
|
||||
/// <returns></returns>
|
||||
public static string FormatSpeed(float speed)
|
||||
{
|
||||
string formatSpeed;
|
||||
if (speed <= 0)
|
||||
{
|
||||
formatSpeed = "0B/s";
|
||||
}
|
||||
else if (speed < 1024)
|
||||
{
|
||||
formatSpeed = speed.ToString("#.##") + "B/s";
|
||||
}
|
||||
else if (speed < 1024 * 1024)
|
||||
{
|
||||
formatSpeed = (speed / 1024).ToString("#.##") + "KB/s";
|
||||
}
|
||||
else
|
||||
{
|
||||
formatSpeed = (speed / 1024 / 1024).ToString("#.##") + "MB/s";
|
||||
}
|
||||
return formatSpeed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化字节大小,可用于文件大小的显示
|
||||
/// </summary>
|
||||
/// <param name="fileSize"></param>
|
||||
/// <returns></returns>
|
||||
public static string FormatFileSize(long fileSize)
|
||||
{
|
||||
string formatFileSize;
|
||||
if (fileSize <= 0)
|
||||
{
|
||||
formatFileSize = "0B";
|
||||
}
|
||||
else if (fileSize < 1024)
|
||||
{
|
||||
formatFileSize = fileSize.ToString() + "B";
|
||||
}
|
||||
else if (fileSize < 1024 * 1024)
|
||||
{
|
||||
formatFileSize = (fileSize / 1024.0).ToString("#.##") + "KB";
|
||||
}
|
||||
else if (fileSize < 1024 * 1024 * 1024)
|
||||
{
|
||||
formatFileSize = (fileSize / 1024.0 / 1024.0).ToString("#.##") + "MB";
|
||||
}
|
||||
else
|
||||
{
|
||||
formatFileSize = (fileSize / 1024.0 / 1024.0 / 1024.0).ToString("#.##") + "GB";
|
||||
}
|
||||
return formatFileSize;
|
||||
}
|
||||
|
||||
private static long GetInt(string value)
|
||||
{
|
||||
if (IsInt(value))
|
||||
{
|
||||
return long.Parse(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsInt(string value)
|
||||
{
|
||||
return Regex.IsMatch(value, @"^\d+$");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 支持的视频类型
|
||||
/// </summary>
|
||||
public enum VideoType
|
||||
{
|
||||
NONE,
|
||||
VIDEO, // 对应 /video/BV
|
||||
VIDEO_AV, // 对应 /video/av
|
||||
// BANGUMI, // BANGUMI细分为以下三个部分
|
||||
BANGUMI_SEASON, // 对应 /bangumi/play/ss
|
||||
BANGUMI_EPISODE, // 对应 /bangumi/play/ep
|
||||
BANGUMI_MEDIA, // 对应 /bangumi/media/md
|
||||
CHEESE_SEASON, // 对应 /cheese/play/ss
|
||||
CHEESE_EPISODE // 对应 /cheese/play/ep
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 线程
|
||||
/// </summary>
|
||||
public enum ThreadStatus
|
||||
{
|
||||
MAIN_UI, // 主线程
|
||||
START_PARSE, // 开始解析url
|
||||
ADD_ALL_TO_DOWNLOAD,
|
||||
START_DOWNLOAD
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 视频的编码格式,flv也视为编码放这里
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public enum VideoCodec
|
||||
{
|
||||
NONE = 1,
|
||||
AVC,
|
||||
HEVC,
|
||||
FLV
|
||||
}
|
||||
|
||||
}
|
@ -1,534 +0,0 @@
|
||||
using Core.entity;
|
||||
using Core.settings;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
public static class Downloader
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得远程文件的大小
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="referer"></param>
|
||||
/// <returns></returns>
|
||||
public static long GetRemoteFileSize(string url, string referer)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||||
request.Method = "GET";
|
||||
request.Timeout = 30 * 1000;
|
||||
request.UserAgent = Utils.GetUserAgent();
|
||||
//request.ContentType = "text/html;charset=UTF-8";
|
||||
request.Headers["accept-language"] = "zh-CN,zh;q=0.9,en;q=0.8";
|
||||
request.Referer = referer;
|
||||
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
return response.ContentLength;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetRemoteFileSize()发生异常: {0}", e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得视频详情及播放列表
|
||||
/// </summary>
|
||||
/// <param name="bvid"></param>
|
||||
/// <returns></returns>
|
||||
public static VideoViewData GetVideoInfo(string bvid, long aid, string referer, bool isBackup = false)
|
||||
{
|
||||
string url;
|
||||
if (bvid != null)
|
||||
{
|
||||
url = $"https://api.bilibili.com/x/web-interface/view?bvid={bvid}";
|
||||
}
|
||||
else if (aid >= 0)
|
||||
{
|
||||
url = $"https://api.bilibili.com/x/web-interface/view?aid={aid}";
|
||||
}
|
||||
else
|
||||
{ return null; }
|
||||
|
||||
// 采用备用的api,只能获取cid
|
||||
if (isBackup)
|
||||
{
|
||||
string backupUrl = $"https://api.bilibili.com/x/player/pagelist?bvid={bvid}&jsonp=jsonp";
|
||||
url = backupUrl;
|
||||
}
|
||||
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
VideoView videoView;
|
||||
if (isBackup)
|
||||
{
|
||||
Pagelist pagelist = JsonConvert.DeserializeObject<Pagelist>(response);
|
||||
|
||||
videoView = new VideoView
|
||||
{
|
||||
code = pagelist.code,
|
||||
message = pagelist.message,
|
||||
ttl = pagelist.ttl
|
||||
};
|
||||
videoView.data.pages = pagelist.data;
|
||||
}
|
||||
else
|
||||
{
|
||||
videoView = JsonConvert.DeserializeObject<VideoView>(response);
|
||||
}
|
||||
|
||||
if (videoView != null)
|
||||
{
|
||||
if (videoView.data != null)
|
||||
{
|
||||
return videoView.data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
|
||||
// 进入备选的url中
|
||||
//return GetVideoInfo(bvid, referer, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (JsonReaderException e)
|
||||
{
|
||||
Console.WriteLine("GetVideoInfo()发生JsonReader异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetVideoInfo()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过seasonId获得番剧的剧集详情
|
||||
/// </summary>
|
||||
/// <param name="seasonId"></param>
|
||||
/// <returns></returns>
|
||||
public static BangumiSeasonResult GetBangumiSeason(long seasonId, string referer)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/pgc/view/web/season?season_id={seasonId}";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
BangumiSeason bangumiSeason = JsonConvert.DeserializeObject<BangumiSeason>(response);
|
||||
if (bangumiSeason != null) { return bangumiSeason.result; }
|
||||
else { return null; }
|
||||
}
|
||||
catch (JsonReaderException e)
|
||||
{
|
||||
Console.WriteLine("GetBangumiSeason()发生JsonReader异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetBangumiSeason()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static long GetBangumiSeasonIdByMedia(long mediaId, string referer)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/pgc/review/user?media_id={mediaId}";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
BangumiMedia bangumiMedia = JsonConvert.DeserializeObject<BangumiMedia>(response);
|
||||
if (bangumiMedia.result.media != null) { return bangumiMedia.result.media.season_id; }
|
||||
else { return 0; }
|
||||
}
|
||||
catch (JsonReaderException e)
|
||||
{
|
||||
Console.WriteLine("GetBangumiSeasonIdByMedia()发生JsonReader异常: {0}", e);
|
||||
return 0;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetBangumiSeasonIdByMedia()发生异常: {0}", e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static long GetBangumiSeasonIdByEpisode(long episode, string referer)
|
||||
{
|
||||
string url = $"https://www.bilibili.com/bangumi/play/ep{episode}";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
// "ssId": 28324,
|
||||
string pattern = "\"ssId\":\\s?\\d+,";
|
||||
Regex regex = new Regex(pattern);
|
||||
Match match = regex.Match(response);
|
||||
|
||||
// 删除多余的字符
|
||||
string ssId = match.Value.Replace("ssId", "");
|
||||
ssId = ssId.Replace("\"", "");
|
||||
ssId = ssId.Replace(":", "");
|
||||
ssId = ssId.Replace(" ", "");
|
||||
ssId = ssId.Replace(",", "");
|
||||
|
||||
long seasonId;
|
||||
try
|
||||
{
|
||||
seasonId = long.Parse(ssId);
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
Console.WriteLine("GetBangumiSeasonIdByEpisode()发生异常: {0}", e);
|
||||
return 0;
|
||||
}
|
||||
return seasonId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过ep_id获得课程的信息
|
||||
/// </summary>
|
||||
/// <param name="episode"></param>
|
||||
/// <param name="referer"></param>
|
||||
/// <returns></returns>
|
||||
public static CheeseSeasonData GetCheeseSeason(long seasonId, long episode, string referer)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/pugv/view/web/season?";
|
||||
if (seasonId != 0)
|
||||
{
|
||||
url += $"season_id={seasonId}";
|
||||
}
|
||||
else if (episode != 0)
|
||||
{
|
||||
url += $"ep_id={episode}";
|
||||
}
|
||||
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
CheeseSeason cheeseSeason = JsonConvert.DeserializeObject<CheeseSeason>(response);
|
||||
if (cheeseSeason != null) { return cheeseSeason.data; }
|
||||
else { return null; }
|
||||
}
|
||||
catch (JsonReaderException e)
|
||||
{
|
||||
Console.WriteLine("GetCheeseSeason()发生JsonReader异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetCheeseSeason()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//public static long GetCheeseEpisodeIdBySeasonId(long seasonId, string referer)
|
||||
//{
|
||||
// string url = $"https://api.bilibili.com/pugv/view/web/ep/list?season_id={seasonId}&pn=1";
|
||||
// string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
// try
|
||||
// {
|
||||
// CheeseList cheeseList = JsonConvert.DeserializeObject<CheeseList>(response);
|
||||
// if (cheeseList.data.items != null && cheeseList.data.items.Count > 0)
|
||||
// {
|
||||
// return cheeseList.data.items[0].id;
|
||||
// }
|
||||
// else { return 0; }
|
||||
// }
|
||||
// catch (JsonReaderException e)
|
||||
// {
|
||||
// Console.WriteLine("发生异常: {0}", e);
|
||||
// return 0;
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 获得音视频流链接
|
||||
/// </summary>
|
||||
/// <param name="bvid">视频的bvid</param>
|
||||
/// <param name="cid">视频的cid</param>
|
||||
public static PlayUrlData GetStreamInfo(string bvid, long avid, long cid, long episodeId, int quality, string referer, bool isProxy = false, int proxy = 0)
|
||||
{
|
||||
string baseUrlVideo = "https://api.bilibili.com/x/player/playurl";
|
||||
string baseUrlSeason = "https://api.bilibili.com/pgc/player/web/playurl";
|
||||
string baseUrlCheese = "https://api.bilibili.com/pugv/player/web/playurl";
|
||||
string baseUrl;
|
||||
VideoType videoType = Common.GetVideoType(referer);
|
||||
switch (videoType)
|
||||
{
|
||||
case VideoType.VIDEO:
|
||||
baseUrl = baseUrlVideo;
|
||||
break;
|
||||
case VideoType.VIDEO_AV:
|
||||
baseUrl = baseUrlVideo;
|
||||
break;
|
||||
case VideoType.BANGUMI_SEASON:
|
||||
baseUrl = baseUrlSeason;
|
||||
break;
|
||||
case VideoType.BANGUMI_EPISODE:
|
||||
baseUrl = baseUrlSeason;
|
||||
break;
|
||||
case VideoType.BANGUMI_MEDIA:
|
||||
baseUrl = baseUrlSeason;
|
||||
break;
|
||||
case VideoType.CHEESE_SEASON:
|
||||
baseUrl = baseUrlCheese;
|
||||
break;
|
||||
case VideoType.CHEESE_EPISODE:
|
||||
baseUrl = baseUrlCheese;
|
||||
break;
|
||||
default:
|
||||
baseUrl = baseUrlVideo;
|
||||
break;
|
||||
}
|
||||
// TODO 没有的参数不加入url
|
||||
//string url = $"{baseUrl}?cid={cid}&bvid={bvid}&avid={avid}&ep_id={episodeId}&qn={quality}&otype=json&fourk=1&fnver=0&fnval=16";
|
||||
string url = $"{baseUrl}?cid={cid}&qn={quality}&otype=json&fourk=1&fnver=0&fnval=16";
|
||||
if (bvid != null)
|
||||
{
|
||||
url += $"&bvid={bvid}";
|
||||
}
|
||||
if (avid != 0)
|
||||
{
|
||||
url += $"&avid={avid}";
|
||||
}
|
||||
if (episodeId != 0)
|
||||
{
|
||||
url += $"&ep_id={episodeId}";
|
||||
}
|
||||
|
||||
// 代理网址
|
||||
//https://www.biliplus.com/BPplayurl.php?cid=180873425&qn=116&type=&otype=json&fourk=1&bvid=BV1pV411o7yD&ep_id=317925&fnver=0&fnval=16&module=pgc
|
||||
if (isProxy && proxy == 1)
|
||||
{
|
||||
string proxyUrl1 = "https://www.biliplus.com/BPplayurl.php";
|
||||
url = $"{proxyUrl1}?cid={cid}&bvid={bvid}&qn={quality}&otype=json&fourk=1&fnver=0&fnval=16&module=pgc";
|
||||
}
|
||||
else if (isProxy && proxy == 2)
|
||||
{
|
||||
string proxyUrl2 = "https://biliplus.ipcjs.top/BPplayurl.php";
|
||||
url = $"{proxyUrl2}?cid={cid}&bvid={bvid}&qn={quality}&otype=json&fourk=1&fnver=0&fnval=16&module=pgc";
|
||||
}
|
||||
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
//Console.WriteLine(response);
|
||||
|
||||
try
|
||||
{
|
||||
PlayUrl playUrl;
|
||||
if (isProxy)
|
||||
{
|
||||
PlayUrlData playUrlData = JsonConvert.DeserializeObject<PlayUrlData>(response);
|
||||
|
||||
playUrl = new PlayUrl
|
||||
{
|
||||
result = playUrlData
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
playUrl = JsonConvert.DeserializeObject<PlayUrl>(response);
|
||||
}
|
||||
|
||||
if (playUrl != null)
|
||||
{
|
||||
if (playUrl.data != null) { return playUrl.data; }
|
||||
if (playUrl.result != null) { return playUrl.result; }
|
||||
|
||||
// 无法从B站获取数据,进入代理网站
|
||||
if (Settings.GetInstance().IsLiftingOfRegion() == ALLOW_STATUS.YES)
|
||||
{
|
||||
switch (proxy)
|
||||
{
|
||||
case 0:
|
||||
return GetStreamInfo(bvid, avid, cid, episodeId, quality, referer, true, 1);
|
||||
case 1:
|
||||
return GetStreamInfo(bvid, avid, cid, episodeId, quality, referer, true, 2);
|
||||
case 2:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
else { return null; }
|
||||
}
|
||||
catch (JsonReaderException e)
|
||||
{
|
||||
Console.WriteLine("GetStreamInfo()发生JsonReader异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetStreamInfo()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//public static List<Danmaku> GetAllDanmaku(long cid, long publishTime, string referer)
|
||||
//{
|
||||
// List<Danmaku> danmakus = new List<Danmaku>();
|
||||
|
||||
// // 设置视频发布日期
|
||||
// DateTime publishDate = new DateTime(1970, 1, 1);
|
||||
// publishDate = publishDate.AddSeconds(publishTime);
|
||||
|
||||
// // 获得有弹幕的日期date
|
||||
// List<string> danmakuDateList = new List<string>();
|
||||
// while (true)
|
||||
// {
|
||||
// string month = publishDate.ToString("yyyy-MM");
|
||||
// string url = $"https://api.bilibili.com/x/v2/dm/history/index?type=1&oid={cid}&month={month}";
|
||||
// string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
// DanmuDate danmakuDate;
|
||||
// try
|
||||
// {
|
||||
// danmakuDate = JsonConvert.DeserializeObject<DanmuDate>(response);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// Console.WriteLine("GetAllDanmaku()发生异常: {0}", e);
|
||||
// continue;
|
||||
// }
|
||||
// if (danmakuDate != null || danmakuDate.data != null) { danmakuDateList.AddRange(danmakuDate.data); }
|
||||
|
||||
// if (publishDate.CompareTo(DateTime.Now) > 0) { break; }
|
||||
// publishDate = publishDate.AddMonths(1);
|
||||
// Thread.Sleep(100);
|
||||
// }
|
||||
|
||||
// // 获取弹幕
|
||||
// foreach (var date in danmakuDateList)
|
||||
// {
|
||||
// Console.WriteLine(date);
|
||||
|
||||
// List<Danmaku> danmakusOfOneDay = GetDanmaku(cid, date);
|
||||
|
||||
// foreach (Danmaku danmaku in danmakusOfOneDay)
|
||||
// {
|
||||
// if (danmakus.Find(it => it.DanmuId == danmaku.DanmuId) == null)
|
||||
// {
|
||||
// danmakus.Add(danmaku);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 按弹幕发布时间排序
|
||||
// danmakus = danmakus.OrderBy(it => it.Timestamp).ToList();
|
||||
|
||||
// return danmakus;
|
||||
//}
|
||||
|
||||
//public static List<Danmaku> GetDanmaku(long cid, string date, string referer)
|
||||
//{
|
||||
// string url = $"https://api.bilibili.com/x/v2/dm/history?type=1&oid={cid}&date={date}";
|
||||
// string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
// // <?xml version="1.0" encoding="UTF-8"?>
|
||||
// // {"code":-101,"message":"账号未登录","ttl":1}
|
||||
// if (response.Contains("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"))
|
||||
// {
|
||||
// List<Danmaku> danmakus = new List<Danmaku>();
|
||||
|
||||
// XmlDocument doc = new XmlDocument();
|
||||
// doc.LoadXml(response);
|
||||
// // 取得节点名为d的XmlNode集合
|
||||
// XmlNodeList danmuList = doc.GetElementsByTagName("d");
|
||||
// foreach (XmlNode node in danmuList)
|
||||
// {
|
||||
// // 返回的是文字内容
|
||||
// string nodeText = node.InnerText;
|
||||
// // 节点p属性值
|
||||
// string childValue = node.Attributes["p"].Value;
|
||||
// // 拆分属性
|
||||
// string[] attrs = childValue.Split(',');
|
||||
|
||||
// Danmaku danmaku = new Danmaku
|
||||
// {
|
||||
// Text = nodeText,
|
||||
// Time = float.Parse(attrs[0]),
|
||||
// Type = int.Parse(attrs[1]),
|
||||
// Fontsize = int.Parse(attrs[2]),
|
||||
// Color = long.Parse(attrs[3]),
|
||||
// Timestamp = long.Parse(attrs[4]),
|
||||
// Pool = int.Parse(attrs[5]),
|
||||
// UserId = attrs[6],
|
||||
// DanmuId = attrs[7]
|
||||
// };
|
||||
// danmakus.Add(danmaku);
|
||||
// }
|
||||
|
||||
// return danmakus;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// DanmuFromWeb danmu = JsonConvert.DeserializeObject<DanmuFromWeb>(response);
|
||||
// if (danmu != null) { Console.WriteLine(danmu.message); }
|
||||
// return null;
|
||||
// }
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
///// 获取弹幕,不需要登录信息,只能获取3000条弹幕
|
||||
///// </summary>
|
||||
///// <param name="cid"></param>
|
||||
///// <returns></returns>
|
||||
//public static List<Danmaku> GetDanmaku(long cid, string referer)
|
||||
//{
|
||||
// string url = $"https://api.bilibili.com/x/v1/dm/list.so?oid={cid}";
|
||||
// string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
// if (response.Contains("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"))
|
||||
// {
|
||||
// List<Danmaku> danmakus = new List<Danmaku>();
|
||||
|
||||
// XmlDocument doc = new XmlDocument();
|
||||
// doc.LoadXml(response);
|
||||
// // 取得节点名为d的XmlNode集合
|
||||
// XmlNodeList danmuList = doc.GetElementsByTagName("d");
|
||||
// foreach (XmlNode node in danmuList)
|
||||
// {
|
||||
// // 返回的是文字内容
|
||||
// string nodeText = node.InnerText;
|
||||
// // 节点p属性值
|
||||
// string childValue = node.Attributes["p"].Value;
|
||||
// // 拆分属性
|
||||
// string[] attrs = childValue.Split(',');
|
||||
|
||||
// Danmaku danmaku = new Danmaku
|
||||
// {
|
||||
// Text = nodeText,
|
||||
// Time = float.Parse(attrs[0]),
|
||||
// Type = int.Parse(attrs[1]),
|
||||
// Fontsize = int.Parse(attrs[2]),
|
||||
// Color = long.Parse(attrs[3]),
|
||||
// Timestamp = long.Parse(attrs[4]),
|
||||
// Pool = int.Parse(attrs[5]),
|
||||
// UserId = attrs[6],
|
||||
// DanmuId = attrs[7]
|
||||
// };
|
||||
// danmakus.Add(danmaku);
|
||||
// }
|
||||
|
||||
// return danmakus;
|
||||
// }
|
||||
// return null;
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
@ -1,254 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
public static class FFmpegHelper
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 合并音频和视频
|
||||
/// </summary>
|
||||
/// <param name="video1"></param>
|
||||
/// <param name="video2"></param>
|
||||
/// <param name="destVideo"></param>
|
||||
public static bool MergeVideo(string video1, string video2, string destVideo)
|
||||
{
|
||||
string param = $"-i \"{video1}\" -i \"{video2}\" -acodec copy -vcodec copy -f mp4 \"{destVideo}\"";
|
||||
if (video1 == null || !File.Exists(video1))
|
||||
{
|
||||
param = $"-i \"{video2}\" -acodec copy -vcodec copy -f mp4 \"{destVideo}\"";
|
||||
}
|
||||
if (video2 == null || !File.Exists(video2))
|
||||
{
|
||||
param = $"-i \"{video1}\" -acodec copy -vcodec copy -f mp4 \"{destVideo}\"";
|
||||
}
|
||||
if (!File.Exists(video1) && !File.Exists(video2)) { return false; }
|
||||
|
||||
// 如果存在
|
||||
try { File.Delete(destVideo); }
|
||||
catch (IOException e)
|
||||
{
|
||||
Console.WriteLine("MergeVideo()发生IO异常: {0}", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
ExcuteProcess("ffmpeg.exe", param, null, (s, e) => Console.WriteLine(e.Data));
|
||||
|
||||
try
|
||||
{
|
||||
if (video1 != null) { File.Delete(video1); }
|
||||
if (video2 != null) { File.Delete(video2); }
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Console.WriteLine("MergeVideo()发生IO异常: {0}", e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拼接多个视频
|
||||
/// </summary>
|
||||
/// <param name="workingDirectory"></param>
|
||||
/// <param name="flvFiles"></param>
|
||||
/// <param name="destVideo"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ConcatVideo(string workingDirectory, List<string> flvFiles, string destVideo)
|
||||
{
|
||||
// contact的文件名,不包含路径
|
||||
string concatFileName = Guid.NewGuid().ToString("N") + "_concat.txt";
|
||||
try
|
||||
{
|
||||
string contact = "";
|
||||
foreach (string flv in flvFiles)
|
||||
{
|
||||
contact += $"file '{flv}'\n";
|
||||
}
|
||||
|
||||
FileStream fileStream = new FileStream(workingDirectory + "/" + concatFileName, FileMode.Create);
|
||||
StreamWriter streamWriter = new StreamWriter(fileStream);
|
||||
//开始写入
|
||||
streamWriter.Write(contact);
|
||||
//清空缓冲区
|
||||
streamWriter.Flush();
|
||||
//关闭流
|
||||
streamWriter.Close();
|
||||
fileStream.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("ConcatVideo()发生异常: {0}", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mkv
|
||||
// 加上-y,表示如果有同名文件,则默认覆盖
|
||||
string param = $"-f concat -safe 0 -i {concatFileName} -c copy \"{destVideo}\" -y";
|
||||
ExcuteProcess("ffmpeg.exe", param, workingDirectory, (s, e) => Console.WriteLine(e.Data));
|
||||
|
||||
// 删除临时文件
|
||||
try
|
||||
{
|
||||
// 删除concat文件
|
||||
File.Delete(workingDirectory + "/" + concatFileName);
|
||||
|
||||
foreach (string flv in flvFiles)
|
||||
{
|
||||
File.Delete(flv);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("ConcatVideo()发生异常: {0}", e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 去水印,非常消耗cpu资源
|
||||
/// </summary>
|
||||
/// <param name="video"></param>
|
||||
/// <param name="destVideo"></param>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="output"></param>
|
||||
/// <param name="window"></param>
|
||||
public static void Delogo(string video, string destVideo, int x, int y, int width, int height, TextBox output = null, Window window = null)
|
||||
{
|
||||
// ffmpeg -i "video.mp4" -vf delogo=x=1670:y=50:w=180:h=70:show=1 "delogo.mp4"
|
||||
string param = $"-i \"{video}\" -vf delogo=x={x}:y={y}:w={width}:h={height} \"{destVideo}\" -hide_banner";
|
||||
ExcuteProcess("ffmpeg.exe", param,
|
||||
null, (s, e) =>
|
||||
{
|
||||
Console.WriteLine(e.Data);
|
||||
if (output != null && window != null)
|
||||
{
|
||||
window.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
output.Text += e.Data + "\n";
|
||||
output.ScrollToEnd();
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从一个视频中仅提取音频
|
||||
/// </summary>
|
||||
/// <param name="video">源视频</param>
|
||||
/// <param name="audio">目标音频</param>
|
||||
/// <param name="output">输出信息</param>
|
||||
/// <param name="window"></param>
|
||||
public static void ExtractAudio(string video, string audio, TextBox output = null, Window window = null)
|
||||
{
|
||||
// 抽取音频命令
|
||||
// ffmpeg -i 3.mp4 -vn -y -acodec copy 3.aac
|
||||
// ffmpeg -i 3.mp4 -vn -y -acodec copy 3.m4a
|
||||
string param = $"-i \"{video}\" -vn -y -acodec copy \"{audio}\" -hide_banner";
|
||||
ExcuteProcess("ffmpeg.exe", param,
|
||||
null, (s, e) =>
|
||||
{
|
||||
Console.WriteLine(e.Data);
|
||||
if (output != null && window != null)
|
||||
{
|
||||
window.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
output.Text += e.Data + "\n";
|
||||
output.ScrollToEnd();
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从一个视频中仅提取视频
|
||||
/// </summary>
|
||||
/// <param name="video">源视频</param>
|
||||
/// <param name="destVideo">目标视频</param>
|
||||
/// <param name="output">输出信息</param>
|
||||
/// <param name="window"></param>
|
||||
public static void ExtractVideo(string video, string destVideo, TextBox output = null, Window window = null)
|
||||
{
|
||||
// 提取视频 (Extract Video)
|
||||
// ffmpeg -i Life.of.Pi.has.subtitles.mkv -vcodec copy –an videoNoAudioSubtitle.mp4
|
||||
string param = $"-i \"{video}\" -y -vcodec copy -an \"{destVideo}\" -hide_banner";
|
||||
ExcuteProcess("ffmpeg.exe", param,
|
||||
null, (s, e) =>
|
||||
{
|
||||
Console.WriteLine(e.Data);
|
||||
if (output != null && window != null)
|
||||
{
|
||||
window.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
output.Text += e.Data + "\n";
|
||||
output.ScrollToEnd();
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提取视频的帧,输出为图片
|
||||
/// </summary>
|
||||
/// <param name="video"></param>
|
||||
/// <param name="image"></param>
|
||||
/// <param name="number"></param>
|
||||
public static void ExtractFrame(string video, string image, uint number)
|
||||
{
|
||||
// 提取帧
|
||||
// ffmpeg -i caiyilin.wmv -vframes 1 wm.bmp
|
||||
string param = $"-i \"{video}\" -y -vframes {number} \"{image}\"";
|
||||
ExcuteProcess("ffmpeg.exe", param, null, (s, e) => Console.WriteLine(e.Data));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 执行一个控制台程序
|
||||
/// </summary>
|
||||
/// <param name="exe">程序名称</param>
|
||||
/// <param name="arg">参数</param>
|
||||
/// <param name="workingDirectory">工作路径</param>
|
||||
/// <param name="output">输出重定向</param>
|
||||
private static void ExcuteProcess(string exe, string arg, string workingDirectory, DataReceivedEventHandler output)
|
||||
{
|
||||
using (var p = new Process())
|
||||
{
|
||||
p.StartInfo.FileName = exe;
|
||||
p.StartInfo.Arguments = arg;
|
||||
|
||||
// 工作目录
|
||||
if (workingDirectory != null)
|
||||
{
|
||||
p.StartInfo.WorkingDirectory = workingDirectory;
|
||||
}
|
||||
|
||||
p.StartInfo.UseShellExecute = false; //输出信息重定向
|
||||
p.StartInfo.CreateNoWindow = true;
|
||||
p.StartInfo.RedirectStandardError = true;
|
||||
p.StartInfo.RedirectStandardOutput = true;
|
||||
|
||||
// 将 StandardErrorEncoding 改为 UTF-8 才不会出现中文乱码
|
||||
p.StartInfo.StandardOutputEncoding = System.Text.Encoding.UTF8;
|
||||
p.StartInfo.StandardErrorEncoding = System.Text.Encoding.UTF8;
|
||||
|
||||
p.OutputDataReceived += output;
|
||||
p.ErrorDataReceived += output;
|
||||
|
||||
p.Start(); //启动线程
|
||||
p.BeginOutputReadLine();
|
||||
p.BeginErrorReadLine();
|
||||
p.WaitForExit(); //等待进程结束
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,198 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
// from https://www.jianshu.com/p/f31910ed8435
|
||||
public class FileDownloadUtil
|
||||
{
|
||||
private string url; //文件下载网络地址
|
||||
private string referer; //访问url的referer
|
||||
private string path; //文件下载位置,如d:/download
|
||||
private string filename; //文件名,如test.jpg
|
||||
private string fileId; //文件ID,文件唯一标识,一般为UUID
|
||||
|
||||
private System.Threading.Timer FileTimer; // 定时器
|
||||
private readonly int SPD_INTERVAL_SEC = 1; // 每隔多少秒计算一次速度
|
||||
private long FileTemp = 0; // 临时储存长度
|
||||
private float FileSpeed = 0; // //SPD_INTERVAL_SEC秒下载字节数
|
||||
|
||||
// 下载进度回调
|
||||
public delegate void ProgressChangedHandler(int progress, string fileId);
|
||||
public event ProgressChangedHandler ProgressChanged;
|
||||
protected virtual void OnProgressChanged(int progress, string fileId)
|
||||
{
|
||||
ProgressChanged?.Invoke(progress, fileId);
|
||||
}
|
||||
|
||||
public delegate void ProgressChanged2Handler(long totalBytes, long totalDownloadedByte, float speed, string fileId);
|
||||
public event ProgressChanged2Handler ProgressChanged2;
|
||||
protected virtual void OnProgressChanged2(long totalBytes, long totalDownloadedByte, float speed, string fileId)
|
||||
{
|
||||
ProgressChanged2?.Invoke(totalBytes, totalDownloadedByte, speed, fileId);
|
||||
}
|
||||
|
||||
// 下载结果回调
|
||||
public delegate void DownloadFinishHandler(bool isSuccess, string downloadPath, string fileId, string msg = null);
|
||||
public event DownloadFinishHandler DownloadFinish;
|
||||
protected virtual void OnDownloadFinish(bool isSuccess, string downloadPath, string fileId, string msg = null)
|
||||
{
|
||||
DownloadFinish?.Invoke(isSuccess, downloadPath, fileId, msg);
|
||||
}
|
||||
|
||||
//通过网络链接直接下载任意文件
|
||||
public FileDownloadUtil Init(string url, string referer, string path, string filename, string fileId)
|
||||
{
|
||||
this.url = url;
|
||||
this.referer = referer;
|
||||
this.path = path;
|
||||
this.filename = filename;
|
||||
this.fileId = fileId;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Download()
|
||||
{
|
||||
Download(url, path, filename, fileId);
|
||||
}
|
||||
|
||||
private void Download(string url, string path, string filename, string fileId)
|
||||
{
|
||||
|
||||
if (!Directory.Exists(path)) //判断文件夹是否存在
|
||||
Directory.CreateDirectory(path);
|
||||
path = path + "\\" + filename;
|
||||
|
||||
// 临时文件 "bilidownkyi\\"
|
||||
string tempFile = Path.GetTempPath() + "downkyi." + Guid.NewGuid().ToString("N");
|
||||
//string tempFile = path + ".temp";
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(tempFile))
|
||||
{
|
||||
File.Delete(tempFile); //存在则删除
|
||||
}
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path); //存在则删除
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Console.WriteLine("Download()发生IO异常: {0}", e);
|
||||
}
|
||||
|
||||
FileStream fs = null;
|
||||
HttpWebRequest request = null;
|
||||
HttpWebResponse response = null;
|
||||
Stream responseStream = null;
|
||||
try
|
||||
{
|
||||
//创建临时文件
|
||||
fs = new FileStream(tempFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
|
||||
request = WebRequest.Create(url) as HttpWebRequest;
|
||||
request.Method = "GET";
|
||||
request.Timeout = 60 * 1000;
|
||||
request.UserAgent = Utils.GetUserAgent();
|
||||
//request.ContentType = "text/html;charset=UTF-8";
|
||||
request.Headers["accept-language"] = "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7";
|
||||
//request.Headers["accept-encoding"] = "gzip, deflate, br";
|
||||
request.Headers["origin"] = "https://www.bilibili.com";
|
||||
request.Referer = referer;
|
||||
|
||||
// 构造cookie
|
||||
// web端请求视频链接时没有加入cookie
|
||||
//if (!url.Contains("getLogin"))
|
||||
//{
|
||||
// CookieContainer cookies = Login.GetLoginInfoCookies();
|
||||
// if (cookies != null)
|
||||
// {
|
||||
// request.CookieContainer = cookies;
|
||||
// }
|
||||
//}
|
||||
|
||||
//发送请求并获取相应回应数据
|
||||
response = request.GetResponse() as HttpWebResponse;
|
||||
//直到request.GetResponse()程序才开始向目标网页发送Post请求
|
||||
responseStream = response.GetResponseStream();
|
||||
byte[] bArr = new byte[1024];
|
||||
long totalBytes = response.ContentLength; //通过响应头获取文件大小,前提是响应头有文件大小
|
||||
int size = responseStream.Read(bArr, 0, (int)bArr.Length); //读取响应流到bArr,读取大小
|
||||
float percent = 0; //用来保存计算好的百分比
|
||||
long totalDownloadedByte = 0; //总共下载字节数
|
||||
|
||||
FileTimer = new System.Threading.Timer(SpeedTimer, null, 0, SPD_INTERVAL_SEC * 1000);
|
||||
while (size > 0) //while (totalBytes > totalDownloadedByte) //while循环读取响应流
|
||||
{
|
||||
fs.Write(bArr, 0, size); //写到临时文件
|
||||
// 定期刷新数据到磁盘,影响下载速度
|
||||
//fs.Flush(true);
|
||||
|
||||
totalDownloadedByte += size;
|
||||
FileTemp += size;
|
||||
size = responseStream.Read(bArr, 0, (int)bArr.Length);
|
||||
percent = (float)totalDownloadedByte / (float)totalBytes * 100;
|
||||
|
||||
// 下载进度回调
|
||||
OnProgressChanged((int)percent, fileId);
|
||||
OnProgressChanged2(totalBytes, totalDownloadedByte, FileSpeed, fileId);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path); //存在则删除
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Console.WriteLine("Download()发生IO异常: {0}", e);
|
||||
}
|
||||
|
||||
if (fs != null)
|
||||
fs.Close();
|
||||
File.Move(tempFile, path); //重命名为正式文件
|
||||
OnDownloadFinish(true, path, fileId, null); //下载完成,成功回调
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Download()发生异常: {0}", ex);
|
||||
OnDownloadFinish(false, null, fileId, ex.Message); //下载完成,失败回调
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (fs != null)
|
||||
fs.Close();
|
||||
if (request != null)
|
||||
request.Abort();
|
||||
if (response != null)
|
||||
response.Close();
|
||||
if (responseStream != null)
|
||||
responseStream.Close();
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(tempFile))
|
||||
{
|
||||
File.Delete(tempFile); //存在则删除
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Console.WriteLine("Download()发生IO异常: {0}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SpeedTimer(object state)
|
||||
{
|
||||
FileSpeed = FileTemp / SPD_INTERVAL_SEC; //SPD_INTERVAL_SEC秒下载字节数,
|
||||
FileTemp = 0; //清空临时储存
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
using Core.entity;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
public static class UserSpaceOld
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 获取我创建的收藏夹
|
||||
/// </summary>
|
||||
/// <param name="mid"></param>
|
||||
/// <returns></returns>
|
||||
public static FavFolderData GetCreatedFavFolder(long mid)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/v3/fav/folder/created/list?up_mid={mid}&ps=50";
|
||||
return GetAllFavFolder(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取我收藏的收藏夹
|
||||
/// </summary>
|
||||
/// <param name="mid"></param>
|
||||
/// <returns></returns>
|
||||
public static FavFolderData GetCollectedFavFolder(long mid)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/v3/fav/folder/collected/list?up_mid={mid}&ps=50";
|
||||
return GetAllFavFolder(url);
|
||||
}
|
||||
|
||||
private static FavFolderData GetAllFavFolder(string baseUrl)
|
||||
{
|
||||
FavFolderData userFavoriteData = new FavFolderData
|
||||
{
|
||||
count = 0,
|
||||
list = new List<FavFolderDataList>()
|
||||
};
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
string url = baseUrl + $"&pn={i}";
|
||||
|
||||
var data = GetFavFolder(url);
|
||||
if (data == null)
|
||||
{ break; }
|
||||
if (data.count == 0 || data.list == null)
|
||||
{ break; }
|
||||
|
||||
userFavoriteData.list.AddRange(data.list);
|
||||
}
|
||||
userFavoriteData.count = userFavoriteData.list.Count;
|
||||
return userFavoriteData;
|
||||
}
|
||||
|
||||
private static FavFolderData GetFavFolder(string url)
|
||||
{
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
FavFolder favFolder = JsonConvert.DeserializeObject<FavFolder>(response);
|
||||
if (favFolder == null || favFolder.data == null) { return null; }
|
||||
|
||||
return favFolder.data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetFavFolder()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得某个收藏夹的内容
|
||||
/// </summary>
|
||||
/// <param name="mediaId"></param>
|
||||
/// <returns></returns>
|
||||
public static List<FavResourceDataMedia> GetAllFavResource(long mediaId)
|
||||
{
|
||||
string baseUrl = $"https://api.bilibili.com/x/v3/fav/resource/list?media_id={mediaId}&ps=20";
|
||||
List<FavResourceDataMedia> medias = new List<FavResourceDataMedia>();
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
string url = baseUrl + $"&pn={i}";
|
||||
|
||||
var data = GetFavResource(url);
|
||||
if (data == null || data.Count == 0)
|
||||
{ break; }
|
||||
|
||||
medias.AddRange(data);
|
||||
}
|
||||
return medias;
|
||||
}
|
||||
|
||||
private static List<FavResourceDataMedia> GetFavResource(string url)
|
||||
{
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
FavResource favResource = JsonConvert.DeserializeObject<FavResource>(response);
|
||||
if (favResource == null || favResource.data == null) { return null; }
|
||||
return favResource.data.medias;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetFavResource()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取订阅番剧的数量
|
||||
/// 废弃
|
||||
/// </summary>
|
||||
/// <param name="mid"></param>
|
||||
/// <returns></returns>
|
||||
//public static int GetBangumiFollowList(long mid)
|
||||
//{
|
||||
// string url = $"https://space.bilibili.com/ajax/Bangumi/getList?mid={mid}";
|
||||
// string referer = "https://www.bilibili.com";
|
||||
// string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
// try
|
||||
// {
|
||||
// BangumiList bangumiList = JsonConvert.DeserializeObject<BangumiList>(response);
|
||||
// if (bangumiList == null || bangumiList.data == null) { return -1; }
|
||||
|
||||
// return bangumiList.data.count;
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// Console.WriteLine("发生异常: {0}", e);
|
||||
// return 0;
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
@ -1,430 +0,0 @@
|
||||
using Brotli;
|
||||
using Core.api.login;
|
||||
using Core.history;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
public static class Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// 随机的UserAgent
|
||||
/// </summary>
|
||||
/// <returns>userAgent</returns>
|
||||
public static string GetUserAgent()
|
||||
{
|
||||
string[] userAgents = {
|
||||
// Chrome
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36",
|
||||
|
||||
// 新版Edge
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.58",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.66",
|
||||
|
||||
// IE 11
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)",
|
||||
|
||||
// 火狐
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0",
|
||||
|
||||
// Opera
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36 OPR/63.0.3368.43",
|
||||
|
||||
// MacOS Chrome
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36",
|
||||
|
||||
// MacOS Safari
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15"
|
||||
};
|
||||
|
||||
var time = DateTime.Now;
|
||||
|
||||
Random random = new Random(time.GetHashCode());
|
||||
int number = random.Next(0, userAgents.Length - 1);
|
||||
|
||||
return userAgents[number];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送get或post请求
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="referer"></param>
|
||||
/// <param name="method"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns></returns>
|
||||
public static string RequestWeb(string url, string referer = null, string method = "GET", Dictionary<string, string> parameters = null, int retry = 3)
|
||||
{
|
||||
// 重试次数
|
||||
if (retry <= 0) { return ""; }
|
||||
|
||||
// post请求,发送参数
|
||||
if (method == "POST" && parameters != null)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int i = 0;
|
||||
foreach (var item in parameters)
|
||||
{
|
||||
if (i > 0) builder.Append("&");
|
||||
builder.AppendFormat("{0}={1}", item.Key, item.Value);
|
||||
i++;
|
||||
}
|
||||
|
||||
url += "?" + builder.ToString();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||||
request.Method = method;
|
||||
request.Timeout = 30 * 1000;
|
||||
request.UserAgent = GetUserAgent();
|
||||
//request.ContentType = "application/json,text/html,application/xhtml+xml,application/xml;charset=UTF-8";
|
||||
request.Headers["accept-language"] = "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7";
|
||||
request.Headers["accept-encoding"] = "gzip, deflate, br";
|
||||
|
||||
//request.Headers["sec-fetch-dest"] = "empty";
|
||||
//request.Headers["sec-fetch-mode"] = "cors";
|
||||
//request.Headers["sec-fetch-site"] = "same-site";
|
||||
|
||||
// referer
|
||||
if (referer != null)
|
||||
{
|
||||
request.Referer = referer;
|
||||
}
|
||||
|
||||
// 构造cookie
|
||||
if (!url.Contains("getLogin"))
|
||||
{
|
||||
request.Headers["origin"] = "https://www.bilibili.com";
|
||||
|
||||
CookieContainer cookies = LoginHelper.GetInstance().GetLoginInfoCookies();
|
||||
if (cookies != null)
|
||||
{
|
||||
request.CookieContainer = cookies;
|
||||
}
|
||||
}
|
||||
|
||||
//// post请求,发送参数
|
||||
//if (method == "POST" && parameters != null)
|
||||
//{
|
||||
// StringBuilder builder = new StringBuilder();
|
||||
// int i = 0;
|
||||
// foreach (var item in parameters)
|
||||
// {
|
||||
// if (i > 0) builder.Append("&");
|
||||
// builder.AppendFormat("{0}={1}", item.Key, item.Value);
|
||||
// i++;
|
||||
// }
|
||||
// byte[] data = Encoding.UTF8.GetBytes(builder.ToString());
|
||||
// request.ContentLength = data.Length;
|
||||
|
||||
// Stream reqStream = request.GetRequestStream();
|
||||
// reqStream.Write(data, 0, data.Length);
|
||||
// reqStream.Close();
|
||||
|
||||
// Console.WriteLine("\n" + builder.ToString() + "\t" + data.Length + "\n");
|
||||
//}
|
||||
|
||||
//HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
//Stream responseStream = response.GetResponseStream();
|
||||
//StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8);
|
||||
//string str = streamReader.ReadToEnd();
|
||||
//streamReader.Close();
|
||||
//responseStream.Close();
|
||||
|
||||
string html = string.Empty;
|
||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
if (response.ContentEncoding.ToLower().Contains("gzip"))
|
||||
{
|
||||
using (GZipStream stream = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress))
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
html = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (response.ContentEncoding.ToLower().Contains("deflate"))
|
||||
{
|
||||
using (DeflateStream stream = new DeflateStream(response.GetResponseStream(), CompressionMode.Decompress))
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
html = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (response.ContentEncoding.ToLower().Contains("br"))
|
||||
{
|
||||
using (BrotliStream stream = new BrotliStream(response.GetResponseStream(), CompressionMode.Decompress))
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
html = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (Stream stream = response.GetResponseStream())
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
html = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
Console.WriteLine("RequestWeb()发生Web异常: {0}", e);
|
||||
return RequestWeb(url, referer, method, parameters, retry - 1);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Console.WriteLine("RequestWeb()发生IO异常: {0}", e);
|
||||
return RequestWeb(url, referer, method, parameters, retry - 1);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("RequestWeb()发生其他异常: {0}", e);
|
||||
return RequestWeb(url, referer, method, parameters, retry - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析二维码登录返回的url,用于设置cookie
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public static CookieContainer ParseCookie(string url)
|
||||
{
|
||||
CookieContainer cookieContainer = new CookieContainer();
|
||||
|
||||
if (url == null || url == "") { return cookieContainer; }
|
||||
|
||||
string[] strList = url.Split('?');
|
||||
if (strList.Count() < 2) { return cookieContainer; }
|
||||
|
||||
string[] strList2 = strList[1].Split('&');
|
||||
if (strList2.Count() == 0) { return cookieContainer; }
|
||||
|
||||
// 获取expires
|
||||
string expires = strList2.FirstOrDefault(it => it.Contains("Expires")).Split('=')[1];
|
||||
DateTime dateTime = DateTime.Now;
|
||||
dateTime = dateTime.AddSeconds(int.Parse(expires));
|
||||
|
||||
foreach (var item in strList2)
|
||||
{
|
||||
string[] strList3 = item.Split('=');
|
||||
if (strList3.Count() < 2) { continue; }
|
||||
|
||||
string name = strList3[0];
|
||||
string value = strList3[1];
|
||||
|
||||
// 不需要
|
||||
if (name == "Expires" || name == "gourl") { continue; }
|
||||
|
||||
// 添加cookie
|
||||
cookieContainer.Add(new Cookie(name, value, "/", ".bilibili.com") { Expires = dateTime });
|
||||
#if DEBUG
|
||||
Console.WriteLine(name + ": " + value + "\t" + cookieContainer.Count);
|
||||
#endif
|
||||
}
|
||||
|
||||
return cookieContainer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将CookieContainer中的所有的Cookie读出来
|
||||
/// </summary>
|
||||
/// <param name="cc"></param>
|
||||
/// <returns></returns>
|
||||
public static List<Cookie> GetAllCookies(CookieContainer cc)
|
||||
{
|
||||
List<Cookie> lstCookies = new List<Cookie>();
|
||||
|
||||
Hashtable table = (Hashtable)cc.GetType().InvokeMember("m_domainTable",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField |
|
||||
System.Reflection.BindingFlags.Instance, null, cc, new object[] { });
|
||||
|
||||
foreach (object pathList in table.Values)
|
||||
{
|
||||
SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField
|
||||
| System.Reflection.BindingFlags.Instance, null, pathList, new object[] { });
|
||||
foreach (CookieCollection colCookies in lstCookieCol.Values)
|
||||
foreach (Cookie c in colCookies) lstCookies.Add(c);
|
||||
}
|
||||
|
||||
return lstCookies;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入cookies到磁盘
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <param name="cookieJar"></param>
|
||||
/// <returns></returns>
|
||||
public static bool WriteCookiesToDisk(string file, CookieContainer cookieJar)
|
||||
{
|
||||
return WriteObjectToDisk(file, cookieJar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从磁盘读取cookie
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
public static CookieContainer ReadCookiesFromDisk(string file)
|
||||
{
|
||||
return (CookieContainer)ReadObjectFromDisk(file);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入历史数据到磁盘
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <param name="history"></param>
|
||||
/// <returns></returns>
|
||||
public static bool WriteHistoryToDisk(string file, HistoryEntity history)
|
||||
{
|
||||
return WriteObjectToDisk(file, history);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从磁盘读取历史数据
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
public static HistoryEntity ReadHistoryFromDisk(string file)
|
||||
{
|
||||
return (HistoryEntity)ReadObjectFromDisk(file);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入序列化对象到磁盘
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static bool WriteObjectToDisk(string file, object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Stream stream = File.Create(file))
|
||||
{
|
||||
#if DEBUG
|
||||
Console.Out.Write("Writing object to disk... ");
|
||||
#endif
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
formatter.Serialize(stream, obj);
|
||||
#if DEBUG
|
||||
Console.Out.WriteLine("Done.");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Console.WriteLine("WriteObjectToDisk()发生IO异常: {0}", e);
|
||||
return false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//Console.Out.WriteLine("Problem writing object to disk: " + e.GetType());
|
||||
Console.WriteLine("WriteObjectToDisk()发生异常: {0}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从磁盘读取序列化对象
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
public static object ReadObjectFromDisk(string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Stream stream = File.Open(file, FileMode.Open))
|
||||
{
|
||||
#if DEBUG
|
||||
Console.Out.Write("Reading object from disk... ");
|
||||
#endif
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
#if DEBUG
|
||||
Console.Out.WriteLine("Done.");
|
||||
#endif
|
||||
return formatter.Deserialize(stream);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Console.WriteLine("ReadObjectFromDisk()发生IO异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//Console.Out.WriteLine("Problem reading object from disk: " + e.GetType());
|
||||
Console.WriteLine("ReadObjectFromDisk()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成二维码
|
||||
/// </summary>
|
||||
/// <param name="msg">信息</param>
|
||||
/// <param name="version">版本 1 ~ 40</param>
|
||||
/// <param name="pixel">像素点大小</param>
|
||||
/// <param name="icon_path">图标路径</param>
|
||||
/// <param name="icon_size">图标尺寸</param>
|
||||
/// <param name="icon_border">图标边框厚度</param>
|
||||
/// <param name="white_edge">二维码白边</param>
|
||||
/// <returns>位图</returns>
|
||||
public static Bitmap EncodeQRCode(string msg, int version, int pixel, string icon_path, int icon_size, int icon_border, bool white_edge)
|
||||
{
|
||||
QRCoder.QRCodeGenerator code_generator = new QRCoder.QRCodeGenerator();
|
||||
|
||||
QRCoder.QRCodeData code_data = code_generator.CreateQrCode(msg, QRCoder.QRCodeGenerator.ECCLevel.H/* 这里设置容错率的一个级别 */, true, false, QRCoder.QRCodeGenerator.EciMode.Utf8, version);
|
||||
|
||||
QRCoder.QRCode code = new QRCoder.QRCode(code_data);
|
||||
|
||||
Bitmap icon;
|
||||
if (icon_path == null || icon_path == "")
|
||||
{
|
||||
icon = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
icon = new Bitmap(icon_path);
|
||||
}
|
||||
|
||||
Bitmap bmp = code.GetGraphic(pixel, Color.Black, Color.White, icon, icon_size, icon_border, white_edge);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
namespace Core.api.danmaku.entity
|
||||
{
|
||||
public class BiliDanmaku
|
||||
{
|
||||
public long Id { get; set; } //弹幕dmID
|
||||
public int Progress { get; set; } //出现时间
|
||||
public int Mode { get; set; } //弹幕类型
|
||||
public int Fontsize { get; set; } //文字大小
|
||||
public uint Color { get; set; } //弹幕颜色
|
||||
public string MidHash { get; set; } //发送者UID的HASH
|
||||
public string Content { get; set; } //弹幕内容
|
||||
public long Ctime { get; set; } //发送时间
|
||||
public int Weight { get; set; } //权重
|
||||
//public string Action { get; set; } //动作?
|
||||
public int Pool { get; set; } //弹幕池
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
//return base.ToString();
|
||||
|
||||
string separator = "\n";
|
||||
return $"id: {Id}{separator}" +
|
||||
$"progress: {Progress}{separator}" +
|
||||
$"mode: {Mode}{separator}" +
|
||||
$"fontsize: {Fontsize}{separator}" +
|
||||
$"color: {Color}{separator}" +
|
||||
$"midHash: {MidHash}{separator}" +
|
||||
$"content: {Content}{separator}" +
|
||||
$"ctime: {Ctime}{separator}" +
|
||||
$"weight: {Weight}{separator}" +
|
||||
//$"action: {Action}{separator}" +
|
||||
$"pool: {Pool}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
using Core.api.danmaku.entity;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Core.api.danmaku
|
||||
{
|
||||
/// <summary>
|
||||
/// protobuf弹幕
|
||||
/// </summary>
|
||||
public class DanmakuProtobuf
|
||||
{
|
||||
private static DanmakuProtobuf instance;
|
||||
|
||||
/// <summary>
|
||||
/// 获取DanmakuProtobuf实例
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static DanmakuProtobuf GetInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new DanmakuProtobuf();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏DanmakuProtobuf()方法,必须使用单例模式
|
||||
/// </summary>
|
||||
private DanmakuProtobuf() { }
|
||||
|
||||
/// <summary>
|
||||
/// 下载6分钟内的弹幕,返回弹幕列表
|
||||
/// </summary>
|
||||
/// <param name="avid">稿件avID</param>
|
||||
/// <param name="cid">视频CID</param>
|
||||
/// <param name="segmentIndex">分包,每6分钟一包</param>
|
||||
/// <returns></returns>
|
||||
public List<BiliDanmaku> GetDanmakuProto(long avid, long cid, int segmentIndex)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/v2/dm/web/seg.so?type=1&oid={cid}&pid={avid}&segment_index={segmentIndex}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
|
||||
FileDownloadUtil fileDownload = new FileDownloadUtil();
|
||||
fileDownload.Init(url, referer, Path.GetTempPath() + "downkyi/danmaku", $"{cid}-{segmentIndex}.proto", "DanmakuProtobuf");
|
||||
fileDownload.Download();
|
||||
|
||||
var danmakuList = new List<BiliDanmaku>();
|
||||
|
||||
DmSegMobileReply danmakus;
|
||||
try
|
||||
{
|
||||
using (var input = File.OpenRead(Path.GetTempPath() + $"downkyi/danmaku/{cid}-{segmentIndex}.proto"))
|
||||
{
|
||||
danmakus = DmSegMobileReply.Parser.ParseFrom(input);
|
||||
if (danmakus == null || danmakus.Elems == null)
|
||||
{
|
||||
return danmakuList;
|
||||
}
|
||||
|
||||
foreach (var dm in danmakus.Elems)
|
||||
{
|
||||
var danmaku = new BiliDanmaku
|
||||
{
|
||||
Id = dm.Id,
|
||||
Progress = dm.Progress,
|
||||
Mode = dm.Mode,
|
||||
Fontsize = dm.Fontsize,
|
||||
Color = dm.Color,
|
||||
MidHash = dm.MidHash,
|
||||
Content = dm.Content,
|
||||
Ctime = dm.Ctime,
|
||||
Weight = dm.Weight,
|
||||
//Action = dm.Action,
|
||||
Pool = dm.Pool
|
||||
};
|
||||
danmakuList.Add(danmaku);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine("发生异常: {0}", e);
|
||||
#endif
|
||||
return null;
|
||||
}
|
||||
|
||||
return danmakuList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载所有弹幕,返回弹幕列表
|
||||
/// </summary>
|
||||
/// <param name="avid">稿件avID</param>
|
||||
/// <param name="cid">视频CID</param>
|
||||
/// <returns></returns>
|
||||
public List<BiliDanmaku> GetAllDanmakuProto(long avid, long cid)
|
||||
{
|
||||
var danmakuList = new List<BiliDanmaku>();
|
||||
|
||||
int segmentIndex = 0;
|
||||
while (true)
|
||||
{
|
||||
segmentIndex += 1;
|
||||
var danmakus = GetDanmakuProto(avid, cid, segmentIndex);
|
||||
if (danmakus == null) { break; }
|
||||
danmakuList.AddRange(danmakus);
|
||||
}
|
||||
return danmakuList;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,814 +0,0 @@
|
||||
// <auto-generated>
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: Danmaku.proto
|
||||
// </auto-generated>
|
||||
#pragma warning disable 1591, 0612, 3021
|
||||
#region Designer generated code
|
||||
|
||||
using pb = global::Google.Protobuf;
|
||||
using pbc = global::Google.Protobuf.Collections;
|
||||
using pbr = global::Google.Protobuf.Reflection;
|
||||
using scg = global::System.Collections.Generic;
|
||||
/// <summary>Holder for reflection information generated from Danmaku.proto</summary>
|
||||
public static partial class DanmakuReflection {
|
||||
|
||||
#region Descriptor
|
||||
/// <summary>File descriptor for Danmaku.proto</summary>
|
||||
public static pbr::FileDescriptor Descriptor {
|
||||
get { return descriptor; }
|
||||
}
|
||||
private static pbr::FileDescriptor descriptor;
|
||||
|
||||
static DanmakuReflection() {
|
||||
byte[] descriptorData = global::System.Convert.FromBase64String(
|
||||
string.Concat(
|
||||
"Cg1EYW5tYWt1LnByb3RvIsgBCgtEYW5tYWt1RWxlbRIKCgJpZBgBIAEoAxIQ",
|
||||
"Cghwcm9ncmVzcxgCIAEoBRIMCgRtb2RlGAMgASgFEhAKCGZvbnRzaXplGAQg",
|
||||
"ASgFEg0KBWNvbG9yGAUgASgNEg8KB21pZEhhc2gYBiABKAkSDwoHY29udGVu",
|
||||
"dBgHIAEoCRINCgVjdGltZRgIIAEoAxIOCgZ3ZWlnaHQYCSABKAUSDgoGYWN0",
|
||||
"aW9uGAogASgJEgwKBHBvb2wYCyABKAUSDQoFaWRTdHIYDCABKAkiLwoQRG1T",
|
||||
"ZWdNb2JpbGVSZXBseRIbCgVlbGVtcxgBIAMoCzIMLkRhbm1ha3VFbGVtYgZw",
|
||||
"cm90bzM="));
|
||||
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
|
||||
new pbr::FileDescriptor[] { },
|
||||
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::DanmakuElem), global::DanmakuElem.Parser, new[]{ "Id", "Progress", "Mode", "Fontsize", "Color", "MidHash", "Content", "Ctime", "Weight", "Action", "Pool", "IdStr" }, null, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::DmSegMobileReply), global::DmSegMobileReply.Parser, new[]{ "Elems" }, null, null, null, null)
|
||||
}));
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
#region Messages
|
||||
public sealed partial class DanmakuElem : pb::IMessage<DanmakuElem>
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
, pb::IBufferMessage
|
||||
#endif
|
||||
{
|
||||
private static readonly pb::MessageParser<DanmakuElem> _parser = new pb::MessageParser<DanmakuElem>(() => new DanmakuElem());
|
||||
private pb::UnknownFieldSet _unknownFields;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public static pb::MessageParser<DanmakuElem> Parser { get { return _parser; } }
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public static pbr::MessageDescriptor Descriptor {
|
||||
get { return global::DanmakuReflection.Descriptor.MessageTypes[0]; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
pbr::MessageDescriptor pb::IMessage.Descriptor {
|
||||
get { return Descriptor; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public DanmakuElem() {
|
||||
OnConstruction();
|
||||
}
|
||||
|
||||
partial void OnConstruction();
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public DanmakuElem(DanmakuElem other) : this() {
|
||||
id_ = other.id_;
|
||||
progress_ = other.progress_;
|
||||
mode_ = other.mode_;
|
||||
fontsize_ = other.fontsize_;
|
||||
color_ = other.color_;
|
||||
midHash_ = other.midHash_;
|
||||
content_ = other.content_;
|
||||
ctime_ = other.ctime_;
|
||||
weight_ = other.weight_;
|
||||
action_ = other.action_;
|
||||
pool_ = other.pool_;
|
||||
idStr_ = other.idStr_;
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public DanmakuElem Clone() {
|
||||
return new DanmakuElem(this);
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "id" field.</summary>
|
||||
public const int IdFieldNumber = 1;
|
||||
private long id_;
|
||||
/// <summary>
|
||||
///弹幕dmID
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public long Id {
|
||||
get { return id_; }
|
||||
set {
|
||||
id_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "progress" field.</summary>
|
||||
public const int ProgressFieldNumber = 2;
|
||||
private int progress_;
|
||||
/// <summary>
|
||||
///出现时间
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public int Progress {
|
||||
get { return progress_; }
|
||||
set {
|
||||
progress_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "mode" field.</summary>
|
||||
public const int ModeFieldNumber = 3;
|
||||
private int mode_;
|
||||
/// <summary>
|
||||
///弹幕类型
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public int Mode {
|
||||
get { return mode_; }
|
||||
set {
|
||||
mode_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "fontsize" field.</summary>
|
||||
public const int FontsizeFieldNumber = 4;
|
||||
private int fontsize_;
|
||||
/// <summary>
|
||||
///文字大小
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public int Fontsize {
|
||||
get { return fontsize_; }
|
||||
set {
|
||||
fontsize_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "color" field.</summary>
|
||||
public const int ColorFieldNumber = 5;
|
||||
private uint color_;
|
||||
/// <summary>
|
||||
///弹幕颜色
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public uint Color {
|
||||
get { return color_; }
|
||||
set {
|
||||
color_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "midHash" field.</summary>
|
||||
public const int MidHashFieldNumber = 6;
|
||||
private string midHash_ = "";
|
||||
/// <summary>
|
||||
///发送者UID的HASH
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public string MidHash {
|
||||
get { return midHash_; }
|
||||
set {
|
||||
midHash_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "content" field.</summary>
|
||||
public const int ContentFieldNumber = 7;
|
||||
private string content_ = "";
|
||||
/// <summary>
|
||||
///弹幕内容
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public string Content {
|
||||
get { return content_; }
|
||||
set {
|
||||
content_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "ctime" field.</summary>
|
||||
public const int CtimeFieldNumber = 8;
|
||||
private long ctime_;
|
||||
/// <summary>
|
||||
///发送时间
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public long Ctime {
|
||||
get { return ctime_; }
|
||||
set {
|
||||
ctime_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "weight" field.</summary>
|
||||
public const int WeightFieldNumber = 9;
|
||||
private int weight_;
|
||||
/// <summary>
|
||||
///权重
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public int Weight {
|
||||
get { return weight_; }
|
||||
set {
|
||||
weight_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "action" field.</summary>
|
||||
public const int ActionFieldNumber = 10;
|
||||
private string action_ = "";
|
||||
/// <summary>
|
||||
///动作?
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public string Action {
|
||||
get { return action_; }
|
||||
set {
|
||||
action_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "pool" field.</summary>
|
||||
public const int PoolFieldNumber = 11;
|
||||
private int pool_;
|
||||
/// <summary>
|
||||
///弹幕池
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public int Pool {
|
||||
get { return pool_; }
|
||||
set {
|
||||
pool_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "idStr" field.</summary>
|
||||
public const int IdStrFieldNumber = 12;
|
||||
private string idStr_ = "";
|
||||
/// <summary>
|
||||
///弹幕dmID(字串形式)
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public string IdStr {
|
||||
get { return idStr_; }
|
||||
set {
|
||||
idStr_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public override bool Equals(object other) {
|
||||
return Equals(other as DanmakuElem);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public bool Equals(DanmakuElem other) {
|
||||
if (ReferenceEquals(other, null)) {
|
||||
return false;
|
||||
}
|
||||
if (ReferenceEquals(other, this)) {
|
||||
return true;
|
||||
}
|
||||
if (Id != other.Id) return false;
|
||||
if (Progress != other.Progress) return false;
|
||||
if (Mode != other.Mode) return false;
|
||||
if (Fontsize != other.Fontsize) return false;
|
||||
if (Color != other.Color) return false;
|
||||
if (MidHash != other.MidHash) return false;
|
||||
if (Content != other.Content) return false;
|
||||
if (Ctime != other.Ctime) return false;
|
||||
if (Weight != other.Weight) return false;
|
||||
if (Action != other.Action) return false;
|
||||
if (Pool != other.Pool) return false;
|
||||
if (IdStr != other.IdStr) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public override int GetHashCode() {
|
||||
int hash = 1;
|
||||
if (Id != 0L) hash ^= Id.GetHashCode();
|
||||
if (Progress != 0) hash ^= Progress.GetHashCode();
|
||||
if (Mode != 0) hash ^= Mode.GetHashCode();
|
||||
if (Fontsize != 0) hash ^= Fontsize.GetHashCode();
|
||||
if (Color != 0) hash ^= Color.GetHashCode();
|
||||
if (MidHash.Length != 0) hash ^= MidHash.GetHashCode();
|
||||
if (Content.Length != 0) hash ^= Content.GetHashCode();
|
||||
if (Ctime != 0L) hash ^= Ctime.GetHashCode();
|
||||
if (Weight != 0) hash ^= Weight.GetHashCode();
|
||||
if (Action.Length != 0) hash ^= Action.GetHashCode();
|
||||
if (Pool != 0) hash ^= Pool.GetHashCode();
|
||||
if (IdStr.Length != 0) hash ^= IdStr.GetHashCode();
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public override string ToString() {
|
||||
return pb::JsonFormatter.ToDiagnosticString(this);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public void WriteTo(pb::CodedOutputStream output) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
output.WriteRawMessage(this);
|
||||
#else
|
||||
if (Id != 0L) {
|
||||
output.WriteRawTag(8);
|
||||
output.WriteInt64(Id);
|
||||
}
|
||||
if (Progress != 0) {
|
||||
output.WriteRawTag(16);
|
||||
output.WriteInt32(Progress);
|
||||
}
|
||||
if (Mode != 0) {
|
||||
output.WriteRawTag(24);
|
||||
output.WriteInt32(Mode);
|
||||
}
|
||||
if (Fontsize != 0) {
|
||||
output.WriteRawTag(32);
|
||||
output.WriteInt32(Fontsize);
|
||||
}
|
||||
if (Color != 0) {
|
||||
output.WriteRawTag(40);
|
||||
output.WriteUInt32(Color);
|
||||
}
|
||||
if (MidHash.Length != 0) {
|
||||
output.WriteRawTag(50);
|
||||
output.WriteString(MidHash);
|
||||
}
|
||||
if (Content.Length != 0) {
|
||||
output.WriteRawTag(58);
|
||||
output.WriteString(Content);
|
||||
}
|
||||
if (Ctime != 0L) {
|
||||
output.WriteRawTag(64);
|
||||
output.WriteInt64(Ctime);
|
||||
}
|
||||
if (Weight != 0) {
|
||||
output.WriteRawTag(72);
|
||||
output.WriteInt32(Weight);
|
||||
}
|
||||
if (Action.Length != 0) {
|
||||
output.WriteRawTag(82);
|
||||
output.WriteString(Action);
|
||||
}
|
||||
if (Pool != 0) {
|
||||
output.WriteRawTag(88);
|
||||
output.WriteInt32(Pool);
|
||||
}
|
||||
if (IdStr.Length != 0) {
|
||||
output.WriteRawTag(98);
|
||||
output.WriteString(IdStr);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
|
||||
if (Id != 0L) {
|
||||
output.WriteRawTag(8);
|
||||
output.WriteInt64(Id);
|
||||
}
|
||||
if (Progress != 0) {
|
||||
output.WriteRawTag(16);
|
||||
output.WriteInt32(Progress);
|
||||
}
|
||||
if (Mode != 0) {
|
||||
output.WriteRawTag(24);
|
||||
output.WriteInt32(Mode);
|
||||
}
|
||||
if (Fontsize != 0) {
|
||||
output.WriteRawTag(32);
|
||||
output.WriteInt32(Fontsize);
|
||||
}
|
||||
if (Color != 0) {
|
||||
output.WriteRawTag(40);
|
||||
output.WriteUInt32(Color);
|
||||
}
|
||||
if (MidHash.Length != 0) {
|
||||
output.WriteRawTag(50);
|
||||
output.WriteString(MidHash);
|
||||
}
|
||||
if (Content.Length != 0) {
|
||||
output.WriteRawTag(58);
|
||||
output.WriteString(Content);
|
||||
}
|
||||
if (Ctime != 0L) {
|
||||
output.WriteRawTag(64);
|
||||
output.WriteInt64(Ctime);
|
||||
}
|
||||
if (Weight != 0) {
|
||||
output.WriteRawTag(72);
|
||||
output.WriteInt32(Weight);
|
||||
}
|
||||
if (Action.Length != 0) {
|
||||
output.WriteRawTag(82);
|
||||
output.WriteString(Action);
|
||||
}
|
||||
if (Pool != 0) {
|
||||
output.WriteRawTag(88);
|
||||
output.WriteInt32(Pool);
|
||||
}
|
||||
if (IdStr.Length != 0) {
|
||||
output.WriteRawTag(98);
|
||||
output.WriteString(IdStr);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public int CalculateSize() {
|
||||
int size = 0;
|
||||
if (Id != 0L) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeInt64Size(Id);
|
||||
}
|
||||
if (Progress != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Progress);
|
||||
}
|
||||
if (Mode != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Mode);
|
||||
}
|
||||
if (Fontsize != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Fontsize);
|
||||
}
|
||||
if (Color != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Color);
|
||||
}
|
||||
if (MidHash.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(MidHash);
|
||||
}
|
||||
if (Content.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Content);
|
||||
}
|
||||
if (Ctime != 0L) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeInt64Size(Ctime);
|
||||
}
|
||||
if (Weight != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Weight);
|
||||
}
|
||||
if (Action.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Action);
|
||||
}
|
||||
if (Pool != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Pool);
|
||||
}
|
||||
if (IdStr.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(IdStr);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public void MergeFrom(DanmakuElem other) {
|
||||
if (other == null) {
|
||||
return;
|
||||
}
|
||||
if (other.Id != 0L) {
|
||||
Id = other.Id;
|
||||
}
|
||||
if (other.Progress != 0) {
|
||||
Progress = other.Progress;
|
||||
}
|
||||
if (other.Mode != 0) {
|
||||
Mode = other.Mode;
|
||||
}
|
||||
if (other.Fontsize != 0) {
|
||||
Fontsize = other.Fontsize;
|
||||
}
|
||||
if (other.Color != 0) {
|
||||
Color = other.Color;
|
||||
}
|
||||
if (other.MidHash.Length != 0) {
|
||||
MidHash = other.MidHash;
|
||||
}
|
||||
if (other.Content.Length != 0) {
|
||||
Content = other.Content;
|
||||
}
|
||||
if (other.Ctime != 0L) {
|
||||
Ctime = other.Ctime;
|
||||
}
|
||||
if (other.Weight != 0) {
|
||||
Weight = other.Weight;
|
||||
}
|
||||
if (other.Action.Length != 0) {
|
||||
Action = other.Action;
|
||||
}
|
||||
if (other.Pool != 0) {
|
||||
Pool = other.Pool;
|
||||
}
|
||||
if (other.IdStr.Length != 0) {
|
||||
IdStr = other.IdStr;
|
||||
}
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public void MergeFrom(pb::CodedInputStream input) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
input.ReadRawMessage(this);
|
||||
#else
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
|
||||
break;
|
||||
case 8: {
|
||||
Id = input.ReadInt64();
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
Progress = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
Mode = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
Fontsize = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
case 40: {
|
||||
Color = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 50: {
|
||||
MidHash = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 58: {
|
||||
Content = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 64: {
|
||||
Ctime = input.ReadInt64();
|
||||
break;
|
||||
}
|
||||
case 72: {
|
||||
Weight = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
case 82: {
|
||||
Action = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 88: {
|
||||
Pool = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
case 98: {
|
||||
IdStr = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
|
||||
break;
|
||||
case 8: {
|
||||
Id = input.ReadInt64();
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
Progress = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
Mode = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
Fontsize = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
case 40: {
|
||||
Color = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 50: {
|
||||
MidHash = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 58: {
|
||||
Content = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 64: {
|
||||
Ctime = input.ReadInt64();
|
||||
break;
|
||||
}
|
||||
case 72: {
|
||||
Weight = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
case 82: {
|
||||
Action = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 88: {
|
||||
Pool = input.ReadInt32();
|
||||
break;
|
||||
}
|
||||
case 98: {
|
||||
IdStr = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class DmSegMobileReply : pb::IMessage<DmSegMobileReply>
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
, pb::IBufferMessage
|
||||
#endif
|
||||
{
|
||||
private static readonly pb::MessageParser<DmSegMobileReply> _parser = new pb::MessageParser<DmSegMobileReply>(() => new DmSegMobileReply());
|
||||
private pb::UnknownFieldSet _unknownFields;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public static pb::MessageParser<DmSegMobileReply> Parser { get { return _parser; } }
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public static pbr::MessageDescriptor Descriptor {
|
||||
get { return global::DanmakuReflection.Descriptor.MessageTypes[1]; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
pbr::MessageDescriptor pb::IMessage.Descriptor {
|
||||
get { return Descriptor; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public DmSegMobileReply() {
|
||||
OnConstruction();
|
||||
}
|
||||
|
||||
partial void OnConstruction();
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public DmSegMobileReply(DmSegMobileReply other) : this() {
|
||||
elems_ = other.elems_.Clone();
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public DmSegMobileReply Clone() {
|
||||
return new DmSegMobileReply(this);
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "elems" field.</summary>
|
||||
public const int ElemsFieldNumber = 1;
|
||||
private static readonly pb::FieldCodec<global::DanmakuElem> _repeated_elems_codec
|
||||
= pb::FieldCodec.ForMessage(10, global::DanmakuElem.Parser);
|
||||
private readonly pbc::RepeatedField<global::DanmakuElem> elems_ = new pbc::RepeatedField<global::DanmakuElem>();
|
||||
/// <summary>
|
||||
///弹幕条目
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public pbc::RepeatedField<global::DanmakuElem> Elems {
|
||||
get { return elems_; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public override bool Equals(object other) {
|
||||
return Equals(other as DmSegMobileReply);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public bool Equals(DmSegMobileReply other) {
|
||||
if (ReferenceEquals(other, null)) {
|
||||
return false;
|
||||
}
|
||||
if (ReferenceEquals(other, this)) {
|
||||
return true;
|
||||
}
|
||||
if(!elems_.Equals(other.elems_)) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public override int GetHashCode() {
|
||||
int hash = 1;
|
||||
hash ^= elems_.GetHashCode();
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public override string ToString() {
|
||||
return pb::JsonFormatter.ToDiagnosticString(this);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public void WriteTo(pb::CodedOutputStream output) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
output.WriteRawMessage(this);
|
||||
#else
|
||||
elems_.WriteTo(output, _repeated_elems_codec);
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
|
||||
elems_.WriteTo(ref output, _repeated_elems_codec);
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public int CalculateSize() {
|
||||
int size = 0;
|
||||
size += elems_.CalculateSize(_repeated_elems_codec);
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public void MergeFrom(DmSegMobileReply other) {
|
||||
if (other == null) {
|
||||
return;
|
||||
}
|
||||
elems_.Add(other.elems_);
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
public void MergeFrom(pb::CodedInputStream input) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
input.ReadRawMessage(this);
|
||||
#else
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
|
||||
break;
|
||||
case 10: {
|
||||
elems_.AddEntriesFrom(input, _repeated_elems_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
|
||||
break;
|
||||
case 10: {
|
||||
elems_.AddEntriesFrom(ref input, _repeated_elems_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#endregion Designer generated code
|
@ -1,20 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
message DanmakuElem {
|
||||
int64 id = 1; //弹幕dmID
|
||||
int32 progress = 2; //出现时间
|
||||
int32 mode = 3; //弹幕类型
|
||||
int32 fontsize = 4; //文字大小
|
||||
uint32 color = 5; //弹幕颜色
|
||||
string midHash = 6; //发送者UID的HASH
|
||||
string content = 7; //弹幕内容
|
||||
int64 ctime = 8; //发送时间
|
||||
int32 weight = 9; //权重
|
||||
string action = 10; //动作?
|
||||
int32 pool = 11; //弹幕池
|
||||
string idStr = 12; //弹幕dmID(字串形式)
|
||||
}
|
||||
|
||||
message DmSegMobileReply {
|
||||
repeated DanmakuElem elems = 1; //弹幕条目
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.api.fileDownload
|
||||
{
|
||||
[Serializable]
|
||||
internal class FileDownloadConfig
|
||||
{
|
||||
public long DownloadSize { get; set; }
|
||||
public long TotalSize { get; set; }
|
||||
public Queue<ThreadDownloadInfo> DownloadQueue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 保存文件下载的配置信息,包括总字节数、已下载字节数、下载队列信息
|
||||
/// </summary>
|
||||
/// <param name="configFile"></param>
|
||||
/// <param name="downloadSize"></param>
|
||||
/// <param name="totalSize"></param>
|
||||
/// <param name="downloadQueue"></param>
|
||||
public static void SaveConfig(string configFile, long downloadSize, long totalSize, Queue<ThreadDownloadInfo> downloadQueue)
|
||||
{
|
||||
var config = new FileDownloadConfig()
|
||||
{
|
||||
DownloadSize = downloadSize,
|
||||
TotalSize = totalSize,
|
||||
DownloadQueue = downloadQueue
|
||||
};
|
||||
Utils.WriteObjectToDisk(configFile, config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取文件下载的配置信息,包括总字节数、已下载字节数、下载队列信息
|
||||
/// </summary>
|
||||
/// <param name="configFile"></param>
|
||||
/// <returns></returns>
|
||||
public static FileDownloadConfig ReadConfig(string configFile)
|
||||
{
|
||||
return (FileDownloadConfig)Utils.ReadObjectFromDisk(configFile);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
namespace Core.api.fileDownload
|
||||
{
|
||||
public class FileDownloadEvent
|
||||
{
|
||||
|
||||
//private long _downloadSize;
|
||||
//private long _totalSize;
|
||||
public FileDownloadEvent() { }
|
||||
|
||||
// 每秒下载的速度 B/s
|
||||
public float Speed { get; set; }
|
||||
|
||||
public float Percent
|
||||
{
|
||||
get { return DownloadSize * 100.0f / TotalSize; }
|
||||
}
|
||||
|
||||
public long DownloadSize { get; set; }
|
||||
|
||||
public long TotalSize { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,317 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Core.api.fileDownload
|
||||
{
|
||||
public class FileDownloadHelper
|
||||
{
|
||||
private const int DOWNLOAD_BUFFER_SIZE = 102400; //每次下载量 100KB
|
||||
private const int THREAD_BUFFER_SIZE = 10485760; //每个线程每次最大下载大小 设为10MB 不能太小 否则会创建太多的request对象
|
||||
public delegate void ErrorMakedEventHandler(string errorstring);
|
||||
public event ErrorMakedEventHandler ErrorMakedEvent;
|
||||
public delegate void DownloadEventHandler(FileDownloadEvent e);
|
||||
public event DownloadEventHandler DownloadEvent;
|
||||
public delegate void StopEventHandler();
|
||||
public event StopEventHandler StopEvent;
|
||||
private object locker = new object();
|
||||
private long downloadSize = 0; //已经下载的字节
|
||||
private CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
|
||||
private ManualResetEvent mre = new ManualResetEvent(true); //初始化不等待
|
||||
private AutoResetEvent eventFinished = new AutoResetEvent(false);
|
||||
|
||||
private void ThreadWork(string url, FileStream fs, Queue<ThreadDownloadInfo> downQueue)
|
||||
{
|
||||
mre.WaitOne();
|
||||
if (cancelTokenSource.IsCancellationRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Monitor.Enter(downQueue);
|
||||
if (downQueue.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ThreadDownloadInfo downInfo = downQueue.Dequeue();
|
||||
Monitor.Exit(downQueue);
|
||||
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||||
request.AddRange(downInfo.StartLength); //设置Range值
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
Stream ns = response.GetResponseStream();
|
||||
byte[] nbytes = new byte[DOWNLOAD_BUFFER_SIZE];
|
||||
int temp = 0;
|
||||
int nReadSize = 0;
|
||||
byte[] buffer = new byte[downInfo.Length]; //文件写入缓冲
|
||||
nReadSize = ns.Read(nbytes, 0, Math.Min(DOWNLOAD_BUFFER_SIZE, downInfo.Length));
|
||||
while (temp < downInfo.Length)
|
||||
{
|
||||
mre.WaitOne();
|
||||
Buffer.BlockCopy(nbytes, 0, buffer, temp, nReadSize);
|
||||
lock (locker)
|
||||
{
|
||||
downloadSize += nReadSize;
|
||||
}
|
||||
temp += nReadSize;
|
||||
nReadSize = ns.Read(nbytes, 0, Math.Min(DOWNLOAD_BUFFER_SIZE, downInfo.Length - temp));
|
||||
}
|
||||
|
||||
lock (locker)
|
||||
{
|
||||
fs.Seek(downInfo.StartLength, SeekOrigin.Begin);
|
||||
fs.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
ns.Close();
|
||||
ThreadWork(url, fs, downQueue);
|
||||
}
|
||||
|
||||
public async void StartDownload(FileDownloadInfo info)
|
||||
{
|
||||
if (string.IsNullOrEmpty(info.DownLoadUrl))
|
||||
{ throw new Exception("下载地址不能为空!"); }
|
||||
if (!info.DownLoadUrl.ToLower().StartsWith("http://") || !info.DownLoadUrl.ToLower().StartsWith("https://"))
|
||||
{ throw new Exception("非法的下载地址!"); }
|
||||
|
||||
downloadSize = 0;
|
||||
await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
long totalSize = 0;
|
||||
long threadInitedLength = 0; //分配线程任务的下载量
|
||||
|
||||
#region 获取文件信息
|
||||
//打开网络连接
|
||||
HttpWebRequest initRequest = (HttpWebRequest)WebRequest.Create(info.DownLoadUrl);
|
||||
WebResponse initResponse = initRequest.GetResponse();
|
||||
FileInfo fileMsg = FileInfo.GetFileMessage(initResponse);
|
||||
totalSize = fileMsg.Length;
|
||||
if ((!string.IsNullOrEmpty(fileMsg.FileName)) && info.LocalSaveFolder != null)
|
||||
{
|
||||
info.SavePath = Path.Combine(info.LocalSaveFolder, fileMsg.FileName);
|
||||
}
|
||||
//ReaderWriterLock readWriteLock = new ReaderWriterLock();
|
||||
#endregion
|
||||
|
||||
#region 读取配置文件
|
||||
string configPath = info.SavePath.Substring(0, info.SavePath.LastIndexOf(".")) + ".cfg";
|
||||
FileDownloadConfig initInfo = null;
|
||||
if (File.Exists(configPath) && (info.IsNew == false))
|
||||
{
|
||||
initInfo = FileDownloadConfig.ReadConfig(configPath);
|
||||
downloadSize = (long)initInfo.DownloadSize;
|
||||
totalSize = (long)initInfo.TotalSize;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 计算速度
|
||||
//Stopwatch MyStopWatch = new Stopwatch();
|
||||
long lastDownloadSize = 0; //上次下载量
|
||||
bool isSendCompleteEvent = false; //是否完成
|
||||
Timer timer = new Timer(new TimerCallback((o) =>
|
||||
{
|
||||
if (!isSendCompleteEvent)
|
||||
{
|
||||
FileDownloadEvent e = new FileDownloadEvent();
|
||||
e.DownloadSize = downloadSize;
|
||||
e.TotalSize = totalSize;
|
||||
if (totalSize > 0 && downloadSize == totalSize)
|
||||
{
|
||||
e.Speed = 0;
|
||||
isSendCompleteEvent = true;
|
||||
eventFinished.Set();
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Speed = downloadSize - lastDownloadSize;
|
||||
lastDownloadSize = downloadSize; //更新上次下载量
|
||||
}
|
||||
|
||||
DownloadEvent(e);
|
||||
}
|
||||
|
||||
}), null, 0, 1000);
|
||||
#endregion
|
||||
|
||||
string tempPath = info.SavePath.Substring(0, info.SavePath.LastIndexOf(".")) + ".dat";
|
||||
|
||||
#region 多线程下载
|
||||
//分配下载队列
|
||||
Queue<ThreadDownloadInfo> downQueue = null;
|
||||
if (initInfo == null || info.IsNew)
|
||||
{
|
||||
downQueue = new Queue<ThreadDownloadInfo>(); //下载信息队列
|
||||
while (threadInitedLength < totalSize)
|
||||
{
|
||||
ThreadDownloadInfo downInfo = new ThreadDownloadInfo();
|
||||
downInfo.StartLength = threadInitedLength;
|
||||
downInfo.Length = (int)Math.Min(Math.Min(THREAD_BUFFER_SIZE, totalSize - threadInitedLength), totalSize / info.ThreadCount); //下载量
|
||||
downQueue.Enqueue(downInfo);
|
||||
threadInitedLength += downInfo.Length;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
downQueue = initInfo.DownloadQueue;
|
||||
}
|
||||
|
||||
FileStream fs = new FileStream(tempPath, FileMode.OpenOrCreate);
|
||||
fs.SetLength(totalSize);
|
||||
int threads = info.ThreadCount;
|
||||
|
||||
for (int i = 0; i < info.ThreadCount; i++)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem((state) =>
|
||||
{
|
||||
ThreadWork(info.DownLoadUrl, fs, downQueue);
|
||||
if (Interlocked.Decrement(ref threads) == 0)
|
||||
{
|
||||
(state as AutoResetEvent).Set();
|
||||
}
|
||||
}, eventFinished);
|
||||
}
|
||||
|
||||
//等待所有线程完成
|
||||
eventFinished.WaitOne();
|
||||
if (fs != null)
|
||||
{
|
||||
fs.Close();
|
||||
}
|
||||
fs = null;
|
||||
if (File.Exists(info.SavePath))
|
||||
{
|
||||
File.Delete(info.SavePath);
|
||||
}
|
||||
|
||||
if (downloadSize == totalSize)
|
||||
{
|
||||
File.Move(tempPath, info.SavePath);
|
||||
File.Delete(configPath);
|
||||
}
|
||||
|
||||
if (cancelTokenSource.IsCancellationRequested && StopEvent != null)
|
||||
{
|
||||
StopEvent();
|
||||
//保存配置文件
|
||||
FileDownloadConfig.SaveConfig(configPath, downloadSize, totalSize, downQueue);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ErrorMakedEvent?.Invoke(ex.Message);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
cancelTokenSource.Cancel();
|
||||
}
|
||||
|
||||
public void Suspend()
|
||||
{
|
||||
mre.Reset();
|
||||
}
|
||||
|
||||
public void Resume()
|
||||
{
|
||||
mre.Set();
|
||||
}
|
||||
|
||||
//#region 获取文件信息
|
||||
//public class FileMessage
|
||||
//{
|
||||
// public long Length { get; set; }
|
||||
// public string FileName { get; set; }
|
||||
//}
|
||||
|
||||
//public FileMessage GetFileMessage(WebResponse response)
|
||||
//{
|
||||
// FileMessage info = new FileMessage();
|
||||
|
||||
// if (response.Headers["Content-Disposition"] != null)
|
||||
// {
|
||||
// Match match = Regex.Match(response.Headers["Content-Disposition"], "filename=(.*)");
|
||||
// if (match.Success)
|
||||
// {
|
||||
// string fileName = match.Groups[1].Value;
|
||||
// Encoding encoding = Encoding.UTF8;
|
||||
// string str = (response as HttpWebResponse).CharacterSet;
|
||||
// if (!string.IsNullOrEmpty(str))
|
||||
// {
|
||||
// encoding = Encoding.GetEncoding(str);
|
||||
// }
|
||||
// info.FileName = System.Web.HttpUtility.UrlDecode(fileName, encoding);
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (response.Headers["Content-Length"] != null)
|
||||
// {
|
||||
// info.Length = long.Parse(response.Headers.Get("Content-Length"));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// info.Length = response.ContentLength;
|
||||
// }
|
||||
|
||||
// return info;
|
||||
//}
|
||||
|
||||
|
||||
//#endregion
|
||||
|
||||
//private void SaveConfig(string configPath, long downloadSize, long totalSize, Queue downQueue)
|
||||
//{
|
||||
// stringBuilder sb = new stringBuilder();
|
||||
// sb.Append(downloadSize + ";" + totalSize + ";");
|
||||
// foreach (ThreadDownloadInfo info in downQueue)
|
||||
// {
|
||||
// sb.Append("(" + info.startLength + ",");
|
||||
// sb.Append(info.length + ");");
|
||||
// }
|
||||
|
||||
// byte[] buffer = Encoding.UTF8.GetBytes(sb.Tostring());
|
||||
// string str = Convert.ToBase64string(buffer);
|
||||
// File.WriteAllText(configPath, str);
|
||||
//}
|
||||
|
||||
//private List ReadConfig(string configPath)
|
||||
//{
|
||||
// List list = new List();
|
||||
// string str = File.ReadAllText(configPath);
|
||||
// byte[] buffer = Convert.FromBase64string(str);
|
||||
// str =Encoding.UTF8.Getstring(buffer);
|
||||
// lock (locker)
|
||||
// {
|
||||
// string[] split = str.Split(';');
|
||||
// long downloadSize = Convert.ToInt64(split[0]);
|
||||
// long totalSize = Convert.ToInt64(split[1]);
|
||||
// Queue downQueue = new Queue(); //下载信息队列
|
||||
// foreach (Match match in Regex.Matches(str, "\\((\\d+),(\\d+)\\);"))
|
||||
// {
|
||||
// ThreadDownloadInfo downInfo = new ThreadDownloadInfo();
|
||||
// downInfo.startLength = Convert.ToInt64(match.Groups[1].Value);
|
||||
// downInfo.length = Convert.ToInt32(match.Groups[2].Value);
|
||||
// downQueue.Enqueue(downInfo);
|
||||
// }
|
||||
|
||||
// list.Add(downloadSize);
|
||||
// list.Add(totalSize);
|
||||
// list.Add(downQueue);
|
||||
// }
|
||||
|
||||
// return list;
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Core.api.fileDownload
|
||||
{
|
||||
public class FileDownloadInfo
|
||||
{
|
||||
|
||||
|
||||
// 下载地址
|
||||
public string DownLoadUrl { get; set; }
|
||||
|
||||
private string _localSaveFolder;
|
||||
// 本地保存路径
|
||||
public string LocalSaveFolder
|
||||
{
|
||||
get { return _localSaveFolder; }
|
||||
set
|
||||
{ _localSaveFolder = value; }
|
||||
}
|
||||
|
||||
// 包含文件名的完整保存路径
|
||||
private string _savePath;
|
||||
public string SavePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_savePath == null)
|
||||
{
|
||||
if (_localSaveFolder == null)
|
||||
{
|
||||
throw new Exception("本地保存路径不能为空");
|
||||
}
|
||||
|
||||
_savePath = Path.Combine(_localSaveFolder, Path.GetFileName(DownLoadUrl));
|
||||
|
||||
if (File.Exists(_savePath))
|
||||
{
|
||||
if (IsNew)
|
||||
{
|
||||
if (IsOver)
|
||||
{
|
||||
File.Delete(_savePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
_savePath = _savePath.Substring(0, _savePath.LastIndexOf(".")) + "(2)" + _savePath.Substring(_savePath.LastIndexOf("."));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _savePath;
|
||||
}
|
||||
set
|
||||
{
|
||||
_savePath = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int _threadCount = 1;
|
||||
////// 线程数
|
||||
public int ThreadCount
|
||||
{
|
||||
get { return _threadCount; }
|
||||
set { _threadCount = value; }
|
||||
}
|
||||
|
||||
////// 是否覆盖已存在的文件
|
||||
public bool IsOver { get; set; }
|
||||
|
||||
////// 是否重新下载
|
||||
public bool IsNew { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Core.api.fileDownload
|
||||
{
|
||||
internal class FileInfo
|
||||
{
|
||||
public long Length { get; set; }
|
||||
public string FileName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取远程文件的信息
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
/// <returns></returns>
|
||||
public static FileInfo GetFileMessage(WebResponse response)
|
||||
{
|
||||
FileInfo info = new FileInfo();
|
||||
|
||||
if (response.Headers["Content-Disposition"] != null)
|
||||
{
|
||||
Match match = Regex.Match(response.Headers["Content-Disposition"], "filename=(.*)");
|
||||
if (match.Success)
|
||||
{
|
||||
string fileName = match.Groups[1].Value;
|
||||
info.FileName = WebUtility.UrlDecode(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
if (response.Headers["Content-Length"] != null)
|
||||
{
|
||||
info.Length = long.Parse(response.Headers.Get("Content-Length"));
|
||||
}
|
||||
else
|
||||
{
|
||||
info.Length = response.ContentLength;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace Core.api.fileDownload
|
||||
{
|
||||
internal class ThreadDownloadInfo
|
||||
{
|
||||
// 开始位置
|
||||
public long StartLength { get; set; }
|
||||
|
||||
// 下载量
|
||||
public int Length { get; set; }
|
||||
}
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
using Core.entity2.history;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Core.api.history
|
||||
{
|
||||
/// <summary>
|
||||
/// 历史记录
|
||||
/// </summary>
|
||||
public class History
|
||||
{
|
||||
private static History instance;
|
||||
|
||||
/// <summary>
|
||||
/// 获取UserInfo实例
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static History GetInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new History();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// History()方法,必须使用单例模式
|
||||
/// </summary>
|
||||
private History() { }
|
||||
|
||||
/// <summary>
|
||||
/// 获取历史记录列表(视频、直播、专栏)
|
||||
/// startId和startTime必须同时使用才有效,分别对应结果中的max和view_at,默认为0
|
||||
/// </summary>
|
||||
/// <param name="startId">历史记录开始目标ID</param>
|
||||
/// <param name="startTime">历史记录开始时间</param>
|
||||
/// <param name="ps">每页项数</param>
|
||||
/// <param name="business">历史记录ID类型</param>
|
||||
/// <returns></returns>
|
||||
public HistoryData GetHistory(long startId, long startTime, int ps = 30, HistoryBusiness business = HistoryBusiness.ARCHIVE)
|
||||
{
|
||||
string businessStr = string.Empty;
|
||||
switch (business)
|
||||
{
|
||||
case HistoryBusiness.ARCHIVE:
|
||||
businessStr = "archive";
|
||||
break;
|
||||
case HistoryBusiness.PGC:
|
||||
businessStr = "pgc";
|
||||
break;
|
||||
case HistoryBusiness.LIVE:
|
||||
businessStr = "live";
|
||||
break;
|
||||
case HistoryBusiness.ARTICLE_LIST:
|
||||
businessStr = "article-list";
|
||||
break;
|
||||
case HistoryBusiness.ARTICLE:
|
||||
businessStr = "article";
|
||||
break;
|
||||
}
|
||||
string url = $"https://api.bilibili.com/x/web-interface/history/cursor?max={startId}&view_at={startTime}&ps={ps}&business={businessStr}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var history = JsonConvert.DeserializeObject<HistoryOrigin>(response);
|
||||
if (history == null || history.Data == null) { return null; }
|
||||
return history.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetHistory()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum HistoryBusiness
|
||||
{
|
||||
ARCHIVE = 1, // 稿件
|
||||
PGC, // 番剧(影视)
|
||||
LIVE, // 直播
|
||||
ARTICLE_LIST, // 文集
|
||||
ARTICLE, // 文章
|
||||
}
|
||||
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
using Core.entity2.history;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.api.history
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取稍后再看列表
|
||||
/// </summary>
|
||||
public class ToView
|
||||
{
|
||||
private static ToView instance;
|
||||
|
||||
/// <summary>
|
||||
/// 获取ToView实例
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static ToView GetInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new ToView();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏ToView()方法,必须使用单例模式
|
||||
/// </summary>
|
||||
private ToView() { }
|
||||
|
||||
/// <summary>
|
||||
/// 获取稍后再看视频列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<ToViewDataList> GetHistoryToView()
|
||||
{
|
||||
string url = "https://api.bilibili.com/x/v2/history/toview/web";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var toView = JsonConvert.DeserializeObject<ToViewOrigin>(response);
|
||||
if (toView == null || toView.Data == null) { return null; }
|
||||
return toView.Data.List;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetHistoryToView()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
using Core.settings;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace Core.api.login
|
||||
{
|
||||
public class LoginHelper
|
||||
{
|
||||
private static LoginHelper instance;
|
||||
|
||||
/// <summary>
|
||||
/// 获取LoginHelper实例
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static LoginHelper GetInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new LoginHelper();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏LoginHelper()方法,必须使用单例模式
|
||||
/// </summary>
|
||||
private LoginHelper() { }
|
||||
|
||||
private static readonly string LOCAL_LOGIN_INFO = Common.ConfigPath + "Login";
|
||||
private static readonly string SecretKey = "Ps*rB$TGaM#&JvOe"; // 16位密码,ps:密码位数没有限制,可任意设置
|
||||
|
||||
/// <summary>
|
||||
/// 获得登录二维码
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public BitmapImage GetLoginQRCode()
|
||||
{
|
||||
try
|
||||
{
|
||||
string loginUrl = Login.GetInstance().GetLoginUrl().Data.Url;
|
||||
return GetLoginQRCode(loginUrl);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetLoginQRCode()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据输入url生成二维码
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public BitmapImage GetLoginQRCode(string url)
|
||||
{
|
||||
// 设置的参数影响app能否成功扫码
|
||||
Bitmap qrCode = Utils.EncodeQRCode(url, 10, 10, null, 0, 0, false);
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
qrCode.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
|
||||
byte[] bytes = ms.GetBuffer();
|
||||
ms.Close();
|
||||
|
||||
BitmapImage image = new BitmapImage();
|
||||
image.BeginInit();
|
||||
image.StreamSource = new MemoryStream(bytes);
|
||||
image.EndInit();
|
||||
return image;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存登录的cookies到文件
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public bool SaveLoginInfoCookies(string url)
|
||||
{
|
||||
if (!Directory.Exists(Common.ConfigPath))
|
||||
{
|
||||
Directory.CreateDirectory(Common.ConfigPath);
|
||||
}
|
||||
|
||||
string tempFile = LOCAL_LOGIN_INFO + "-" + Guid.NewGuid().ToString("N");
|
||||
CookieContainer cookieContainer = Utils.ParseCookie(url);
|
||||
|
||||
bool isSucceed = Utils.WriteCookiesToDisk(tempFile, cookieContainer);
|
||||
if (isSucceed)
|
||||
{
|
||||
// 加密密钥,增加机器码
|
||||
string password = SecretKey + MachineCode.GetMachineCodeString();
|
||||
|
||||
try
|
||||
{
|
||||
Encryptor.EncryptFile(tempFile, LOCAL_LOGIN_INFO, password);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("SaveLoginInfoCookies()发生异常: {0}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(tempFile))
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
return isSucceed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得登录的cookies
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public CookieContainer GetLoginInfoCookies()
|
||||
{
|
||||
string tempFile = LOCAL_LOGIN_INFO + "-" + Guid.NewGuid().ToString("N");
|
||||
|
||||
if (File.Exists(LOCAL_LOGIN_INFO))
|
||||
{
|
||||
try
|
||||
{
|
||||
// 加密密钥,增加机器码
|
||||
string password = SecretKey + MachineCode.GetMachineCodeString();
|
||||
Encryptor.DecryptFile(LOCAL_LOGIN_INFO, tempFile, password);
|
||||
}
|
||||
catch (CryptoHelpException e)
|
||||
{
|
||||
Console.WriteLine("GetLoginInfoCookies()发生异常: {0}", e);
|
||||
if (File.Exists(tempFile))
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
Console.WriteLine("GetLoginInfoCookies()发生异常: {0}", e);
|
||||
if (File.Exists(tempFile))
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (DirectoryNotFoundException e)
|
||||
{
|
||||
Console.WriteLine("GetLoginInfoCookies()发生异常: {0}", e);
|
||||
if (File.Exists(tempFile))
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetLoginInfoCookies()发生异常: {0}", e);
|
||||
if (File.Exists(tempFile))
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else { return null; }
|
||||
|
||||
CookieContainer cookies = Utils.ReadCookiesFromDisk(tempFile);
|
||||
|
||||
if (File.Exists(tempFile))
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
return cookies;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回登录信息的cookies的字符串
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetLoginInfoCookiesString()
|
||||
{
|
||||
var cookieContainer = GetLoginInfoCookies();
|
||||
if (cookieContainer == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
var cookies = Utils.GetAllCookies(cookieContainer);
|
||||
|
||||
string cookie = string.Empty;
|
||||
foreach (var item in cookies)
|
||||
{
|
||||
cookie += item.ToString() + ";";
|
||||
}
|
||||
return cookie.TrimEnd(';');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注销登录
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Logout()
|
||||
{
|
||||
if (File.Exists(LOCAL_LOGIN_INFO))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(LOCAL_LOGIN_INFO);
|
||||
|
||||
Settings.GetInstance().SetUserInfo(new UserInfoForSetting
|
||||
{
|
||||
Mid = -1,
|
||||
Name = "",
|
||||
IsLogin = false,
|
||||
IsVip = false
|
||||
});
|
||||
return true;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Console.WriteLine("Logout()发生异常: {0}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
using Core.entity2.users;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Core.api.users
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户基本信息
|
||||
/// </summary>
|
||||
public class UserInfo
|
||||
{
|
||||
private static UserInfo instance;
|
||||
|
||||
/// <summary>
|
||||
/// 获取UserInfo实例
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static UserInfo GetInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new UserInfo();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏UserInfo()方法,必须使用单例模式
|
||||
/// </summary>
|
||||
private UserInfo() { }
|
||||
|
||||
/// <summary>
|
||||
/// 用户详细信息1 (用于空间)
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <returns></returns>
|
||||
public SpaceInfo GetInfoForSpace(long mid)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/space/acc/info?mid={mid}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var spaceInfo = JsonConvert.DeserializeObject<SpaceInfoOrigin>(response);
|
||||
if (spaceInfo == null || spaceInfo.Data == null) { return null; }
|
||||
return spaceInfo.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetInfoForSpace()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 本用户详细信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public MyInfo GetMyInfo()
|
||||
{
|
||||
string url = "https://api.bilibili.com/x/space/myinfo";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var myInfo = JsonConvert.DeserializeObject<MyInfoOrigin>(response);
|
||||
if (myInfo == null || myInfo.Data == null) { return null; }
|
||||
return myInfo.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetMyInfo()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,290 +0,0 @@
|
||||
using Core.entity2.users;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.api.users
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户关系相关
|
||||
/// </summary>
|
||||
public class UserRelation
|
||||
{
|
||||
private static UserRelation instance;
|
||||
|
||||
/// <summary>
|
||||
/// 获取UserRelation实例
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static UserRelation GetInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new UserRelation();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏UserRelation()方法,必须使用单例模式
|
||||
/// </summary>
|
||||
private UserRelation() { }
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户粉丝明细
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <param name="pn">页码</param>
|
||||
/// <param name="ps">每页项数</param>
|
||||
/// <returns></returns>
|
||||
public RelationFollow GetFollowers(long mid, int pn, int ps)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/relation/followers?vmid={mid}&pn={pn}&ps={ps}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var relationFollower = JsonConvert.DeserializeObject<RelationFollowOrigin>(response);
|
||||
if (relationFollower == null || relationFollower.Data == null) { return null; }
|
||||
return relationFollower.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetFollowers()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户所有的粉丝明细
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <returns></returns>
|
||||
public List<RelationFollowInfo> GetAllFollowers(long mid)
|
||||
{
|
||||
List<RelationFollowInfo> result = new List<RelationFollowInfo>();
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
int ps = 50;
|
||||
|
||||
var data = GetFollowers(mid, i, ps);
|
||||
//if (data == null) { continue; }
|
||||
|
||||
if (data == null || data.List == null || data.List.Count == 0)
|
||||
{ break; }
|
||||
|
||||
result.AddRange(data.List);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户关注明细
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <param name="pn">页码</param>
|
||||
/// <param name="ps">每页项数</param>
|
||||
/// <param name="order">排序方式</param>
|
||||
/// <returns></returns>
|
||||
public RelationFollow GetFollowings(long mid, int pn, int ps, FollowingOrder order = FollowingOrder.DEFAULT)
|
||||
{
|
||||
string orderType = "";
|
||||
if (order == FollowingOrder.ATTENTION)
|
||||
{
|
||||
orderType = "attention";
|
||||
}
|
||||
|
||||
string url = $"https://api.bilibili.com/x/relation/followings?vmid={mid}&pn={pn}&ps={ps}&order_type={orderType}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var relationFollower = JsonConvert.DeserializeObject<RelationFollowOrigin>(response);
|
||||
if (relationFollower == null || relationFollower.Data == null) { return null; }
|
||||
return relationFollower.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetFollowings()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户所有的关注明细
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <param name="order">排序方式</param>
|
||||
/// <returns></returns>
|
||||
public List<RelationFollowInfo> GetAllFollowings(long mid, FollowingOrder order = FollowingOrder.DEFAULT)
|
||||
{
|
||||
List<RelationFollowInfo> result = new List<RelationFollowInfo>();
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
int ps = 50;
|
||||
|
||||
var data = GetFollowings(mid, i, ps, order);
|
||||
//if (data == null) { continue; }
|
||||
|
||||
if (data == null || data.List == null || data.List.Count == 0)
|
||||
{ break; }
|
||||
|
||||
result.AddRange(data.List);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询悄悄关注明细
|
||||
/// </summary>
|
||||
/// <param name="pn">页码</param>
|
||||
/// <param name="ps">每页项数</param>
|
||||
/// <returns></returns>
|
||||
public List<RelationWhisper> GetWhispers(int pn, int ps)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/relation/whispers?pn={pn}&ps={ps}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var relationWhisper = JsonConvert.DeserializeObject<RelationWhisperOrigin>(response);
|
||||
if (relationWhisper == null || relationWhisper.Data == null) { return null; }
|
||||
return relationWhisper.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetWhispers()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询黑名单明细
|
||||
/// </summary>
|
||||
/// <param name="pn">页码</param>
|
||||
/// <param name="ps">每页项数</param>
|
||||
/// <returns></returns>
|
||||
public List<RelationBlack> GetBlacks(int pn, int ps)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/relation/blacks?pn={pn}&ps={ps}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var relationBlack = JsonConvert.DeserializeObject<RelationBlackOrigin>(response);
|
||||
if (relationBlack == null || relationBlack.Data == null) { return null; }
|
||||
return relationBlack.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetBlacks()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 关注分组相关,只能查询当前登录账户的信息
|
||||
|
||||
/// <summary>
|
||||
/// 查询关注分组列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<FollowingGroup> GetFollowingGroup()
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/relation/tags";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var followingGroup = JsonConvert.DeserializeObject<FollowingGroupOrigin>(response);
|
||||
if (followingGroup == null || followingGroup.Data == null) { return null; }
|
||||
return followingGroup.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetFollowingGroup()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询关注分组明细
|
||||
/// </summary>
|
||||
/// <param name="tagId">分组ID</param>
|
||||
/// <param name="pn">页数</param>
|
||||
/// <param name="ps">每页项数</param>
|
||||
/// <param name="order">排序方式</param>
|
||||
/// <returns></returns>
|
||||
public List<FollowingGroupContent> GetFollowingGroupContent(int tagId, int pn, int ps, FollowingOrder order = FollowingOrder.DEFAULT)
|
||||
{
|
||||
string orderType = "";
|
||||
if (order == FollowingOrder.ATTENTION)
|
||||
{
|
||||
orderType = "attention";
|
||||
}
|
||||
|
||||
string url = $"https://api.bilibili.com/x/relation/tag?tagid={tagId}&pn={pn}&ps={ps}&order_type={orderType}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var content = JsonConvert.DeserializeObject<FollowingGroupContentOrigin>(response);
|
||||
if (content == null || content.Data == null) { return null; }
|
||||
return content.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetFollowingGroupContent()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询所有的关注分组明细
|
||||
/// </summary>
|
||||
/// <param name="tagId">分组ID</param>
|
||||
/// <param name="order">排序方式</param>
|
||||
/// <returns></returns>
|
||||
public List<FollowingGroupContent> GetAllFollowingGroupContent(int tagId, FollowingOrder order = FollowingOrder.DEFAULT)
|
||||
{
|
||||
List<FollowingGroupContent> result = new List<FollowingGroupContent>();
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
int ps = 50;
|
||||
|
||||
var data = GetFollowingGroupContent(tagId, i, ps, order);
|
||||
|
||||
if (data == null || data.Count == 0)
|
||||
{ break; }
|
||||
|
||||
result.AddRange(data);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum FollowingOrder
|
||||
{
|
||||
DEFAULT = 1, // 按照关注顺序排列,默认
|
||||
ATTENTION // 按照最常访问排列
|
||||
}
|
||||
|
||||
}
|
@ -1,520 +0,0 @@
|
||||
using Core.entity2.users;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Core.api.users
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户空间信息
|
||||
/// </summary>
|
||||
public class UserSpace
|
||||
{
|
||||
private static UserSpace instance;
|
||||
|
||||
/// <summary>
|
||||
/// 获取UserSpace实例
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static UserSpace GetInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new UserSpace();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏UserSpace()方法,必须使用单例模式
|
||||
/// </summary>
|
||||
private UserSpace() { }
|
||||
|
||||
/// <summary>
|
||||
/// 查询空间设置
|
||||
/// </summary>
|
||||
/// <param name="mid"></param>
|
||||
/// <returns></returns>
|
||||
public SpaceSettings GetSpaceSettings(long mid)
|
||||
{
|
||||
string url = $"https://space.bilibili.com/ajax/settings/getSettings?mid={mid}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var settings = JsonConvert.DeserializeObject<SpaceSettingsOrigin>(response);
|
||||
if (settings == null || settings.Data == null || !settings.Status) { return null; }
|
||||
|
||||
return settings.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetSpaceSettings()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户投稿视频的所有分区
|
||||
/// </summary>
|
||||
/// <param name="mid">用户id</param>
|
||||
/// <returns></returns>
|
||||
public List<SpacePublicationListTypeVideoZone> GetPublicationType(long mid)
|
||||
{
|
||||
int pn = 1;
|
||||
int ps = 1;
|
||||
var publication = GetPublication(mid, pn, ps);
|
||||
return GetPublicationType(publication);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户投稿视频的所有分区
|
||||
/// </summary>
|
||||
/// <param name="mid">用户id</param>
|
||||
/// <returns></returns>
|
||||
public List<SpacePublicationListTypeVideoZone> GetPublicationType(SpacePublicationList publication)
|
||||
{
|
||||
if (publication == null || publication.Tlist == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<SpacePublicationListTypeVideoZone> result = new List<SpacePublicationListTypeVideoZone>();
|
||||
JObject typeList = JObject.Parse(publication.Tlist.ToString("N"));
|
||||
foreach (var item in typeList)
|
||||
{
|
||||
var value = JsonConvert.DeserializeObject<SpacePublicationListTypeVideoZone>(item.Value.ToString());
|
||||
result.Add(value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户所有的投稿视频明细
|
||||
/// </summary>
|
||||
/// <param name="mid">用户id</param>
|
||||
/// <param name="order">排序</param>
|
||||
/// <param name="tid">视频分区</param>
|
||||
/// <param name="keyword">搜索关键词</param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<SpacePublicationListVideo>> GetAllPublication(long mid, int tid = 0, PublicationOrder order = PublicationOrder.PUBDATE, string keyword = "")
|
||||
{
|
||||
List<SpacePublicationListVideo> result = new List<SpacePublicationListVideo>();
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
int ps = 100;
|
||||
|
||||
var data = GetPublication(mid, i, ps, tid, order, keyword);
|
||||
//if (data == null) { continue; }
|
||||
|
||||
if (data == null || data.Vlist == null || data.Vlist.Count == 0)
|
||||
{ break; }
|
||||
|
||||
result.AddRange(data.Vlist);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户投稿视频明细
|
||||
/// </summary>
|
||||
/// <param name="mid">用户id</param>
|
||||
/// <param name="pn">页码</param>
|
||||
/// <param name="ps">每页的视频数</param>
|
||||
/// <param name="order">排序</param>
|
||||
/// <param name="tid">视频分区</param>
|
||||
/// <param name="keyword">搜索关键词</param>
|
||||
/// <returns></returns>
|
||||
public SpacePublicationList GetPublication(long mid, int pn, int ps, int tid = 0, PublicationOrder order = PublicationOrder.PUBDATE, string keyword = "")
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/space/arc/search?mid={mid}&pn={pn}&ps={ps}&order={order.ToString("G").ToLower()}&tid={tid}&keyword={keyword}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
// 忽略play的值为“--”时的类型错误
|
||||
var settings = new JsonSerializerSettings
|
||||
{
|
||||
Error = (sender, args) =>
|
||||
{
|
||||
if (Equals(args.ErrorContext.Member, "play") &&
|
||||
args.ErrorContext.OriginalObject.GetType() == typeof(SpacePublicationListVideo))
|
||||
{
|
||||
args.ErrorContext.Handled = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var spacePublication = JsonConvert.DeserializeObject<SpacePublicationOrigin>(response, settings);
|
||||
if (spacePublication == null || spacePublication.Data == null) { return null; }
|
||||
return spacePublication.Data.List;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetPublication()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户频道列表
|
||||
/// </summary>
|
||||
/// <param name="mid">用户id</param>
|
||||
/// <returns></returns>
|
||||
public List<SpaceChannelList> GetChannelList(long mid)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/space/channel/list?mid={mid}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var spaceChannel = JsonConvert.DeserializeObject<SpaceChannelOrigin>(response);
|
||||
if (spaceChannel == null || spaceChannel.Data == null) { return null; }
|
||||
return spaceChannel.Data.List;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetChannelList()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户频道中的所有视频
|
||||
/// </summary>
|
||||
/// <param name="mid"></param>
|
||||
/// <param name="cid"></param>
|
||||
/// <returns></returns>
|
||||
public List<SpaceChannelVideoArchive> GetAllChannelVideoList(long mid, long cid)
|
||||
{
|
||||
List<SpaceChannelVideoArchive> result = new List<SpaceChannelVideoArchive>();
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
int ps = 100;
|
||||
|
||||
var data = GetChannelVideoList(mid, cid, i, ps);
|
||||
if (data == null || data.Count == 0)
|
||||
{ break; }
|
||||
|
||||
result.AddRange(data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户频道中的视频
|
||||
/// </summary>
|
||||
/// <param name="mid"></param>
|
||||
/// <param name="cid"></param>
|
||||
/// <param name="pn"></param>
|
||||
/// <param name="ps"></param>
|
||||
/// <returns></returns>
|
||||
public List<SpaceChannelVideoArchive> GetChannelVideoList(long mid, long cid, int pn, int ps)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/space/channel/video?mid={mid}&cid={cid}&pn={pn}&ps={ps}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var spaceChannelVideo = JsonConvert.DeserializeObject<SpaceChannelVideoOrigin>(response);
|
||||
if (spaceChannelVideo == null || spaceChannelVideo.Data == null || spaceChannelVideo.Data.List == null)
|
||||
{ return null; }
|
||||
return spaceChannelVideo.Data.List.Archives;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetChannelVideoList()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户创建的视频收藏夹
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <param name="pn">页码</param>
|
||||
/// <param name="ps">每页项数</param>
|
||||
/// <returns></returns>
|
||||
public List<SpaceFavoriteFolderList> GetCreatedFavoriteFolder(long mid, int pn, int ps)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/v3/fav/folder/created/list?up_mid={mid}&pn={pn}&ps={ps}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var favoriteFolder = JsonConvert.DeserializeObject<SpaceFavoriteFolderOrigin>(response);
|
||||
if (favoriteFolder == null || favoriteFolder.Data == null || favoriteFolder.Data.List == null)
|
||||
{ return null; }
|
||||
return favoriteFolder.Data.List;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetCreatedFavoriteFolder()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询所有的用户创建的视频收藏夹
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <returns></returns>
|
||||
public List<SpaceFavoriteFolderList> GetAllCreatedFavoriteFolder(long mid)
|
||||
{
|
||||
List<SpaceFavoriteFolderList> result = new List<SpaceFavoriteFolderList>();
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
int ps = 50;
|
||||
|
||||
var data = GetCreatedFavoriteFolder(mid, i, ps);
|
||||
if (data == null || data.Count == 0)
|
||||
{ break; }
|
||||
|
||||
result.AddRange(data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户收藏的视频收藏夹
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <param name="pn">页码</param>
|
||||
/// <param name="ps">每页项数</param>
|
||||
/// <returns></returns>
|
||||
public List<SpaceFavoriteFolderList> GetCollectedFavoriteFolder(long mid, int pn, int ps)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/v3/fav/folder/collected/list?up_mid={mid}&pn={pn}&ps={ps}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var favoriteFolder = JsonConvert.DeserializeObject<SpaceFavoriteFolderOrigin>(response);
|
||||
if (favoriteFolder == null || favoriteFolder.Data == null || favoriteFolder.Data.List == null)
|
||||
{ return null; }
|
||||
return favoriteFolder.Data.List;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetCollectedFavoriteFolder()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询所有的用户收藏的视频收藏夹
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <returns></returns>
|
||||
public List<SpaceFavoriteFolderList> GetAllCollectedFavoriteFolder(long mid)
|
||||
{
|
||||
List<SpaceFavoriteFolderList> result = new List<SpaceFavoriteFolderList>();
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
int ps = 50;
|
||||
|
||||
var data = GetCollectedFavoriteFolder(mid, i, ps);
|
||||
if (data == null || data.Count == 0)
|
||||
{ break; }
|
||||
|
||||
result.AddRange(data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询视频收藏夹的内容
|
||||
/// </summary>
|
||||
/// <param name="mediaId">收藏夹ID</param>
|
||||
/// <param name="pn">页码</param>
|
||||
/// <param name="ps">每页项数</param>
|
||||
/// <returns></returns>
|
||||
public List<SpaceFavoriteFolderMedia> GetFavoriteFolderResource(long mediaId, int pn, int ps)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/v3/fav/resource/list?media_id={mediaId}&pn={pn}&ps={ps}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var resource = JsonConvert.DeserializeObject<SpaceFavoriteFolderResourceOrigin>(response);
|
||||
if (resource == null || resource.Data == null || resource.Data.Medias == null)
|
||||
{ return null; }
|
||||
return resource.Data.Medias;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetFavoriteFolderResource()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询视频收藏夹的所有内容
|
||||
/// </summary>
|
||||
/// <param name="mediaId">收藏夹ID</param>
|
||||
/// <returns></returns>
|
||||
public List<SpaceFavoriteFolderMedia> GetAllFavoriteFolderResource(long mediaId)
|
||||
{
|
||||
List<SpaceFavoriteFolderMedia> result = new List<SpaceFavoriteFolderMedia>();
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
int ps = 20;
|
||||
|
||||
var data = GetFavoriteFolderResource(mediaId, i, ps);
|
||||
if (data == null || data.Count == 0)
|
||||
{ break; }
|
||||
|
||||
result.AddRange(data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户发布的课程列表
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <param name="pn">页码</param>
|
||||
/// <param name="ps">每页项数</param>
|
||||
/// <returns></returns>
|
||||
public List<SpaceCheese> GetCheese(long mid, int pn, int ps)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/pugv/app/web/season/page?mid={mid}&pn={pn}&ps={ps}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var cheese = JsonConvert.DeserializeObject<SpaceCheeseOrigin>(response);
|
||||
if (cheese == null || cheese.Data == null || cheese.Data.Items == null)
|
||||
{ return null; }
|
||||
return cheese.Data.Items;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetCheese()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户发布的所有课程列表
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <returns></returns>
|
||||
public List<SpaceCheese> GetAllCheese(long mid)
|
||||
{
|
||||
List<SpaceCheese> result = new List<SpaceCheese>();
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
int ps = 50;
|
||||
|
||||
var data = GetCheese(mid, i, ps);
|
||||
if (data == null || data.Count == 0)
|
||||
{ break; }
|
||||
|
||||
result.AddRange(data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户追番(追剧)明细
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <param name="type">查询类型</param>
|
||||
/// <param name="pn">页码</param>
|
||||
/// <param name="ps">每页项数</param>
|
||||
/// <returns></returns>
|
||||
public BangumiFollowData GetBangumiFollow(long mid, BangumiType type, int pn, int ps)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/space/bangumi/follow/list?vmid={mid}&type={type:D}&pn={pn}&ps={ps}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var bangumiFollow = JsonConvert.DeserializeObject<BangumiFollowOrigin>(response);
|
||||
if (bangumiFollow == null || bangumiFollow.Data == null)
|
||||
{ return null; }
|
||||
return bangumiFollow.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetBangumiFollow()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户所有的追番(追剧)明细
|
||||
/// </summary>
|
||||
/// <param name="mid">目标用户UID</param>
|
||||
/// <param name="type">查询类型</param>
|
||||
/// <returns></returns>
|
||||
public List<BangumiFollow> GetAllBangumiFollow(long mid, BangumiType type)
|
||||
{
|
||||
List<BangumiFollow> result = new List<BangumiFollow>();
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
i++;
|
||||
int ps = 30;
|
||||
|
||||
var data = GetBangumiFollow(mid, type, i, ps);
|
||||
if (data == null || data.List == null || data.List.Count == 0)
|
||||
{ break; }
|
||||
|
||||
result.AddRange(data.List);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public enum PublicationOrder
|
||||
{
|
||||
PUBDATE = 1, // 最新发布,默认
|
||||
CLICK, // 最多播放
|
||||
STOW // 最多收藏
|
||||
}
|
||||
|
||||
public enum BangumiType
|
||||
{
|
||||
ANIME = 1, // 番剧
|
||||
EPISODE = 2 // 剧集、电影
|
||||
}
|
||||
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
using Core.entity2.users;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Core.api.users
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户状态数
|
||||
/// </summary>
|
||||
public class UserStatus
|
||||
{
|
||||
private static UserStatus instance;
|
||||
|
||||
/// <summary>
|
||||
/// 获取UserStatus实例
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static UserStatus GetInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new UserStatus();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏UserStatus()方法,必须使用单例模式
|
||||
/// </summary>
|
||||
private UserStatus() { }
|
||||
|
||||
/// <summary>
|
||||
/// 关系状态数
|
||||
/// </summary>
|
||||
/// <param name="mid"></param>
|
||||
/// <returns></returns>
|
||||
public UserRelationStat GetUserRelationStat(long mid)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/relation/stat?vmid={mid}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var userRelationStat = JsonConvert.DeserializeObject<UserRelationStatOrigin>(response);
|
||||
if (userRelationStat == null || userRelationStat.Data == null) { return null; }
|
||||
return userRelationStat.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetUserRelationStat()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UP主状态数
|
||||
///
|
||||
/// 注:该接口需要任意用户登录,否则不会返回任何数据
|
||||
/// </summary>
|
||||
/// <param name="mid"></param>
|
||||
/// <returns></returns>
|
||||
public UpStat GetUpStat(long mid)
|
||||
{
|
||||
string url = $"https://api.bilibili.com/x/space/upstat?mid={mid}";
|
||||
string referer = "https://www.bilibili.com";
|
||||
string response = Utils.RequestWeb(url, referer);
|
||||
|
||||
try
|
||||
{
|
||||
var upStat = JsonConvert.DeserializeObject<UpStatOrigin>(response);
|
||||
if (upStat == null || upStat.Data == null) { return null; }
|
||||
return upStat.Data;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetUpStat()发生异常: {0}", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,433 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// 代码来源
|
||||
// https://blog.csdn.net/haibin258/article/details/87905628
|
||||
|
||||
// Aria2详细信息请看
|
||||
// https://aria2.github.io/manual/en/html/aria2c.html#rpc-interface
|
||||
|
||||
// 废弃
|
||||
namespace Core.aria2cNet
|
||||
{
|
||||
//定义一个类用于转码成JSON字符串发送给Aria2 json-rpc接口
|
||||
public class JsonClass
|
||||
{
|
||||
public string Jsonrpc { get; set; }
|
||||
public string Id { get; set; }
|
||||
public string Method { get; set; }
|
||||
public List<string> Params { get; set; }
|
||||
}
|
||||
|
||||
public class Aria2
|
||||
{
|
||||
public static ClientWebSocket webSocket; // 用于连接到Aria2Rpc的客户端
|
||||
public static CancellationToken cancellationToken; // 传播有关应取消操作的通知
|
||||
|
||||
/// <summary>
|
||||
/// 连接Aria2Rpc服务器
|
||||
/// </summary>
|
||||
/// <param name="uri"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> ConnectServer(string uri)
|
||||
{
|
||||
webSocket = new ClientWebSocket(); // 用于连接到Aria2Rpc的客户端
|
||||
cancellationToken = new CancellationToken(); // 传播有关应取消操作的通知
|
||||
bool status = false; //储存连接状态
|
||||
try
|
||||
{
|
||||
//连接服务器
|
||||
await webSocket.ConnectAsync(new Uri(uri), cancellationToken);
|
||||
}
|
||||
catch
|
||||
{
|
||||
status = false;
|
||||
}
|
||||
//检查连接是否成功
|
||||
if (webSocket.State == WebSocketState.Open)
|
||||
{
|
||||
status = true;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// JsonClass类转为json格式
|
||||
/// </summary>
|
||||
/// <param name="json"></param>
|
||||
/// <returns></returns>
|
||||
private static string ToJson(JsonClass json)
|
||||
{
|
||||
string str = "{" + "\"jsonrpc\":\"" + json.Jsonrpc + "\",\"id\":\"" + json.Id + "\",\"method\":\"" + json.Method + "\",\"params\":[";
|
||||
for (int i = 0; i < json.Params.Count; i++)
|
||||
{
|
||||
if (json.Method == "aria2.addUri")
|
||||
{
|
||||
str += "[\"" + json.Params[i] + "\"]";
|
||||
}
|
||||
else if (json.Method == "aria2.tellStatus")
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
str += "\"" + json.Params[i] + "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
str += "[\"" + json.Params[i] + "\"]";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
str += "\"" + json.Params[i] + "\"";
|
||||
}
|
||||
if (json.Params.Count - 1 > i)
|
||||
{
|
||||
str += ",";
|
||||
}
|
||||
}
|
||||
str += "]}";
|
||||
//最后得到类似
|
||||
//{"jsonrpc":"2.0","id":"qwer","method":"aria2.addUri","params:"[["http://www.baidu.com"]]}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 发送json并返回json消息
|
||||
/// </summary>
|
||||
/// <param name="json"></param>
|
||||
/// <returns></returns>
|
||||
private static async Task<string> SendAndReceive(JsonClass json)
|
||||
{
|
||||
string str = ToJson(json);
|
||||
try
|
||||
{
|
||||
//发送json数据
|
||||
await webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(str)), WebSocketMessageType.Text, true, cancellationToken);
|
||||
var result = new byte[1024];
|
||||
//接收数据
|
||||
await webSocket.ReceiveAsync(new ArraySegment<byte>(result), new CancellationToken());
|
||||
str += "\r\n" + Encoding.UTF8.GetString(result, 0, result.Length) + "\r\n";
|
||||
}
|
||||
catch
|
||||
{
|
||||
str = "连接错误";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加新的下载
|
||||
/// </summary>
|
||||
/// <param name="uri"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> AddUri(string uri)
|
||||
{
|
||||
var json = new JsonClass
|
||||
{
|
||||
Jsonrpc = "2.0",
|
||||
Id = "qwer",
|
||||
Method = "aria2.addUri"
|
||||
};
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add(uri);
|
||||
json.Params = paramslist;
|
||||
string str = await SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 上传“.torrent”文件添加BitTorrent下载
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> AddTorrent(string path)
|
||||
{
|
||||
string str = "";
|
||||
string fsbase64 = "";
|
||||
byte[] fs = File.ReadAllBytes(path);
|
||||
fsbase64 = Convert.ToBase64String(fs); //转为Base64编码
|
||||
|
||||
var json = new JsonClass();
|
||||
json.Jsonrpc = "2.0";
|
||||
json.Id = "qwer";
|
||||
json.Method = "aria2.addTorrent";
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加“.torrent”文件本地地址
|
||||
paramslist.Add(fsbase64);
|
||||
json.Params = paramslist;
|
||||
str = await SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 删除已经停止的任务,强制删除请使用ForceRemove方法
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> Remove(string gid)
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass
|
||||
{
|
||||
Jsonrpc = "2.0",
|
||||
Id = "qwer",
|
||||
Method = "aria2.remove"
|
||||
};
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add(gid);
|
||||
json.Params = paramslist;
|
||||
str = await SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 强制删除
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> ForceRemove(string gid)
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass
|
||||
{
|
||||
Jsonrpc = "2.0",
|
||||
Id = "qwer",
|
||||
Method = "aria2.forceRemove"
|
||||
};
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add(gid);
|
||||
json.Params = paramslist;
|
||||
str = await SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 暂停下载,强制暂停请使用ForcePause方法
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> Pause(string gid)
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass
|
||||
{
|
||||
Jsonrpc = "2.0",
|
||||
Id = "qwer",
|
||||
Method = "aria2.pause"
|
||||
};
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add(gid);
|
||||
json.Params = paramslist;
|
||||
str = await SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 暂停全部任务
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> PauseAll()
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass();
|
||||
json.Jsonrpc = "2.0";
|
||||
json.Id = "qwer";
|
||||
json.Method = "aria2.pauseAll";
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add("");
|
||||
json.Params = paramslist;
|
||||
str = await Aria2.SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 强制暂停下载
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> ForcePause(string gid)
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass();
|
||||
json.Jsonrpc = "2.0";
|
||||
json.Id = "qwer";
|
||||
json.Method = "aria2.forcePause";
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add(gid);
|
||||
json.Params = paramslist;
|
||||
str = await Aria2.SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 强制暂停全部下载
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> ForcePauseAll()
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass();
|
||||
json.Jsonrpc = "2.0";
|
||||
json.Id = "qwer";
|
||||
json.Method = "aria2.forcePauseAll";
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add("");
|
||||
json.Params = paramslist;
|
||||
str = await Aria2.SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 把正在下载的任务状态改为等待下载
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> PauseToWaiting(string gid)
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass();
|
||||
json.Jsonrpc = "2.0";
|
||||
json.Id = "qwer";
|
||||
json.Method = "aria2.unpause";
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add(gid);
|
||||
json.Params = paramslist;
|
||||
str = await Aria2.SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 把全部在下载的任务状态改为等待下载
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> PauseToWaitingAll()
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass();
|
||||
json.Jsonrpc = "2.0";
|
||||
json.Id = "qwer";
|
||||
json.Method = "aria2.unpauseAll";
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add("");
|
||||
json.Params = paramslist;
|
||||
str = await Aria2.SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 返回下载进度
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> TellStatus(string gid)
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass();
|
||||
json.Jsonrpc = "2.0";
|
||||
json.Id = "qwer";
|
||||
json.Method = "aria2.tellStatus";
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add(gid);
|
||||
paramslist.Add("completedLength\", \"totalLength\",\"downloadSpeed");
|
||||
|
||||
json.Params = paramslist;
|
||||
str = await Aria2.SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 返回全局统计信息,例如整体下载和上载速度
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> GetGlobalStat(string gid)
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass();
|
||||
json.Jsonrpc = "2.0";
|
||||
json.Id = "qwer";
|
||||
json.Method = "aria2.getGlobalStat";
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add(gid);
|
||||
json.Params = paramslist;
|
||||
str = await Aria2.SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 返回由gid(字符串)表示的下载中使用的URI 。响应是一个结构数组
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> GetUris(string gid)
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass();
|
||||
json.Jsonrpc = "2.0";
|
||||
json.Id = "qwer";
|
||||
json.Method = "aria2.getUris";
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add(gid);
|
||||
json.Params = paramslist;
|
||||
str = await Aria2.SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 返回由gid(字符串)表示的下载文件列表
|
||||
/// </summary>
|
||||
/// <param name="gid"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> GetFiles(string gid)
|
||||
{
|
||||
string str = "";
|
||||
var json = new JsonClass();
|
||||
json.Jsonrpc = "2.0";
|
||||
json.Id = "qwer";
|
||||
json.Method = "aria2.getFiles";
|
||||
List<string> paramslist = new List<string>();
|
||||
//添加下载地址
|
||||
paramslist.Add(gid);
|
||||
json.Params = paramslist;
|
||||
str = await Aria2.SendAndReceive(json);
|
||||
return str;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
using Core.aria2cNet.client.entity;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Core.aria2cNet.client
|
||||
{
|
||||
public class AriaClientWebSocket
|
||||
{
|
||||
private static readonly string JSONRPC = "2.0";
|
||||
private static readonly string TOKEN = "downkyi";
|
||||
|
||||
public static ClientWebSocket webSocket; // 用于连接到Aria2Rpc的客户端
|
||||
public static CancellationToken cancellationToken; // 传播有关应取消操作的通知
|
||||
public static bool Status; // 储存连接状态
|
||||
|
||||
/// <summary>
|
||||
/// 连接Aria2Rpc服务器
|
||||
/// </summary>
|
||||
/// <param name="uri"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> ConnectServerAsync(string uri)
|
||||
{
|
||||
webSocket = new ClientWebSocket(); // 用于连接到Aria2Rpc的客户端
|
||||
cancellationToken = new CancellationToken(); // 传播有关应取消操作的通知
|
||||
Status = false; // 储存连接状态
|
||||
|
||||
try
|
||||
{
|
||||
//连接服务器
|
||||
await webSocket.ConnectAsync(new Uri(uri), cancellationToken);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Status = false;
|
||||
}
|
||||
//检查连接是否成功
|
||||
if (webSocket.State == WebSocketState.Open)
|
||||
{
|
||||
Status = true;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// add
|
||||
/// </summary>
|
||||
/// <param name="uris"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> AddUriAsync(List<string> uris)
|
||||
{
|
||||
AriaSendOption option = new AriaSendOption
|
||||
{
|
||||
Out = "index测试.html",
|
||||
Dir = "home/"
|
||||
};
|
||||
|
||||
List<object> ariaParams = new List<object>
|
||||
{
|
||||
"token:" + TOKEN,
|
||||
uris,
|
||||
option
|
||||
};
|
||||
|
||||
AriaSendData ariaSend = new AriaSendData
|
||||
{
|
||||
Id = Guid.NewGuid().ToString("N"),
|
||||
Jsonrpc = JSONRPC,
|
||||
Method = "aria2.addUri",
|
||||
Params = ariaParams
|
||||
};
|
||||
|
||||
string sendJson = JsonConvert.SerializeObject(ariaSend);
|
||||
|
||||
string result = await SendAndReceiveAsync(sendJson);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 发送并接受数据
|
||||
/// </summary>
|
||||
/// <param name="sendJson"></param>
|
||||
/// <returns></returns>
|
||||
private static async Task<string> SendAndReceiveAsync(string sendJson)
|
||||
{
|
||||
string result;
|
||||
try
|
||||
{
|
||||
//发送json数据
|
||||
await webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(sendJson)), WebSocketMessageType.Text, true, cancellationToken);
|
||||
byte[] receive = new byte[1024];
|
||||
//接收数据
|
||||
await webSocket.ReceiveAsync(new ArraySegment<byte>(receive), new CancellationToken());
|
||||
result = Encoding.UTF8.GetString(receive).TrimEnd('\0');
|
||||
}
|
||||
catch
|
||||
{
|
||||
result = "{\"id\":null,\"jsonrpc\":\"2.0\",\"error\":{\"code\":-2020,\"message\":\"连接错误\"}}";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,163 +0,0 @@
|
||||
using Core.api.danmaku;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
public class Bilibili
|
||||
{
|
||||
private static Bilibili instance;
|
||||
|
||||
private Dictionary<string, bool> config = new Dictionary<string, bool>
|
||||
{
|
||||
{ "top_filter", false },
|
||||
{ "bottom_filter", false },
|
||||
{ "scroll_filter", false }
|
||||
};
|
||||
|
||||
private readonly Dictionary<int, string> mapping = new Dictionary<int, string>
|
||||
{
|
||||
{ 1, "scroll" },
|
||||
{ 2, "scroll" },
|
||||
{ 3, "scroll" },
|
||||
{ 4, "bottom" },
|
||||
{ 5, "top" },
|
||||
{ 6, "scroll" }, // 逆向滚动弹幕,还是当滚动处理
|
||||
{ 7, "none" }, // 高级弹幕,暂时不要考虑
|
||||
{ 8, "none" }, // 代码弹幕,暂时不要考虑
|
||||
{ 9, "none" } // BAS弹幕,暂时不要考虑
|
||||
};
|
||||
|
||||
// 弹幕标准字体大小
|
||||
private readonly int normalFontSize = 25;
|
||||
|
||||
/// <summary>
|
||||
/// 获取Bilibili实例
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Bilibili GetInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new Bilibili();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏Bilibili()方法,必须使用单例模式
|
||||
/// </summary>
|
||||
private Bilibili() { }
|
||||
|
||||
/// <summary>
|
||||
/// 是否屏蔽顶部弹幕
|
||||
/// </summary>
|
||||
/// <param name="isFilter"></param>
|
||||
/// <returns></returns>
|
||||
public Bilibili SetTopFilter(bool isFilter)
|
||||
{
|
||||
config["top_filter"] = isFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否屏蔽底部弹幕
|
||||
/// </summary>
|
||||
/// <param name="isFilter"></param>
|
||||
/// <returns></returns>
|
||||
public Bilibili SetBottomFilter(bool isFilter)
|
||||
{
|
||||
config["bottom_filter"] = isFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否屏蔽滚动弹幕
|
||||
/// </summary>
|
||||
/// <param name="isFilter"></param>
|
||||
/// <returns></returns>
|
||||
public Bilibili SetScrollFilter(bool isFilter)
|
||||
{
|
||||
config["scroll_filter"] = isFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Create(long avid, long cid, Config subtitleConfig, string assFile)
|
||||
{
|
||||
// 弹幕转换
|
||||
var biliDanmakus = DanmakuProtobuf.GetInstance().GetAllDanmakuProto(avid, cid);
|
||||
|
||||
// 按弹幕出现顺序排序
|
||||
biliDanmakus.Sort((x, y) => { return x.Progress.CompareTo(y.Progress); });
|
||||
|
||||
var danmakus = new List<Danmaku>();
|
||||
foreach (var biliDanmaku in biliDanmakus)
|
||||
{
|
||||
var danmaku = new Danmaku
|
||||
{
|
||||
// biliDanmaku.Progress单位是毫秒,所以除以1000,单位变为秒
|
||||
Start = biliDanmaku.Progress / 1000.0f,
|
||||
Style = mapping[biliDanmaku.Mode],
|
||||
Color = (int)biliDanmaku.Color,
|
||||
Commenter = biliDanmaku.MidHash,
|
||||
Content = biliDanmaku.Content,
|
||||
SizeRatio = 1.0f * biliDanmaku.Fontsize / normalFontSize
|
||||
};
|
||||
|
||||
danmakus.Add(danmaku);
|
||||
}
|
||||
|
||||
// 弹幕预处理
|
||||
Producer producer = new Producer(config, danmakus);
|
||||
producer.StartHandle();
|
||||
|
||||
// 字幕生成
|
||||
var keepedDanmakus = producer.KeepedDanmakus;
|
||||
var studio = new Studio(subtitleConfig, keepedDanmakus);
|
||||
studio.StartHandle();
|
||||
studio.CreateAssFile(assFile);
|
||||
}
|
||||
|
||||
public Dictionary<string, int> GetResolution(int quality)
|
||||
{
|
||||
var resolution = new Dictionary<string, int>
|
||||
{
|
||||
{ "width", 0 },
|
||||
{ "height", 0 }
|
||||
};
|
||||
|
||||
switch (quality)
|
||||
{
|
||||
// 240P 极速(仅mp4方式)
|
||||
case 6:
|
||||
break;
|
||||
// 360P 流畅
|
||||
case 16:
|
||||
break;
|
||||
// 480P 清晰
|
||||
case 32:
|
||||
break;
|
||||
// 720P 高清(登录)
|
||||
case 64:
|
||||
break;
|
||||
// 720P60 高清(大会员)
|
||||
case 74:
|
||||
break;
|
||||
// 1080P 高清(登录)
|
||||
case 80:
|
||||
break;
|
||||
// 1080P+ 高清(大会员)
|
||||
case 112:
|
||||
break;
|
||||
// 1080P60 高清(大会员)
|
||||
case 116:
|
||||
break;
|
||||
// 4K 超清(大会员)(需要fourk=1)
|
||||
case 120:
|
||||
break;
|
||||
}
|
||||
return resolution;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
/// <summary>
|
||||
/// 碰撞处理
|
||||
/// </summary>
|
||||
public class Collision
|
||||
{
|
||||
private readonly int lineCount;
|
||||
private readonly List<int> leaves;
|
||||
|
||||
public Collision(int lineCount)
|
||||
{
|
||||
this.lineCount = lineCount;
|
||||
leaves = Leaves();
|
||||
}
|
||||
|
||||
private List<int> Leaves()
|
||||
{
|
||||
var ret = new List<int>(lineCount);
|
||||
for (int i = 0; i < lineCount; i++) ret.Add(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 碰撞检测
|
||||
/// 返回行号和时间偏移
|
||||
/// </summary>
|
||||
/// <param name="display"></param>
|
||||
/// <returns></returns>
|
||||
public Tuple<int, float> Detect(Display display)
|
||||
{
|
||||
List<float> beyonds = new List<float>();
|
||||
for (int i = 0; i < leaves.Count; i++)
|
||||
{
|
||||
float beyond = display.Danmaku.Start - leaves[i];
|
||||
// 某一行有足够空间,直接返回行号和 0 偏移
|
||||
if (beyond >= 0)
|
||||
{
|
||||
return Tuple.Create(i, 0f);
|
||||
}
|
||||
beyonds.Add(beyond);
|
||||
}
|
||||
|
||||
// 所有行都没有空间了,那么找出哪一行能在最短时间内让出空间
|
||||
float soon = beyonds.Max();
|
||||
int lineIndex = beyonds.IndexOf(soon);
|
||||
float offset = -soon;
|
||||
return Tuple.Create(lineIndex, offset);
|
||||
}
|
||||
|
||||
public void Update(float leave, int lineIndex, float offset)
|
||||
{
|
||||
leaves[lineIndex] = Utils.IntCeiling(leave + offset);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
public class Config
|
||||
{
|
||||
public string Title = "Downkyi";
|
||||
public int ScreenWidth = 1920;
|
||||
public int ScreenHeight = 1080;
|
||||
public string FontName = "黑体";
|
||||
public int BaseFontSize; // 字体大小,像素
|
||||
// 限制行数
|
||||
private int lineCount;
|
||||
public int LineCount
|
||||
{
|
||||
get { return lineCount; }
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
lineCount = (int)Math.Floor(ScreenHeight / BaseFontSize * 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
lineCount = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public string LayoutAlgorithm; // 布局算法,async/sync
|
||||
public int TuneDuration; // 微调时长
|
||||
public int DropOffset; // 丢弃偏移
|
||||
public int BottomMargin; // 底部边距
|
||||
public int CustomOffset; // 自定义偏移
|
||||
public string HeaderTemplate = @"[Script Info]
|
||||
; Script generated by Downkyi Danmaku Converter
|
||||
; https://github.com/FlySelfLog/downkyi
|
||||
Title: {title}
|
||||
ScriptType: v4.00+
|
||||
Collisions: Normal
|
||||
PlayResX: {width}
|
||||
PlayResY: {height}
|
||||
Timer: 10.0000
|
||||
WrapStyle: 2
|
||||
ScaledBorderAndShadow: no
|
||||
|
||||
[V4+ Styles]
|
||||
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
|
||||
Style: Default,{fontname},54,&H00FFFFFF,&H00FFFFFF,&H00000000,&H00000000,0,0,0,0,100,100,0.00,0.00,1,2.00,0.00,2,30,30,120,0
|
||||
Style: Alternate,{fontname},36,&H00FFFFFF,&H00FFFFFF,&H00000000,&H00000000,0,0,0,0,100,100,0.00,0.00,1,2.00,0.00,2,30,30,84,0
|
||||
Style: Danmaku,{fontname},{fontsize},&H00FFFFFF,&H00FFFFFF,&H00000000,&H00000000,0,0,0,0,100,100,0.00,0.00,1,1.00,0.00,2,30,30,30,0
|
||||
|
||||
[Events]
|
||||
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text";
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建器
|
||||
/// </summary>
|
||||
public class Creater
|
||||
{
|
||||
public Config Config;
|
||||
public List<Danmaku> Danmakus;
|
||||
public List<Subtitle> Subtitles;
|
||||
public string Text;
|
||||
|
||||
public Creater(Config config, List<Danmaku> danmakus)
|
||||
{
|
||||
Config = config;
|
||||
Danmakus = danmakus;
|
||||
Subtitles = SetSubtitles();
|
||||
Text = SetText();
|
||||
}
|
||||
|
||||
protected List<Subtitle> SetSubtitles()
|
||||
{
|
||||
var scroll = new Collision(Config.LineCount);
|
||||
var stayed = new Collision(Config.LineCount);
|
||||
Dictionary<string, Collision> collisions = new Dictionary<string, Collision>
|
||||
{
|
||||
{ "scroll", scroll },
|
||||
{ "top", stayed },
|
||||
{ "bottom", stayed }
|
||||
};
|
||||
|
||||
List<Subtitle> subtitles = new List<Subtitle>();
|
||||
foreach (var danmaku in Danmakus)
|
||||
{
|
||||
// 丢弃不支持的
|
||||
if (danmaku.Style == "none")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 创建显示方式对象
|
||||
var display = Display.Factory(Config, danmaku);
|
||||
var collision = collisions[danmaku.Style];
|
||||
var detect = collision.Detect(display);
|
||||
int lineIndex = detect.Item1;
|
||||
float waitingOffset = detect.Item2;
|
||||
|
||||
// 超过容忍的偏移量,丢弃掉此条弹幕
|
||||
if (waitingOffset > Config.DropOffset)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 接受偏移,更新碰撞信息
|
||||
display.Relayout(lineIndex);
|
||||
collision.Update(display.Leave, lineIndex, waitingOffset);
|
||||
|
||||
// 再加上自定义偏移
|
||||
float offset = waitingOffset + Config.CustomOffset;
|
||||
Subtitle subtitle = new Subtitle(danmaku, display, offset);
|
||||
|
||||
subtitles.Add(subtitle);
|
||||
}
|
||||
return subtitles;
|
||||
}
|
||||
|
||||
protected string SetText()
|
||||
{
|
||||
string header = Config.HeaderTemplate
|
||||
.Replace("{title}", Config.Title)
|
||||
.Replace("{width}", Config.ScreenWidth.ToString())
|
||||
.Replace("{height}", Config.ScreenHeight.ToString())
|
||||
.Replace("{fontname}", Config.FontName)
|
||||
.Replace("{fontsize}", Config.BaseFontSize.ToString());
|
||||
|
||||
string events = string.Empty;
|
||||
foreach (var subtitle in Subtitles)
|
||||
{
|
||||
events += "\n" + subtitle.Text;
|
||||
}
|
||||
|
||||
return header + events;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
public class Danmaku
|
||||
{
|
||||
public float Start { get; set; }
|
||||
public string Style { get; set; }
|
||||
public int Color { get; set; }
|
||||
public string Commenter { get; set; }
|
||||
public string Content { get; set; }
|
||||
public float SizeRatio { get; set; }
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
public class Dictionary<T>
|
||||
{
|
||||
}
|
||||
}
|
@ -1,406 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
/// <summary>
|
||||
/// 显示方式
|
||||
/// </summary>
|
||||
public class Display
|
||||
{
|
||||
public Config Config;
|
||||
public Danmaku Danmaku;
|
||||
public int LineIndex;
|
||||
|
||||
public int FontSize;
|
||||
public bool IsScaled;
|
||||
public int MaxLength;
|
||||
public int Width;
|
||||
public int Height;
|
||||
|
||||
public Tuple<int, int> Horizontal;
|
||||
public Tuple<int, int> Vertical;
|
||||
|
||||
public int Duration;
|
||||
public int Leave;
|
||||
|
||||
protected Display() { }
|
||||
|
||||
public Display(Config config, Danmaku danmaku)
|
||||
{
|
||||
Config = config;
|
||||
Danmaku = danmaku;
|
||||
LineIndex = 0;
|
||||
|
||||
IsScaled = SetIsScaled();
|
||||
FontSize = SetFontSize();
|
||||
MaxLength = SetMaxLength();
|
||||
Width = SetWidth();
|
||||
Height = SetHeight();
|
||||
|
||||
Horizontal = SetHorizontal();
|
||||
Vertical = SetVertical();
|
||||
|
||||
Duration = SetDuration();
|
||||
Leave = SetLeave();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据弹幕样式自动创建对应的 Display 类
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Display Factory(Config config, Danmaku danmaku)
|
||||
{
|
||||
Dictionary<string, Display> dict = new Dictionary<string, Display>
|
||||
{
|
||||
{ "scroll", new ScrollDisplay(config, danmaku) },
|
||||
{ "top", new TopDisplay(config, danmaku) },
|
||||
{ "bottom", new BottomDisplay(config, danmaku) }
|
||||
};
|
||||
return dict[danmaku.Style];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字体大小
|
||||
/// 按用户自定义的字体大小来缩放
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected int SetFontSize()
|
||||
{
|
||||
if (IsScaled)
|
||||
{
|
||||
Console.WriteLine($"{Danmaku.SizeRatio}");
|
||||
}
|
||||
return Utils.IntCeiling(Config.BaseFontSize * Danmaku.SizeRatio);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字体是否被缩放过
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected bool SetIsScaled()
|
||||
{
|
||||
return !Math.Round(Danmaku.SizeRatio, 2).Equals(1.0);
|
||||
//return Danmaku.SizeRatio.Equals(1.0f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最长的行字符数
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected int SetMaxLength()
|
||||
{
|
||||
string[] lines = Danmaku.Content.Split('\n');
|
||||
int maxLength = 0;
|
||||
foreach (string line in lines)
|
||||
{
|
||||
int length = Utils.DisplayLength(line);
|
||||
if (maxLength < length)
|
||||
{
|
||||
maxLength = length;
|
||||
}
|
||||
}
|
||||
return maxLength;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整条字幕宽度
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected int SetWidth()
|
||||
{
|
||||
float charCount = MaxLength;// / 2;
|
||||
return Utils.IntCeiling(FontSize * charCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整条字幕高度
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected int SetHeight()
|
||||
{
|
||||
int lineCount = Danmaku.Content.Split('\n').Length;
|
||||
return lineCount * FontSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 出现和消失的水平坐标位置
|
||||
/// 默认在屏幕中间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual Tuple<int, int> SetHorizontal()
|
||||
{
|
||||
int x = (int)Math.Floor(Config.ScreenWidth / 2.0);
|
||||
return Tuple.Create(x, x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 出现和消失的垂直坐标位置
|
||||
/// 默认在屏幕中间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual Tuple<int, int> SetVertical()
|
||||
{
|
||||
int y = (int)Math.Floor(Config.ScreenHeight / 2.0);
|
||||
return Tuple.Create(y, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整条字幕的显示时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual int SetDuration()
|
||||
{
|
||||
int baseDuration = 3 + Config.TuneDuration;
|
||||
if (baseDuration <= 0)
|
||||
{
|
||||
baseDuration = 0;
|
||||
}
|
||||
float charCount = MaxLength / 2;
|
||||
|
||||
int value;
|
||||
if (charCount < 6)
|
||||
{
|
||||
value = baseDuration + 1;
|
||||
}
|
||||
else if (charCount < 12)
|
||||
{
|
||||
value = baseDuration + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = baseDuration + 3;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离开碰撞时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual int SetLeave()
|
||||
{
|
||||
return (int)(Danmaku.Start + Duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按照新的行号重新布局
|
||||
/// </summary>
|
||||
/// <param name="lineIndex"></param>
|
||||
public void Relayout(int lineIndex)
|
||||
{
|
||||
LineIndex = lineIndex;
|
||||
Horizontal = SetHorizontal();
|
||||
Vertical = SetVertical();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 顶部
|
||||
/// </summary>
|
||||
public class TopDisplay : Display
|
||||
{
|
||||
public TopDisplay(Config config, Danmaku danmaku) : base(config, danmaku)
|
||||
{
|
||||
Console.WriteLine("TopDisplay constructor.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override Tuple<int, int> SetVertical()
|
||||
{
|
||||
// 这里 y 坐标为 0 就是最顶行了
|
||||
int y = LineIndex * Config.BaseFontSize;
|
||||
return Tuple.Create(y, y);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 底部
|
||||
/// </summary>
|
||||
public class BottomDisplay : Display
|
||||
{
|
||||
public BottomDisplay(Config config, Danmaku danmaku) : base(config, danmaku)
|
||||
{
|
||||
Console.WriteLine("BottomDisplay constructor.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override Tuple<int, int> SetVertical()
|
||||
{
|
||||
// 要让字幕不超出底部,减去高度
|
||||
int y = Config.ScreenHeight - (LineIndex * Config.BaseFontSize) - Height;
|
||||
// 再减去自定义的底部边距
|
||||
y -= Config.BottomMargin;
|
||||
return Tuple.Create(y, y);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 滚动
|
||||
/// </summary>
|
||||
public class ScrollDisplay : Display
|
||||
{
|
||||
public int Distance;
|
||||
public int Speed;
|
||||
|
||||
public ScrollDisplay(Config config, Danmaku danmaku) : base()
|
||||
{
|
||||
Console.WriteLine("ScrollDisplay constructor.");
|
||||
|
||||
Config = config;
|
||||
Danmaku = danmaku;
|
||||
LineIndex = 0;
|
||||
|
||||
IsScaled = SetIsScaled();
|
||||
FontSize = SetFontSize();
|
||||
MaxLength = SetMaxLength();
|
||||
Width = SetWidth();
|
||||
Height = SetHeight();
|
||||
|
||||
Horizontal = SetHorizontal();
|
||||
Vertical = SetVertical();
|
||||
|
||||
Distance = SetDistance();
|
||||
Speed = SetSpeed();
|
||||
|
||||
Duration = SetDuration();
|
||||
Leave = SetLeave();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ASS 的水平位置参考点是整条字幕文本的中点
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override Tuple<int, int> SetHorizontal()
|
||||
{
|
||||
int x1 = Config.ScreenWidth + (int)Math.Floor(Width / 2.0);
|
||||
int x2 = 0 - (int)Math.Floor(Width / 2.0);
|
||||
return Tuple.Create(x1, x2);
|
||||
}
|
||||
|
||||
protected override Tuple<int, int> SetVertical()
|
||||
{
|
||||
int baseFontSize = Config.BaseFontSize;
|
||||
|
||||
// 垂直位置,按基准字体大小算每一行的高度
|
||||
int y = (LineIndex + 1) * baseFontSize;
|
||||
|
||||
// 个别弹幕可能字体比基准要大,所以最上的一行还要避免挤出顶部屏幕
|
||||
// 坐标不能小于字体大小
|
||||
if (y < FontSize)
|
||||
{
|
||||
y = FontSize;
|
||||
}
|
||||
return Tuple.Create(y, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字幕坐标点的移动距离
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected int SetDistance()
|
||||
{
|
||||
Tuple<int, int> x = Horizontal;
|
||||
return x.Item1 - x.Item2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字幕每个字的移动的速度
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected int SetSpeed()
|
||||
{
|
||||
// 基准时间,就是每个字的移动时间
|
||||
// 12 秒加上用户自定义的微调
|
||||
int baseDuration = 12 + Config.TuneDuration;
|
||||
if (baseDuration <= 0)
|
||||
{
|
||||
baseDuration = 1;
|
||||
}
|
||||
return Utils.IntCeiling(Config.ScreenWidth / baseDuration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算每条弹幕的显示时长,同步方式
|
||||
/// 每个弹幕的滚动速度都一样,辨认度好,适合观看剧集类视频。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int SyncDuration()
|
||||
{
|
||||
return Distance / Speed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算每条弹幕的显示时长,异步方式
|
||||
/// 每个弹幕的滚动速度都不一样,动态调整,辨认度低,适合观看 MTV 类视频。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int AsyncDuration()
|
||||
{
|
||||
int baseDuration = 6 + Config.TuneDuration;
|
||||
if (baseDuration <= 0)
|
||||
{
|
||||
baseDuration = 0;
|
||||
}
|
||||
float charCount = MaxLength / 2;
|
||||
|
||||
int value;
|
||||
if (charCount < 6)
|
||||
{
|
||||
value = (int)(baseDuration + charCount);
|
||||
}
|
||||
else if (charCount < 12)
|
||||
{
|
||||
value = baseDuration + (int)(charCount / 2);
|
||||
}
|
||||
else if (charCount < 24)
|
||||
{
|
||||
value = baseDuration + (int)(charCount / 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = baseDuration + 10;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 整条字幕的移动时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override int SetDuration()
|
||||
{
|
||||
string methodName = Config.LayoutAlgorithm.Substring(0, 1).ToUpper() + Config.LayoutAlgorithm.Substring(1);
|
||||
methodName += "Duration";
|
||||
MethodInfo method = typeof(ScrollDisplay).GetMethod(methodName);
|
||||
if (method != null)
|
||||
{
|
||||
return (int)method.Invoke(this, null);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离开碰撞时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override int SetLeave()
|
||||
{
|
||||
// 对于滚动样式弹幕来说,就是最后一个字符离开最右边缘的时间
|
||||
// 坐标是字幕中点,在屏幕外和内各有半个字幕宽度
|
||||
// 也就是跑过一个字幕宽度的路程
|
||||
float duration = Width / Speed;
|
||||
return (int)(Danmaku.Start + duration);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
/// <summary>
|
||||
/// 过滤器基类
|
||||
/// </summary>
|
||||
public class Filter
|
||||
{
|
||||
public virtual List<Danmaku> DoFilter(List<Danmaku> danmakus)
|
||||
{
|
||||
throw new NotImplementedException("使用了过滤器的未实现的方法。");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 顶部样式过滤器
|
||||
/// </summary>
|
||||
public class TopFilter : Filter
|
||||
{
|
||||
public override List<Danmaku> DoFilter(List<Danmaku> danmakus)
|
||||
{
|
||||
List<Danmaku> keep = new List<Danmaku>();
|
||||
foreach (var danmaku in danmakus)
|
||||
{
|
||||
if (danmaku.Style == "top")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
keep.Add(danmaku);
|
||||
}
|
||||
return keep;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 底部样式过滤器
|
||||
/// </summary>
|
||||
public class BottomFilter : Filter
|
||||
{
|
||||
public override List<Danmaku> DoFilter(List<Danmaku> danmakus)
|
||||
{
|
||||
List<Danmaku> keep = new List<Danmaku>();
|
||||
foreach (var danmaku in danmakus)
|
||||
{
|
||||
if (danmaku.Style == "bottom")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
keep.Add(danmaku);
|
||||
}
|
||||
return keep;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 滚动样式过滤器
|
||||
/// </summary>
|
||||
public class ScrollFilter : Filter
|
||||
{
|
||||
public override List<Danmaku> DoFilter(List<Danmaku> danmakus)
|
||||
{
|
||||
List<Danmaku> keep = new List<Danmaku>();
|
||||
foreach (var danmaku in danmakus)
|
||||
{
|
||||
if (danmaku.Style == "scroll")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
keep.Add(danmaku);
|
||||
}
|
||||
return keep;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自定义过滤器
|
||||
/// </summary>
|
||||
public class CustomFilter : Filter
|
||||
{
|
||||
public override List<Danmaku> DoFilter(List<Danmaku> danmakus)
|
||||
{
|
||||
// TODO
|
||||
return base.DoFilter(danmakus);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
public class Producer
|
||||
{
|
||||
public Dictionary<string, bool> Config;
|
||||
public Dictionary<string, Filter> Filters;
|
||||
public List<Danmaku> Danmakus;
|
||||
public List<Danmaku> KeepedDanmakus;
|
||||
public Dictionary<string, int> FilterDetail;
|
||||
|
||||
public Producer(Dictionary<string, bool> config, List<Danmaku> danmakus)
|
||||
{
|
||||
Config = config;
|
||||
Danmakus = danmakus;
|
||||
}
|
||||
|
||||
public void StartHandle()
|
||||
{
|
||||
LoadFilter();
|
||||
ApplyFilter();
|
||||
}
|
||||
|
||||
public void LoadFilter()
|
||||
{
|
||||
Filters = new Dictionary<string, Filter>();
|
||||
if (Config["top_filter"])
|
||||
{
|
||||
Filters.Add("top_filter", new TopFilter());
|
||||
}
|
||||
if (Config["bottom_filter"])
|
||||
{
|
||||
Filters.Add("bottom_filter", new BottomFilter());
|
||||
}
|
||||
if (Config["scroll_filter"])
|
||||
{
|
||||
Filters.Add("scroll_filter", new ScrollFilter());
|
||||
}
|
||||
//if (Config["custom_filter"])
|
||||
//{
|
||||
// Filters.Add("custom_filter", new CustomFilter());
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
public void ApplyFilter()
|
||||
{
|
||||
Dictionary<string, int> filterDetail = new Dictionary<string, int>() {
|
||||
{ "top_filter",0},
|
||||
{ "bottom_filter",0},
|
||||
{ "scroll_filter",0},
|
||||
//{ "custom_filter",0}
|
||||
};
|
||||
|
||||
List<Danmaku> danmakus = Danmakus;
|
||||
//string[] orders = { "top_filter", "bottom_filter", "scroll_filter", "custom_filter" };
|
||||
string[] orders = { "top_filter", "bottom_filter", "scroll_filter" };
|
||||
foreach (var name in orders)
|
||||
{
|
||||
Filter filter;
|
||||
try
|
||||
{
|
||||
filter = Filters[name];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("ApplyFilter()发生异常: {0}", e);
|
||||
continue;
|
||||
}
|
||||
|
||||
int count = danmakus.Count;
|
||||
danmakus = filter.DoFilter(danmakus);
|
||||
filterDetail[name] = count - danmakus.Count;
|
||||
}
|
||||
|
||||
KeepedDanmakus = danmakus;
|
||||
FilterDetail = filterDetail;
|
||||
}
|
||||
|
||||
public Dictionary<string, int> Report()
|
||||
{
|
||||
int blockedCount = 0;
|
||||
foreach (int count in FilterDetail.Values)
|
||||
{
|
||||
blockedCount += count;
|
||||
}
|
||||
|
||||
int passedCount = KeepedDanmakus.Count;
|
||||
int totalCount = blockedCount + passedCount;
|
||||
|
||||
Dictionary<string, int> ret = new Dictionary<string, int>
|
||||
{
|
||||
{ "blocked", blockedCount },
|
||||
{ "passed", passedCount },
|
||||
{ "total", totalCount }
|
||||
};
|
||||
|
||||
return (Dictionary<string, int>)ret.Concat(FilterDetail);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
/// <summary>
|
||||
/// 字幕工程类
|
||||
/// </summary>
|
||||
public class Studio
|
||||
{
|
||||
public Config Config;
|
||||
public List<Danmaku> Danmakus;
|
||||
|
||||
public Creater Creater;
|
||||
public int KeepedCount;
|
||||
public int DropedCount;
|
||||
|
||||
public Studio(Config config, List<Danmaku> danmakus)
|
||||
{
|
||||
Config = config;
|
||||
Danmakus = danmakus;
|
||||
}
|
||||
|
||||
public void StartHandle()
|
||||
{
|
||||
Creater = SetCreater();
|
||||
KeepedCount = SetKeepedCount();
|
||||
DropedCount = SetDropedCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ass 创建器
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected Creater SetCreater()
|
||||
{
|
||||
return new Creater(Config, Danmakus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保留条数
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected int SetKeepedCount()
|
||||
{
|
||||
return Creater.Subtitles.Count();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 丢弃条数
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected int SetDropedCount()
|
||||
{
|
||||
return Danmakus.Count - KeepedCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 ass 字幕
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
public void CreateAssFile(string fileName)
|
||||
{
|
||||
CreateFile(fileName, Creater.Text);
|
||||
}
|
||||
|
||||
public void CreateFile(string fileName, string text)
|
||||
{
|
||||
File.WriteAllText(fileName, text);
|
||||
}
|
||||
|
||||
public Dictionary<string, int> Report()
|
||||
{
|
||||
return new Dictionary<string, int>()
|
||||
{
|
||||
{"total", Danmakus.Count},
|
||||
{"droped", DropedCount},
|
||||
{"keeped", KeepedCount},
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
/// <summary>
|
||||
/// 字幕
|
||||
/// </summary>
|
||||
public class Subtitle
|
||||
{
|
||||
public Danmaku Danmaku;
|
||||
public Display Display;
|
||||
public float Offset;
|
||||
|
||||
public float Start;
|
||||
public float End;
|
||||
public string Color;
|
||||
public Dictionary<string, int> Position;
|
||||
public string StartMarkup;
|
||||
public string EndMarkup;
|
||||
public string ColorMarkup;
|
||||
public string BorderMarkup;
|
||||
public string FontSizeMarkup;
|
||||
public string StyleMarkup;
|
||||
public string LayerMarkup;
|
||||
public string ContentMarkup;
|
||||
public string Text;
|
||||
|
||||
public Subtitle(Danmaku danmaku, Display display, float offset = 0)
|
||||
{
|
||||
Danmaku = danmaku;
|
||||
Display = display;
|
||||
Offset = offset;
|
||||
|
||||
Start = SetStart();
|
||||
End = SetEnd();
|
||||
Color = SetColor();
|
||||
Position = SetPosition();
|
||||
StartMarkup = SetStartMarkup();
|
||||
EndMarkup = SetEndMarkup();
|
||||
ColorMarkup = SetColorMarkup();
|
||||
BorderMarkup = SetBorderMarkup();
|
||||
FontSizeMarkup = SetFontSizeMarkup();
|
||||
StyleMarkup = SetStyleMarkup();
|
||||
LayerMarkup = SetLayerMarkup();
|
||||
ContentMarkup = SetContentMarkup();
|
||||
Text = SetText();
|
||||
}
|
||||
|
||||
protected float SetStart()
|
||||
{
|
||||
return Danmaku.Start + Offset;
|
||||
}
|
||||
|
||||
protected float SetEnd()
|
||||
{
|
||||
return Start + Display.Duration;
|
||||
}
|
||||
|
||||
protected string SetColor()
|
||||
{
|
||||
return Utils.Int2bgr(Danmaku.Color);
|
||||
}
|
||||
|
||||
protected Dictionary<string, int> SetPosition()
|
||||
{
|
||||
Tuple<int, int> x = Display.Horizontal;
|
||||
Tuple<int, int> y = Display.Vertical;
|
||||
|
||||
Dictionary<string, int> value = new Dictionary<string, int>
|
||||
{
|
||||
{ "x1", x.Item1 },
|
||||
{ "x2", x.Item2 },
|
||||
{ "y1", y.Item1 },
|
||||
{ "y2", y.Item2 }
|
||||
};
|
||||
return value;
|
||||
}
|
||||
|
||||
protected string SetStartMarkup()
|
||||
{
|
||||
return Utils.Second2hms(Start);
|
||||
}
|
||||
|
||||
protected string SetEndMarkup()
|
||||
{
|
||||
return Utils.Second2hms(End);
|
||||
}
|
||||
|
||||
protected string SetColorMarkup()
|
||||
{
|
||||
// 白色不需要加特别标记
|
||||
if (Color == "FFFFFF")
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return "\\c&H" + Color;
|
||||
}
|
||||
|
||||
protected string SetBorderMarkup()
|
||||
{
|
||||
// 暗色加个亮色边框,方便阅读
|
||||
if (Utils.IsDark(Danmaku.Color))
|
||||
{
|
||||
//return "\\3c&HFFFFFF";
|
||||
return "\\3c&H000000";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "\\3c&H000000";
|
||||
}
|
||||
//return "";
|
||||
}
|
||||
|
||||
protected string SetFontSizeMarkup()
|
||||
{
|
||||
if (Display.IsScaled)
|
||||
{
|
||||
return $"\\fs{Display.FontSize}";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
protected string SetStyleMarkup()
|
||||
{
|
||||
if (Danmaku.Style == "scroll")
|
||||
{
|
||||
return $"\\move({Position["x1"]}, {Position["y1"]}, {Position["x2"]}, {Position["y2"]})";
|
||||
}
|
||||
return $"\\a6\\pos({Position["x1"]}, {Position["y1"]})";
|
||||
}
|
||||
|
||||
protected string SetLayerMarkup()
|
||||
{
|
||||
if (Danmaku.Style != "scroll")
|
||||
{
|
||||
return "-2";
|
||||
}
|
||||
return "-1";
|
||||
}
|
||||
|
||||
protected string SetContentMarkup()
|
||||
{
|
||||
string markup = StyleMarkup + ColorMarkup + BorderMarkup + FontSizeMarkup;
|
||||
string content = Utils.CorrectTypos(Danmaku.Content);
|
||||
return $"{{{markup}}}{content}";
|
||||
}
|
||||
|
||||
protected string SetText()
|
||||
{
|
||||
return $"Dialogue: {LayerMarkup},{StartMarkup},{EndMarkup},Danmaku,,0000,0000,0000,,{ContentMarkup}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,228 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Core.danmaku2ass
|
||||
{
|
||||
internal static class Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// 向上取整,返回int类型
|
||||
/// </summary>
|
||||
/// <param name="number"></param>
|
||||
/// <returns></returns>
|
||||
public static int IntCeiling(float number)
|
||||
{
|
||||
return (int)Math.Ceiling(number);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字符长度,1个汉字当2个英文
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <returns></returns>
|
||||
public static int DisplayLength(string text)
|
||||
{
|
||||
return Encoding.Default.GetBytes(text).Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修正一些评论者的拼写错误
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <returns></returns>
|
||||
public static string CorrectTypos(string text)
|
||||
{
|
||||
text = text.Replace("/n", "\\N");
|
||||
text = text.Replace(">", ">");
|
||||
text = text.Replace("<", "<");
|
||||
return text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 秒数转 时:分:秒 格式
|
||||
/// </summary>
|
||||
/// <param name="seconds"></param>
|
||||
/// <returns></returns>
|
||||
public static string Second2hms(float seconds)
|
||||
{
|
||||
if (seconds < 0)
|
||||
{
|
||||
return "0:00:00.00";
|
||||
}
|
||||
|
||||
int i = (int)Math.Floor(seconds / 1.0);
|
||||
int dec = (int)(Math.Round(seconds % 1.0f, 2) * 100);
|
||||
if (dec >= 100)
|
||||
{
|
||||
dec = 99;
|
||||
}
|
||||
|
||||
int min = (int)Math.Floor(i / 60.0);
|
||||
int second = (int)(i % 60.0f);
|
||||
|
||||
int hour = (int)Math.Floor(min / 60.0);
|
||||
|
||||
return $"{hour:D}:{min:D2}:{second:D2}.{dec:D2}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 时:分:秒 格式转 秒数
|
||||
/// </summary>
|
||||
/// <param name="hms"></param>
|
||||
/// <returns></returns>
|
||||
public static float Hms2second(string hms)
|
||||
{
|
||||
string[] numbers = hms.Split(':');
|
||||
float seconds = 0;
|
||||
|
||||
for (int i = 0; i < numbers.Length; i++)
|
||||
{
|
||||
seconds += (float)(float.Parse(numbers[numbers.Length - i - 1]) * Math.Pow(60, i));
|
||||
}
|
||||
return seconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同Hms2second(string hms),不过可以用 +/- 符号来连接多个
|
||||
/// 即 3:00-2:30 相当于 30 秒
|
||||
/// </summary>
|
||||
/// <param name="xhms"></param>
|
||||
/// <returns></returns>
|
||||
public static float Xhms2second(string xhms)
|
||||
{
|
||||
string[] args = xhms.Replace("+", " +").Replace("-", " -").Split(' ');
|
||||
float result = 0;
|
||||
foreach (string hms in args)
|
||||
{
|
||||
result += Hms2second(hms);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 颜色值,整型转 RGB
|
||||
/// </summary>
|
||||
/// <param name="integer"></param>
|
||||
/// <returns></returns>
|
||||
public static string Int2rgb(int integer)
|
||||
{
|
||||
return integer.ToString("X").PadLeft(6, '0'); ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 颜色值,整型转 BGR
|
||||
/// </summary>
|
||||
/// <param name="integer"></param>
|
||||
/// <returns></returns>
|
||||
public static string Int2bgr(int integer)
|
||||
{
|
||||
string rgb = Int2rgb(integer);
|
||||
string bgr = rgb.Substring(4, 2) + rgb.Substring(2, 2) + rgb.Substring(0, 2);
|
||||
return bgr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 颜色值,整型转 HLS
|
||||
/// </summary>
|
||||
/// <param name="integer"></param>
|
||||
/// <returns></returns>
|
||||
public static float[] Int2hls(int integer)
|
||||
{
|
||||
string rgb = Int2rgb(integer);
|
||||
int[] rgb_decimals = { 0, 0, 0 };
|
||||
rgb_decimals[0] = int.Parse(rgb.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
|
||||
rgb_decimals[1] = int.Parse(rgb.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
|
||||
rgb_decimals[2] = int.Parse(rgb.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
|
||||
|
||||
int[] rgb_coordinates = { 0, 0, 0 };
|
||||
rgb_coordinates[0] = (int)Math.Floor(rgb_decimals[0] / 255.0);
|
||||
rgb_coordinates[1] = (int)Math.Floor(rgb_decimals[1] / 255.0);
|
||||
rgb_coordinates[2] = (int)Math.Floor(rgb_decimals[2] / 255.0);
|
||||
float[] hls_corrdinates = Rgb2hls(rgb_coordinates);
|
||||
|
||||
float[] hls = { 0, 0, 0 };
|
||||
hls[0] = hls_corrdinates[0] * 360;
|
||||
hls[1] = hls_corrdinates[1] * 100;
|
||||
hls[2] = hls_corrdinates[2] * 100;
|
||||
return hls;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HLS: Hue, Luminance, Saturation
|
||||
/// H: position in the spectrum
|
||||
/// L: color lightness
|
||||
/// S: color saturation
|
||||
/// </summary>
|
||||
/// <param name="rgb"></param>
|
||||
/// <returns></returns>
|
||||
private static float[] Rgb2hls(int[] rgb)
|
||||
{
|
||||
float[] hls = { 0, 0, 0 };
|
||||
int maxc = rgb.Max();
|
||||
int minc = rgb.Min();
|
||||
hls[1] = (minc + maxc) / 2.0f;
|
||||
if (minc == maxc)
|
||||
{
|
||||
return hls;
|
||||
}
|
||||
|
||||
if (hls[1] <= 0.5)
|
||||
{
|
||||
hls[2] = (maxc - minc) / (maxc + minc);
|
||||
}
|
||||
else
|
||||
{
|
||||
hls[2] = (maxc - minc) / (2.0f - maxc - minc);
|
||||
}
|
||||
float rc = (maxc - rgb[0]) / (maxc - minc);
|
||||
float gc = (maxc - rgb[1]) / (maxc - minc);
|
||||
float bc = (maxc - rgb[2]) / (maxc - minc);
|
||||
if (rgb[0] == maxc)
|
||||
{
|
||||
hls[0] = bc - gc;
|
||||
}
|
||||
else if (rgb[1] == maxc)
|
||||
{
|
||||
hls[0] = 2.0f + rc - bc;
|
||||
}
|
||||
else
|
||||
{
|
||||
hls[0] = 4.0f + gc - rc;
|
||||
}
|
||||
hls[0] = (hls[0] / 6.0f) % 1.0f;
|
||||
return hls;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否属于暗色
|
||||
/// </summary>
|
||||
/// <param name="integer"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsDark(int integer)
|
||||
{
|
||||
if (integer == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
float[] hls = Int2hls(integer);
|
||||
float hue = hls[0];
|
||||
float lightness = hls[1];
|
||||
|
||||
// HSL 色轮见
|
||||
// http://zh.wikipedia.org/zh-cn/HSL和HSV色彩空间
|
||||
// 以下的数值都是我的主观判断认为是暗色
|
||||
if ((hue > 30 && hue < 210) && lightness < 33)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ((hue < 30 || hue > 210) && lightness < 66)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
// 注释掉未使用的属性
|
||||
namespace Core.entity
|
||||
{
|
||||
// https://api.bilibili.com/pgc/review/user?media_id=28228367
|
||||
class BangumiMedia
|
||||
{
|
||||
//public int code { get; set; }
|
||||
//public string message { get; set; }
|
||||
public BangumiMediaData result { get; set; }
|
||||
}
|
||||
|
||||
public class BangumiMediaData
|
||||
{
|
||||
public BangumiMediaDataMedia media { get; set; }
|
||||
//public BangumiMediaDataReview review { get; set; }
|
||||
}
|
||||
|
||||
public class BangumiMediaDataMedia
|
||||
{
|
||||
// TODO 暂时只实现部分字段
|
||||
//public long media_id { get; set; }
|
||||
|
||||
public long season_id { get; set; }
|
||||
//public string share_url { get; set; }
|
||||
//public string title { get; set; }
|
||||
//public string type_name { get; set; }
|
||||
}
|
||||
|
||||
//public class BangumiMediaDataReview
|
||||
//{
|
||||
// public int is_coin { get; set; }
|
||||
// public int is_open { get; set; }
|
||||
//}
|
||||
|
||||
}
|
@ -1,199 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
// 注释掉未使用的属性
|
||||
namespace Core.entity
|
||||
{
|
||||
//https://api.bilibili.com/pgc/view/web/season?season_id=28324
|
||||
public class BangumiSeason
|
||||
{
|
||||
//public int code { get; set; }
|
||||
//public string message { get; set; }
|
||||
public BangumiSeasonResult result { get; set; }
|
||||
}
|
||||
|
||||
public class BangumiSeasonResult
|
||||
{
|
||||
//public BangumiSeasonResultActivity activity { get; set; }
|
||||
//public string alias { get; set; }
|
||||
//public string bkg_cover { get; set; }
|
||||
public string cover { get; set; }
|
||||
public List<BangumiSeasonResultEpisodes> episodes { get; set; }
|
||||
public string evaluate { get; set; }
|
||||
//public string jp_title { get; set; }
|
||||
//public string link { get; set; }
|
||||
//public long media_id { get; set; }
|
||||
//public int mode { get; set; }
|
||||
//public BangumiSeasonResultNewEp new_ep { get; set; }
|
||||
//public BangumiSeasonResultPositive positive { get; set; }
|
||||
//public BangumiSeasonResultPublish publish { get; set; }
|
||||
//public BangumiSeasonResultRating rating { get; set; }
|
||||
//public string record { get; set; }
|
||||
//public BangumiSeasonResultRights rights { get; set; }
|
||||
//public long season_id { get; set; }
|
||||
//public string season_title { get; set; }
|
||||
//public List<BangumiSeasonResultSeasons> seasons { get; set; }
|
||||
//public BangumiSeasonResultSeries series { get; set; }
|
||||
//public string share_copy { get; set; }
|
||||
//public string share_sub_title { get; set; }
|
||||
//public string share_url { get; set; }
|
||||
//public BangumiSeasonResultShow show { get; set; }
|
||||
//public string square_cover { get; set; }
|
||||
public BangumiSeasonResultStat stat { get; set; }
|
||||
//public int status { get; set; }
|
||||
//public string subtitle { get; set; }
|
||||
public string title { get; set; }
|
||||
//public int total { get; set; }
|
||||
public int type { get; set; }
|
||||
}
|
||||
|
||||
//public class BangumiSeasonResultActivity
|
||||
//{
|
||||
// public string head_bg_url { get; set; }
|
||||
// public long id { get; set; }
|
||||
// public string title { get; set; }
|
||||
//}
|
||||
|
||||
public class BangumiSeasonResultEpisodes
|
||||
{
|
||||
public long aid { get; set; }
|
||||
//public string badge { get; set; }
|
||||
//public BangumiSeasonResultBadgeInfo badge_info { get; set; }
|
||||
//public int badge_type { get; set; }
|
||||
public string bvid { get; set; }
|
||||
public long cid { get; set; }
|
||||
//public string cover { get; set; }
|
||||
public BangumiSeasonResultEpisodesDimension dimension { get; set; }
|
||||
//public string from { get; set; }
|
||||
//public long id { get; set; }
|
||||
//public string link { get; set; }
|
||||
//public string long_title { get; set; }
|
||||
//public long pub_time { get; set; }
|
||||
//public string release_date { get; set; }
|
||||
//public BangumiSeasonResultEpisodesRights rights { get; set; }
|
||||
public string share_copy { get; set; }
|
||||
//public string share_url { get; set; }
|
||||
//public string short_link { get; set; }
|
||||
//public int status { get; set; }
|
||||
//public string subtitle { get; set; }
|
||||
public string title { get; set; }
|
||||
//public string vid { get; set; }
|
||||
}
|
||||
|
||||
//public class BangumiSeasonResultBadgeInfo
|
||||
//{
|
||||
// public string bg_color { get; set; }
|
||||
// public string bg_color_night { get; set; }
|
||||
// public string text { get; set; }
|
||||
//}
|
||||
|
||||
public class BangumiSeasonResultEpisodesDimension
|
||||
{
|
||||
public int width { get; set; }
|
||||
public int height { get; set; }
|
||||
//public int rotate { get; set; }
|
||||
}
|
||||
|
||||
//public class BangumiSeasonResultEpisodesRights
|
||||
//{
|
||||
// public int allow_dm { get; set; }
|
||||
//}
|
||||
|
||||
//public class BangumiSeasonResultNewEp
|
||||
//{
|
||||
// public string desc { get; set; }
|
||||
// public long id { get; set; }
|
||||
// public int is_new { get; set; }
|
||||
// public string title { get; set; }
|
||||
//}
|
||||
|
||||
//public class BangumiSeasonResultPositive
|
||||
//{
|
||||
// public long id { get; set; }
|
||||
// public string title { get; set; }
|
||||
//}
|
||||
|
||||
//public class BangumiSeasonResultPublish
|
||||
//{
|
||||
// public int is_finish { get; set; }
|
||||
// public int is_started { get; set; }
|
||||
// public string pub_time { get; set; }
|
||||
// public string pub_time_show { get; set; }
|
||||
// public int unknow_pub_date { get; set; }
|
||||
// public int weekday { get; set; }
|
||||
//}
|
||||
|
||||
//public class BangumiSeasonResultRating
|
||||
//{
|
||||
// public long count { get; set; }
|
||||
// public float score { get; set; }
|
||||
//}
|
||||
|
||||
//public class BangumiSeasonResultRights
|
||||
//{
|
||||
// public int allow_bp { get; set; }
|
||||
// public int allow_bp_rank { get; set; }
|
||||
// public int allow_download { get; set; }
|
||||
// public int allow_review { get; set; }
|
||||
// public int area_limit { get; set; }
|
||||
// public int ban_area_show { get; set; }
|
||||
// public int can_watch { get; set; }
|
||||
// public string copyright { get; set; }
|
||||
// public int forbid_pre { get; set; }
|
||||
// public int is_cover_show { get; set; }
|
||||
// public int is_preview { get; set; }
|
||||
// public int only_vip_download { get; set; }
|
||||
// public string resource { get; set; }
|
||||
// public int watch_platform { get; set; }
|
||||
//}
|
||||
|
||||
//public class BangumiSeasonResultSeasons
|
||||
//{
|
||||
// public string badge { get; set; }
|
||||
// public BangumiSeasonResultBadgeInfo badge_info { get; set; }
|
||||
// public int badge_type { get; set; }
|
||||
// public string cover { get; set; }
|
||||
// public long media_id { get; set; }
|
||||
// public BangumiSeasonResultSeasonsNewEp new_ep { get; set; }
|
||||
// public long season_id { get; set; }
|
||||
// public string season_title { get; set; }
|
||||
// public int season_type { get; set; }
|
||||
// public BangumiSeasonResultSeasonsStat stat { get; set; }
|
||||
//}
|
||||
|
||||
//public class BangumiSeasonResultSeasonsNewEp
|
||||
//{
|
||||
// public string cover { get; set; }
|
||||
// public long id { get; set; }
|
||||
// public string index_show { get; set; }
|
||||
//}
|
||||
|
||||
//public class BangumiSeasonResultSeasonsStat
|
||||
//{
|
||||
// public long favorites { get; set; }
|
||||
// public long series_follow { get; set; }
|
||||
// public long views { get; set; }
|
||||
//}
|
||||
|
||||
//public class BangumiSeasonResultSeries
|
||||
//{
|
||||
// public long series_id { get; set; }
|
||||
// public string series_title { get; set; }
|
||||
//}
|
||||
|
||||
//public class BangumiSeasonResultShow
|
||||
//{
|
||||
// public int wide_screen { get; set; }
|
||||
//}
|
||||
|
||||
public class BangumiSeasonResultStat
|
||||
{
|
||||
public long coins { get; set; }
|
||||
public long danmakus { get; set; }
|
||||
public long favorites { get; set; }
|
||||
public long likes { get; set; }
|
||||
public long reply { get; set; }
|
||||
public long share { get; set; }
|
||||
public long views { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity
|
||||
{
|
||||
// https://api.bilibili.com/pugv/view/web/ep/list?season_id=112&pn=1
|
||||
public class CheeseList
|
||||
{
|
||||
public int code { get; set; }
|
||||
public CheeseListData data { get; set; }
|
||||
public string message { get; set; }
|
||||
}
|
||||
|
||||
public class CheeseListData
|
||||
{
|
||||
public List<CheeseListDataItem> items { get; set; }
|
||||
public CheeseListDataPage page { get; set; }
|
||||
}
|
||||
|
||||
public class CheeseListDataItem
|
||||
{
|
||||
public long aid { get; set; }
|
||||
public long cid { get; set; }
|
||||
public long duration { get; set; }
|
||||
public string from { get; set; }
|
||||
public long id { get; set; } // ep_id
|
||||
public int index { get; set; }
|
||||
public int page { get; set; }
|
||||
public long play { get; set; }
|
||||
public long release_date { get; set; }
|
||||
public int status { get; set; }
|
||||
public string title { get; set; }
|
||||
public bool watched { get; set; }
|
||||
public int watchedHistory { get; set; }
|
||||
}
|
||||
|
||||
public class CheeseListDataPage
|
||||
{
|
||||
public bool next { get; set; } // 是否还有下一页
|
||||
public int num { get; set; } // 当前页
|
||||
public int size { get; set; } // list大小
|
||||
public int total { get; set; } // 总的视频数量
|
||||
}
|
||||
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity
|
||||
{
|
||||
// https://api.bilibili.com/pugv/view/web/season?ep_id=2126
|
||||
class CheeseSeason
|
||||
{
|
||||
//public int code { get; set; }
|
||||
public CheeseSeasonData data { get; set; }
|
||||
//public string message { get; set; }
|
||||
}
|
||||
|
||||
public class CheeseSeasonData
|
||||
{
|
||||
|
||||
public string cover { get; set; }
|
||||
|
||||
public List<CheeseSeasonDataEpisode> episodes { get; set; }
|
||||
|
||||
public long season_id { get; set; }
|
||||
|
||||
public CheeseSeasonDataStat stat { get; set; }
|
||||
|
||||
public string subtitle { get; set; }
|
||||
public string title { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class CheeseSeasonDataEpisode
|
||||
{
|
||||
public long aid { get; set; }
|
||||
public long cid { get; set; }
|
||||
public long duration { get; set; }
|
||||
public string from { get; set; }
|
||||
public long id { get; set; } // ep_id
|
||||
public int index { get; set; }
|
||||
public int page { get; set; }
|
||||
public long play { get; set; }
|
||||
public long release_date { get; set; }
|
||||
public int status { get; set; }
|
||||
public string title { get; set; }
|
||||
public bool watched { get; set; }
|
||||
public int watchedHistory { get; set; }
|
||||
}
|
||||
|
||||
public class CheeseSeasonDataStat
|
||||
{
|
||||
public long play { get; set; }
|
||||
public string play_desc { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
// 注释掉未使用的属性
|
||||
namespace Core.entity
|
||||
{
|
||||
|
||||
public class DanmuDate
|
||||
{
|
||||
//{"code":0,"message":"0","ttl":1,"data":["2020-07-01","2020-07-02","2020-07-03","2020-07-04","2020-07-05","2020-07-06","2020-07-07","2020-07-08"]}
|
||||
//public int code { get; set; }
|
||||
//public string message { get; set; }
|
||||
//public int ttl { get; set; }
|
||||
public List<string> data { get; set; }
|
||||
}
|
||||
|
||||
public class DanmuFromWeb
|
||||
{
|
||||
//public int code { get; set; }
|
||||
public string message { get; set; }
|
||||
//public int ttl { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity
|
||||
{
|
||||
/// <summary>
|
||||
/// https://api.bilibili.com/x/v3/fav/folder/created/list?pn=1&ps=10&up_mid=42018135
|
||||
/// https://api.bilibili.com/x/v3/fav/folder/collected/list?pn=1&ps=20&up_mid=42018135
|
||||
/// 上述两个网址都使用同一个class解析
|
||||
/// </summary>
|
||||
public class FavFolder
|
||||
{
|
||||
//public int code { get; set; }
|
||||
public FavFolderData data { get; set; }
|
||||
//public string message { get; set; }
|
||||
//public int ttl { get; set; }
|
||||
}
|
||||
|
||||
public class FavFolderData
|
||||
{
|
||||
public int count { get; set; }
|
||||
public List<FavFolderDataList> list { get; set; }
|
||||
}
|
||||
|
||||
public class FavFolderDataList
|
||||
{
|
||||
public int attr { get; set; }
|
||||
public string cover { get; set; }
|
||||
public int cover_type { get; set; }
|
||||
public long ctime { get; set; }
|
||||
public int fav_state { get; set; }
|
||||
public long fid { get; set; }
|
||||
public long id { get; set; }
|
||||
public string intro { get; set; }
|
||||
public int media_count { get; set; }
|
||||
public long mid { get; set; }
|
||||
public long mtime { get; set; }
|
||||
public int state { get; set; }
|
||||
public string title { get; set; }
|
||||
public FavFolderDataUpper upper { get; set; }
|
||||
}
|
||||
|
||||
public class FavFolderDataUpper
|
||||
{
|
||||
public string face { get; set; }
|
||||
public long mid { get; set; }
|
||||
public string name { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity
|
||||
{
|
||||
// https://api.bilibili.com/x/v3/fav/resource/list?media_id=94341835&pn=1&ps=20
|
||||
public class FavResource
|
||||
{
|
||||
//public int code { get; set; }
|
||||
public FavResourceData data { get; set; }
|
||||
//public string message { get; set; }
|
||||
//public int ttl { get; set; }
|
||||
}
|
||||
|
||||
public class FavResourceData
|
||||
{
|
||||
//public FavResourceDataInfo info{get;set;}
|
||||
public List<FavResourceDataMedia> medias { get; set; }
|
||||
}
|
||||
|
||||
public class FavResourceDataMedia
|
||||
{
|
||||
public int attr { get; set; }
|
||||
public string bv_id { get; set; }
|
||||
public string bvid { get; set; }
|
||||
public FavResourceDataMediaCnt_info cnt_info { get; set; }
|
||||
public string cover { get; set; }
|
||||
public long ctime { get; set; }
|
||||
public long duration { get; set; }
|
||||
public long fav_time { get; set; }
|
||||
public long id { get; set; }
|
||||
public string intro { get; set; }
|
||||
public string link { get; set; }
|
||||
public int page { get; set; }
|
||||
public long pubtime { get; set; }
|
||||
public string title { get; set; }
|
||||
public int type { get; set; }
|
||||
public FavResourceDataMediaUpper upper { get; set; }
|
||||
}
|
||||
|
||||
public class FavResourceDataMediaCnt_info
|
||||
{
|
||||
public long collect { get; set; }
|
||||
public long danmaku { get; set; }
|
||||
public long play { get; set; }
|
||||
}
|
||||
|
||||
public class FavResourceDataMediaUpper
|
||||
{
|
||||
public string face { get; set; }
|
||||
public long mid { get; set; }
|
||||
public string name { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
// 注释掉未使用的属性
|
||||
namespace Core.entity
|
||||
{
|
||||
public class LoginUrl
|
||||
{
|
||||
//public int code { get; set; }
|
||||
public LoginData data { get; set; }
|
||||
public bool status { get; set; }
|
||||
//public long ts { get; set; }
|
||||
}
|
||||
|
||||
public class LoginData
|
||||
{
|
||||
public string oauthKey { get; set; }
|
||||
public string url { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class LoginInfo
|
||||
{
|
||||
public int code { get; set; }
|
||||
public bool status { get; set; }
|
||||
public string message { get; set; }
|
||||
public string url { get; set; }
|
||||
}
|
||||
|
||||
public class LoginInfoScanning
|
||||
{
|
||||
public bool status { get; set; }
|
||||
public int data { get; set; }
|
||||
public string message { get; set; }
|
||||
}
|
||||
|
||||
public class LoginInfoReady
|
||||
{
|
||||
// {"code":0,"status":true,"ts":1594131179,"data":{"url":"https://passport.biligame.com/crossDomain?DedeUserID=42018135&DedeUserID__ckMd5=44e22fa30fe34ac4&Expires=15551000&SESSDATA=92334e44%2C1609683179%2C54db1%2A71&bili_jct=979b94fb3879c68574f02800d8a39484&gourl=https%3A%2F%2Fwww.bilibili.com"}}
|
||||
|
||||
public int code { get; set; }
|
||||
public bool status { get; set; }
|
||||
|
||||
//public long ts { get; set; }
|
||||
public LoginInfoData data { get; set; }
|
||||
}
|
||||
|
||||
public class LoginInfoData
|
||||
{
|
||||
public string url { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
namespace Core.entity
|
||||
{
|
||||
// https://api.bilibili.com/x/space/myinfo
|
||||
public class MyInfo
|
||||
{
|
||||
//public int code { get; set; }
|
||||
public MyInfoData data { get; set; }
|
||||
public string message { get; set; }
|
||||
//public int ttl { get; set; }
|
||||
}
|
||||
|
||||
public class MyInfoData
|
||||
{
|
||||
public long birthday { get; set; }
|
||||
public float coins { get; set; }
|
||||
public int email_status { get; set; }
|
||||
public string face { get; set; }
|
||||
public int follower { get; set; }
|
||||
public int following { get; set; }
|
||||
public int identification { get; set; }
|
||||
public int is_deleted { get; set; }
|
||||
public int is_fake_account { get; set; }
|
||||
public int is_tourist { get; set; }
|
||||
public int jointime { get; set; }
|
||||
public int level { get; set; }
|
||||
public MyInfoDataLevelExp level_exp { get; set; }
|
||||
public long mid { get; set; }
|
||||
public int moral { get; set; }
|
||||
public string name { get; set; }
|
||||
public MyInfoDataNamePlate nameplate { get; set; }
|
||||
public MyInfoDataOfficial official { get; set; }
|
||||
public MyInfoDataPendant pendant { get; set; }
|
||||
public int pin_prompting { get; set; }
|
||||
public int rank { get; set; }
|
||||
public string sex { get; set; }
|
||||
public string sign { get; set; }
|
||||
public int silence { get; set; }
|
||||
public int tel_status { get; set; }
|
||||
public MyInfoDataVip vip { get; set; }
|
||||
}
|
||||
|
||||
public class MyInfoDataLevelExp
|
||||
{
|
||||
public int current_exp { get; set; }
|
||||
public int current_level { get; set; }
|
||||
public int current_min { get; set; }
|
||||
public int next_exp { get; set; }
|
||||
}
|
||||
|
||||
public class MyInfoDataNamePlate
|
||||
{
|
||||
public string condition { get; set; }
|
||||
public string image { get; set; }
|
||||
public string image_small { get; set; }
|
||||
public string level { get; set; }
|
||||
public string name { get; set; }
|
||||
public int nid { get; set; }
|
||||
}
|
||||
|
||||
public class MyInfoDataOfficial
|
||||
{
|
||||
public string desc { get; set; }
|
||||
public int role { get; set; }
|
||||
public string title { get; set; }
|
||||
public int type { get; set; }
|
||||
}
|
||||
|
||||
public class MyInfoDataPendant
|
||||
{
|
||||
public int expire { get; set; }
|
||||
public string image { get; set; }
|
||||
public string image_enhance { get; set; }
|
||||
public string name { get; set; }
|
||||
public int pid { get; set; }
|
||||
}
|
||||
|
||||
public class MyInfoDataVip
|
||||
{
|
||||
public int avatar_subscript { get; set; }
|
||||
public long due_date { get; set; }
|
||||
public MyInfoDataVipLabel label { get; set; }
|
||||
public string nickname_color { get; set; }
|
||||
public int status { get; set; }
|
||||
public int theme_type { get; set; }
|
||||
public int type { get; set; }
|
||||
public int vip_pay_type { get; set; }
|
||||
}
|
||||
|
||||
public class MyInfoDataVipLabel
|
||||
{
|
||||
public string label_theme { get; set; }
|
||||
public string path { get; set; }
|
||||
public string text { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
// 注释掉未使用的属性
|
||||
namespace Core.entity
|
||||
{
|
||||
public class Nav
|
||||
{
|
||||
//public int code { get; set; }
|
||||
public NavData data { get; set; }
|
||||
public string message { get; set; }
|
||||
//public int ttl { get; set; }
|
||||
}
|
||||
|
||||
public class NavData
|
||||
{
|
||||
//public int allowance_count { get; set; }
|
||||
//public int answer_status { get; set; }
|
||||
//public int email_verified { get; set; }
|
||||
public string face { get; set; }
|
||||
//public bool has_shop { get; set; }
|
||||
public bool isLogin { get; set; }
|
||||
//public NavDataLevelInfo level_info { get; set; }
|
||||
public long mid { get; set; }
|
||||
//public int mobile_verified { get; set; }
|
||||
public float money { get; set; }
|
||||
//public int moral { get; set; }
|
||||
//public NavDataOfficial official { get; set; }
|
||||
//public NavDataOfficialVerify officialVerify { get; set; }
|
||||
//public NavDataPendant pendant { get; set; }
|
||||
//public int scores { get; set; }
|
||||
//public string shop_url { get; set; }
|
||||
public string uname { get; set; }
|
||||
//public long vipDueDate { get; set; }
|
||||
public int vipStatus { get; set; }
|
||||
//public int vipType { get; set; }
|
||||
//public int vip_avatar_subscript { get; set; }
|
||||
//public NavDataVipLabel vip_label { get; set; }
|
||||
//public string vip_nickname_color { get; set; }
|
||||
//public int vip_pay_type { get; set; }
|
||||
//public int vip_theme_type { get; set; }
|
||||
public NavDataWallet wallet { get; set; }
|
||||
}
|
||||
|
||||
public class NavDataLevelInfo
|
||||
{
|
||||
public int current_exp { get; set; }
|
||||
public int current_level { get; set; }
|
||||
public int current_min { get; set; }
|
||||
//public int next_exp { get; set; } // 当等级为6时,next_exp为string类型,值为"--"
|
||||
}
|
||||
|
||||
//public class NavDataOfficial
|
||||
//{
|
||||
// public string desc { get; set; }
|
||||
// public int role { get; set; }
|
||||
// public string title { get; set; }
|
||||
// public int type { get; set; }
|
||||
//}
|
||||
|
||||
//public class NavDataOfficialVerify
|
||||
//{
|
||||
// public string desc { get; set; }
|
||||
// public int type { get; set; }
|
||||
//}
|
||||
|
||||
//public class NavDataPendant
|
||||
//{
|
||||
// public int expire { get; set; }
|
||||
// public string image { get; set; }
|
||||
// public string image_enhance { get; set; }
|
||||
// public string name { get; set; }
|
||||
// public int pid { get; set; }
|
||||
//}
|
||||
|
||||
//public class NavDataVipLabel
|
||||
//{
|
||||
// public string label_theme { get; set; }
|
||||
// public string path { get; set; }
|
||||
// public string text { get; set; }
|
||||
//}
|
||||
|
||||
public class NavDataWallet
|
||||
{
|
||||
public float bcoin_balance { get; set; }
|
||||
public float coupon_balance { get; set; }
|
||||
public long coupon_due_time { get; set; }
|
||||
public long mid { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
// 注释掉未使用的属性
|
||||
namespace Core.entity
|
||||
{
|
||||
public class PlayUrl
|
||||
{
|
||||
//public int code { get; set; }
|
||||
public PlayUrlData data { get; set; }
|
||||
public PlayUrlData result { get; set; }
|
||||
//public string message { get; set; }
|
||||
//public int ttl { get; set; }
|
||||
}
|
||||
|
||||
public class PlayUrlData
|
||||
{
|
||||
public List<string> accept_description { get; set; }
|
||||
//public string accept_format { get; set; }
|
||||
public List<int> accept_quality { get; set; }
|
||||
public PlayUrlDataDash dash { get; set; }
|
||||
//public string format { get; set; }
|
||||
//public string from { get; set; }
|
||||
//public string message { get; set; }
|
||||
public int quality { get; set; }
|
||||
//public string result { get; set; }
|
||||
//public string seek_param { get; set; }
|
||||
//public string seek_type { get; set; }
|
||||
//public string timelength { get; set; }
|
||||
//public int video_codecid { get; set; }
|
||||
|
||||
public List<PlayUrlDUrl> durl { get; set; }
|
||||
}
|
||||
|
||||
public class PlayUrlDataDash
|
||||
{
|
||||
public List<PlayUrlDataDashVideo> audio { get; set; }
|
||||
public long duration { get; set; }
|
||||
//public float minBufferTime { get; set; }
|
||||
//public float min_buffer_time { get; set; }
|
||||
public List<PlayUrlDataDashVideo> video { get; set; }
|
||||
}
|
||||
|
||||
public class PlayUrlDataDashVideo
|
||||
{
|
||||
//public PlayUrlDataDashSegmentBaseCls SegmentBase { get; set; }
|
||||
public List<string> backupUrl { get; set; }
|
||||
public List<string> backup_url { get; set; }
|
||||
//public long bandwidth { get; set; }
|
||||
public string baseUrl { get; set; }
|
||||
public string base_url { get; set; }
|
||||
//public int codecid { get; set; }
|
||||
public string codecs { get; set; }
|
||||
public string frameRate { get; set; }
|
||||
//public string frame_rate { get; set; }
|
||||
public int height { get; set; }
|
||||
public int id { get; set; }
|
||||
public string mimeType { get; set; }
|
||||
//public string mime_type { get; set; }
|
||||
//public string sar { get; set; }
|
||||
//public PlayUrlDataDashSegmentBaseCls2 segment_base { get; set; }
|
||||
//public int startWithSap { get; set; }
|
||||
//public int start_with_sap { get; set; }
|
||||
public int width { get; set; }
|
||||
}
|
||||
|
||||
//public class PlayUrlDataDashSegmentBaseCls
|
||||
//{
|
||||
// public string Initialization { get; set; }
|
||||
// public string indexRange { get; set; }
|
||||
//}
|
||||
|
||||
//public class PlayUrlDataDashSegmentBaseCls2
|
||||
//{
|
||||
// public string initialization { get; set; }
|
||||
// public string index_range { get; set; }
|
||||
//}
|
||||
|
||||
public class PlayUrlDUrl
|
||||
{
|
||||
//public int order { get; set; }
|
||||
public long length { get; set; }
|
||||
public long size { get; set; }
|
||||
//public string ahead { get; set; }
|
||||
//public string vhead { get; set; }
|
||||
public string url { get; set; }
|
||||
public List<string> backup_url { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
namespace Core.entity
|
||||
{
|
||||
// https://api.bilibili.com/x/relation/stat?vmid=42018135
|
||||
public class Stat
|
||||
{
|
||||
//public int code { get; set; }
|
||||
public StatData data { get; set; }
|
||||
//public string message { get; set; }
|
||||
//public int ttl { get; set; }
|
||||
}
|
||||
|
||||
public class StatData
|
||||
{
|
||||
public int black { get; set; } // 黑名单
|
||||
public int follower { get; set; } // 粉丝数
|
||||
public int following { get; set; } // 关注数
|
||||
public long mid { get; set; } // 用户id
|
||||
public int whisper { get; set; } // 悄悄关注数
|
||||
}
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
namespace Core.entity
|
||||
{
|
||||
// https://space.bilibili.com/ajax/settings/getSettings?mid=42018135
|
||||
public class UserSettings
|
||||
{
|
||||
public UserSettingsData data { get; set; }
|
||||
public bool status { get; set; }
|
||||
}
|
||||
|
||||
public class UserSettingsData
|
||||
{
|
||||
// ……
|
||||
|
||||
public UserSettingsDataToutu toutu { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class UserSettingsDataToutu
|
||||
{
|
||||
public string android_img { get; set; }
|
||||
public long expire { get; set; }
|
||||
public string ipad_img { get; set; }
|
||||
public string iphone_img { get; set; }
|
||||
public string l_img { get; set; }
|
||||
public int platform { get; set; }
|
||||
public string s_img { get; set; }
|
||||
public int sid { get; set; }
|
||||
public string thumbnail_img { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
namespace Core.entity
|
||||
{
|
||||
// https://api.bilibili.com/x/web-interface/view/detail?bvid=BV1TJ411h7E6
|
||||
public class VideoDetail
|
||||
{
|
||||
//public int code { get; set; }
|
||||
public VideoDetailData data { get; set; }
|
||||
//public string message { get; set; }
|
||||
//public int ttl { get; set; }
|
||||
}
|
||||
|
||||
public class VideoDetailData
|
||||
{
|
||||
//public VideoDetailDataCard Card { get; set; }
|
||||
//public VideoDetailDataRelated Related { get; set; }
|
||||
//public VideoDetailDataReply Reply { get; set; }
|
||||
//public VideoDetailDataTags Tags { get; set; }
|
||||
public VideoDetailDataView View { get; set; }
|
||||
}
|
||||
|
||||
public class VideoDetailDataView
|
||||
{
|
||||
// ...
|
||||
public string redirect_url { get; set; }
|
||||
// ...
|
||||
}
|
||||
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
// 注释掉未使用的属性
|
||||
namespace Core.entity
|
||||
{
|
||||
public class VideoView
|
||||
{
|
||||
public int code { get; set; }
|
||||
public VideoViewData data { get; set; }
|
||||
public string message { get; set; }
|
||||
public int ttl { get; set; }
|
||||
}
|
||||
|
||||
public class VideoViewData
|
||||
{
|
||||
public long aid { get; set; }
|
||||
//public long attribute { get; set; }
|
||||
public string bvid { get; set; }
|
||||
//public long cid { get; set; }
|
||||
//public int copyright { get; set; }
|
||||
public long ctime { get; set; }
|
||||
public string desc { get; set; }
|
||||
//public VideoViewDataDimension dimension { get; set; }
|
||||
//public long duration { get; set; }
|
||||
//public string dynamic { get; set; }
|
||||
//public VideoViewDataLabel label { get; set; }
|
||||
//public long mission_id { get; set; }
|
||||
//public bool no_cache { get; set; }
|
||||
public VideoViewDataOwner owner { get; set; }
|
||||
public List<VideoViewDataPages> pages { get; set; }
|
||||
public string pic { get; set; }
|
||||
public long pubdate { get; set; }
|
||||
//public VideoViewDataRights rights { get; set; }
|
||||
//public long season_id { get; set; }
|
||||
public VideoViewDataStat stat { get; set; }
|
||||
//public int state { get; set; }
|
||||
//public VideoViewDataSubtitle subtitle { get; set; }
|
||||
public long tid { get; set; }
|
||||
public string title { get; set; }
|
||||
public string tname { get; set; }
|
||||
//public VideoViewDataUgcSeason ugc_season { get; set; }
|
||||
//public int videos { get; set; }
|
||||
}
|
||||
|
||||
public class VideoViewDataDimension
|
||||
{
|
||||
public int width { get; set; }
|
||||
public int height { get; set; }
|
||||
//public int rotate { get; set; }
|
||||
}
|
||||
|
||||
//public class VideoViewDataLabel
|
||||
//{
|
||||
// public int type { get; set; }
|
||||
//}
|
||||
|
||||
public class VideoViewDataOwner
|
||||
{
|
||||
public string face { get; set; }
|
||||
public long mid { get; set; }
|
||||
public string name { get; set; }
|
||||
}
|
||||
|
||||
public class VideoViewDataPages
|
||||
{
|
||||
public long cid { get; set; }
|
||||
public VideoViewDataDimension dimension { get; set; }
|
||||
public long duration { get; set; }
|
||||
//public string from { get; set; }
|
||||
public int page { get; set; }
|
||||
public string part { get; set; }
|
||||
//public string vid { get; set; }
|
||||
//public string weblink { get; set; }
|
||||
}
|
||||
|
||||
//public class VideoViewDataRights
|
||||
//{
|
||||
// public int autoplay { get; set; }
|
||||
// public int bp { get; set; }
|
||||
// public int download { get; set; }
|
||||
// public int elec { get; set; }
|
||||
// public int hd5 { get; set; }
|
||||
// public int is_cooperation { get; set; }
|
||||
// public int movie { get; set; }
|
||||
// public int no_background { get; set; }
|
||||
// public int no_reprint { get; set; }
|
||||
// public int pay { get; set; }
|
||||
// public int ugc_pay { get; set; }
|
||||
// public int ugc_pay_preview { get; set; }
|
||||
//}
|
||||
|
||||
public class VideoViewDataStat
|
||||
{
|
||||
public long aid { get; set; }
|
||||
public long coin { get; set; }
|
||||
public long danmaku { get; set; }
|
||||
public long dislike { get; set; }
|
||||
public string evaluation { get; set; }
|
||||
public long favorite { get; set; }
|
||||
public long his_rank { get; set; }
|
||||
public long like { get; set; }
|
||||
public long now_rank { get; set; }
|
||||
public long reply { get; set; }
|
||||
public long share { get; set; }
|
||||
public long view { get; set; }
|
||||
}
|
||||
|
||||
//public class VideoViewDataSubtitle
|
||||
//{
|
||||
// public bool allow_submit { get; set; }
|
||||
// //public List<string> list { get; set; }
|
||||
//}
|
||||
|
||||
//public class VideoViewDataUgcSeason
|
||||
//{
|
||||
// public int attribute { get; set; }
|
||||
// public string cover { get; set; }
|
||||
// public int ep_count { get; set; }
|
||||
// public long id { get; set; }
|
||||
// public string intro { get; set; }
|
||||
// public long mid { get; set; }
|
||||
// public List<VideoViewDataUgcSeasonSections> sections { get; set; }
|
||||
// public int sign_state { get; set; }
|
||||
// public VideoViewDataStat stat { get; set; }
|
||||
// public string title { get; set; }
|
||||
//}
|
||||
|
||||
//public class VideoViewDataUgcSeasonSections
|
||||
//{
|
||||
// public List<VideoViewDataUgcSeasonSectionsEpisodes> episodes { get; set; }
|
||||
// public long id { get; set; }
|
||||
// public long season_id { get; set; }
|
||||
// public string title { get; set; }
|
||||
// public int type { get; set; }
|
||||
//}
|
||||
|
||||
//public class VideoViewDataUgcSeasonStat
|
||||
//{
|
||||
// public long coin { get; set; }
|
||||
// public long danmaku { get; set; }
|
||||
// public long favorite { get; set; }
|
||||
// public long his_rank { get; set; }
|
||||
// public long like { get; set; }
|
||||
// public long now_rank { get; set; }
|
||||
// public long reply { get; set; }
|
||||
// public long season_id { get; set; }
|
||||
// public long share { get; set; }
|
||||
// public long view { get; set; }
|
||||
//}
|
||||
|
||||
//public class VideoViewDataUgcSeasonSectionsEpisodes
|
||||
//{
|
||||
// public long aid { get; set; }
|
||||
// public VideoViewDataUgcSeasonSectionsEpisodesArc arc { get; set; }
|
||||
// public int attribute { get; set; }
|
||||
// public long cid { get; set; }
|
||||
// public long id { get; set; }
|
||||
// public VideoViewDataUgcSeasonSectionsEpisodesPage page { get; set; }
|
||||
// public long season_id { get; set; }
|
||||
// public long section_id { get; set; }
|
||||
// public string title { get; set; }
|
||||
//}
|
||||
|
||||
//public class VideoViewDataUgcSeasonSectionsEpisodesArc
|
||||
//{
|
||||
// public long aid { get; set; }
|
||||
// public int copyright { get; set; }
|
||||
// public long ctime { get; set; }
|
||||
// public string desc { get; set; }
|
||||
// public VideoViewDataDimension dimension { get; set; }
|
||||
// public long duration { get; set; }
|
||||
// public string dynamic { get; set; }
|
||||
// public VideoViewDataOwner owner { get; set; }
|
||||
// public string pic { get; set; }
|
||||
// public long pubdate { get; set; }
|
||||
// public VideoViewDataRights rights { get; set; }
|
||||
// public VideoViewDataStat stat { get; set; }
|
||||
// public int state { get; set; }
|
||||
// public long tid { get; set; }
|
||||
// public string title { get; set; }
|
||||
// public string tname { get; set; }
|
||||
// public int videos { get; set; }
|
||||
//}
|
||||
|
||||
//public class VideoViewDataUgcSeasonSectionsEpisodesPage
|
||||
//{
|
||||
// public long cid { get; set; }
|
||||
// public VideoViewDataDimension dimension { get; set; }
|
||||
// public long duration { get; set; }
|
||||
// public string from { get; set; }
|
||||
// public int page { get; set; }
|
||||
// public string part { get; set; }
|
||||
// public string vid { get; set; }
|
||||
// public string weblink { get; set; }
|
||||
//}
|
||||
|
||||
|
||||
// https://api.bilibili.com/x/player/pagelist?bvid={bvid}&jsonp=jsonp
|
||||
public class Pagelist
|
||||
{
|
||||
public int code { get; set; }
|
||||
public List<VideoViewDataPages> data { get; set; }
|
||||
public string message { get; set; }
|
||||
public int ttl { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.history
|
||||
{
|
||||
// https://api.bilibili.com/x/web-interface/history/cursor?max={startId}&view_at={startTime}&ps={ps}&business={businessStr}
|
||||
[JsonObject]
|
||||
public class HistoryOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public HistoryData Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class HistoryData : BaseEntity
|
||||
{
|
||||
[JsonProperty("cursor")]
|
||||
public HistoryDataCursor Cursor { get; set; }
|
||||
[JsonProperty("list")]
|
||||
public List<HistoryDataList> List { get; set; }
|
||||
//public List<HistoryDataTab> tab { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class HistoryDataCursor : BaseEntity
|
||||
{
|
||||
[JsonProperty("business")]
|
||||
public string Business { get; set; }
|
||||
[JsonProperty("max")]
|
||||
public long Max { get; set; }
|
||||
[JsonProperty("ps")]
|
||||
public int Ps { get; set; }
|
||||
[JsonProperty("view_at")]
|
||||
public long ViewAt { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class HistoryDataList : BaseEntity
|
||||
{
|
||||
[JsonProperty("author_face")]
|
||||
public string AuthorFace { get; set; }
|
||||
[JsonProperty("author_mid")]
|
||||
public long AuthorMid { get; set; }
|
||||
[JsonProperty("author_name")]
|
||||
public string AuthorName { get; set; }
|
||||
// ...
|
||||
[JsonProperty("cover")]
|
||||
public string Cover { get; set; }
|
||||
// ...
|
||||
[JsonProperty("duration")]
|
||||
public long Duration { get; set; }
|
||||
[JsonProperty("history")]
|
||||
public HistoryDataListHistory History { get; set; }
|
||||
// ...
|
||||
[JsonProperty("new_desc")]
|
||||
public string NewDesc { get; set; }
|
||||
[JsonProperty("progress")]
|
||||
public long Progress { get; set; }
|
||||
[JsonProperty("show_title")]
|
||||
public string ShowTitle { get; set; }
|
||||
[JsonProperty("tag_name")]
|
||||
public string TagName { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
// ...
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
[JsonProperty("videos")]
|
||||
public int Videos { get; set; }
|
||||
[JsonProperty("view_at")]
|
||||
public long ViewAt { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class HistoryDataListHistory : BaseEntity
|
||||
{
|
||||
[JsonProperty("business")]
|
||||
public string Business { get; set; }
|
||||
[JsonProperty("bvid")]
|
||||
public string Bvid { get; set; }
|
||||
[JsonProperty("cid")]
|
||||
public long Cid { get; set; }
|
||||
[JsonProperty("dt")]
|
||||
public int Dt { get; set; }
|
||||
[JsonProperty("epid")]
|
||||
public long Epid { get; set; }
|
||||
[JsonProperty("oid")]
|
||||
public long Oid { get; set; }
|
||||
[JsonProperty("page")]
|
||||
public int Page { get; set; }
|
||||
[JsonProperty("part")]
|
||||
public string Part { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.history
|
||||
{
|
||||
// https://api.bilibili.com/x/v2/history/toview/web
|
||||
[JsonObject]
|
||||
public class ToViewOrigin : BaseEntity
|
||||
{
|
||||
//public int code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public ToViewData Data { get; set; }
|
||||
//public string message { get; set; }
|
||||
//public int ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class ToViewData : BaseEntity
|
||||
{
|
||||
[JsonProperty("count")]
|
||||
public int Count { get; set; }
|
||||
[JsonProperty("list")]
|
||||
public List<ToViewDataList> List { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class ToViewDataList : BaseEntity
|
||||
{
|
||||
[JsonProperty("add_at")]
|
||||
public long AddAt { get; set; }
|
||||
[JsonProperty("aid")]
|
||||
public long Aid { get; set; }
|
||||
//public long attribute { get; set; }
|
||||
[JsonProperty("bvid")]
|
||||
public string Bvid { get; set; }
|
||||
[JsonProperty("cid")]
|
||||
public long Cid { get; set; }
|
||||
// ...
|
||||
[JsonProperty("owner")]
|
||||
public ToViewDataListOwner Owner { get; set; }
|
||||
// ...
|
||||
[JsonProperty("pic")]
|
||||
public string Cover { get; set; }
|
||||
// ...
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class ToViewDataListOwner : BaseEntity
|
||||
{
|
||||
[JsonProperty("face")]
|
||||
public string Face { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/space/bangumi/follow/list?vmid={mid}&type={type}&pn={pn}&ps={ps}
|
||||
[JsonObject]
|
||||
public class BangumiFollowOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public BangumiFollowData Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class BangumiFollowData : BaseEntity
|
||||
{
|
||||
[JsonProperty("list")]
|
||||
public List<BangumiFollow> List { get; set; }
|
||||
[JsonProperty("pn")]
|
||||
public int Pn { get; set; }
|
||||
[JsonProperty("ps")]
|
||||
public int Ps { get; set; }
|
||||
[JsonProperty("total")]
|
||||
public int Total { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class BangumiFollow : BaseEntity
|
||||
{
|
||||
[JsonProperty("areas")]
|
||||
public List<BangumiFollowAreas> Areas { get; set; }
|
||||
[JsonProperty("badge")]
|
||||
public string Badge { get; set; }
|
||||
[JsonProperty("badge_ep")]
|
||||
public string BadgeEp { get; set; }
|
||||
// ...
|
||||
[JsonProperty("cover")]
|
||||
public string Cover { get; set; }
|
||||
[JsonProperty("evaluate")]
|
||||
public string Evaluate { get; set; }
|
||||
// ...
|
||||
[JsonProperty("media_id")]
|
||||
public long MediaId { get; set; }
|
||||
// ...
|
||||
[JsonProperty("new_ep")]
|
||||
public BangumiFollowNewEp NewEp { get; set; }
|
||||
[JsonProperty("progress")]
|
||||
public string Progress { get; set; }
|
||||
// ...
|
||||
[JsonProperty("season_id")]
|
||||
public long SeasonId { get; set; }
|
||||
[JsonProperty("season_status")]
|
||||
public int SeasonStatus { get; set; }
|
||||
[JsonProperty("season_title")]
|
||||
public string SeasonTitle { get; set; }
|
||||
[JsonProperty("season_type")]
|
||||
public int SeasonType { get; set; }
|
||||
[JsonProperty("season_type_name")]
|
||||
public string SeasonTypeName { get; set; }
|
||||
// ...
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
[JsonProperty("total_count")]
|
||||
public int TotalCount { get; set; }
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class BangumiFollowAreas : BaseEntity
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int Id { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class BangumiFollowNewEp : BaseEntity
|
||||
{
|
||||
[JsonProperty("cover")]
|
||||
public string Cover { get; set; }
|
||||
[JsonProperty("duration")]
|
||||
public long Duration { get; set; }
|
||||
[JsonProperty("id")]
|
||||
public long Id { get; set; }
|
||||
[JsonProperty("index_show")]
|
||||
public string IndexShow { get; set; }
|
||||
[JsonProperty("long_title")]
|
||||
public string LongTitle { get; set; }
|
||||
[JsonProperty("pub_time")]
|
||||
public string PubTime { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/relation/tags
|
||||
[JsonObject]
|
||||
public class FollowingGroupOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public List<FollowingGroup> Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class FollowingGroup : BaseEntity
|
||||
{
|
||||
[JsonProperty("count")]
|
||||
public int Count { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("tagid")]
|
||||
public int TagId { get; set; }
|
||||
[JsonProperty("tip")]
|
||||
public string Tip { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/relation/tag?tagid={tagId}&pn={pn}&ps={ps}&order_type={orderType}
|
||||
[JsonObject]
|
||||
public class FollowingGroupContentOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public List<FollowingGroupContent> Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class FollowingGroupContent : BaseEntity
|
||||
{
|
||||
[JsonProperty("attribute")]
|
||||
public int Attribute { get; set; }
|
||||
// ...
|
||||
[JsonProperty("face")]
|
||||
public string Face { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
// ...
|
||||
[JsonProperty("sign")]
|
||||
public string Sign { get; set; }
|
||||
[JsonProperty("special")]
|
||||
public int Special { get; set; }
|
||||
[JsonProperty("tag")]
|
||||
public List<long> Tag { get; set; }
|
||||
[JsonProperty("uname")]
|
||||
public string Name { get; set; }
|
||||
// ...
|
||||
}
|
||||
|
||||
}
|
@ -1,166 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/space/myinfo
|
||||
[JsonObject]
|
||||
public class MyInfoOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public MyInfo Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class MyInfo : BaseEntity
|
||||
{
|
||||
[JsonProperty("birthday")]
|
||||
public long Birthday { get; set; }
|
||||
[JsonProperty("coins")]
|
||||
public float Coins { get; set; }
|
||||
[JsonProperty("email_status")]
|
||||
public int EmailStatus { get; set; }
|
||||
[JsonProperty("face")]
|
||||
public string Face { get; set; }
|
||||
[JsonProperty("follower")]
|
||||
public int Follower { get; set; }
|
||||
[JsonProperty("following")]
|
||||
public int Following { get; set; }
|
||||
[JsonProperty("identification")]
|
||||
public int Identification { get; set; }
|
||||
[JsonProperty("is_deleted")]
|
||||
public int IsDeleted { get; set; }
|
||||
[JsonProperty("is_fake_account")]
|
||||
public int IsFakeAccount { get; set; }
|
||||
[JsonProperty("is_tourist")]
|
||||
public int IsTourist { get; set; }
|
||||
[JsonProperty("jointime")]
|
||||
public int Jointime { get; set; }
|
||||
[JsonProperty("level")]
|
||||
public int Level { get; set; }
|
||||
[JsonProperty("level_exp")]
|
||||
public MyInfoLevelExp LevelExp { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("moral")]
|
||||
public int Moral { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("nameplate")]
|
||||
public MyInfoNamePlate Nameplate { get; set; }
|
||||
[JsonProperty("official")]
|
||||
public MyInfoOfficial Official { get; set; }
|
||||
[JsonProperty("pendant")]
|
||||
public MyInfoPendant Pendant { get; set; }
|
||||
[JsonProperty("pin_prompting")]
|
||||
public int PinPrompting { get; set; }
|
||||
[JsonProperty("rank")]
|
||||
public int Rank { get; set; }
|
||||
[JsonProperty("sex")]
|
||||
public string Sex { get; set; }
|
||||
[JsonProperty("sign")]
|
||||
public string Sign { get; set; }
|
||||
[JsonProperty("silence")]
|
||||
public int Silence { get; set; }
|
||||
[JsonProperty("tel_status")]
|
||||
public int TelStatus { get; set; }
|
||||
[JsonProperty("vip")]
|
||||
public MyInfoVip Vip { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class MyInfoLevelExp : BaseEntity
|
||||
{
|
||||
[JsonProperty("current_exp")]
|
||||
public int CurrentExp { get; set; }
|
||||
[JsonProperty("current_level")]
|
||||
public int CurrentLevel { get; set; }
|
||||
[JsonProperty("current_min")]
|
||||
public int CurrentMin { get; set; }
|
||||
[JsonProperty("next_exp")]
|
||||
public int NextExp { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class MyInfoNamePlate : BaseEntity
|
||||
{
|
||||
[JsonProperty("condition")]
|
||||
public string Condition { get; set; }
|
||||
[JsonProperty("image")]
|
||||
public string Image { get; set; }
|
||||
[JsonProperty("image_small")]
|
||||
public string ImageSmall { get; set; }
|
||||
[JsonProperty("level")]
|
||||
public string Level { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("nid")]
|
||||
public int Nid { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class MyInfoOfficial : BaseEntity
|
||||
{
|
||||
[JsonProperty("desc")]
|
||||
public string Desc { get; set; }
|
||||
[JsonProperty("role")]
|
||||
public int Role { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public int Type { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class MyInfoPendant : BaseEntity
|
||||
{
|
||||
[JsonProperty("expire")]
|
||||
public int Expire { get; set; }
|
||||
[JsonProperty("image")]
|
||||
public string Image { get; set; }
|
||||
[JsonProperty("image_enhance")]
|
||||
public string ImageEnhance { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("pid")]
|
||||
public int Pid { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class MyInfoVip : BaseEntity
|
||||
{
|
||||
[JsonProperty("avatar_subscript")]
|
||||
public int AvatarSubscript { get; set; }
|
||||
[JsonProperty("due_date")]
|
||||
public long DueDate { get; set; }
|
||||
[JsonProperty("label")]
|
||||
public MyInfoDataVipLabel Label { get; set; }
|
||||
[JsonProperty("nickname_color")]
|
||||
public string NicknameColor { get; set; }
|
||||
[JsonProperty("status")]
|
||||
public int Status { get; set; }
|
||||
[JsonProperty("theme_type")]
|
||||
public int ThemeType { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public int Type { get; set; }
|
||||
[JsonProperty("vip_pay_type")]
|
||||
public int VipPayType { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class MyInfoDataVipLabel : BaseEntity
|
||||
{
|
||||
[JsonProperty("label_theme")]
|
||||
public string LabelTheme { get; set; }
|
||||
[JsonProperty("path")]
|
||||
public string Path { get; set; }
|
||||
[JsonProperty("text")]
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/relation/blacks?pn={pn}&ps={ps}
|
||||
[JsonObject]
|
||||
public class RelationBlackOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public List<RelationBlack> Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
public class RelationBlack : BaseEntity
|
||||
{
|
||||
[JsonProperty("attribute")]
|
||||
public int Attribute { get; set; }
|
||||
// ...
|
||||
[JsonProperty("face")]
|
||||
public string Face { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("mtime")]
|
||||
public long Mtime { get; set; }
|
||||
// ...
|
||||
[JsonProperty("sign")]
|
||||
public string Sign { get; set; }
|
||||
[JsonProperty("special")]
|
||||
public int Special { get; set; }
|
||||
[JsonProperty("tag")]
|
||||
public List<long> Tag { get; set; }
|
||||
[JsonProperty("uname")]
|
||||
public string Name { get; set; }
|
||||
// ...
|
||||
}
|
||||
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/relation/followers?vmid={mid}&pn={pn}&ps={ps}
|
||||
// https://api.bilibili.com/x/relation/followings?vmid={mid}&pn={pn}&ps={ps}&order_type={orderType}
|
||||
[JsonObject]
|
||||
public class RelationFollowOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public RelationFollow Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class RelationFollow : BaseEntity
|
||||
{
|
||||
[JsonProperty("list")]
|
||||
public List<RelationFollowInfo> List { get; set; }
|
||||
//[JsonProperty("re_version")]
|
||||
//public long reVersion { get; set; }
|
||||
[JsonProperty("total")]
|
||||
public int Total { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class RelationFollowInfo : BaseEntity
|
||||
{
|
||||
[JsonProperty("attribute")]
|
||||
public int Attribute { get; set; }
|
||||
// ...
|
||||
[JsonProperty("face")]
|
||||
public string Face { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("mtime")]
|
||||
public long Mtime { get; set; }
|
||||
// ...
|
||||
[JsonProperty("sign")]
|
||||
public string Sign { get; set; }
|
||||
[JsonProperty("special")]
|
||||
public int Special { get; set; }
|
||||
[JsonProperty("tag")]
|
||||
public List<long> Tag { get; set; }
|
||||
[JsonProperty("uname")]
|
||||
public string Name { get; set; }
|
||||
// ...
|
||||
}
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/relation/whispers?pn={pn}&ps={ps}
|
||||
[JsonObject]
|
||||
public class RelationWhisperOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public List<RelationWhisper> Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
public class RelationWhisper : BaseEntity
|
||||
{
|
||||
[JsonProperty("attribute")]
|
||||
public int Attribute { get; set; }
|
||||
// ...
|
||||
[JsonProperty("face")]
|
||||
public string Face { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("mtime")]
|
||||
public long Mtime { get; set; }
|
||||
// ...
|
||||
[JsonProperty("sign")]
|
||||
public string Sign { get; set; }
|
||||
[JsonProperty("special")]
|
||||
public int Special { get; set; }
|
||||
[JsonProperty("tag")]
|
||||
public List<long> Tag { get; set; }
|
||||
[JsonProperty("uname")]
|
||||
public string Name { get; set; }
|
||||
// ...
|
||||
}
|
||||
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/space/channel/list?mid=
|
||||
[JsonObject]
|
||||
public class SpaceChannelOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public SpaceChannel Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceChannel : BaseEntity
|
||||
{
|
||||
[JsonProperty("count")]
|
||||
public int Count { get; set; }
|
||||
[JsonProperty("list")]
|
||||
public List<SpaceChannelList> List { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceChannelList : BaseEntity
|
||||
{
|
||||
[JsonProperty("cid")]
|
||||
public long Cid { get; set; }
|
||||
[JsonProperty("count")]
|
||||
public int Count { get; set; }
|
||||
[JsonProperty("cover")]
|
||||
public string Cover { get; set; }
|
||||
[JsonProperty("intro")]
|
||||
public string Intro { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("mtime")]
|
||||
public long Mtime { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/space/channel/video?mid={mid}&cid={cid}&pn={pn}&ps={ps}
|
||||
[JsonObject]
|
||||
public class SpaceChannelVideoOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public SpaceChannelVideo Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceChannelVideo : BaseEntity
|
||||
{
|
||||
[JsonProperty("list")]
|
||||
public SpaceChannelVideoList List { get; set; }
|
||||
[JsonProperty("page")]
|
||||
public SpaceChannelVideoPage Page { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceChannelVideoList : BaseEntity
|
||||
{
|
||||
[JsonProperty("archives")]
|
||||
public List<SpaceChannelVideoArchive> Archives { get; set; }
|
||||
[JsonProperty("cid")]
|
||||
public long Cid { get; set; }
|
||||
[JsonProperty("count")]
|
||||
public int Count { get; set; }
|
||||
[JsonProperty("cover")]
|
||||
public string Cover { get; set; }
|
||||
[JsonProperty("intro")]
|
||||
public string Intro { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("mtime")]
|
||||
public long Mtime { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceChannelVideoPage : BaseEntity
|
||||
{
|
||||
[JsonProperty("count")]
|
||||
public int Count { get; set; }
|
||||
[JsonProperty("num")]
|
||||
public int Num { get; set; }
|
||||
[JsonProperty("size")]
|
||||
public int Size { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceChannelVideoArchive : BaseEntity
|
||||
{
|
||||
[JsonProperty("aid")]
|
||||
public long Aid { get; set; }
|
||||
[JsonProperty("bvid")]
|
||||
public string Bvid { get; set; }
|
||||
[JsonProperty("cid")]
|
||||
public long Cid { get; set; }
|
||||
// ...
|
||||
[JsonProperty("ctime")]
|
||||
public long Ctime { get; set; }
|
||||
[JsonProperty("desc")]
|
||||
public string Desc { get; set; }
|
||||
// ...
|
||||
[JsonProperty("duration")]
|
||||
public long Duration { get; set; }
|
||||
// ...
|
||||
[JsonProperty("pic")]
|
||||
public string Pic { get; set; }
|
||||
[JsonProperty("pubdate")]
|
||||
public long Pubdate { get; set; }
|
||||
// ...
|
||||
[JsonProperty("stat")]
|
||||
public SpaceChannelVideoArchiveStat Stat { get; set; }
|
||||
// ...
|
||||
[JsonProperty("tid")]
|
||||
public int Tid { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
[JsonProperty("tname")]
|
||||
public string Tname { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceChannelVideoArchiveStat : BaseEntity
|
||||
{
|
||||
// ...
|
||||
[JsonProperty("view")]
|
||||
public long View { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/pugv/app/web/season/page?mid={mid}&pn={pn}&ps={ps}
|
||||
[JsonObject]
|
||||
public class SpaceCheeseOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public SpaceCheeseList Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceCheeseList : BaseEntity
|
||||
{
|
||||
[JsonProperty("items")]
|
||||
public List<SpaceCheese> Items { get; set; }
|
||||
[JsonProperty("page")]
|
||||
public SpaceCheesePage Page { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceCheese : BaseEntity
|
||||
{
|
||||
[JsonProperty("cover")]
|
||||
public string Cover { get; set; }
|
||||
[JsonProperty("ep_count")]
|
||||
public int EpCount { get; set; }
|
||||
[JsonProperty("link")]
|
||||
public string Link { get; set; }
|
||||
[JsonProperty("page")]
|
||||
public int Page { get; set; }
|
||||
[JsonProperty("play")]
|
||||
public int Play { get; set; }
|
||||
[JsonProperty("season_id")]
|
||||
public long SeasonId { get; set; }
|
||||
[JsonProperty("status")]
|
||||
public string Status { get; set; }
|
||||
[JsonProperty("subtitle")]
|
||||
public string SubTitle { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceCheesePage : BaseEntity
|
||||
{
|
||||
[JsonProperty("next")]
|
||||
public bool Next { get; set; }
|
||||
[JsonProperty("num")]
|
||||
public int Num { get; set; }
|
||||
[JsonProperty("size")]
|
||||
public int Size { get; set; }
|
||||
[JsonProperty("total")]
|
||||
public int Total { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/v3/fav/folder/created/list?up_mid={mid}&pn={pn}&ps={ps}
|
||||
// https://api.bilibili.com/x/v3/fav/folder/collected/list?up_mid={mid}&pn={pn}&ps={ps}
|
||||
[JsonObject]
|
||||
public class SpaceFavoriteFolderOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public SpaceFavoriteFolder Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceFavoriteFolder : BaseEntity
|
||||
{
|
||||
[JsonProperty("count")]
|
||||
public int Count { get; set; }
|
||||
[JsonProperty("has_more")]
|
||||
public int HasMore { get; set; }
|
||||
[JsonProperty("list")]
|
||||
public List<SpaceFavoriteFolderList> List { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceFavoriteFolderList : BaseEntity
|
||||
{
|
||||
[JsonProperty("attr")]
|
||||
public int Attr { get; set; }
|
||||
[JsonProperty("cover")]
|
||||
public string Cover { get; set; }
|
||||
[JsonProperty("cover_type")]
|
||||
public int CoverType { get; set; }
|
||||
[JsonProperty("ctime")]
|
||||
public long Ctime { get; set; }
|
||||
[JsonProperty("fav_state")]
|
||||
public int FavState { get; set; }
|
||||
[JsonProperty("fid")]
|
||||
public long Fid { get; set; }
|
||||
[JsonProperty("id")]
|
||||
public long Id { get; set; }
|
||||
[JsonProperty("intro")]
|
||||
public string Intro { get; set; }
|
||||
[JsonProperty("link")]
|
||||
public string Link { get; set; }
|
||||
[JsonProperty("media_count")]
|
||||
public int MediaCount { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("mtime")]
|
||||
public long Mtime { get; set; }
|
||||
[JsonProperty("state")]
|
||||
public int State { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
[JsonProperty("upper")]
|
||||
public FavoriteFolderUpper Upper { get; set; }
|
||||
// ...
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class FavoriteFolderUpper : BaseEntity
|
||||
{
|
||||
[JsonProperty("face")]
|
||||
public string Face { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/v3/fav/resource/list?media_id={mediaId}&pn={pn}&ps={ps}
|
||||
[JsonObject]
|
||||
public class SpaceFavoriteFolderResourceOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public SpaceFavoriteFolderResource Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceFavoriteFolderResource : BaseEntity
|
||||
{
|
||||
[JsonProperty("has_more")]
|
||||
public int HasMore { get; set; }
|
||||
// ...
|
||||
[JsonProperty("medias")]
|
||||
public List<SpaceFavoriteFolderMedia> Medias { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceFavoriteFolderMedia : BaseEntity
|
||||
{
|
||||
[JsonProperty("attr")]
|
||||
public int Attr { get; set; }
|
||||
[JsonProperty("bv_id")]
|
||||
public string BvId { get; set; }
|
||||
[JsonProperty("bvid")]
|
||||
public string Bvid { get; set; }
|
||||
[JsonProperty("cnt_info")]
|
||||
public SpaceFavoriteFolderMediaCntInfo CntInfo { get; set; }
|
||||
[JsonProperty("cover")]
|
||||
public string Cover { get; set; }
|
||||
[JsonProperty("ctime")]
|
||||
public long Ctime { get; set; }
|
||||
[JsonProperty("duration")]
|
||||
public long Duration { get; set; }
|
||||
[JsonProperty("fav_time")]
|
||||
public long FavTime { get; set; }
|
||||
[JsonProperty("id")]
|
||||
public long Id { get; set; }
|
||||
[JsonProperty("intro")]
|
||||
public string Intro { get; set; }
|
||||
[JsonProperty("link")]
|
||||
public string Link { get; set; }
|
||||
[JsonProperty("page")]
|
||||
public int Page { get; set; }
|
||||
[JsonProperty("pubtime")]
|
||||
public long Pubtime { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public int Type { get; set; }
|
||||
[JsonProperty("upper")]
|
||||
public SpaceFavoriteFolderMediaUpper Upper { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceFavoriteFolderMediaCntInfo : BaseEntity
|
||||
{
|
||||
[JsonProperty("collect")]
|
||||
public long Collect { get; set; }
|
||||
[JsonProperty("danmaku")]
|
||||
public long Danmaku { get; set; }
|
||||
[JsonProperty("play")]
|
||||
public long Play { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceFavoriteFolderMediaUpper : BaseEntity
|
||||
{
|
||||
[JsonProperty("face")]
|
||||
public string Face { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/space/acc/info?mid={mid}
|
||||
[JsonObject]
|
||||
public class SpaceInfoOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public SpaceInfo Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceInfo : BaseEntity
|
||||
{
|
||||
// ...
|
||||
[JsonProperty("face")]
|
||||
public string Face { get; set; }
|
||||
[JsonProperty("fans_badge")]
|
||||
public bool FansBadge { get; set; }
|
||||
[JsonProperty("is_followed")]
|
||||
public bool IsFollowed { get; set; }
|
||||
// ...
|
||||
[JsonProperty("level")]
|
||||
public int Level { get; set; }
|
||||
// ...
|
||||
[JsonProperty("mid")]
|
||||
public int Mid { get; set; }
|
||||
// ...
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
// ...
|
||||
[JsonProperty("sex")]
|
||||
public string Sex { get; set; }
|
||||
// ...
|
||||
[JsonProperty("sign")]
|
||||
public string Sign { get; set; }
|
||||
// ...
|
||||
[JsonProperty("top_photo")]
|
||||
public string TopPhoto { get; set; }
|
||||
[JsonProperty("vip")]
|
||||
public SpaceInfoVip Vip { get; set; }
|
||||
}
|
||||
|
||||
public class SpaceInfoVip
|
||||
{
|
||||
[JsonProperty("avatar_subscript")]
|
||||
public int AvatarSubscript { get; set; }
|
||||
[JsonProperty("label")]
|
||||
public SpaceInfoVipLabel Label { get; set; }
|
||||
[JsonProperty("nickname_color")]
|
||||
public string NicknameColor { get; set; }
|
||||
[JsonProperty("status")]
|
||||
public int Status { get; set; }
|
||||
[JsonProperty("theme_type")]
|
||||
public int ThemeType { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public int Type { get; set; }
|
||||
}
|
||||
|
||||
public class SpaceInfoVipLabel
|
||||
{
|
||||
[JsonProperty("label_theme")]
|
||||
public string LabelTheme { get; set; }
|
||||
[JsonProperty("path")]
|
||||
public string Path { get; set; }
|
||||
[JsonProperty("text")]
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,150 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/space/arc/search
|
||||
[JsonObject]
|
||||
public class SpacePublicationOrigin : BaseEntity
|
||||
{
|
||||
//[JsonProperty("code")]
|
||||
//public int Code { get; set; }
|
||||
[JsonProperty("data")]
|
||||
public SpacePublication Data { get; set; }
|
||||
//[JsonProperty("message")]
|
||||
//public string Message { get; set; }
|
||||
//[JsonProperty("ttl")]
|
||||
//public int Ttl { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpacePublication : BaseEntity
|
||||
{
|
||||
[JsonProperty("list")]
|
||||
public SpacePublicationList List { get; set; }
|
||||
[JsonProperty("page")]
|
||||
public SpacePublicationPage Page { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpacePublicationList : BaseEntity
|
||||
{
|
||||
[JsonProperty("tlist")]
|
||||
public SpacePublicationListType Tlist { get; set; }
|
||||
[JsonProperty("vlist")]
|
||||
public List<SpacePublicationListVideo> Vlist { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpacePublicationPage : BaseEntity
|
||||
{
|
||||
[JsonProperty("count")]
|
||||
public int Count { get; set; }
|
||||
[JsonProperty("pn")]
|
||||
public int Pn { get; set; }
|
||||
[JsonProperty("ps")]
|
||||
public int Ps { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpacePublicationListType : BaseEntity
|
||||
{
|
||||
[JsonProperty("1")]
|
||||
public SpacePublicationListTypeVideoZone Douga { get; set; }
|
||||
[JsonProperty("13")]
|
||||
public SpacePublicationListTypeVideoZone Anime { get; set; }
|
||||
[JsonProperty("167")]
|
||||
public SpacePublicationListTypeVideoZone Guochuang { get; set; }
|
||||
[JsonProperty("3")]
|
||||
public SpacePublicationListTypeVideoZone Music { get; set; }
|
||||
[JsonProperty("129")]
|
||||
public SpacePublicationListTypeVideoZone Dance { get; set; }
|
||||
[JsonProperty("4")]
|
||||
public SpacePublicationListTypeVideoZone Game { get; set; }
|
||||
[JsonProperty("36")]
|
||||
public SpacePublicationListTypeVideoZone Technology { get; set; }
|
||||
[JsonProperty("188")]
|
||||
public SpacePublicationListTypeVideoZone Digital { get; set; }
|
||||
[JsonProperty("223")]
|
||||
public SpacePublicationListTypeVideoZone Car { get; set; }
|
||||
[JsonProperty("160")]
|
||||
public SpacePublicationListTypeVideoZone Life { get; set; }
|
||||
[JsonProperty("211")]
|
||||
public SpacePublicationListTypeVideoZone Food { get; set; }
|
||||
[JsonProperty("217")]
|
||||
public SpacePublicationListTypeVideoZone Animal { get; set; }
|
||||
[JsonProperty("119")]
|
||||
public SpacePublicationListTypeVideoZone Kichiku { get; set; }
|
||||
[JsonProperty("155")]
|
||||
public SpacePublicationListTypeVideoZone Fashion { get; set; }
|
||||
[JsonProperty("202")]
|
||||
public SpacePublicationListTypeVideoZone Information { get; set; }
|
||||
[JsonProperty("5")]
|
||||
public SpacePublicationListTypeVideoZone Ent { get; set; }
|
||||
[JsonProperty("181")]
|
||||
public SpacePublicationListTypeVideoZone Cinephile { get; set; }
|
||||
[JsonProperty("177")]
|
||||
public SpacePublicationListTypeVideoZone Documentary { get; set; }
|
||||
[JsonProperty("23")]
|
||||
public SpacePublicationListTypeVideoZone Movie { get; set; }
|
||||
[JsonProperty("11")]
|
||||
public SpacePublicationListTypeVideoZone Tv { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpacePublicationListVideo : BaseEntity
|
||||
{
|
||||
[JsonProperty("aid")]
|
||||
public long Aid { get; set; }
|
||||
//[JsonProperty("author")]
|
||||
//public string Author { get; set; }
|
||||
[JsonProperty("bvid")]
|
||||
public string Bvid { get; set; }
|
||||
//[JsonProperty("comment")]
|
||||
//public int Comment { get; set; }
|
||||
//[JsonProperty("copyright")]
|
||||
//public string Copyright { get; set; }
|
||||
[JsonProperty("created")]
|
||||
public long Created { get; set; }
|
||||
//[JsonProperty("description")]
|
||||
//public string Description { get; set; }
|
||||
//[JsonProperty("hide_click")]
|
||||
//public bool HideClick { get; set; }
|
||||
//[JsonProperty("is_pay")]
|
||||
//public int IsPay { get; set; }
|
||||
//[JsonProperty("is_steins_gate")]
|
||||
//public int IsSteinsGate { get; set; }
|
||||
//[JsonProperty("is_union_video")]
|
||||
//public int IsUnionVideo { get; set; }
|
||||
[JsonProperty("length")]
|
||||
public string Length { get; set; }
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("pic")]
|
||||
public string Pic { get; set; }
|
||||
[JsonProperty("play")]
|
||||
public int Play { get; set; }
|
||||
//[JsonProperty("review")]
|
||||
//public int Review { get; set; }
|
||||
//[JsonProperty("subtitle")]
|
||||
//public string Subtitle { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
[JsonProperty("typeid")]
|
||||
public int Typeid { get; set; }
|
||||
//[JsonProperty("video_review")]
|
||||
//public int VideoReview { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpacePublicationListTypeVideoZone : BaseEntity
|
||||
{
|
||||
[JsonProperty("count")]
|
||||
public int Count { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("tid")]
|
||||
public int Tid { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://space.bilibili.com/ajax/settings/getSettings?mid={mid}
|
||||
[JsonObject]
|
||||
public class SpaceSettingsOrigin : BaseEntity
|
||||
{
|
||||
[JsonProperty("data")]
|
||||
public SpaceSettings Data { get; set; }
|
||||
[JsonProperty("status")]
|
||||
public bool Status { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceSettings : BaseEntity
|
||||
{
|
||||
// ...
|
||||
[JsonProperty("toutu")]
|
||||
public SpaceSettingsToutu Toutu { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class SpaceSettingsToutu : BaseEntity
|
||||
{
|
||||
[JsonProperty("android_img")]
|
||||
public string AndroidImg { get; set; }
|
||||
[JsonProperty("expire")]
|
||||
public long Expire { get; set; }
|
||||
[JsonProperty("ipad_img")]
|
||||
public string IpadImg { get; set; }
|
||||
[JsonProperty("iphone_img")]
|
||||
public string IphoneImg { get; set; }
|
||||
[JsonProperty("l_img")]
|
||||
public string Limg { get; set; } // 完整url为http://i0.hdslb.com/+相对路径
|
||||
[JsonProperty("platform")]
|
||||
public int Platform { get; set; }
|
||||
[JsonProperty("s_img")]
|
||||
public string Simg { get; set; } // 完整url为http://i0.hdslb.com/+相对路径
|
||||
[JsonProperty("sid")]
|
||||
public int Sid { get; set; }
|
||||
[JsonProperty("thumbnail_img")]
|
||||
public string ThumbnailImg { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/space/upstat?mid={mid}
|
||||
[JsonObject]
|
||||
public class UpStatOrigin : BaseEntity
|
||||
{
|
||||
[JsonProperty("data")]
|
||||
public UpStat Data { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class UpStat : BaseEntity
|
||||
{
|
||||
[JsonProperty("archive")]
|
||||
public UpStatArchive Archive { get; set; }
|
||||
[JsonProperty("article")]
|
||||
public UpStatArchive Article { get; set; }
|
||||
[JsonProperty("likes")]
|
||||
public long Likes { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class UpStatArchive : BaseEntity
|
||||
{
|
||||
[JsonProperty("view")]
|
||||
public long View { get; set; } // 视频播放量
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.entity2.users
|
||||
{
|
||||
// https://api.bilibili.com/x/relation/stat?vmid={mid}
|
||||
[JsonObject]
|
||||
public class UserRelationStatOrigin : BaseEntity
|
||||
{
|
||||
[JsonProperty("data")]
|
||||
public UserRelationStat Data { get; set; }
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class UserRelationStat : BaseEntity
|
||||
{
|
||||
[JsonProperty("black")]
|
||||
public long Black { get; set; }
|
||||
[JsonProperty("follower")]
|
||||
public long Follower { get; set; } // 粉丝数
|
||||
[JsonProperty("following")]
|
||||
public long Following { get; set; } // 关注数
|
||||
[JsonProperty("mid")]
|
||||
public long Mid { get; set; }
|
||||
[JsonProperty("whisper")]
|
||||
public long Whisper { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,167 +0,0 @@
|
||||
# 设置
|
||||
|
||||
Settings类位于`Core.settings`命名空间中,采用单例模式调用。设置属性使用json格式保存,并将加密后的字符串保存到文件。
|
||||
|
||||
| 文件名 | 内容 |
|
||||
| ------------------- | -------------------------------------- |
|
||||
| Settings.cs | Settings类的基本属性,单例模式的代码等 |
|
||||
| Settings.class.cs | SettingsEntity类等 |
|
||||
| Settings.base.cs | `基本`设置的代码 |
|
||||
| Settings.network.cs | `网络`设置的代码 |
|
||||
| Settings.video.cs | `视频`设置的代码 |
|
||||
| Settings.about.cs | `关于`设置的代码 |
|
||||
|
||||
## 基本
|
||||
|
||||
获取/设置下载完成后的操作。
|
||||
|
||||
```c#
|
||||
public AfterDownloadOperation GetAfterDownloadOperation();
|
||||
public bool SetAfterDownloadOperation(AfterDownloadOperation afterDownload);
|
||||
```
|
||||
|
||||
## 网络
|
||||
|
||||
获取/设置是否解除地区限制。
|
||||
|
||||
```c#
|
||||
public LiftingOfRegion IsLiftingOfRegion();
|
||||
public bool IsLiftingOfRegion(LiftingOfRegion isLiftingOfRegion);
|
||||
```
|
||||
|
||||
获取/设置Aria服务器的端口号。
|
||||
|
||||
```c#
|
||||
public int GetAriaListenPort();
|
||||
public bool SetAriaListenPort(int ariaListenPort);
|
||||
```
|
||||
|
||||
获取/设置Aria日志等级。
|
||||
|
||||
```c#
|
||||
public AriaConfigLogLevel GetAriaLogLevel();
|
||||
public bool SetAriaLogLevel(AriaConfigLogLevel ariaLogLevel);
|
||||
```
|
||||
|
||||
获取/设置Aria最大同时下载数(任务数)。
|
||||
|
||||
```c#
|
||||
public int GetAriaMaxConcurrentDownloads();
|
||||
public bool SetAriaMaxConcurrentDownloads(int ariaMaxConcurrentDownloads);
|
||||
```
|
||||
|
||||
获取/设置Aria单文件最大线程数。
|
||||
|
||||
```c#
|
||||
public int GetAriaSplit();
|
||||
public bool SetAriaSplit(int ariaSplit);
|
||||
```
|
||||
|
||||
获取/设置Aria下载速度限制。
|
||||
|
||||
```c#
|
||||
public int GetAriaMaxOverallDownloadLimit();
|
||||
public bool SetAriaMaxOverallDownloadLimit(int ariaMaxOverallDownloadLimit);
|
||||
```
|
||||
|
||||
获取/设置Aria下载单文件速度限制。
|
||||
|
||||
```c#
|
||||
public int GetAriaMaxDownloadLimit();
|
||||
public bool SetAriaMaxDownloadLimit(int ariaMaxDownloadLimit);
|
||||
```
|
||||
|
||||
获取/设置Aria文件预分配。
|
||||
|
||||
```c#
|
||||
public AriaConfigFileAllocation GetAriaFileAllocation();
|
||||
public bool SetAriaFileAllocation(AriaConfigFileAllocation ariaFileAllocation);
|
||||
```
|
||||
|
||||
获取/设置是否开启Aria http代理。
|
||||
|
||||
```c#
|
||||
public AriaHttpProxy IsAriaHttpProxy();
|
||||
public bool IsAriaHttpProxy(AriaHttpProxy isAriaHttpProxy);
|
||||
```
|
||||
|
||||
获取/设置Aria的http代理的地址。
|
||||
|
||||
```c#
|
||||
public string GetAriaHttpProxy();
|
||||
public bool SetAriaHttpProxy(string ariaHttpProxy);
|
||||
```
|
||||
|
||||
获取/设置Aria的http代理的端口。
|
||||
|
||||
```c#
|
||||
public int GetAriaHttpProxyListenPort();
|
||||
public bool SetAriaHttpProxyListenPort(int ariaHttpProxyListenPort);
|
||||
```
|
||||
|
||||
## 视频
|
||||
|
||||
获取/设置优先下载的视频编码。
|
||||
|
||||
```c#
|
||||
public VideoCodecs GetVideoCodecs();
|
||||
public bool SetVideoCodecs(VideoCodecs videoCodecs);
|
||||
```
|
||||
|
||||
获取/设置优先下载画质。
|
||||
|
||||
```c#
|
||||
public int GetQuality();
|
||||
public bool SetQuality(int quality);
|
||||
```
|
||||
|
||||
获取/设置是否给视频增加序号。
|
||||
|
||||
```c#
|
||||
public AddOrder IsAddOrder();
|
||||
public bool IsAddOrder(AddOrder isAddOrder);
|
||||
```
|
||||
|
||||
获取/设置是否下载flv视频后转码为mp4。
|
||||
|
||||
```c#
|
||||
public TranscodingFlvToMp4 IsTranscodingFlvToMp4();
|
||||
public bool IsTranscodingFlvToMp4(TranscodingFlvToMp4 isTranscodingFlvToMp4);
|
||||
```
|
||||
|
||||
获取/设置下载目录。
|
||||
|
||||
```c#
|
||||
public string GetSaveVideoRootPath();
|
||||
public bool SetSaveVideoRootPath(string path);
|
||||
```
|
||||
|
||||
获取/设置是否使用默认下载目录。
|
||||
|
||||
```c#
|
||||
public UseSaveVideoRootPath IsUseSaveVideoRootPath();
|
||||
public bool IsUseSaveVideoRootPath(UseSaveVideoRootPath isUseSaveVideoRootPath);
|
||||
```
|
||||
|
||||
获取/设置是否为不同视频分别创建文件夹。
|
||||
|
||||
```c#
|
||||
public CreateFolderForMedia IsCreateFolderForMedia();
|
||||
public bool IsCreateFolderForMedia(CreateFolderForMedia isCreateFolderForMedia);
|
||||
```
|
||||
|
||||
## 关于
|
||||
|
||||
获取/设置是否接收测试版更新。
|
||||
|
||||
```c#
|
||||
public ReceiveBetaVersion IsReceiveBetaVersion();
|
||||
public bool IsReceiveBetaVersion(ReceiveBetaVersion isReceiveBetaVersion);
|
||||
```
|
||||
|
||||
获取/设置是否允许启动时检查更新。
|
||||
|
||||
```c#
|
||||
public AutoUpdateWhenLaunch GetAutoUpdateWhenLaunch();
|
||||
public bool SetAutoUpdateWhenLaunch(AutoUpdateWhenLaunch autoUpdateWhenLaunch);
|
||||
```
|
@ -1,90 +0,0 @@
|
||||
using Core.aria2cNet.server;
|
||||
|
||||
namespace Core.settings
|
||||
{
|
||||
public class SettingsEntity
|
||||
{
|
||||
public UserInfoForSetting UserInfo { get; set; }
|
||||
|
||||
// 基本
|
||||
public AfterDownloadOperation AfterDownload { get; set; }
|
||||
public ALLOW_STATUS IsListenClipboard { get; set; }
|
||||
public ALLOW_STATUS IsAutoParseVideo { get; set; }
|
||||
public DownloadFinishedSort DownloadFinishedSort { get; set; }
|
||||
|
||||
// 网络
|
||||
public ALLOW_STATUS IsLiftingOfRegion { get; set; }
|
||||
public int AriaListenPort { get; set; }
|
||||
public AriaConfigLogLevel AriaLogLevel { get; set; }
|
||||
public int AriaMaxConcurrentDownloads { get; set; }
|
||||
public int AriaSplit { get; set; }
|
||||
public int AriaMaxOverallDownloadLimit { get; set; }
|
||||
public int AriaMaxDownloadLimit { get; set; }
|
||||
public AriaConfigFileAllocation AriaFileAllocation { get; set; }
|
||||
|
||||
public ALLOW_STATUS IsAriaHttpProxy { get; set; }
|
||||
public string AriaHttpProxy { get; set; }
|
||||
public int AriaHttpProxyListenPort { get; set; }
|
||||
|
||||
// 视频
|
||||
public VideoCodecs VideoCodecs { get; set; }
|
||||
public int Quality { get; set; }
|
||||
public ALLOW_STATUS IsAddOrder { get; set; }
|
||||
public ALLOW_STATUS IsTranscodingFlvToMp4 { get; set; }
|
||||
public string SaveVideoRootPath { get; set; }
|
||||
public ALLOW_STATUS IsUseSaveVideoRootPath { get; set; }
|
||||
public ALLOW_STATUS IsCreateFolderForMedia { get; set; }
|
||||
public ALLOW_STATUS IsDownloadDanmaku { get; set; }
|
||||
public ALLOW_STATUS IsDownloadCover { get; set; }
|
||||
|
||||
// 弹幕
|
||||
public ALLOW_STATUS DanmakuTopFilter { get; set; }
|
||||
public ALLOW_STATUS DanmakuBottomFilter { get; set; }
|
||||
public ALLOW_STATUS DanmakuScrollFilter { get; set; }
|
||||
public ALLOW_STATUS IsCustomDanmakuResolution { get; set; }
|
||||
public int DanmakuScreenWidth { get; set; }
|
||||
public int DanmakuScreenHeight { get; set; }
|
||||
public string DanmakuFontName { get; set; }
|
||||
public int DanmakuFontSize { get; set; }
|
||||
public int DanmakuLineCount { get; set; }
|
||||
public DanmakuLayoutAlgorithm DanmakuLayoutAlgorithm { get; set; }
|
||||
|
||||
// 关于
|
||||
public ALLOW_STATUS IsReceiveBetaVersion { get; set; }
|
||||
public ALLOW_STATUS AutoUpdateWhenLaunch { get; set; }
|
||||
}
|
||||
|
||||
public class UserInfoForSetting
|
||||
{
|
||||
public long Mid { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool IsLogin { get; set; } // 是否登录
|
||||
public bool IsVip { get; set; } // 是否为大会员,未登录时为false
|
||||
}
|
||||
|
||||
public enum AfterDownloadOperation
|
||||
{
|
||||
NONE = 1, OPEN_FOLDER, CLOSE_APP, CLOSE_SYSTEM
|
||||
}
|
||||
|
||||
public enum ALLOW_STATUS
|
||||
{
|
||||
NONE = 0, YES, NO
|
||||
}
|
||||
|
||||
public enum DownloadFinishedSort
|
||||
{
|
||||
DOWNLOAD = 0, NUMBER
|
||||
}
|
||||
|
||||
public enum VideoCodecs
|
||||
{
|
||||
NONE = 0, AVC, HEVC
|
||||
}
|
||||
|
||||
public enum DanmakuLayoutAlgorithm
|
||||
{
|
||||
NONE = 0, ASYNC, SYNC
|
||||
}
|
||||
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Core.settings
|
||||
{
|
||||
public partial class Settings
|
||||
{
|
||||
private static Settings instance;
|
||||
|
||||
/// <summary>
|
||||
/// 获取Settings实例
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Settings GetInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new Settings();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏Settings()方法,必须使用单例模式
|
||||
/// </summary>
|
||||
private Settings()
|
||||
{
|
||||
settingsEntity = GetEntity();
|
||||
}
|
||||
|
||||
|
||||
// 内存中保存一份配置
|
||||
private readonly SettingsEntity settingsEntity;
|
||||
|
||||
// 设置的配置文件
|
||||
private readonly string settingsName = Common.ConfigPath + "Settings";
|
||||
|
||||
// 密钥
|
||||
private readonly string password = "QA!M^gE@";
|
||||
|
||||
// 登录用户的mid
|
||||
private readonly UserInfoForSetting userInfo = new UserInfoForSetting
|
||||
{
|
||||
Mid = -1,
|
||||
Name = "",
|
||||
IsLogin = false,
|
||||
IsVip = false
|
||||
};
|
||||
|
||||
private SettingsEntity GetEntity()
|
||||
{
|
||||
try
|
||||
{
|
||||
StreamReader streamReader = File.OpenText(settingsName);
|
||||
string jsonWordTemplate = streamReader.ReadToEnd();
|
||||
streamReader.Close();
|
||||
|
||||
// 解密字符串
|
||||
jsonWordTemplate = Encryptor.DecryptString(jsonWordTemplate, password);
|
||||
|
||||
return JsonConvert.DeserializeObject<SettingsEntity>(jsonWordTemplate);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
Console.WriteLine("GetEntity()发生异常: {0}", e);
|
||||
return new SettingsEntity();
|
||||
}
|
||||
catch (DirectoryNotFoundException e)
|
||||
{
|
||||
Console.WriteLine("GetEntity()发生异常: {0}", e);
|
||||
return new SettingsEntity();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("GetEntity()发生异常: {0}", e);
|
||||
return new SettingsEntity();
|
||||
}
|
||||
}
|
||||
|
||||
private bool SetEntity()
|
||||
{
|
||||
if (!Directory.Exists(Common.ConfigPath))
|
||||
{
|
||||
Directory.CreateDirectory(Common.ConfigPath);
|
||||
}
|
||||
|
||||
string json = JsonConvert.SerializeObject(settingsEntity);
|
||||
|
||||
// 加密字符串
|
||||
json = Encryptor.EncryptString(json, password);
|
||||
try
|
||||
{
|
||||
File.WriteAllText(settingsName, json);
|
||||
return true;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Console.WriteLine("SetEntity()发生异常: {0}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取登录用户信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public UserInfoForSetting GetUserInfo()
|
||||
{
|
||||
if (settingsEntity.UserInfo == null)
|
||||
{
|
||||
// 第一次获取,先设置默认值
|
||||
SetUserInfo(userInfo);
|
||||
return userInfo;
|
||||
}
|
||||
return settingsEntity.UserInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置中保存登录用户的信息,在index刷新用户状态时使用
|
||||
/// </summary>
|
||||
/// <param name="mid"></param>
|
||||
/// <returns></returns>
|
||||
public bool SetUserInfo(UserInfoForSetting userInfo)
|
||||
{
|
||||
settingsEntity.UserInfo = userInfo;
|
||||
return SetEntity();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
using Core.aria2cNet.client;
|
||||
using System;
|
||||
using DownKyi.Core.Aria2cNet.Client;
|
||||
using DownKyi.Core.Logging;
|
||||
using System.Threading;
|
||||
|
||||
namespace Core.aria2cNet
|
||||
namespace DownKyi.Core.Aria2cNet
|
||||
{
|
||||
public class AriaManager
|
||||
{
|
||||
@ -69,7 +69,8 @@ namespace Core.aria2cNet
|
||||
}
|
||||
if (status.Result.Result.ErrorCode != null && status.Result.Result.ErrorCode != "0")
|
||||
{
|
||||
Console.WriteLine("ErrorMessage: " + status.Result.Result.ErrorMessage);
|
||||
Utils.Debug.Console.PrintLine("ErrorMessage: " + status.Result.Result.ErrorMessage);
|
||||
LogManager.Error("AriaManager", status.Result.Result.ErrorMessage);
|
||||
|
||||
//// 如果返回状态码不是200,则继续
|
||||
//if (status.Result.Result.ErrorMessage.Contains("The response status is not successful"))
|
||||
@ -80,7 +81,8 @@ namespace Core.aria2cNet
|
||||
|
||||
// aira中删除记录
|
||||
var ariaRemove1 = AriaClient.RemoveDownloadResultAsync(gid);
|
||||
Console.WriteLine(ariaRemove1);
|
||||
Utils.Debug.Console.PrintLine(ariaRemove1);
|
||||
LogManager.Debug("AriaManager", ariaRemove1.Result.Result);
|
||||
|
||||
// 返回回调信息,退出函数
|
||||
OnDownloadFinish(false, null, gid, status.Result.Result.ErrorMessage);
|
||||
@ -114,46 +116,5 @@ namespace Core.aria2cNet
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//private async void Poll()
|
||||
//{
|
||||
// while (true)
|
||||
// {
|
||||
// // 查询全局status
|
||||
// var globalStatus = await AriaClient.GetGlobalStatAsync();
|
||||
// if (globalStatus == null || globalStatus.Result == null) { continue; }
|
||||
|
||||
// long globalSpeed = long.Parse(globalStatus.Result.DownloadSpeed);
|
||||
// // 回调
|
||||
// OnGetGlobalStatus(globalSpeed);
|
||||
|
||||
// // 查询gid对应的项目的status
|
||||
// foreach (var gid in gidList)
|
||||
// {
|
||||
// var status = await AriaClient.TellStatus(gid);
|
||||
// if (status == null || status.Result == null) { continue; }
|
||||
|
||||
// long totalLength = long.Parse(status.Result.TotalLength);
|
||||
// long completedLength = long.Parse(status.Result.CompletedLength);
|
||||
// long speed = long.Parse(status.Result.DownloadSpeed);
|
||||
// // 回调
|
||||
// OnTellStatus(totalLength, completedLength, speed, gid);
|
||||
// }
|
||||
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 下载状态
|
||||
/// </summary>
|
||||
public enum DownloadStatus
|
||||
{
|
||||
SUCCESS = 1,
|
||||
FAILED,
|
||||
ABORT
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using Core.aria2cNet.client.entity;
|
||||
using DownKyi.Core.Aria2cNet.Client.Entity;
|
||||
using DownKyi.Core.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -7,9 +8,8 @@ using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Core.aria2cNet.client
|
||||
namespace DownKyi.Core.Aria2cNet.Client
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// http://aria2.github.io/manual/en/html/aria2c.html#methods
|
||||
/// </summary>
|
||||
@ -1093,7 +1093,8 @@ namespace Core.aria2cNet.client
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
Console.WriteLine("Request()发生Web异常: {0}", e);
|
||||
Utils.Debug.Console.PrintLine("Request()发生Web异常: {0}", e);
|
||||
LogManager.Error("AriaClient", e);
|
||||
//return Request(url, parameters, retry - 1);
|
||||
|
||||
string html = string.Empty;
|
||||
@ -1106,34 +1107,24 @@ namespace Core.aria2cNet.client
|
||||
html = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
|
||||
Console.WriteLine($"本次请求使用的参数:{parameters}");
|
||||
Console.WriteLine($"返回的web数据:{html}");
|
||||
#endif
|
||||
return html;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Console.WriteLine("Request()发生IO异常: {0}", e);
|
||||
Utils.Debug.Console.PrintLine("Request()发生IO异常: {0}", e);
|
||||
LogManager.Error("AriaClient", e);
|
||||
return Request(url, parameters, retry - 1);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Request()发生其他异常: {0}", e);
|
||||
Utils.Debug.Console.PrintLine("Request()发生其他异常: {0}", e);
|
||||
LogManager.Error("AriaClient", e);
|
||||
return Request(url, parameters, retry - 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// changePosition函数的how参数
|
||||
/// </summary>
|
||||
public enum HowChangePosition
|
||||
{
|
||||
POS_SET = 1,
|
||||
POS_CUR,
|
||||
POS_END
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaAddMetalink
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaAddTorrent
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
//{
|
||||
//"id": "downkyi",
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaChangeOption
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaChangePosition
|
@ -1,7 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaChangeUri
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
//"error": {
|
||||
// "code": 1,
|
@ -1,7 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaGetFiles
|
||||
@ -50,5 +50,4 @@ namespace Core.aria2cNet.client.entity
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
/*
|
||||
{
|
||||
"id": "qwer",
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"downloadSpeed": "0",
|
||||
"numActive": "0",
|
||||
"numStopped": "0",
|
||||
"numStoppedTotal": "0",
|
||||
"numWaiting": "0",
|
||||
"uploadSpeed": "0"
|
||||
}
|
||||
}
|
||||
*/
|
||||
{
|
||||
"id": "qwer",
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"downloadSpeed": "0",
|
||||
"numActive": "0",
|
||||
"numStopped": "0",
|
||||
"numStoppedTotal": "0",
|
||||
"numWaiting": "0",
|
||||
"uploadSpeed": "0"
|
||||
}
|
||||
}
|
||||
*/
|
||||
[JsonObject]
|
||||
public class AriaGetGlobalStat
|
||||
{
|
||||
@ -63,5 +63,4 @@ namespace Core.aria2cNet.client.entity
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaGetOption
|
@ -1,7 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaGetPeers
|
||||
@ -59,5 +59,4 @@ namespace Core.aria2cNet.client.entity
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaGetServers
|
||||
@ -56,5 +56,4 @@ namespace Core.aria2cNet.client.entity
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaGetSessionInfo
|
||||
@ -34,5 +34,4 @@ namespace Core.aria2cNet.client.entity
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaGetUris
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaOption
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaPause
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaRemove
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaSaveSession
|
@ -1,7 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaSendData
|
||||
@ -50,5 +50,4 @@ namespace Core.aria2cNet.client.entity
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaShutdown
|
@ -1,49 +1,8 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
/*
|
||||
{
|
||||
"id": "qwer",
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"bitfield": "80",
|
||||
"completedLength": "118188",
|
||||
"connections": "0",
|
||||
"dir": "D:\\home",
|
||||
"downloadSpeed": "0",
|
||||
"errorCode": "0",
|
||||
"errorMessage": "",
|
||||
"files": [
|
||||
{
|
||||
"completedLength": "118188",
|
||||
"index": "1",
|
||||
"length": "118188",
|
||||
"path": "D:/home/ariaTest.html",
|
||||
"selected": "true",
|
||||
"uris": [
|
||||
{
|
||||
"status": "used",
|
||||
"uri": "https://www.bilibili.com/"
|
||||
},
|
||||
{
|
||||
"status": "waiting",
|
||||
"uri": "https://www.bilibili.com/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"gid": "4e7f671a6134b5ac",
|
||||
"numPieces": "1",
|
||||
"pieceLength": "1048576",
|
||||
"status": "complete",
|
||||
"totalLength": "118188",
|
||||
"uploadLength": "0",
|
||||
"uploadSpeed": "0"
|
||||
}
|
||||
}
|
||||
*/
|
||||
[JsonObject]
|
||||
public class AriaTellStatus
|
||||
{
|
||||
@ -166,5 +125,4 @@ namespace Core.aria2cNet.client.entity
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaUri
|
@ -1,7 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class AriaVersion
|
||||
@ -38,5 +38,4 @@ namespace Core.aria2cNet.client.entity
|
||||
return JsonConvert.SerializeObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.aria2cNet.client.entity
|
||||
namespace DownKyi.Core.Aria2cNet.Client.Entity
|
||||
{
|
||||
[JsonObject]
|
||||
public class SystemListMethods
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user