/// <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", BiliTool.mid); param.Add("offset_dynamic_id", offset); param.Add("rsp_type", "2"); param.Add("type_list", "268435455"); string url = BiliTool.UrlContact(Api.DYNAMIC_HISTORY, param, true); var data = await BiliTool.GetTextFromWebAsync(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="aid">番剧类型标识</param> /// <param name="cid">视频分Pid</param> /// <param name="qn">分辨率ID</param> /// <returns></returns> public async Task <VideoPlayBase> GetBangumiPlayAsync(int type, int cid, int qn = 64) { var param = new Dictionary <string, string>(); param.Add("module", "bangumi"); param.Add("season_type", type.ToString()); param.Add("cid", cid.ToString()); param.Add("qn", qn.ToString()); param.Add("fnver", "0"); param.Add("otype", "json"); param.Add("fnval", "16"); string url = BiliTool.UrlContact(Api.ANIME_PLAY, param, true, true); var data = await BiliTool.GetTextFromWebAsync(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 = BiliTool.UrlContact(Api.CHANNEL_VIDEO, param, true); string content = await BiliTool.GetTextFromWebAsync(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> /// <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(BiliTool.mid)) { param.Add("visitor_uid", BiliTool.mid); } param.Add("offset_dynamic_id", offset_id); param.Add("page", page.ToString()); string url = BiliTool.UrlContact(Api.DYNAMIC_USER_HISTORY, param, true); var data = await BiliTool.GetTextFromWebAsync(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 = BiliTool.UrlContact(Api.ACCOUNT_MEDIALIST, param, true); string response = await BiliTool.GetTextFromWebAsync(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="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 = BiliTool.UrlContact(Api.VIDEO_RECOMMEND_DISLIKE, param, true); var response = await BiliTool.GetTextFromWebAsync(url, true); if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); return(jobj["code"].ToString() == "0"); } return(false); }
/// <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 = BiliTool.UrlContact(Api.ANIME_INDEX_RESULT, param, true); var response = await BiliTool.GetTextFromWebAsync(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> /// Cookie转化处理 /// </summary> /// <returns></returns> public async Task SSO() { try { var url = BiliTool.UrlContact(Api.PASSPORT_SSO, hasAccessKey: true); await BiliTool.GetTextFromWebAsync(url, true); } catch (Exception) { } }
/// <summary> /// 获取关注者的未读消息数 /// </summary> /// <returns></returns> public async Task <int> GetFollowerUnreadCountAsync() { string url = BiliTool.UrlContact(Api.APP_FOLLOWER_UNREAD, null, true); string response = await BiliTool.GetTextFromWebAsync(url); if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); return(Convert.ToInt32(jobj["count"].ToString())); } return(-1); }
/// <summary> /// 不喜欢某番剧 /// </summary> /// <param name="arg">参数</param> /// <returns></returns> public async Task <bool> DislikeRecommendVideoAsync(string bangumiId) { var param = new Dictionary <string, string>(); param.Add("id", bangumiId); param.Add("goto", "bangumi"); param.Add("reason_id", "1"); var url = BiliTool.UrlContact(Api.VIDEO_RECOMMEND_DISLIKE, param, true); var response = await BiliTool.GetTextFromWebAsync(url, true); 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="cid">分PID</param> /// <returns></returns> public async Task <List <SubtitleIndexItem> > GetVideoSubtitleIndexAsync(int aid, int cid) { var param = new Dictionary <string, string>(); param.Add("id", $"cid:{cid}"); param.Add("aid", aid.ToString()); string url = BiliTool.UrlContact(Api.VIDEO_SUBTITLE, param, true); string result = await BiliTool.GetTextFromWebAsync(url, true, needReferer : true); if (!string.IsNullOrEmpty(result) && result.Contains("subtitle")) { var json = Regex.Match(result, @"<subtitle>(.*?)</subtitle>").Groups[1].Value; var index = JsonConvert.DeserializeObject <VideoSubtitleIndex>(json); return(index.subtitles); } return(null); }
/// <summary> /// 加载默认的分区内容 /// </summary> /// <param name="rid">分区ID</param> /// <param name="ctime">偏移值</param> /// <returns></returns> public async Task <Tuple <List <RegionBanner>, int, List <RegionVideo> > > GetRegionSquareAsync(int rid, int ctime = 0) { var param = new Dictionary <string, string>(); param.Add("rid", rid.ToString()); param.Add("pull", "0"); string api = ""; if (ctime == 0) { api = Api.REGION_DYNAMIC_INIT; } else { api = Api.REGION_DYNAMIC_REFRESH; param.Add("ctime", ctime.ToString()); } string url = BiliTool.UrlContact(api, param, true); string content = await BiliTool.GetTextFromWebAsync(url); if (!string.IsNullOrEmpty(content)) { var jobj = JObject.Parse(content); var list = new List <RegionVideo>(); List <RegionBanner> banner = new List <RegionBanner>(); if (jobj.ContainsKey("banner")) { var ban = JsonConvert.DeserializeObject <List <RegionBanner> >(jobj["banner"]["top"].ToString()); ban.ForEach(p => banner.Add(p)); } if (jobj.ContainsKey("recommend")) { var rec = JsonConvert.DeserializeObject <List <RegionVideo> >(jobj["recommend"].ToString()); rec.ForEach(p => list.Add(p)); } if (jobj.ContainsKey("new")) { var news = JsonConvert.DeserializeObject <List <RegionVideo> >(jobj["new"].ToString()); news.ForEach(p => list.Add(p)); } var result = new Tuple <List <RegionBanner>, int, List <RegionVideo> >(banner, Convert.ToInt32(jobj["cbottom"]), list); return(result); } return(null); }
/// <summary> /// 检查用户是否投币 /// </summary> /// <param name="epid">标识ID</param> /// <returns></returns> public async Task <bool> CheckUserCoinAsync(int epid) { var param = new Dictionary <string, string>(); param.Add("ep_id", epid.ToString()); string url = BiliTool.UrlContact(Api.ANIME_CHECK_COIN, param, true); try { var num = await BiliTool.GetTextFromWebAsync(url, false, "result.number"); return(Convert.ToInt32(num) > 0); } catch (Exception) { return(false); } }
/// <summary> /// 检查视频状态(是否投币,点赞,收藏等) /// </summary> /// <param name="aid">视频ID</param> /// <param name="type">检查类型</param> /// <returns></returns> public async Task <bool> CheckVideoStatusAsync(int aid, string type = "like") { var param = new Dictionary <string, string>(); param.Add("aid", aid.ToString()); string url = ""; switch (type) { case "like": url = Api.VIDEO_IS_LIKE; break; case "coin": url = Api.VIDEO_IS_COIN; break; case "favorite": url = Api.VIDEO_IS_FAVORITE; break; } url = BiliTool.UrlContact(url, param, true); var content = await BiliTool.GetTextFromWebAsync(url); if (type == "like") { return(content == "1"); } else { var jobj = JObject.Parse(content); if (type == "coin") { return(jobj["multiply"].ToString() == "1"); } else if (type == "favorite") { return(Convert.ToBoolean(jobj["favoured"])); } } return(false); }
/// <summary> /// 检查令牌状态 /// </summary> /// <returns></returns> public async Task <bool> CheckTokenStatusAsync() { try { var param = new Dictionary <string, string>(); param.Add("access_token", _accessToken); var url = BiliTool.UrlContact(Api.PASSPORT_CHECK_TOKEN, param); var content = await BiliTool.GetTextFromWebAsync(url, true); var obj = JObject.Parse(content); if (Convert.ToInt32(obj["code"]) == 0) { return(true); } } catch (Exception) { } return(false); }
/// <summary> /// 获取频道页综合信息 /// </summary> /// <returns></returns> public async Task <ChannelSquare> GetSquareAsync() { var param = new Dictionary <string, string>(); _squareChannelOffset = _squareChannelOffset > 100 ? 15 : _squareChannelOffset + 15; param.Add("offset_rcmd", _squareChannelOffset.ToString()); param.Add("pn", "0"); param.Add("qn", "32"); param.Add("spmid", "traffic.channel-square.0.0"); string url = BiliTool.UrlContact(Api.CHANNEL_SQUARE, param, true); string content = await BiliTool.GetTextFromWebAsync(url); if (!string.IsNullOrEmpty(content)) { try { var jarr = JArray.Parse(content); string subString = jarr.Where(p => p["model_type"].ToString() == "subscribe").First().SelectToken("items").ToString(); var subscribes = JsonConvert.DeserializeObject <List <ChannelSlim> >(subString); subscribes.RemoveAll(p => p.id == 0); var square = new ChannelSquare() { Subscribes = subscribes }; if (!string.IsNullOrEmpty(BiliTool._accessToken)) { var scanToken = jarr.Where(p => p["model_type"].ToString() == "scaned").FirstOrDefault(); if (scanToken != null) { var scaneds = JsonConvert.DeserializeObject <List <ChannelView> >(scanToken.SelectToken("items").ToString()); square.Scaneds = scaneds; } } return(square); } catch (Exception) { } } return(null); }
private async void BackupWebView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args) { if (args.Uri == null) { return; } if (args.Uri.AbsoluteUri == "https://passport.bilibili.com/ajax/miniLogin/redirect") { var results = await BiliTool.GetTextFromWebAsync("https://passport.bilibili.com/login/app/third?appkey=27eb53fc9058f8c3&api=http%3A%2F%2Flink.acg.tv%2Fforum.php&sign=67ec798004373253d60114caaad89a8c", true); var obj = JObject.Parse(results); if (Convert.ToInt32(obj["code"].ToString()) == 0) { BackupWebView.Navigate(new Uri(obj["data"]["confirm_uri"].ToString())); } else { new TipPopup("登陆失败,请重试").ShowError(); } } }
/// <summary> /// 获取评论列表 /// </summary> /// <param name="oid">源ID</param> /// <param name="next">下一页偏移值</param> /// <param name="mode">排序方式:3-按热度,2-按时间</param> /// <returns>Item1:下一次偏移值,Item2:评论总数,Item3:评论列表,Item4: 是否到了结尾,Item5: 置顶回复</returns> public async Task <Tuple <int, int, List <Reply>, bool, Reply> > GetReplyAsync(string oid, int next, int mode, string type = "1") { var param = new Dictionary <string, string>(); param.Add("oid", oid); param.Add("next", next.ToString()); param.Add("prev", "0"); param.Add("type", type); param.Add("mode", mode.ToString()); param.Add("ps", "30"); param.Add("plat", "3"); var url = BiliTool.UrlContact(Api.REPLY_LIST, param, true); string response = await BiliTool.GetTextFromWebAsync(url); if (!string.IsNullOrEmpty(response)) { try { var jobj = JObject.Parse(response); int ne = Convert.ToInt32(jobj["cursor"]["next"].ToString()); int all = Convert.ToInt32(jobj["cursor"]["all_count"].ToString()); bool isEnd = Convert.ToBoolean(jobj["cursor"]["is_end"].ToString()); Reply top = null; if (jobj["top"]["upper"].Type != JTokenType.Null) { top = JsonConvert.DeserializeObject <Reply>(jobj["top"]["upper"].ToString()); } var replies = JsonConvert.DeserializeObject <List <Reply> >(jobj["replies"].ToString()); return(new Tuple <int, int, List <Reply>, bool, Reply>(ne, all, replies, isEnd, top)); } catch (Exception) { return(null); } } else { return(null); } }
/// <summary> /// 获取Emoji表情列表 /// </summary> /// <returns></returns> public async Task <List <EmojiContainer> > GetTotalEmojiAsync() { string response = await BiliTool.GetTextFromWebAsync(Api.APP_EMOJI); var list = new List <EmojiContainer>(); if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); if (jobj.ContainsKey("vip")) { var vips = JsonConvert.DeserializeObject <List <EmojiContainer> >(jobj["vip"].ToString()); list = list.Concat(vips).ToList(); } if (jobj.ContainsKey("free")) { var frees = JsonConvert.DeserializeObject <List <EmojiContainer> >(jobj["free"].ToString()); list = list.Concat(frees).ToList(); } } return(list); }
/// <summary> /// 测试请求,验证网络是否可访问 /// </summary> /// <returns></returns> public async Task <bool> ValidateRequestAsync() { string url = Api.OTHER_ZONE; string response = await BiliTool.GetTextFromWebAsync(url, true); try { if (!string.IsNullOrEmpty(response)) { var jobj = JObject.Parse(response); if (jobj["code"].ToString() == "0") { return(true); } } } catch (Exception ex) { return(false); } return(false); }
/// <summary> /// 获取我正在追的影视剧 /// </summary> /// <returns></returns> public async Task <Tuple <int, List <FavoriteAnime> > > GetMyFavoriteCinemaAsync(int page = 1) { var param = new Dictionary <string, string>(); param.Add("ps", "20"); param.Add("pn", page.ToString()); param.Add("status", "2"); string url = BiliTool.UrlContact(Api.ACCOUNT_FAVOROTE_CINEMA, param, true); var respons = await BiliTool.GetTextFromWebAsync(url, false, "result"); if (!string.IsNullOrEmpty(respons)) { var jobj = JObject.Parse(respons); var list = JsonConvert.DeserializeObject <List <FavoriteAnime> >(jobj["follow_list"]?.ToString() ?? "[]"); if (list == null) { list = new List <FavoriteAnime>(); } var total = Convert.ToInt32(jobj["total"].ToString()); return(new Tuple <int, List <FavoriteAnime> >(total, list)); } return(null); }
/// <summary> /// 获取话题动态 /// </summary> /// <param name="topicId">话题ID</param> /// <param name="topicName">话题名</param> /// <param name="offset">偏移值,初次不需要,每次请求会返回下一次请求的偏移值</param> /// <returns>Item1:下次偏移值;Item2:视频列表</returns> public async Task <Tuple <string, List <Topic> > > GetTopicAsync(int topicId, string topicName, string offset = "") { var param = new Dictionary <string, string>(); param.Add("topic_id", topicId.ToString()); param.Add("topic_name", Uri.EscapeDataString(topicName)); //param.Add("video_meta", "qn:32,fnval:16,fnver:0,fourk:1"); if (!string.IsNullOrEmpty(offset)) { param.Add("offset", offset); } string url = BiliTool.UrlContact(Api.TOPIC_COMPLEX, param, true); var data = await BiliTool.GetTextFromWebAsync(url); if (!string.IsNullOrEmpty(data)) { var jobj = JObject.Parse(data); string nextOffset = jobj["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)); } return(null); }