/// <summary> /// 读缓存 /// </summary> /// <param name="key">查询的键名</param> /// <param name="ExTime">超时时间,0为永远有效</param> /// <param name="data">查询到的结果</param> /// <returns>该键名是否有对应的数据</returns> public static bool 读缓存(string key, double ExTime, out string data) { data = null; try { if (DataCache.缓存创建时间.TryGetValue(key, out DateTime Cache)) { TimeSpan TS = DateTime.Now - Cache; if ((TS.TotalSeconds < ExTime || ExTime == 0) && DataCache.缓存队列.TryGetValue(key, out string CacheData)) { data = CacheData; InfoLog.InfoPrintf("缓存命中,读取数据:" + key + "|" + CacheData, InfoLog.InfoClass.Debug); return(true); } else { InfoLog.InfoPrintf("命中缓存,但数据已过期,返回false:" + key, InfoLog.InfoClass.Debug); } } return(false); } catch (Exception ex) { InfoLog.InfoPrintf($"读缓存异常:{ex}", InfoLog.InfoClass.Debug); return(false); } }
/// <summary> /// 关闭直播流和弹幕储存流 /// </summary> public static void Clear(bool 续命模式, DownIofoData DOL) { //DOL.备注 = "下载任务结束"; DOL.载状态 = false; if (!续命模式) { try { DOL.阿B直播流对象.Dispose(); InfoLog.InfoPrintf($"{DOL.房间_频道号}房间直播流对象回收完成", InfoLog.InfoClass.Debug); } catch (Exception) { } try { DOL.弹幕储存流.Close(); DOL.弹幕储存流.Dispose(); InfoLog.InfoPrintf($"{DOL.房间_频道号}房间弹幕储存流对象回收完成", InfoLog.InfoClass.Debug); } catch (Exception) { } try { DOL.礼物储存流.Close(); DOL.礼物储存流.Dispose(); InfoLog.InfoPrintf($"{DOL.房间_频道号}房间礼物储存流对象回收完成", InfoLog.InfoClass.Debug); } catch (Exception) { } } try { DOL.WC.Dispose(); InfoLog.InfoPrintf($"{DOL.房间_频道号}房间WebClient对象回收完成", InfoLog.InfoClass.Debug); } catch (Exception) { } }
public static string 载完成合并FLV(DownIofoData downIofo, bool 是否直播结束) { string filename = string.Empty; List <string> DelFileList = new List <string>(); if (downIofo.继承.待合并文件列表.Count > 1) { filename = downIofo.继承.待合并文件列表[0]; for (int i = 0; i < downIofo.继承.待合并文件列表.Count - 1; i++) { DelFileList.Add(downIofo.继承.待合并文件列表[i + 1]); FlvMethod.Flv A = new FlvMethod.Flv() { File1Url = filename, File2Url = downIofo.继承.待合并文件列表[i + 1] }; DelFileList.Add(filename); string BB = FlvMethod.FlvSum(A, 是否直播结束); if (string.IsNullOrEmpty(BB)) { InfoLog.InfoPrintf($"{downIofo.房间_频道号}:{downIofo.主播名称}因为网络连接不稳定,无法获取文件头,放弃合并该flv", InfoLog.InfoClass.载必要提示); return(filename); } filename = BB; } } foreach (var item in DelFileList) { MMPU.文件删除委托(item, "FLV合并任务"); } return(filename); }
public static void 载任务状态检测() { foreach (var item in MMPU.DownList) { if (!item.DownIofo.网络超时 && item.DownIofo.载状态 && item.DownIofo.已下载大小bit > 10000 && item.DownIofo.最后连接时间 != 0 && Gettime() - item.DownIofo.最后连接时间 > 60) { InfoLog.InfoPrintf(item.DownIofo.房间_频道号 + "下载状态异常,重置下载任务", InfoLog.InfoClass.载必要提示); item.DownIofo.网络超时 = true; item.DownIofo.备注 = "下载状态异常,重置下载任务"; Clear(true, item.DownIofo); item.DownIofo.载状态 = false; item.DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); item.DownIofo.WC.CancelAsync(); new Task(() => { string 标题 = bilibili.根据房间号获取房间信息.获取标题(item.DownIofo.标题); if (string.IsNullOrEmpty(标题)) { 标题 = $"重置下载任务{DateTime.Now.ToString("yyyyMMddHHmmssfff")}{new Random().Next(10000,99999)}"; } Downloader DLL = Downloader.新建下载对象(item.DownIofo.平台, item.DownIofo.房间_频道号, bilibili.根据房间号获取房间信息.获取标题(item.DownIofo.标题), Guid.NewGuid().ToString(), bilibili.根据房间号获取房间信息.载地址(item.DownIofo.标题), "下载状态异常,重置下载任务", item.DownIofo.是否保存, item.DownIofo.主播名称, false, null); }).Start(); Upload.UploadTask uploadTask = new Upload.UploadTask(item.DownIofo); uploadTask.UploadVideo(); } } }
new public static void start() { InitializeRoomConfigFile(); InitializeRoomList(0, false, false); bilibili.start(); youtube.start(); Task.Run(async() => { InfoLog.InfoPrintf("开始周期轮询bilibili房间开播状态", InfoLog.InfoClass.Debug); while (true) { 刷新B站房间列表(); bilibili房间信息更新次数++; await Task.Delay(5 * 1000).ConfigureAwait(false); } }); Task.Run(async() => { InfoLog.InfoPrintf("开始周期轮询youtube频道开播状态", InfoLog.InfoClass.Debug); while (true) { 刷新youtube站房间列表(); youtube房间信息更新次数++; await Task.Delay(5 * 1000).ConfigureAwait(false); } }); }
/// <summary> /// 写缓存 /// </summary> /// <param name="key">写入的键名</param> /// <param name="value">写入的值</param> /// <param name="TS"></param> public static void 写缓存(string key, string value) { try { if (缓存队列.ContainsKey(key)) { 缓存队列[key] = value; } else { 缓存队列.Add(key, value); } if (缓存创建时间.ContainsKey(key)) { 缓存创建时间[key] = DateTime.Now; } else { 缓存创建时间.Add(key, DateTime.Now); } InfoLog.InfoPrintf("缓存未命中,缓存数据:" + key + "|" + value, InfoLog.InfoClass.Debug); DataCache.CacheCount++; } catch (Exception ex) { InfoLog.InfoPrintf($"写缓存异常:{ex}", InfoLog.InfoClass.Debug); } }
private static void 周期更新youtube频道状态() { int a = 0; InfoLog.InfoPrintf("本地房间状态缓存更新开始", InfoLog.InfoClass.Debug); foreach (var roomtask in RoomList) { if (MMPU.连接404使能) { RoomInit.RoomInfo A = GetRoomInfo(roomtask.房间号); if (A != null) { for (int i = 0; i < RoomList.Count(); i++) { if (RoomList[i].房间号 == A.房间号) { RoomList[i].平台 = A.平台; RoomList[i].标题 = A.标题; RoomList[i].UID = A.UID; RoomList[i].直播开始时间 = A.直播开始时间; RoomList[i].直播状态 = A.直播状态; RoomList[i].youtubeVideoId = A.youtubeVideoId; if (A.直播状态) { a++; } break; } } } } } InfoLog.InfoPrintf("本地房间状态更新结束", InfoLog.InfoClass.Debug); }
private static void Process_Exited(object sender, EventArgs e) { ProcessPuls P = (ProcessPuls)sender; InfoLog.InfoPrintf("转码任务完成:" + P.StartInfo.Arguments, InfoLog.InfoClass.载必要提示); if (MMPU.转码后自动删除文件) { MMPU.文件删除委托(P.OriginalVideoFilename, "转码完成自动,删除原始文件"); } }
/// <summary> /// 获取BILIBILI直播流下载地址 /// </summary> /// <param name="roomid">房间号</param> /// <param name="R">是否为重试</param> /// <returns></returns> public static string 载地址(string roomid) { roomid = 获取真实房间号(roomid); if (roomid == null) { InfoLog.InfoPrintf("房间号获取错误", InfoLog.InfoClass.Debug); return(null); } var apiUrl = "https://api.live.bilibili.com/room/v1/Room/playUrl?cid=" + roomid + "&otype=json&qn=10000&platform=web"; //访问API获取结果 var wc = new WebClient(); wc.Headers.Add("Accept: */*"); wc.Headers.Add("User-Agent: " + MMPU.UA.Ver.UA()); wc.Headers.Add("Accept-Language: zh-CN,zh;q=0.9,ja;q=0.8"); if (!string.IsNullOrEmpty(MMPU.Cookie)) { wc.Headers.Add("Cookie", MMPU.Cookie); } string resultString; try { resultString = wc.DownloadString(apiUrl); } catch (Exception e) { InfoLog.InfoPrintf("发送解析请求失败:" + e.Message, InfoLog.InfoClass.Debug); return(""); } //解析结果使用最高清晰度 try { MMPU.判断网络路径是否存在 判断文件是否存在 = new MMPU.判断网络路径是否存在(); string BBBC = ""; BBBC = (JObject.Parse(resultString)["data"]["durl"][0]["url"].ToString()); //BBBC = (JObject.Parse(resultString)["data"]["durl"][0]["url"].ToString() + "&platform=web").Replace("&pt=", "&pt=web") + "&pSession=" + Guid.NewGuid(); if (!判断文件是否存在.判断(BBBC, "bilibili", roomid)) { InfoLog.InfoPrintf("请求的开播房间当前推流数据为空,推测还未开播,等待数据流...:", InfoLog.InfoClass.Debug); BBBC = (JObject.Parse(resultString)["data"]["durl"][1]["url"].ToString()); } return(BBBC); } catch (Exception e) { InfoLog.InfoPrintf("视频流地址解析失败:" + e.Message, InfoLog.InfoClass.Debug); return(""); } }
/// <summary> /// 获取BILIBILI直播流下载地址 /// </summary> /// <param name="roomid">房间号</param> /// <param name="R">是否为重试</param> /// <returns></returns> public static string 载地址(string roomid) { roomid = 获取真实房间号(roomid); if (roomid == null) { InfoLog.InfoPrintf("房间号获取错误", InfoLog.InfoClass.Debug); return(null); } string resultString; try { resultString = MMPU.使用WC获取网络内容("https://api.live.bilibili.com/room/v1/Room/playUrl?cid=" + roomid + "&otype=json&qn=10000&platform=web"); } catch (Exception e) { InfoLog.InfoPrintf("发送解析请求失败:" + e.Message, InfoLog.InfoClass.Debug); return(""); } //解析结果使用最高清晰度 try { MMPU.判断网络路径是否存在 判断文件是否存在 = new MMPU.判断网络路径是否存在(); string BBBC = ""; BBBC = (JObject.Parse(resultString)["data"]["durl"][0]["url"].ToString()); //BBBC = (JObject.Parse(resultString)["data"]["durl"][0]["url"].ToString() + "&platform=web").Replace("&pt=", "&pt=web") + "&pSession=" + Guid.NewGuid(); if (!判断文件是否存在.判断(BBBC, "bilibili", roomid)) { InfoLog.InfoPrintf("请求的开播房间当前推流数据为空,推测还未开播,等待数据流...:", InfoLog.InfoClass.Debug); try { if ((JObject.Parse(resultString)["message"].ToString() == "房间已加密")) { InfoLog.InfoPrintf("房间已加密", InfoLog.InfoClass.载必要提示); return(""); } } catch (Exception) { } BBBC = (JObject.Parse(resultString)["data"]["durl"][1]["url"].ToString()); } DataCache.BilibiliApiCount++; return(BBBC); } catch (Exception e) { InfoLog.InfoPrintf("视频流地址解析失败:" + e.Message, InfoLog.InfoClass.系统错误信息); return(""); } }
/// <summary> /// 初始化房间配置文件 /// </summary> public static void InitializeRoomConfigFile() { try { ReadConfigFile(RoomConfigFile); InfoLog.InfoPrintf("房间配置信息加载完成", InfoLog.InfoClass.Debug); } catch (Exception) { File.WriteAllText(RoomConfigFile, "{}"); InfoLog.InfoPrintf("未检测到房间配置文件,生成一个新的缺省配置文件", InfoLog.InfoClass.Debug); } }
/// <summary> /// 获取房间的弹幕 /// </summary> /// <param name="RoomID">房间号</param> /// <returns></returns> public string getDanmaku(string RoomID) { string postString = "roomid=" + RoomID + "&token=&csrf_token="; byte[] postData = Encoding.UTF8.GetBytes(postString); string url = @"http://api.live.bilibili.com/ajax/msg"; List <danmuA> 返回的弹幕数据 = new List <danmuA>(); WebClient webClient = new WebClient(); webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"); webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); if (!string.IsNullOrEmpty(MMPU.Cookie)) { webClient.Headers.Add("Cookie", MMPU.Cookie); } byte[] responseData = webClient.UploadData(url, "POST", postData); string srcString = Encoding.UTF8.GetString(responseData);//解码 try { JObject jo = (JObject)JsonConvert.DeserializeObject(srcString); for (int i = 0; i < jo["data"]["room"].Count(); i++) { string text = jo["data"]["room"][i]["nickname"].ToString() + "㈨" + jo["data"]["room"][i]["text"].ToString(); if (储存的弹幕数据 == null) { 返回的弹幕数据.Add(new danmuA() { Name = jo["data"]["room"][i]["nickname"].ToString(), Text = jo["data"]["room"][i]["text"].ToString(), Time = jo["data"]["room"][i]["timeline"].ToString(), uid = jo["data"]["room"][i]["uid"].ToString() }); 储存的弹幕数据.Add(text); } if (!储存的弹幕数据.Contains(text)) { 返回的弹幕数据.Add(new danmuA() { Name = jo["data"]["room"][i]["nickname"].ToString(), Text = jo["data"]["room"][i]["text"].ToString(), Time = jo["data"]["room"][i]["timeline"].ToString(), uid = jo["data"]["room"][i]["uid"].ToString() }); 储存的弹幕数据.Add(text); } } } catch (Exception ex) { InfoLog.InfoPrintf("弹幕获取出现错误" + ex.ToString(), InfoLog.InfoClass.系统错误信息); } Thread.Sleep(600); return(JsonConvert.SerializeObject(返回的弹幕数据)); }
public static void 更新VTBS房间数据() { while (true) { int 完整错误次数 = 0; try { if (完整错误次数 >= 5) { InfoLog.InfoPrintf($"----------【重要】----------\r\n多次尝试获取服务器RoomList缓存失败,切换为纯WSS连接模式,该模式下初始化连接速度较慢,大约20连接一个房间\r\n----------【重要】----------", InfoLog.InfoClass.载必要提示); wss连接初始化准备已完成 = true; return; } string vtbs房间数据 = string.Empty; try { vtbs房间数据 = MMPU.返回网页内容_GET(VTBS.API.VTBS服务器CDN.VTBS_Url + "/v1/short", 5000); } catch (Exception) { InfoLog.InfoPrintf($"通过原始数据源更新VTBS房间数据失败,切换到备用DDTV服务器获取", InfoLog.InfoClass.Debug); vtbs房间数据 = MMPU.TcpSend(Server.RequestCode.GET_VTBSROOMLIST, "{}", true, 1500); } JArray JO = (JArray)JsonConvert.DeserializeObject(vtbs房间数据); //InfoLog.InfoPrintf($"获取VTBS房间数据完成:{JO}", InfoLog.InfoClass.Debug); foreach (var item in JO) { if (int.Parse(item["roomid"].ToString()) != 0) { VtbsRoomList.Add(new VtbsRoom() { mid = int.Parse(item["mid"].ToString()), room = int.Parse(item["roomid"].ToString()), name = item["uname"].ToString() }); } } InfoLog.InfoPrintf($"VTBS数据数据准备完成", InfoLog.InfoClass.Debug); wss连接初始化准备已完成 = true; break; } catch (Exception) { 完整错误次数++; InfoLog.InfoPrintf($"VTBS获取RoomList失败,再次重试,已重试次数{完整错误次数}/5", InfoLog.InfoClass.Debug); } Thread.Sleep(5000); } }
/// <summary> /// 读缓存 /// </summary> /// <param name="key">查询的键名</param> /// <param name="ExTime">超时时间,0为永远超时</param> /// <param name="data">查询到的结果</param> /// <returns>该键名是否有对应的数据</returns> public static bool 读缓存(string key, double ExTime, out string data) { data = null; if (DataCache.缓存创建时间.TryGetValue(key, out DateTime Cache)) { TimeSpan TS = DateTime.Now - Cache; if ((TS.TotalSeconds < ExTime || ExTime == 0) && DataCache.缓存队列.TryGetValue(key, out string CacheData)) { data = CacheData; InfoLog.InfoPrintf("缓存命中,读取数据:" + key + "|" + CacheData, InfoLog.InfoClass.Debug); return(true); } } return(false); }
public static RoomInit.RoomInfo GetRoomInfo(string originalRoomId) { string roomHtml; try { roomHtml = MMPU.使用WC获取网络内容("https://api.live.bilibili.com/room/v1/Room/get_info?id=" + originalRoomId); } catch (Exception e) { InfoLog.InfoPrintf(originalRoomId + "获取房间信息失败:" + e.Message, InfoLog.InfoClass.Debug); return(null); } //解析返回结果 try { JObject result = JObject.Parse(roomHtml); string uid = result["data"]["uid"].ToString(); if (result["data"]["room_id"].ToString() != originalRoomId) { for (int i = 0; i < RoomList.Count(); i++) { if (RoomList[i].房间号 == originalRoomId) { RoomList[i].房间号 = result["data"]["room_id"].ToString(); break; } } } var roominfo = new RoomInit.RoomInfo { 房间号 = result["data"]["room_id"].ToString(), 标题 = result["data"]["title"].ToString().Replace(" ", "").Replace("/", "").Replace("\\", "").Replace("\"", "").Replace(":", "").Replace("*", "").Replace("?", "").Replace("<", "").Replace(">", "").Replace("|", ""), 直播状态 = result["data"]["live_status"].ToString() == "1" ? true : false, UID = result["data"]["uid"].ToString(), 直播开始时间 = result["data"]["live_time"].ToString(), 平台 = "bilibili" }; InfoLog.InfoPrintf("获取到房间信息:" + roominfo.UID + " " + (roominfo.直播状态 ? "已开播" : "未开播") + " " + (roominfo.直播状态 ? "开播时间:" + roominfo.直播开始时间 : ""), InfoLog.InfoClass.Debug); DataCache.BilibiliApiCount++; return(roominfo); } catch (Exception e) { InfoLog.InfoPrintf(originalRoomId + "房间信息解析失败:" + e.Message, InfoLog.InfoClass.Debug); return(null); } }
public static string 获取真实房间号(string roomID) { string CacheStr = "byROOMIDgetTRUEroomid"; if (DataCache.读缓存(CacheStr + roomID, 0, out string CacheData)) { return(CacheData); } try { if (int.Parse(roomID) > 10000) { DataCache.写缓存(CacheStr + roomID, roomID); return(roomID); } } catch (Exception) { } string roomHtml; try { roomHtml = MMPU.使用WC获取网络内容("https://api.live.bilibili.com/room/v1/Room/get_info?id=" + roomID); } catch (Exception e) { InfoLog.InfoPrintf(roomID + "获取房间信息失败:" + e.Message, InfoLog.InfoClass.Debug); return(null); } //从返回结果中提取真实房间号 try { JObject result = JObject.Parse(roomHtml); //string live_status = result["data"]["live_status"].ToString(); //if (live_status != "1") //{ // return "-1"; //} string roomid = result["data"]["room_id"].ToString(); DataCache.写缓存(CacheStr + roomID, roomid); return(roomid); } catch { return(roomID); } }
public static string 获取标题(string roomid) { roomid = 获取真实房间号(roomid); if (roomid == null) { InfoLog.InfoPrintf("房间号获取错误", InfoLog.InfoClass.载必要提示); return(null); } var roomWebPageUrl = "https://api.live.bilibili.com/room/v1/Room/get_info?id=" + roomid; var wc = new WebClient(); wc.Headers.Add("Accept: */*"); wc.Headers.Add("User-Agent: " + MMPU.UA.Ver.UA()); wc.Headers.Add("Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4"); if (!string.IsNullOrEmpty(MMPU.Cookie)) { wc.Headers.Add("Cookie", MMPU.Cookie); } //发送HTTP请求 byte[] roomHtml; try { roomHtml = wc.DownloadData(roomWebPageUrl); } catch (Exception e) { InfoLog.InfoPrintf(roomid + "获取房间信息失败:" + e.Message, InfoLog.InfoClass.载必要提示); return(null); } //解析结果 try { var roomJson = Encoding.UTF8.GetString(roomHtml); var result = JObject.Parse(roomJson); string roomName = result["data"]["title"].ToString().Replace(" ", "").Replace("/", "").Replace("\\", "").Replace("\"", "").Replace(":", "").Replace("*", "").Replace("?", "").Replace("<", "").Replace(">", "").Replace("|", "").ToString(); InfoLog.InfoPrintf("根据RoomId获取到标题:" + roomName, InfoLog.InfoClass.Debug); return(roomName); } catch (Exception e) { InfoLog.InfoPrintf("视频标题解析失败:" + e.Message, InfoLog.InfoClass.Debug); return(""); } }
public static void 使用vtbsAPI更新房间状态() { try { JArray JO = (JArray)JsonConvert.DeserializeObject(MMPU.返回网页内容_GET("https://api.vtbs.moe/v1/living", 8000)); foreach (var roomtask in RoomList) { roomtask.直播状态 = false; if (JO.ToString().Contains(roomtask.房间号)) { roomtask.直播状态 = true; } else { roomtask.直播状态 = false; } } InfoLog.InfoPrintf("Vtbs数据加载成功", InfoLog.InfoClass.Debug); } catch (Exception e) { InfoLog.InfoPrintf("Vtbs数据加载失败,使用备用数据源开始获取", InfoLog.InfoClass.Debug); try { JArray JO = (JArray)JsonConvert.DeserializeObject(MMPU.TcpSend(Server.RequestCode.GET_LIVELSIT, "{}", true)); foreach (var roomtask in RoomList) { roomtask.直播状态 = false; if (JO.ToString().Contains(roomtask.房间号)) { roomtask.直播状态 = true; } else { roomtask.直播状态 = false; } } InfoLog.InfoPrintf("备用数据源加载成功", InfoLog.InfoClass.Debug); } catch (Exception) { InfoLog.InfoPrintf("备用缓存数据加载失败,使用原生阿Bapi开始获取开始获取", InfoLog.InfoClass.Debug); 使用B站API更新房间状态(); } } }
private JObject _getResponseJObject() { byte[] responseBytes; try { responseBytes = getWebClient().DownloadData(_request.Url); } catch (Exception e) { InfoLog.InfoPrintf($"[{_id}] {_request.ExceptionString}: {e.Message}", InfoLog.InfoClass.Debug); return(null); } var responseString = Encoding.UTF8.GetString(responseBytes); var jsonObject = JObject.Parse(responseString); return(jsonObject); }
public static void start() { Task.Run(async() => { InfoLog.InfoPrintf("启动youtube频道信息本地缓存更新线程", InfoLog.InfoClass.Debug); while (true) { try { 周期更新youtube频道状态(); await Task.Delay(MMPU.直播更新时间 * 1000); } catch (Exception e) { InfoLog.InfoPrintf("youtube频道信息本地缓存更新出现错误:" + e.ToString(), InfoLog.InfoClass.Debug); } } }); }
public static string 获取真实房间号(string roomID) { var roomWebPageUrl = "https://api.live.bilibili.com/room/v1/Room/get_info?id=" + roomID; var wc = new WebClient(); wc.Headers.Add("Accept: */*"); wc.Headers.Add("User-Agent: " + MMPU.UA.Ver.UA()); wc.Headers.Add("Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4"); if (!string.IsNullOrEmpty(MMPU.Cookie)) { wc.Headers.Add("Cookie", MMPU.Cookie); } //发送HTTP请求 byte[] roomHtml; try { roomHtml = wc.DownloadData(roomWebPageUrl); } catch (Exception e) { InfoLog.InfoPrintf(roomID + "获取房间信息失败:" + e.Message, InfoLog.InfoClass.Debug); return(null); } //从返回结果中提取真实房间号 try { var roomJson = Encoding.UTF8.GetString(roomHtml); var result = JObject.Parse(roomJson); var live_status = result["data"]["live_status"].ToString(); if (live_status != "1") { return("-1"); } var roomid = result["data"]["room_id"].ToString(); InfoLog.InfoPrintf("获取到真实房间号: " + roomid, InfoLog.InfoClass.杂项提示); return(roomid); } catch { return(roomID); } }
public static string 通过UID获取房间号(string uid) { var wc = new WebClient(); wc.Headers.Add("Accept: */*"); wc.Headers.Add("Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4"); //发送HTTP请求 byte[] roomHtml = wc.DownloadData("https://api.live.bilibili.com/room/v1/Room/getRoomInfoOld?mid=" + uid); var result = JObject.Parse(Encoding.UTF8.GetString(roomHtml)); string roomId = result["data"]["roomid"].ToString(); InfoLog.InfoPrintf("根据UID获取到房间号:" + roomId, InfoLog.InfoClass.Debug); return(roomId); }
public static string 获取标题(string roomID) { string CacheStr = "byRoomIdgetRoomTitle"; if (DataCache.读缓存(CacheStr + roomID, 20, out string CacheData)) { return(CacheData); } roomID = 获取真实房间号(roomID); if (roomID == null) { InfoLog.InfoPrintf("房间号获取错误", InfoLog.InfoClass.Debug); return(null); } string roomHtml; try { roomHtml = MMPU.使用WC获取网络内容("https://api.live.bilibili.com/room/v1/Room/get_info?id=" + roomID); } catch (Exception e) { InfoLog.InfoPrintf(roomID + "获取房间信息失败:" + e.Message, InfoLog.InfoClass.载必要提示); return(null); } //解析结果 try { JObject result = JObject.Parse(roomHtml); string roomName = result["data"]["title"].ToString().Replace(" ", "").Replace("/", "").Replace("\\", "").Replace("\"", "").Replace(":", "").Replace("*", "").Replace("?", "").Replace("<", "").Replace(">", "").Replace("|", "").ToString(); InfoLog.InfoPrintf("根据RoomId获取到标题:" + roomName, InfoLog.InfoClass.Debug); DataCache.写缓存(CacheStr + roomID, roomName); return(roomName); } catch (Exception e) { InfoLog.InfoPrintf("视频标题解析失败:" + e.Message, InfoLog.InfoClass.Debug); return(""); } }
public static void ByQRCode_QrCodeStatus_Changed(ByQRCode.QrCodeStatus status, Account account = null) { if (status == ByQRCode.QrCodeStatus.Success) { BiliUser.account = account; InfoLog.InfoPrintf("UID:" + account.Uid + ",登陆成功", InfoLog.InfoClass.杂项提示); //MessageBox.Show("UID:"+account.Uid+",登陆成功"); MMPU.UID = account.Uid; MMPU.写ini配置文件("User", "UID", MMPU.UID, MMPU.BiliUserFile); foreach (var item in account.Cookies) { MMPU.Cookie = MMPU.Cookie + item + ";"; } MMPU.CookieEX = account.Expires_Cookies; MMPU.csrf = account.CsrfToken; ; MMPU.写ini配置文件("User", "csrf", MMPU.csrf, MMPU.BiliUserFile); MMPU.写ini配置文件("User", "Cookie", Encryption.AesStr(MMPU.Cookie, MMPU.AESKey, MMPU.AESVal), MMPU.BiliUserFile); MMPU.写ini配置文件("User", "CookieEX", MMPU.CookieEX.ToString("yyyy-MM-dd HH:mm:ss"), MMPU.BiliUserFile); } }
public static void start() { new Task(() => { #region MyRegion while (true) { try { 更新VTBS房间数据(); Thread.Sleep(1000 * 60 * 60); } catch (Exception) { } } #endregion }).Start(); Task.Run(async() => { InfoLog.InfoPrintf("启动房间信息本地缓存更新线程", InfoLog.InfoClass.Debug); //是否启动WS连接组 = MMPU.读取exe默认配置文件("DataSource", "0") == "1" ? true : MMPU.读取exe默认配置文件("NotVTBStatus", "0") == "1"; if (是否启动WS连接组) { new Task(() => { 持续连接获取阿B房间信息类.初始化所有房间连接(); }).Start(); } while (true) { try { 周期更新B站房间状态(); await Task.Delay(MMPU.直播更新时间 * 1000); } catch (Exception e) { InfoLog.InfoPrintf("房间信息本地缓存更新出现错误:" + e.ToString(), InfoLog.InfoClass.Debug); } } }); }
public static void 周期更新B站房间状态() { if (!是否正在更新房间信息) { 是否正在更新房间信息 = true; InfoLog.InfoPrintf("本地房间状态缓存更新开始", InfoLog.InfoClass.Debug); switch (MMPU.数据源) { case 0: { 使用vtbsAPI更新房间状态(); InfoLog.InfoPrintf("本地房间状态更新结束", InfoLog.InfoClass.Debug); 是否正在更新房间信息 = false; break; } case 1: { //启动WS房间连接 是否正在更新房间信息 = false; break; } case 2: { 使用B站API更新房间状态(); InfoLog.InfoPrintf("当前阿B API调用次数为:" + DataCache.BilibiliApiCount, InfoLog.InfoClass.杂项提示); InfoLog.InfoPrintf("本地房间状态更新结束", InfoLog.InfoClass.Debug); 是否正在更新房间信息 = false; break; } default: break; } 是否正在更新房间信息 = false; } }
public void 载结束提醒(bool 是否结束弹幕录制, string 提醒标题, DownIofoData DOL) { try { if (是否结束弹幕录制 && MMPU.录制弹幕 && MMPU.弹幕录制种类 == 2) { try { DOL.弹幕储存流.WriteLine("</i>"); DOL.弹幕储存流.Flush();//写入弹幕数据 } catch (Exception) { } if (DOL != DownIofo) { Clear(false, DownIofo); } Clear(false, DOL); } else { Clear(true, DOL); } } catch (Exception) { } InfoLog.InfoPrintf($"\r\n=============={提醒标题}================\r\n" + $"主播名:{DOL.主播名称}" + $"\r\n房间号:{DOL.房间_频道号}" + $"\r\n标题:{DOL.标题}" + $"\r\n开播时间:{MMPU.Unix转换为DateTime(DOL.开始时间.ToString())}" + $"\r\n结束时间:{MMPU.Unix转换为DateTime(DOL.结束时间.ToString())}" + $"\r\n保存路径:{DOL.文件保存路径}" + $"\r\n下载任务类型:{(DOL.继承.是否为继承对象 ? "续下任务" : "新建下载任务")}" + $"\r\n结束原因:{DOL.备注}" + $"\r\n==============={提醒标题}===============\r\n", InfoLog.InfoClass.载必要提示); }
new public static void start() { InitializeRoomConfigFile(); InitializeRoomList(0, false, false); bilibili.start(); //youtube.start(); Task.Run(async() => { InfoLog.InfoPrintf("开始周期轮询bilibili房间开播状态", InfoLog.InfoClass.Debug); while (true) { try { 刷新B站房间列表(); bilibili房间信息更新次数++; await Task.Delay(5 * 1000).ConfigureAwait(false); } catch (Exception e) { InfoLog.InfoPrintf($"在常规主线程B2中发生严重错误,错误堆栈内容:\n{e}", InfoLog.InfoClass.系统错误信息); } } }); //Task.Run(async () => //{ // InfoLog.InfoPrintf("开始周期轮询youtube频道开播状态", InfoLog.InfoClass.Debug); // while (true) // { // 刷新youtube站房间列表(); // youtube房间信息更新次数++; // await Task.Delay(5 * 1000).ConfigureAwait(false); // } //}); }
// public event EventHandler<EventArgs> DownUpdate; // public event EventHandler<EventArgs> DownOk; private void 载完成事件(object sender, AsyncCompletedEventArgs e) { new Task((() => { try { DownIofo.载状态 = false; DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); DownIofo.备注 = "下载任务结束"; if (e.Cancelled && !DownIofo.网络超时) { if (!DownIofo.播放状态 && DownIofo.是否是播放任务) { DownIofo.备注 = "播放窗口关闭"; DownIofo.载状态 = false; 载结束提醒(true, "下载任务结束", DownIofo); return; } DownIofo.继承.待合并文件列表.Add(DownIofo.文件保存路径); DownIofo.备注 = "用户取消,停止下载"; DownIofo.载状态 = false; 载结束提醒(true, "下载任务结束", DownIofo); } else if (!e.Cancelled && !bilibili.根据房间号获取房间信息.是否正在直播(DownIofo.房间_频道号, true)) { DownIofo.继承.待合并文件列表.Add(DownIofo.文件保存路径); DownIofo.载状态 = false; DownIofo.备注 = "下载完成,直播间已关闭"; if (DownIofo.继承 == null) { DownIofo.继承.是否为继承对象 = false; } if (DownIofo.继承.是否为继承对象 && !DownIofo.是否是播放任务) { DownIofo.继承.合并后的文件路径 = 载完成合并FLV(DownIofo, true); if (!string.IsNullOrEmpty(DownIofo.继承.合并后的文件路径)) { DownIofo.文件保存路径 = DownIofo.继承.合并后的文件路径; } } if (!DownIofo.是否是播放任务) { FlvMethod.转码(DownIofo.文件保存路径); } InfoLog.InfoPrintf(DownIofo.房间_频道号 + "房间:" + DownIofo.主播名称 + " 下播,录制完成", InfoLog.InfoClass.载必要提示); foreach (var item in RoomInit.bilibili房间主表) { if (item.唯一码 == DownIofo.房间_频道号) { item.直播状态 = false; break; } } DownIofo.载状态 = false; 载结束提醒(true, "下载任务结束", DownIofo); return; } else { if (bilibili.根据房间号获取房间信息.是否正在直播(DownIofo.房间_频道号, true) && DownIofo.是否保存) { DownIofo.网络超时 = true; DownIofo.载状态 = false; DownIofo.备注 = "下载流中断,检测到房间仍为开播状态,新建续下任务。"; DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); switch (DownIofo.平台) { case "bilibili": { if (!DownIofo.是否是播放任务) { DownIofo.继承.待合并文件列表.Add(DownIofo.文件保存路径); InfoLog.InfoPrintf($"{DownIofo.房间_频道号}:{DownIofo.主播名称}下载任务续下,历史文件加入待合并文件列表:{DownIofo.文件保存路径}", InfoLog.InfoClass.载必要提示); } DownIofo.载状态 = false; Downloader 重连下载对象 = Downloader.新建下载对象( DownIofo.平台, DownIofo.房间_频道号, bilibili.根据房间号获取房间信息.获取标题(DownIofo.房间_频道号), Guid.NewGuid().ToString(), bilibili.根据房间号获取房间信息.载地址(DownIofo.房间_频道号), "重连", DownIofo.是否保存, DownIofo.主播名称, true, DownIofo.文件保存路径, DownIofo ); if (!重连下载对象.DownIofo.载状态) { try { 重连下载对象.DownIofo.弹幕录制基准时间 = DownIofo.弹幕录制基准时间; 重连下载对象.DownIofo.阿B直播流对象 = DownIofo.阿B直播流对象; 重连下载对象.DownIofo.弹幕储存流 = DownIofo.弹幕储存流; 重连下载对象.DownIofo.礼物储存流 = DownIofo.礼物储存流; 重连下载对象.DownIofo.载状态 = false; 重连下载对象.DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); 重连下载对象.DownIofo.备注 = "服务器主动断开连接,直播结束"; foreach (var item in RoomInit.bilibili房间主表) { if (item.唯一码 == DownIofo.房间_频道号) { item.直播状态 = false; break; } } if (DownIofo.继承.是否为继承对象 && !DownIofo.是否是播放任务) { DownIofo.继承.合并后的文件路径 = 载完成合并FLV(DownIofo, true); if (!string.IsNullOrEmpty(DownIofo.继承.合并后的文件路径)) { DownIofo.文件保存路径 = DownIofo.继承.合并后的文件路径; } } if (!DownIofo.是否是播放任务) { FlvMethod.转码(DownIofo.文件保存路径); } DownIofo.备注 = "服务器主动断开连接,直播结束"; 重连下载对象.DownIofo.载状态 = false; 重连下载对象.DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); DownIofo.载状态 = false; DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); 载结束提醒(true, "下载任务结束", 重连下载对象.DownIofo); } catch (Exception) {} return; } new Task((() => { while (true) { Thread.Sleep(10000); if (重连下载对象.DownIofo.已下载大小bit > 5000) { DownIofo.载状态 = false; DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); 载结束提醒(true, "下载任务结束", DownIofo); 重连下载对象.DownIofo.备注 = "完成重连,正在续命.."; //下载对象.DownIofo.下载状态 = true; return; } if (!bilibili.根据房间号获取房间信息.是否正在直播(DownIofo.房间_频道号, true)) { 重连下载对象.DownIofo.备注 = "停止直播"; DownIofo.备注 = "直播停止,下载完成下载完成"; 重连下载对象.DownIofo.载状态 = false; 重连下载对象.DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); DownIofo.载状态 = false; DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); 重连下载对象.DownIofo.WC.CancelAsync(); MMPU.DownList.Remove(重连下载对象); 载结束提醒(true, "下载任务结束", DownIofo); 载结束提醒(true, "下载任务结束", 重连下载对象.DownIofo); return; } } })).Start(); DownIofo.载状态 = false; break; } default: DownIofo.备注 = "不受支持的平台"; DownIofo.载状态 = false; DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); InfoLog.InfoPrintf("该房间的配置文件发现了与当前版本不支持的平台,请检查文件配置或者检查更新", InfoLog.InfoClass.系统错误信息); //下载结束提醒(false); return; } } else { DownIofo.备注 = "直播停止,下载完成下载完成"; 载结束提醒(true, "下载任务结束", DownIofo); DownIofo.载状态 = false; return; } } DownIofo.载状态 = false; DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); DownIofo.备注 = "下载任务结束"; } catch (Exception ES) { InfoLog.InfoPrintf($"录制任务意外终止:\r\n{ES.ToString()}", InfoLog.InfoClass.系统错误信息); DownIofo.载状态 = false; DownIofo.备注 = "录制任务意外终止,已新建续命任务"; 载结束提醒(true, "录制任务意外终止,已新建续命任务", DownIofo); Downloader 载对象 = new Downloader(); try { DownIofo.载状态 = false; 载对象 = Downloader.新建下载对象( DownIofo.平台, DownIofo.房间_频道号, bilibili.根据房间号获取房间信息.获取标题(DownIofo.房间_频道号), Guid.NewGuid().ToString(), bilibili.根据房间号获取房间信息.载地址(DownIofo.房间_频道号), "前一个下载出现异常,新建下载", DownIofo.是否保存, DownIofo.主播名称, false, DownIofo.文件保存路径 ); } catch (Exception) { try { 载对象.DownIofo.备注 = "新建续下载对象出现异常,放弃新建任务"; 载结束提醒(true, "下载任务结束", DownIofo); 载对象.DownIofo.载状态 = false; 载对象.DownIofo.结束时间 = Convert.ToInt32((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); 载对象.DownIofo.WC.CancelAsync(); MMPU.DownList.Remove(载对象); } catch (Exception) { } } } })).Start(); }
public static Downloader 新建下载对象(string 平台, string 唯一码, string 标题, string GUID, string 载地址, string 备注, bool 是否保存, string 主播名称, bool 是否为继承项目, string 继承项目的原始文件, DownIofoData 继承的项目 = null) { foreach (var item in MMPU.DownList) { if (item.DownIofo.房间_频道号 == 唯一码) { if (item.DownIofo.载状态 && item.DownIofo.是否保存 && 是否保存) { InfoLog.InfoPrintf($"新建任务冲突,放弃新建任务,任务内容:\r\n房间号:{唯一码}\r\n主播名称:{主播名称}\r\n标题:{标题}", InfoLog.InfoClass.载必要提示); return(null); } else { break; } } } if (string.IsNullOrEmpty(标题)) { 标题 = $"V{new Random().Next(10000,99999)}"; } Downloader 载对象 = new Downloader(); 载对象.DownIofo.继承 = new 继承(); string 缓存路径 = MMPU.缓存路径; string 保存路径; if (MMPU.载储存目录 == 缓存路径) { 保存路径 = 缓存路径 + 平台 + "_" + 主播名称 + "_" + 唯一码 + "/"; if (!Directory.Exists(保存路径))//如果不存在就创建文件夹 { Directory.CreateDirectory(保存路径); } 保存路径 = 保存路径 + 标题 + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".flv"; } else { 保存路径 = MMPU.载储存目录 + "/" + 平台 + "_" + 主播名称 + "_" + 唯一码 + "/"; if (!Directory.Exists(保存路径))//如果不存在就创建file文件夹 { try { Directory.CreateDirectory(保存路径); } catch (Exception) { MMPU.载储存目录 = 缓存路径; MMPU.setFiles("file", MMPU.载储存目录); 保存路径 = MMPU.载储存目录 + "/" + 平台 + "_" + 主播名称 + "_" + 唯一码 + "/"; } } 保存路径 = 保存路径 + 标题 + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".flv"; if (File.Exists(保存路径)) { Thread.Sleep(1); 保存路径 = MMPU.载储存目录 + "/" + 平台 + "_" + 主播名称 + "_" + 唯一码 + "/" + 标题 + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".flv"; } } switch (平台) { case "bilibili": { 载地址 = 载地址; break; } case "youtube": { break; } } 载对象.DownIofo = new Downloader.DownIofoData { 平台 = 平台, 载状态 = true, 房间_频道号 = 唯一码, 文件保存路径 = 保存路径, 事件GUID = GUID, 载地址 = 载地址, 是否保存 = 是否保存, 标题 = 标题, 备注 = 备注, 主播名称 = 主播名称, 继承 = new 继承() { 是否为继承对象 = 是否为继承项目, 继承的下载文件路径 = 继承项目的原始文件, } }; if (继承的项目 != null) { 载对象.DownIofo.继承.待合并文件列表 = 继承的项目.继承.待合并文件列表; } if (!是否保存) { int 随机值 = new Random().Next(1000, 9999); 载对象.DownIofo.文件保存路径 = 缓存路径 + "LiveCache/" + 载对象.DownIofo.标题 + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "_" + 随机值 + ".flv"; if (File.Exists(载对象.DownIofo.文件保存路径)) { 载对象.DownIofo.文件保存路径 = 缓存路径 + "LiveCache/" + 载对象.DownIofo.标题 + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "_" + (随机值) + 1 + ".flv"; } } 载对象.Start(备注); return(载对象); }