/// <summary> /// 添加评论 /// </summary> /// <param name="oid">源ID</param> /// <param name="message">信息</param> /// <param name="type">类型</param> /// <returns></returns> public async Task <Reply> AddReplyAsync(string oid, string message, string parentId, string rootId, string type = "1") { var param = new Dictionary <string, string>(); param.Add("oid", oid); param.Add("parent", parentId); param.Add("root", rootId); param.Add("type", type); param.Add("message", Uri.EscapeDataString(message)); param.Add("lottery", "0"); param.Add("vote", "0"); var data = BiliTool.UrlContact("", param, true); try { string response = await BiliTool.PostContentToWebAsync(Api.REPLY_ADD, data); var jobj = JObject.Parse(response); if (jobj.ContainsKey("data")) { return(JsonConvert.DeserializeObject <Reply>(jobj["data"]["reply"].ToString())); } } catch (Exception) { } return(null); }
/// <summary> /// 加密密码 /// </summary> /// <param name="password">密码</param> /// <returns></returns> private async Task <string> EncryptedPasswordAsync(string password) { string base64String; try { string param = BiliTool.UrlContact("").TrimStart('?'); string content = await BiliTool.PostContentToWebAsync(Api.PASSPORT_KEY_ENCRYPT, param); JObject jobj = JObject.Parse(content); string str = jobj["data"]["hash"].ToString(); string str1 = jobj["data"]["key"].ToString(); string str2 = string.Concat(str, password); string str3 = Regex.Match(str1, "BEGIN PUBLIC KEY-----(?<key>[\\s\\S]+)-----END PUBLIC KEY").Groups["key"].Value.Trim(); byte[] numArray = Convert.FromBase64String(str3); AsymmetricKeyAlgorithmProvider asymmetricKeyAlgorithmProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1); CryptographicKey cryptographicKey = asymmetricKeyAlgorithmProvider.ImportPublicKey(WindowsRuntimeBufferExtensions.AsBuffer(numArray), 0); IBuffer buffer = CryptographicEngine.Encrypt(cryptographicKey, WindowsRuntimeBufferExtensions.AsBuffer(Encoding.UTF8.GetBytes(str2)), null); base64String = Convert.ToBase64String(WindowsRuntimeBufferExtensions.ToArray(buffer)); } catch (Exception) { base64String = password; } return(base64String); }
/// <summary> /// 操作收藏夹 /// </summary> /// <param name="aid">视频ID</param> /// <param name="addIds">添加的收藏夹ID列表</param> /// <param name="delIds">移出的收藏夹ID列表</param> /// <returns></returns> public async Task <bool> AddVideoToFavoriteAsync(int aid, List <string> addIds, List <string> delIds) { if (addIds.Count == 0 && delIds.Count == 0) { return(false); } var param = new Dictionary <string, string>(); param.Add("rid", aid.ToString()); param.Add("type", "2"); if (addIds.Count > 0) { param.Add("add_media_ids", string.Join(',', addIds)); } else if (delIds.Count > 0) { param.Add("del_media_ids", string.Join(',', delIds)); } var result = await BiliTool.PostContentToWebAsync(Api.VIDEO_FAVORITE, BiliTool.UrlContact("", param, true)); if (!string.IsNullOrEmpty(result)) { var jobj = JObject.Parse(result); return(jobj["code"].ToString() == "0"); } return(false); }
/// <summary> /// 清空稍后观看列表 /// </summary> /// <returns></returns> public async Task <bool> ClearViewLaterAsync() { string url = BiliTool.UrlContact(Api.ACCOUNT_VIEWLATER_CLEAR, null, true); string content = await BiliTool.PostContentToWebAsync(url, ""); return(content != null); }
/// <summary> /// 转发动态 /// </summary> /// <param name="content">附加内容</param> /// <param name="dynamicId">被转发动态ID</param> /// <param name="rid">被转发动态评论ID</param> /// <param name="type">被转发动态类型</param> /// <param name="atIds">at的人</param> /// <returns></returns> public async Task <bool> RepostDynamicAsync(string content, string dynamicId, string rid, int type, List <RepostLocation> atIds) { if (atIds == null) { atIds = new List <RepostLocation>(); } var param = new Dictionary <string, string>(); param.Add("content", Uri.EscapeDataString(content)); param.Add("at_uids", string.Join(',', atIds.Select(p => p.data))); param.Add("ctrl", Uri.EscapeDataString(JsonConvert.SerializeObject(atIds))); param.Add("dynamic_id", dynamicId); param.Add("rid", rid); param.Add("repost_code", "10000"); param.Add("sync_comment", "0"); param.Add("spec_type", "0"); param.Add("type", type.ToString()); param.Add("uid", BiliTool.mid.ToString()); param.Add("extension", Uri.EscapeDataString("{\"emoji_type\":1}")); param.Add("statistics", Uri.EscapeDataString("{\"appId\":1,\"version\":\"5.56.1\",\"abtest\":\"\",\"platform\":1}")); var req = BiliTool.UrlContact("", param, true); var response = await BiliTool.PostContentToWebAsync(Api.DYNAMIC_REPOST, req); if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); return(jobj["code"].ToString() == "0"); } return(false); }
/// <summary> /// 清空观看历史记录 /// </summary> /// <returns></returns> public async Task <bool> ClearHistoryAsync() { string url = BiliTool.UrlContact(Api.ACCOUNT_HISTORY_CLEAR, null, true); string content = await BiliTool.PostContentToWebAsync(url, ""); return(content != null); }
/// <summary> /// 转发视频 /// </summary> /// <param name="content">转发内容</param> /// <param name="videoId">视频ID</param> /// <param name="atIds">At的人</param> /// <returns></returns> public async Task <bool> RepostVideoAsync(string content, int videoId, List <RepostLocation> atIds) { var param = new Dictionary <string, string>(); param.Add("content", Uri.EscapeDataString(content)); param.Add("at_uids", string.Join(',', atIds.Select(p => p.data))); param.Add("ctrl", Uri.EscapeDataString(JsonConvert.SerializeObject(atIds))); param.Add("share_uid", BiliTool.mid.ToString()); param.Add("rid", videoId.ToString()); param.Add("type", "8"); param.Add("repost_code", "20000"); param.Add("sync_comment", "0"); param.Add("sketch", ""); param.Add("uid", "0"); param.Add("share_info", ""); param.Add("extension", Uri.EscapeDataString("{\"emoji_type\":1}")); param.Add("statistics", Uri.EscapeDataString("{\"appId\":1,\"version\":\"5.56.1\",\"abtest\":\"\",\"platform\":1}")); var req = BiliTool.UrlContact("", param, true); var response = await BiliTool.PostContentToWebAsync(Api.VIDEO_REPOST, req); if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); return(jobj["code"].ToString() == "0"); } return(false); }
/// <summary> /// 设置动态点赞状态 /// </summary> /// <param name="isLike">是否点赞</param> /// <param name="dynamicId">动态ID</param> /// <param name="rid">动态里的参数</param> /// <param name="uid">用户ID</param> /// <returns></returns> public async Task <bool> SetDynamicLikeStatus(bool isLike, string dynamicId, string rid, string uid) { if (string.IsNullOrEmpty(uid) || string.IsNullOrEmpty(dynamicId) || string.IsNullOrEmpty(rid)) { return(false); } var param = new Dictionary <string, string>(); param.Add("dynamic_id", dynamicId); param.Add("rid", rid); param.Add("uid", uid); param.Add("up", isLike ? "1" : "2"); var data = BiliTool.UrlContact("", param, true); var response = await BiliTool.PostContentToWebAsync(Api.DYNAMIC_LIKE, data); if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); if (jobj["code"].ToString() == "0") { return(true); } } return(false); }
/// <summary> /// 刷新令牌 /// </summary> /// <returns></returns> public async Task <bool> RefreshTokenAsync() { try { var param = $"access_token={_accessToken}&refresh_token={_refreshToken}&appkey={BiliTool.AndroidKey.Appkey}&ts={AppTool.GetNowSeconds()}"; param += "&sign=" + BiliTool.GetSign(param); var content = await BiliTool.PostContentToWebAsync(Api.PASSPORT_REFRESH_TOKEN, param); var obj = JObject.Parse(content); if (Convert.ToInt32(obj["code"]) == 0) { var data = JsonConvert.DeserializeObject <TokenInfo>(obj["data"].ToString()); var package = new TokenPackage(data.access_token, data.refresh_token, AppTool.DateToTimeStamp(DateTime.Now.AddSeconds(data.expires_in))); InitToken(package); TokenChanged?.Invoke(this, package); await SSO(); return(true); } return(false); } catch (Exception) { return(false); } }
/// <summary> /// 登录 /// </summary> /// <param name="userName">用户名</param> /// <param name="password">密码</param> /// <param name="captcha">验证码</param> /// <returns></returns> public async Task <LoginCallback> LoginAsync(string userName, string password, string captcha = "") { string param = $"appkey={BiliTool.AndroidKey.Appkey}&build={BiliTool.BuildNumber}&mobi_app=android&password={Uri.EscapeDataString(await EncryptedPasswordAsync(password))}&platform=android&ts={AppTool.GetNowSeconds()}&username={Uri.EscapeDataString(userName)}"; if (!string.IsNullOrEmpty(captcha)) { param += "&captcha=" + captcha; } param += "&sign=" + BiliTool.GetSign(param); string response = await BiliTool.PostContentToWebAsync(Api.PASSPORT_LOGIN, param); var result = new LoginCallback(); result.Status = LoginResultType.Error; if (!string.IsNullOrEmpty(response)) { try { var jobj = JObject.Parse(response); int code = Convert.ToInt32(jobj["code"]); if (code == 0) { var data = JsonConvert.DeserializeObject <LoginResult>(jobj["data"].ToString()); var package = new TokenPackage(data.token_info.access_token, data.token_info.refresh_token, AppTool.DateToTimeStamp(DateTime.Now.AddSeconds(data.token_info.expires_in))); InitToken(package); TokenChanged?.Invoke(this, package); result.Status = LoginResultType.Success; await SSO(); } else if (code == -2100) { result.Status = LoginResultType.NeedValidate; result.Url = jobj["url"].ToString(); } else if (code == -105) { result.Status = LoginResultType.NeedCaptcha; } else if (code == -449) { result.Status = LoginResultType.Busy; } else { result.Status = LoginResultType.Fail; } } catch (Exception) { return(new LoginCallback { Status = LoginResultType.Fail, Url = "" }); } } return(result); }
/// <summary> /// 转发动漫/电影/电视剧等 /// </summary> /// <param name="content">转发内容</param> /// <param name="videoId">视频ID</param> /// <param name="atIds">At的人</param> /// <param name="typeName">番剧:4097,影视:4098,电视剧:4099,国创:4100</param> /// <returns></returns> public async Task <bool> RepostBangumiAsync(string content, int epId, string typeName, List <RepostLocation> atIds) { var param = new Dictionary <string, string>(); string type = ""; switch (typeName) { case "番剧": type = "4097"; break; case "影视": type = "4098"; break; case "电视剧": case "综艺": type = "4099"; break; case "国创": type = "4100"; break; case "纪录片": type = "4101"; break; default: type = "4097"; break; } param.Add("content", Uri.EscapeDataString(content)); param.Add("at_uids", string.Join(',', atIds.Select(p => p.data))); param.Add("ctrl", Uri.EscapeDataString(JsonConvert.SerializeObject(atIds))); param.Add("share_uid", BiliTool.mid.ToString()); param.Add("rid", epId.ToString()); param.Add("type", type); param.Add("repost_code", "20000"); param.Add("sync_comment", "0"); param.Add("sketch", ""); param.Add("uid", "0"); param.Add("share_info", ""); param.Add("extension", Uri.EscapeDataString("{\"emoji_type\":1}")); param.Add("statistics", Uri.EscapeDataString("{\"appId\":1,\"version\":\"5.56.1\",\"abtest\":\"\",\"platform\":1}")); var req = BiliTool.UrlContact("", param, true); var response = await BiliTool.PostContentToWebAsync(Api.VIDEO_REPOST, req); if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); return(jobj["code"].ToString() == "0"); } return(false); }
/// <summary> /// 添加观看视频的历史记录 /// </summary> /// <param name="aid">视频ID</param> /// <returns></returns> public async Task AddVideoHistoryAsync(int aid, int cid, int seconds = 0) { var param = new Dictionary <string, string>(); param.Add("aid", aid.ToString()); param.Add("cid", cid.ToString()); param.Add("progress", seconds.ToString()); param.Add("type", "3"); var data = BiliTool.UrlContact("", param, true); await BiliTool.PostContentToWebAsync(Api.VIDEO_ADD_WATCH, data); }
/// <summary> /// 一键三连 /// </summary> /// <param name="aid">视频ID</param> /// <returns></returns> public async Task <bool> TripleVideoAsync(int aid) { var param = new Dictionary <string, string>(); param.Add("aid", aid.ToString()); var result = await BiliTool.PostContentToWebAsync(Api.VIDEO_TRIPLE, BiliTool.UrlContact("", param, true)); if (!string.IsNullOrEmpty(result)) { var jobj = JObject.Parse(result); return(jobj["code"].ToString() == "0"); } return(false); }
/// <summary> /// 取消追番/追剧 /// </summary> /// <param name="epid">标识ID</param> /// <returns></returns> public async Task <bool> UnfollowBangumiAsync(int epid) { var param = new Dictionary <string, string>(); param.Add("season_id", epid.ToString()); string data = BiliTool.UrlContact("", param, true); string content = await BiliTool.PostContentToWebAsync(Api.ANIME_UNFOLLOW, data); if (!string.IsNullOrEmpty(content)) { var jobj = JObject.Parse(content); return(jobj["message"].ToString() == "success"); } return(false); }
/// <summary> /// 移出稍后再看 /// </summary> /// <param name="aids">视频ID组</param> /// <returns></returns> public async Task <bool> DeleteViewLaterAsync(params int[] aids) { var param = new Dictionary <string, string>(); param.Add("aid", string.Join(',', aids)); var data = BiliTool.UrlContact("", param, true); string content = await BiliTool.PostContentToWebAsync(Api.ACCOUNT_VIEWLATER_DEL, data); if (!string.IsNullOrEmpty(content)) { var jobj = JObject.Parse(content); return(jobj["code"].ToString() == "0"); } return(false); }
/// <summary> /// 取消关注用户 /// </summary> /// <param name="uid">用户ID</param> /// <returns></returns> public async Task <bool> UnfollowUser(int uid) { var param = new Dictionary <string, string>(); param.Add("uid", Me.mid.ToString()); param.Add("follow", uid.ToString()); var data = BiliTool.UrlContact("", param, true); string response = await BiliTool.PostContentToWebAsync(Api.ACCOUNT_UNFOLLOW_USER, data); if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); return(jobj["code"].ToString() == "0"); } return(false); }
/// <summary> /// 点赞/取消点赞评论 /// </summary> /// <param name="isLike">是否点赞</param> /// <param name="oid">源ID</param> /// <param name="rpid">评论ID</param> /// <param name="type">类型</param> /// <returns></returns> public async Task <bool> LikeReplyAsync(bool isLike, string oid, string rpid, string type = "1") { string like = isLike ? "1" : "0"; var param = new Dictionary <string, string>(); param.Add("oid", oid); param.Add("rpid", rpid); param.Add("type", type); param.Add("action", like); var data = BiliTool.UrlContact("", param, true); string response = await BiliTool.PostContentToWebAsync(Api.REPLY_LIKE, data); var jobj = JObject.Parse(response); return(jobj["code"].ToString() == "0"); }
/// <summary> /// 删除收藏夹内视频 /// </summary> /// <param name="aid">视频ID</param> /// <param name="videoType">视频类型</param> /// <param name="listId">收藏夹ID</param> /// <returns></returns> public async Task <bool> RemoveFavoriteVideoAsync(int aid, int videoType, int listId) { var param = new Dictionary <string, string>(); param.Add("media_id", listId.ToString()); param.Add("resources", $"{aid}:{videoType}"); var req = BiliTool.UrlContact("", param, true); var data = await BiliTool.PostContentToWebAsync(Api.ACCOUNT_FAVORITE_VIDEO_DELETE, req); if (!string.IsNullOrEmpty(data)) { var jobj = JObject.Parse(data); return(jobj["code"].ToString() == "0"); } return(false); }
/// <summary> /// 视频投币 /// </summary> /// <param name="aid">视频ID</param> /// <param name="coin">投币数量</param> /// <param name="isLike">是否同时点赞</param> /// <returns></returns> public async Task <bool> GiveCoinToVideoAsync(int aid, int coin, bool isLike) { string is_like = isLike ? "1" : "0"; var param = new Dictionary <string, string>(); param.Add("aid", aid.ToString()); param.Add("select_like", is_like); param.Add("multiply", coin.ToString()); var result = await BiliTool.PostContentToWebAsync(Api.VIDEO_COIN, BiliTool.UrlContact("", param, true)); if (!string.IsNullOrEmpty(result)) { var jobj = JObject.Parse(result); return(jobj["code"].ToString() == "0"); } return(false); }
/// <summary> /// 订阅频道 /// </summary> /// <param name="channelId">频道ID</param> /// <returns></returns> public async Task <bool> SubscribeChannelAsync(int channelId) { var param = new Dictionary <string, string>(); param.Add("channel_id", channelId.ToString()); var data = BiliTool.UrlContact("", param, true); var response = await BiliTool.PostContentToWebAsync(Api.CHANNEL_SUBSCRIBE, data); if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); if (jobj["code"].ToString() == "0") { return(true); } } return(false); }
/// <summary> /// 添加评论 /// </summary> /// <param name="oid">源ID</param> /// <param name="message">信息</param> /// <param name="type">类型</param> /// <returns></returns> public async Task <bool> AddReplyAsync(string oid, string message, string type = "1") { var param = new Dictionary <string, string>(); param.Add("oid", oid); param.Add("type", type); param.Add("message", Uri.EscapeDataString(message)); param.Add("lottery", "0"); param.Add("vote", "0"); var data = BiliTool.UrlContact("", param, true); string response = await BiliTool.PostContentToWebAsync(Api.REPLY_ADD, data); var jobj = JObject.Parse(response); if (jobj.ContainsKey("data")) { return(jobj["data"]["success_action"].ToString() == "0"); } return(false); }
/// <summary> /// 发送弹幕 /// </summary> /// <param name="message">弹幕信息</param> /// <param name="aid">视频ID</param> /// <param name="cid">弹幕块ID</param> /// <param name="progress">进度</param> /// <param name="color">颜色(已处理)</param> /// <param name="fontSize">文本大小</param> /// <param name="mode">模式</param> /// <returns></returns> public async Task <bool> SendDanmakuAsync(string message, int aid, int cid, double progress, string color, string fontSize, string mode) { var param = new Dictionary <string, string>(); param.Add("aid", aid.ToString()); param.Add("msg", Uri.EscapeDataString(message)); param.Add("oid", cid.ToString()); param.Add("color", color); param.Add("fontSize", fontSize); param.Add("mode", mode); param.Add("pool", "0"); param.Add("plat", "3"); param.Add("type", "1"); param.Add("progress", Math.Round(progress).ToString()); var data = BiliTool.UrlContact("", param, true); var response = await BiliTool.PostContentToWebAsync(Api.VIDEO_SEND_DANMAKU, data); if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); return(jobj["code"].ToString() == "0"); } return(false); }