/// <summary> /// 放送情報の取得を開始します。 /// </summary> private static void BeginGetLiveInfo(long liveId, InternalData internalData, AutoResetEvent ev) { WebUtil.RequestHttpTextAsync( NicoString.GetLiveUrl(liveId), null, internalData.Cookie, Encoding.UTF8, (result, text) => { try { // 放送情報が取得できなければエラーとします。 var v = LiveInfo.CreateFromHtml( string.Format("lv{0}", liveId), text); internalData.LiveStreamInfo.LiveInfo = v; } catch (Exception ex) { internalData.Exception = ex; } ev.Set(); }); }
/// <summary> /// コミュニティ情報(累計来場者数など)を取得します。 /// </summary> private static void SetCommunityInfo(LiveInfo live, string pageStr) { // 累計来場者数 var m = CommunityVisitorsRegex.Match(pageStr); if (!m.Success) { throw new NicoLiveException( "累計来場者数の取得に失敗しました。", live.Id); } live.TotalVisitors = int.Parse( m.Groups[1].Value, NumberStyles.AllowThousands); // /レベル m = CommunityLevelRegex.Match(pageStr); if (!m.Success) { throw new NicoLiveException( "コミュニティレベルの取得に失敗しました。", live.Id); } live.CommunityLevel = int.Parse( m.Groups[1].Value, NumberStyles.AllowThousands); }
/// <summary> /// コメントサーバーに接続します。 /// </summary> /// <remarks> /// 接続失敗時には例外が返されます。 /// </remarks> public void Connect(PlayerStatus playerStatus, CookieContainer cc, bool currentRoomOnly, TimeSpan timeout) { lock (ConnectLock) { if (playerStatus == null) { throw new ArgumentNullException("playerStatus"); } // 例外が発生する可能性があります。 var streamInfo = LiveUtil.GetLiveStreamInfo(playerStatus, cc); // 各コメントルームの情報を取得します。 var roomInfoList = GetAllRoomInfo( streamInfo.PlayerStatus, streamInfo.LiveInfo.CommunityLevel); var currentRoomIndex = FindRoomIndex( playerStatus.MS.Port, roomInfoList); var roomList = new List <CommentRoom>(); // 各コメントルームに接続します。 for (var i = 0; i < roomInfoList.Count(); ++i) { if (currentRoomOnly && i != currentRoomIndex) { roomList.Add(null); continue; } var room = new CommentRoom(this, roomInfoList[i], i); // 接続に失敗した場合、例外が返ります。 room.Connect(cc, timeout); roomList.Add(room); } Disconnect(); lock (SyncRoot) { this.connectedRoomCount = 0; this.playerStatus = streamInfo.PlayerStatus; this.publishStatus = streamInfo.PublishStatus; this.liveInfo = streamInfo.LiveInfo; this.roomList = roomList; this.currentRoomIndex = currentRoomIndex; this.cookieContainer = cc; } // フィールド値を設定した後に、OnConnectedRoomを呼びます。 foreach (var room in ClonedCommentRoomList) { OnConnectedRoom(room); } // 接続時のイベントを発生させます。 FireConnected(); } }
private static void SetOfficialInfo(LiveInfo live, string pageStr) { // 累計来場者数 var m = OfficialVisitorsRegex.Match(pageStr); if (!m.Success) { live.TotalVisitors = 0; } else { live.TotalVisitors = int.Parse( m.Groups[1].Value, NumberStyles.AllowThousands); } }
/// <summary> /// 公式放送のコメントサーバーに接続します。 /// </summary> /// <remarks> /// 接続失敗時には例外が返されます。 /// </remarks> public void ConnectToOfficial(string filepath, CookieContainer cc, TimeSpan timeout) { lock (ConnectLock) { // 各コメントルームの情報を取得します。 var roomInfoList = Detail.OfficialLiveInfoCreator .GetAllRoomInfoFromXml(filepath); var roomList = new List <CommentRoom>(); // 各コメントルームに接続します。 for (var i = 0; i < roomInfoList.Count(); ++i) { var room = new CommentRoom(this, roomInfoList[i], i); // 接続に失敗した場合、例外が返ります。 room.Connect(cc, timeout); roomList.Add(room); } Disconnect(); lock (SyncRoot) { this.connectedRoomCount = 0; this.playerStatus = null; this.publishStatus = null; this.liveInfo = null; this.roomList = roomList; this.currentRoomIndex = -1; this.cookieContainer = cc; } // フィールド値を設定した後に、OnConnectedRoomを呼びます。 foreach (var room in ClonedCommentRoomList) { OnConnectedRoom(room); } // 接続時のイベントを発生させます。 FireConnected(); } }
/// <summary> /// 放送関連情報を同期的に取得します。 /// </summary> public static LiveStreamInfo GetLiveStreamInfoSync(string liveUrl, CookieContainer cc) { var playerStatus = PlayerStatus.Create(liveUrl, cc); var id = playerStatus.Stream.Id; // publishstatusは放送主しか取得することが出来ません。 PublishStatus publishStatus = null; if (playerStatus.Stream.IsOwner) { publishStatus = PublishStatus.Create(id, cc); } // 放送情報を取得します。 var liveInfo = LiveInfo.Create(id, cc); return(new LiveStreamInfo() { PlayerStatus = playerStatus, PublishStatus = publishStatus, LiveInfo = liveInfo, }); }
/// <summary> /// html形式の生放送ページから生放送情報を作成します。 /// </summary> public static LiveInfo CreateFromHtml(string idString, string pageStr) { var live = new LiveInfo(); if (string.IsNullOrEmpty(pageStr)) { throw new NicoLiveException( "ページが空です。", idString); } var m = ProviderInfoRegex.Match(pageStr); if (!m.Success) { throw new NicoLiveException( "放送の提供元情報を取得できませんでした。", idString); } var provider = NicoUtil.ParseProvider(m.Groups[1].Value); m = VideoInfoRegex.Match(pageStr); if (!m.Success) { throw new NicoLiveException( "生放送情報を取得できませんでした。", idString); } var infoStr = m.Groups[1].Value; m = IdRegex.Match(infoStr); if (!m.Success) { throw new NicoException( "生放送IDを取得できませんでした。", idString); } live.Id = m.Groups[1].Value; m = TitleRegex.Match(infoStr); if (!m.Success) { throw new NicoException( "生放送タイトルを取得できませんでした。", idString); } live.Title = m.Groups[1].Value .Replace("\\'", "'"); m = DescriptionRegex.Match(infoStr); if (!m.Success) { throw new NicoLiveException( "生放送概要を取得できませんでした。", idString); } live.Description = m.Groups[1].Value .Replace("\\'", "'") .Replace("\\r\\n", "\n"); switch (provider.ProviderType) { case ProviderType.Community: SetCommunityInfo(live, pageStr); break; case ProviderType.Channel: SetChannelInfo(live, pageStr); break; case ProviderType.Official: SetOfficialInfo(live, pageStr); break; default: throw new NotImplementedException( "実装されていない放送提供元です。"); } return(live); }
private static void SetOfficialInfo(LiveInfo live, string pageStr) { // 累計来場者数 var m = OfficialVisitorsRegex.Match(pageStr); if (!m.Success) { live.TotalVisitors = 0; } else { live.TotalVisitors = int.Parse( m.Groups[1].Value, NumberStyles.AllowThousands); } }
/// <summary> /// コミュニティ情報(累計来場者数など)を取得します。 /// </summary> private static void SetCommunityInfo(LiveInfo live, string pageStr) { // 累計来場者数 var m = CommunityVisitorsRegex.Match(pageStr); if (!m.Success) { throw new NicoLiveException( "累計来場者数の取得に失敗しました。", live.IdString); } live.TotalVisitors = int.Parse( m.Groups[1].Value, NumberStyles.AllowThousands); // /レベル m = CommunityLevelRegex.Match(pageStr); if (!m.Success) { throw new NicoLiveException( "コミュニティレベルの取得に失敗しました。", live.IdString); } live.CommunityLevel = int.Parse( m.Groups[1].Value, NumberStyles.AllowThousands); }
/// <summary> /// html形式の生放送ページから生放送情報を作成します。 /// </summary> public static LiveInfo CreateFromHtml(string idString, string pageStr) { var live = new LiveInfo(); if (string.IsNullOrEmpty(pageStr)) { throw new NicoLiveException( "ページが空です。", idString); } var m = ProviderInfoRegex.Match(pageStr); if (!m.Success) { throw new NicoLiveException( "放送の提供元情報を取得できませんでした。", idString); } var provider = LiveUtil.ParseProvider(m.Groups[1].Value); m = VideoInfoRegex.Match(pageStr); if (!m.Success) { throw new NicoLiveException( "生放送情報を取得できませんでした。", idString); } var infoStr = m.Groups[1].Value; m = IdRegex.Match(infoStr); if (!m.Success) { throw new NicoException( "生放送IDを取得できませんでした。", idString); } live.Id = int.Parse(m.Groups[1].Value); m = TitleRegex.Match(infoStr); if (!m.Success) { throw new NicoException( "生放送タイトルを取得できませんでした。", idString); } live.Title = m.Groups[1].Value .Replace("\\'", "'"); m = DescriptionRegex.Match(infoStr); if (!m.Success) { throw new NicoLiveException( "生放送概要を取得できませんでした。", idString); } live.Description = m.Groups[1].Value .Replace("\\'", "'") .Replace("\\r\\n", "\n"); switch (provider.ProviderType) { case ProviderType.Community: SetCommunityInfo(live, pageStr); break; case ProviderType.Official: SetOfficialInfo(live, pageStr); break; default: throw new NotImplementedException( "実装されていない放送提供元です。"); } return live; }
/// <summary> /// 公式放送のコメントサーバーに接続します。 /// </summary> /// <remarks> /// 接続失敗時には例外が返されます。 /// </remarks> public void ConnectToOfficial(string filepath, CookieContainer cc, TimeSpan timeout) { lock (ConnectLock) { // 各コメントルームの情報を取得します。 var roomInfoList = Detail.OfficialLiveInfoCreator .GetAllRoomInfoFromXml(filepath); var roomList = new List<CommentRoom>(); // 各コメントルームに接続します。 for (var i = 0; i < roomInfoList.Count(); ++i) { var room = new CommentRoom(this, roomInfoList[i], i); // 接続に失敗した場合、例外が返ります。 room.Connect(cc, timeout); roomList.Add(room); } Disconnect(); lock (SyncRoot) { this.connectedRoomCount = 0; this.playerStatus = null; this.publishStatus = null; this.liveInfo = null; this.roomList = roomList; this.currentRoomIndex = -1; this.cookieContainer = cc; } // フィールド値を設定した後に、OnConnectedRoomを呼びます。 foreach (var room in ClonedCommentRoomList) { OnConnectedRoom(room); } // 接続時のイベントを発生させます。 FireConnected(); } }
/// <summary> /// コメントサーバーに接続します。 /// </summary> /// <remarks> /// 接続失敗時には例外が返されます。 /// </remarks> public void Connect(PlayerStatus playerStatus, CookieContainer cc, bool currentRoomOnly, TimeSpan timeout) { lock (ConnectLock) { if (playerStatus == null) { throw new ArgumentNullException("playerStatus"); } // 例外が発生する可能性があります。 var streamInfo = LiveUtil.GetLiveStreamInfo(playerStatus, cc); // 各コメントルームの情報を取得します。 var roomInfoList = GetAllRoomInfo( streamInfo.PlayerStatus, streamInfo.LiveInfo.CommunityLevel); var currentRoomIndex = FindRoomIndex( playerStatus.MS.Port, roomInfoList); var roomList = new List<CommentRoom>(); // 各コメントルームに接続します。 for (var i = 0; i < roomInfoList.Count(); ++i) { if (currentRoomOnly && i != currentRoomIndex) { roomList.Add(null); continue; } var room = new CommentRoom(this, roomInfoList[i], i); // 接続に失敗した場合、例外が返ります。 room.Connect(cc, timeout); roomList.Add(room); } Disconnect(); lock (SyncRoot) { this.connectedRoomCount = 0; this.playerStatus = streamInfo.PlayerStatus; this.publishStatus = streamInfo.PublishStatus; this.liveInfo = streamInfo.LiveInfo; this.roomList = roomList; this.currentRoomIndex = currentRoomIndex; this.cookieContainer = cc; } // フィールド値を設定した後に、OnConnectedRoomを呼びます。 foreach (var room in ClonedCommentRoomList) { OnConnectedRoom(room); } // 接続時のイベントを発生させます。 FireConnected(); } }