/// <summary> /// 获取视频播放信息 /// </summary> /// <param name="aid">视频avid</param> /// <param name="cid">视频分Pid</param> /// <param name="qn">分辨率ID</param> /// <returns></returns> public async Task <VideoPlayBase> GetVideoPlayAsync(int aid, int cid, int qn = 64) { var param = new Dictionary <string, string>(); param.Add("avid", aid.ToString()); param.Add("cid", cid.ToString()); param.Add("qn", qn.ToString()); param.Add("mid", BiliClient.Mid); param.Add("fnver", "0"); param.Add("fnval", "16"); param.Add("fourk", "1"); string url = BiliFactory.UrlContact(Api.VIDEO_PLAY, param, true, true); var data = await BiliClient.GetStringFromWebAsync(url); if (!string.IsNullOrEmpty(data)) { var jobj = JObject.Parse(data); if (jobj.ContainsKey("dash")) { return(JsonConvert.DeserializeObject <VideoPlayDash>(data)); } else if (jobj.ContainsKey("durl")) { return(JsonConvert.DeserializeObject <VideoPlayFlv>(data)); } } return(null); }
/// <summary> /// 获取频道下的视频信息 /// </summary> /// <param name="channelId">频道ID</param> /// <param name="sort">排序方式,可选值(hot,view,new)</param> /// <param name="offset">偏移值,初次不需要,每次请求会返回下一次请求的偏移值</param> /// <returns>Item1:下次偏移值;Item2:榜一视频(如果有);Item3:视频列表</returns> public async Task <Tuple <string, VideoBase, List <VideoChannel> > > GetChannelVideosAsync(int channelId, string sort = "hot", string offset = "") { var param = new Dictionary <string, string>(); param.Add("channel_id", channelId.ToString()); param.Add("sort", sort); if (!string.IsNullOrEmpty(offset)) { param.Add("offset", offset); } string url = BiliFactory.UrlContact(Api.CHANNEL_VIDEO, param, true); string content = await BiliClient.GetStringFromWebAsync(url, true); if (!string.IsNullOrEmpty(content)) { var jobj = JObject.Parse(content); if (jobj["code"].ToString() == "0") { var items = jobj["data"]["items"]; string nextOffset = jobj.SelectToken("data.offset").ToString(); VideoBase rankFirst = null; if (items.First()["goto"].ToString() == "channel_detail_rank") { rankFirst = JsonConvert.DeserializeObject <VideoBase>(items.First().SelectToken("items[0]").ToString()); } var videoList = JsonConvert.DeserializeObject <List <VideoChannel> >(items.ToString()); videoList.RemoveAll(p => p.@goto != "av"); return(new Tuple <string, VideoBase, List <VideoChannel> >(nextOffset, rankFirst, videoList)); } } return(null); }
/// <summary> /// 获取频道分类索引 /// </summary> /// <returns></returns> public async Task <List <ChannelTab> > GetChannelTabsAsync() { var url = BiliFactory.UrlContact(Api.CHANNEL_TABS, hasAccessKey: true); var data = await BiliClient.ConvertEntityFromWebAsync <List <ChannelTab> >(url); return(data); }
public async Task <Skin> GetSkinAsync() { string url = BiliFactory.UrlContact(Api.SKIN_PACKAGE, hasAccessKey: true); var data = await BiliClient.ConvertEntityFromWebAsync <Skin>(url); return(data); }
/// <summary> /// 清空观看历史记录 /// </summary> /// <returns></returns> public async Task <bool> ClearHistoryAsync() { string url = BiliFactory.UrlContact(Api.ACCOUNT_HISTORY_CLEAR, null, true); string content = await BiliClient.PostContentToWebAsync(url, ""); return(content != null); }
/// <summary> /// 刷新令牌 /// </summary> /// <returns></returns> public async Task <bool> RefreshTokenAsync() { try { var param = $"access_token={_accessToken}&refresh_token={_refreshToken}&appkey={BiliFactory.AndroidKey.Appkey}&ts={BiliFactory.GetNowSeconds()}"; param += "&sign=" + BiliFactory.GetSign(param); var content = await BiliClient.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, BiliFactory.GetTimeStampFuture(data.expires_in)); InitToken(package); TokenChanged?.Invoke(this, package); await SSO(); return(true); } return(false); } catch (Exception) { return(false); } }
/// <summary> /// 获取历史动态 /// </summary> /// <param name="offset">偏移值,初次不需要,每次请求会返回下一次请求的偏移值</param> /// <returns>Item1:下次偏移值;Item2:动态列表</returns> public async Task <Tuple <string, List <Topic> > > GetHistoryDynamicAsync(string offset) { var param = new Dictionary <string, string>(); param.Add("qn", "32"); param.Add("uid", BiliClient.Mid); param.Add("offset_dynamic_id", offset); param.Add("rsp_type", "2"); param.Add("type_list", "268435455"); string url = BiliFactory.UrlContact(Api.DYNAMIC_HISTORY, param, true); var data = await BiliClient.GetStringFromWebAsync(url); if (!string.IsNullOrEmpty(data)) { try { var jobj = JObject.Parse(data); string nextOffset = jobj["next_offset"].ToString(); var topics = JsonConvert.DeserializeObject <List <Topic> >(jobj["cards"].ToString()); topics.RemoveAll(p => p == null || p.card == null || p.card.Length < 10 || p.desc.status != 1); return(new Tuple <string, List <Topic> >(nextOffset, topics)); } catch (Exception) { } } return(null); }
/// <summary> /// 获取我收藏的播单(最多20个) /// </summary> /// <returns>Item1: 我创建的;Item2: 我收藏的</returns> public async Task <Tuple <List <FavoriteItem>, List <FavoriteItem> > > GetMyMainlyFavoritesAsync() { var param = new Dictionary <string, string>(); param.Add("up_mid", _userId); string url = BiliFactory.UrlContact(Api.ACCOUNT_MEDIALIST, param, true); string response = await BiliClient.GetStringFromWebAsync(url); try { var jarr = JArray.Parse(response); bool hasMy = jarr[0]["mediaListResponse"] != null; bool hasOther = jarr[1]["mediaListResponse"] != null; var myList = new List <FavoriteItem>(); var otherList = new List <FavoriteItem>(); if (hasMy) { myList = JsonConvert.DeserializeObject <List <FavoriteItem> >(jarr[0].SelectToken("mediaListResponse.list").ToString()); } if (hasOther) { otherList = JsonConvert.DeserializeObject <List <FavoriteItem> >(jarr[1].SelectToken("mediaListResponse.list").ToString()); } return(new Tuple <List <FavoriteItem>, List <FavoriteItem> >(myList, otherList)); } catch (Exception) { return(null); } }
/// <summary> /// 获取用户空间历史动态 /// </summary> /// <param name="uid">要查看的用户ID</param> /// <param name="page">页码</param> /// <param name="offset_id">偏移值,初次不需要,每次请求会返回下一次请求的偏移值</param> /// <returns>Item1:下次偏移值;Item2:动态列表</returns> public async Task <Tuple <string, List <Topic> > > GetUserSpaceDynamicAsync(int uid, int page = 1, string offset_id = "0") { var param = new Dictionary <string, string>(); param.Add("host_uid", uid.ToString()); param.Add("qn", "32"); if (!string.IsNullOrEmpty(BiliClient.Mid)) { param.Add("visitor_uid", BiliClient.Mid); } param.Add("offset_dynamic_id", offset_id); param.Add("page", page.ToString()); string url = BiliFactory.UrlContact(Api.DYNAMIC_USER_HISTORY, param, true); var data = await BiliClient.GetStringFromWebAsync(url); if (!string.IsNullOrEmpty(data)) { try { var jobj = JObject.Parse(data); string nextOffset = jobj["next_offset"].ToString(); var topics = JsonConvert.DeserializeObject <List <Topic> >(jobj["cards"].ToString()); topics.RemoveAll(p => p == null || p.card == null || p.card.Length < 10 || p.desc.status != 1); return(new Tuple <string, List <Topic> >(nextOffset, topics)); } catch (Exception) { } } return(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", BiliClient.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 = BiliFactory.UrlContact("", param, true); var response = await BiliClient.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> ClearViewLaterAsync() { string url = BiliFactory.UrlContact(Api.ACCOUNT_VIEWLATER_CLEAR, null, true); string content = await BiliClient.PostContentToWebAsync(url, ""); return(content != null); }
/// <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 = BiliFactory.UrlContact("", param, true); var response = await BiliClient.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 <MyMessage> GetMyUnreadMessageAsync() { string url = BiliFactory.UrlContact(Api.ACCOUNT_UNREAD, null, true); var data = await BiliClient.ConvertEntityFromWebAsync <MyMessage>(url); return(data); }
/// <summary> /// 获取动漫索引筛查结果 /// </summary> /// <param name="page">页码</param> /// <param name="type">分区类型</param> /// <param name="conditions">限制条件</param> /// <returns></returns> public async Task <Tuple <bool, List <AnimeIndexResult> > > GetBangumiIndexResultsAsync(int page, int type, List <KeyValueModel> conditions) { var param = new Dictionary <string, string>(); foreach (var item in conditions) { param.Add(item.Key, item.Value); } param.Add("type", "0"); param.Add("page", page.ToString()); param.Add("season_type", type.ToString()); param.Add("pagesize", "21"); string url = BiliFactory.UrlContact(Api.ANIME_INDEX_RESULT, param, true); var response = await BiliClient.GetStringFromWebAsync(url); try { if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); bool hasNext = jobj["has_next"].ToString() == "1"; var data = JsonConvert.DeserializeObject <List <AnimeIndexResult> >(jobj["list"].ToString()); return(new Tuple <bool, List <AnimeIndexResult> >(hasNext, data)); } } catch (Exception) { } return(null); }
/// <summary> /// 获取动漫区块综合信息 /// </summary> /// <param name="isJp"><c>true</c>代表番剧,<c>false</c>代表国创</param> /// <returns></returns> public async Task <List <AnimeModule> > GetAnimeSquareAsync(bool isJp = true) { string api = isJp ? Api.ANIME_JP_SQUARE : Api.ANIME_CHN_SQUARE; var url = BiliFactory.UrlContact(api, null, true); return(await BiliClient.ConvertEntityFromWebAsync <List <AnimeModule> >(url, "result.modules")); }
/// <summary> /// 不喜欢某视频 /// </summary> /// <param name="arg">参数</param> /// <param name="reason_id">原因ID</param> /// <param name="go">类型</param> /// <param name="isFeedback">标识是反馈还是不感兴趣</param> /// <returns></returns> public async Task <bool> DislikeRecommendVideoAsync(Args arg, int reason_id, string go, bool isFeedback = false) { var param = new Dictionary <string, string>(); param.Add("id", arg.aid.ToString()); param.Add("rid", arg.rid.ToString()); if (isFeedback) { param.Add("feedback_id", reason_id.ToString()); } else { param.Add("reason_id", reason_id.ToString()); } param.Add("goto", go); param.Add("mid", arg.up_id.ToString()); param.Add("tag_id", arg.tid.ToString()); var url = BiliFactory.UrlContact(Api.VIDEO_RECOMMEND_DISLIKE, param, true); var response = await BiliClient.GetStringFromWebAsync(url); if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); return(jobj["code"].ToString() == "0"); } return(false); }
/// <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 BiliClient.PostContentToWebAsync(Api.VIDEO_FAVORITE, BiliFactory.UrlContact("", param, true)); if (!string.IsNullOrEmpty(result)) { var jobj = JObject.Parse(result); return(jobj["code"].ToString() == "0"); } 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={BiliFactory.AndroidKey.Appkey}&build={BiliFactory.BuildNumber}&mobi_app=android&password={Uri.EscapeDataString(await BiliFactory.EncryptAsPasswordAsync(password))}&platform=android&ts={BiliFactory.GetNowSeconds()}&username={Uri.EscapeDataString(userName)}"; if (!string.IsNullOrEmpty(captcha)) { param += "&captcha=" + captcha; } param += "&sign=" + BiliFactory.GetSign(param); string response = await BiliClient.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, BiliFactory.GetTimeStampFuture(data.token_info.expires_in)); InitToken(package); TokenChanged?.Invoke(this, package); result.Status = LoginResultType.Success; await SSO(); await GetUserSpaceAsync(286725648); } 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> /// <returns></returns> public async Task <Me> GetMeAsync() { var url = BiliFactory.UrlContact(Api.ACCOUNT_MINE, hasAccessKey: true); var data = await BiliClient.ConvertEntityFromWebAsync <Me>(url); Me = data; BiliClient.Mid = _userId = data.mid.ToString(); return(data); }
/// <summary> /// 获取标签信息 /// </summary> /// <param name="tagId">标签ID</param> /// <returns></returns> public async Task <ChannelTag> GetTagDetail(int tagId) { var param = new Dictionary <string, string>(); param.Add("channel_id", tagId.ToString()); string url = BiliFactory.UrlContact(Api.CHANNEL_TAG_TAB, param, true); var data = await BiliClient.ConvertEntityFromWebAsync <ChannelTag>(url); return(data); }
/// <summary> /// 获取回复我的列表 /// </summary> /// <param name="replyTime">偏移值(上次请求的底部时间戳)</param> /// <returns></returns> public async Task <FeedReplyResponse> GetReplyMeListAsync(int replyTime = 0) { var param = new Dictionary <string, string>(); param.Add("reply_time", replyTime.ToString()); string url = BiliFactory.UrlContact(Api.ACCOUNT_FEEDBACK_REPLY, param, true); var response = await BiliClient.ConvertEntityFromWebAsync <FeedReplyResponse>(url); return(response); }
/// <summary> /// 获取我的关注的分组 /// </summary> /// <returns></returns> public async Task <List <FollowTag> > GetMyFollowTagsAsync() { var param = new Dictionary <string, string>(); param.Add("vmid", BiliClient.Mid); string url = BiliFactory.UrlContact(Api.ACCOUNT_RELATION_FOLLOW_TAGS, param, true); var data = await BiliClient.ConvertEntityFromWebAsync <List <FollowTag> >(url); return(data); }
/// <summary> /// 获取表情包 /// </summary> /// <returns></returns> public async Task <List <EmojiReplyContainer> > GetUserEmojiAsync() { var param = new Dictionary <string, string>(); param.Add("business", "reply"); string url = BiliFactory.UrlContact(Api.ACCOUNT_EMOJI_PANEL, param, true); var items = await BiliClient.ConvertEntityFromWebAsync <List <EmojiReplyContainer> >(url, "data.packages"); return(items); }
/// <summary> /// 获取用户空间信息(经过删减) /// </summary> /// <param name="uid">用户ID</param> /// <returns></returns> public async Task <UserResponse> GetUserSpaceAsync(int uid) { var param = new Dictionary <string, string>(); param.Add("vmid", uid.ToString()); string url = BiliFactory.UrlContact(Api.ACCOUNT_USER_SPACE, param, true); var data = await BiliClient.ConvertEntityFromWebAsync <UserResponse>(url); return(data); }
/// <summary> /// 获取区块刷新信息 /// </summary> /// <param name="type">类型</param> /// <param name="moduleId">模块ID</param> /// <returns></returns> public async Task <List <AnimeModuleItem> > GetAnimeSectionExchange(int type, int moduleId) { var param = new Dictionary <string, string>(); param.Add("type", type.ToString()); param.Add("oid", moduleId.ToString()); string url = BiliFactory.UrlContact(Api.ANIME_EXCHANGE, param, true); return(await BiliClient.ConvertEntityFromWebAsync <List <AnimeModuleItem> >(url, "result")); }
/// <summary> /// 获取视频分P /// </summary> /// <param name="aid">视频avid</param> /// <returns></returns> public async Task <List <VideoPart> > GetVideoPartsAsync(int aid) { var param = new Dictionary <string, string>(); param.Add("aid", aid.ToString()); string url = BiliFactory.UrlContact(Api.VIDEO_PART, param, true); var parts = await BiliClient.ConvertEntityFromWebAsync <List <VideoPart> >(url); return(parts); }
/// <summary> /// 获取视频简易信息 /// </summary> /// <param name="aid">视频avid</param> /// <returns></returns> public async Task <VideoSlim> GetVideoSlimAsync(int aid) { var param = new Dictionary <string, string>(); param.Add("aid", aid.ToString()); string url = BiliFactory.UrlContact(Api.VIDEO_SLIM_INFO, param, true); var data = await BiliClient.ConvertEntityFromWebAsync <VideoSlim>(url); return(data); }
/// <summary> /// 获取视频相关 /// </summary> /// <param name="aid">视频avid</param> /// <returns></returns> public async Task <List <VideoDetail> > GetVideoRelatedAsync(int aid) { var param = new Dictionary <string, string>(); param.Add("aid", aid.ToString()); string url = BiliFactory.UrlContact(Api.VIDEO_RELATED, param, true); var data = await BiliClient.ConvertEntityFromWebAsync <List <VideoDetail> >(url); return(data); }
/// <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", BiliClient.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 = BiliFactory.UrlContact("", param, true); var response = await BiliClient.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="id">上次请求的Id</param> /// <param name="likeTime">上次请求的底部时间戳</param> /// <returns></returns> public async Task <FeedLikeResponse> GetLikeMeListAsync(long id, int likeTime = 0) { var param = new Dictionary <string, string>(); param.Add("id", id.ToString()); param.Add("at_time", likeTime.ToString()); string url = BiliFactory.UrlContact(Api.ACCOUNT_FEEDBACK_LIKE, param, true); var response = await BiliClient.ConvertEntityFromWebAsync <FeedLikeResponse>(url); return(response); }