BililiveRecorder/BililiveRecorder.Core/StreamMonitor.cs

139 lines
4.2 KiB
C#
Raw Normal View History

2018-03-21 20:56:56 +08:00
using NLog;
using System;
using System.Threading;
2018-03-21 00:33:34 +08:00
using System.Threading.Tasks;
2018-03-13 14:23:53 +08:00
namespace BililiveRecorder.Core
{
2018-10-24 14:33:05 +08:00
public class StreamMonitor : IStreamMonitor
2018-03-13 14:23:53 +08:00
{
2018-03-21 20:56:56 +08:00
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
2018-03-21 00:33:34 +08:00
public int Roomid { get; private set; } = 0;
2018-03-13 14:23:53 +08:00
public event StreamStatusChangedEvent StreamStatusChanged;
2018-10-29 02:13:54 +08:00
public IDanmakuReceiver Receiver { get; }
2018-03-24 02:27:58 +08:00
private CancellationTokenSource TokenSource = null;
2018-03-13 14:23:53 +08:00
2018-10-29 02:13:54 +08:00
public StreamMonitor(int roomid, IDanmakuReceiver danmakuReceiver)
2018-03-13 14:23:53 +08:00
{
2018-10-29 02:13:54 +08:00
Receiver = danmakuReceiver;
2018-03-21 00:33:34 +08:00
Roomid = roomid;
2018-10-29 02:13:54 +08:00
Receiver.Disconnected += Receiver_Disconnected;
Receiver.ReceivedDanmaku += Receiver_ReceivedDanmaku;
Receiver.ReceivedRoomCount += Receiver_ReceivedRoomCount;
2018-03-13 14:23:53 +08:00
}
2018-03-15 21:55:01 +08:00
2018-03-21 00:33:34 +08:00
private void Receiver_ReceivedRoomCount(object sender, ReceivedRoomCountArgs e)
2018-03-15 21:55:01 +08:00
{
2018-03-21 20:56:56 +08:00
logger.Log(Roomid, LogLevel.Trace, "直播间人气: " + e.UserCount.ToString());
2018-03-15 21:55:01 +08:00
}
2018-03-21 00:33:34 +08:00
private void Receiver_ReceivedDanmaku(object sender, ReceivedDanmakuArgs e)
{
switch (e.Danmaku.MsgType)
{
case MsgTypeEnum.LiveStart:
_StartRecord(TriggerType.Danmaku);
break;
case MsgTypeEnum.LiveEnd:
break;
default:
break;
}
}
private void Receiver_Disconnected(object sender, DisconnectEvtArgs e)
{
2018-03-26 06:13:47 +08:00
logger.Warn(e.Error, "弹幕连接被断开将每30秒尝试重连一次");
2018-03-21 20:56:56 +08:00
bool connect_result = false;
2018-10-29 02:13:54 +08:00
while (!Receiver.IsConnected && !TokenSource.Token.IsCancellationRequested)
2018-03-21 00:33:34 +08:00
{
2018-03-21 20:56:56 +08:00
Thread.Sleep(1000 * 30); // 备注:这是运行在 ReceiveMessageLoop 线程上的
logger.Log(Roomid, LogLevel.Info, "重连弹幕服务器...");
2018-10-29 02:13:54 +08:00
connect_result = Receiver.Connect(Roomid);
2018-03-21 20:56:56 +08:00
}
2018-03-21 00:33:34 +08:00
2018-03-21 20:56:56 +08:00
if (connect_result)
{
logger.Log(Roomid, LogLevel.Info, "弹幕服务器重连成功");
2018-03-21 00:33:34 +08:00
}
}
private void _StartRecord(TriggerType status)
{
2018-03-21 20:56:56 +08:00
Task.Run(() => StreamStatusChanged?.Invoke(this, new StreamStatusChangedArgs() { type = status }));
2018-03-21 00:33:34 +08:00
}
2018-03-21 20:56:56 +08:00
private void HttpCheck()
2018-03-21 00:33:34 +08:00
{
2018-03-21 20:56:56 +08:00
try
2018-03-21 00:33:34 +08:00
{
2018-03-21 20:56:56 +08:00
if (BililiveAPI.GetRoomInfo(Roomid).isStreaming)
2018-10-24 14:33:05 +08:00
{
2018-03-21 00:33:34 +08:00
_StartRecord(TriggerType.HttpApi);
2018-10-24 14:33:05 +08:00
}
2018-03-21 00:33:34 +08:00
}
2018-03-21 20:56:56 +08:00
catch (Exception ex)
2018-03-21 00:33:34 +08:00
{
2018-03-21 20:56:56 +08:00
logger.Log(Roomid, LogLevel.Warn, "获取直播间开播状态出错", ex);
2018-03-21 00:33:34 +08:00
}
2018-03-21 20:56:56 +08:00
}
2018-03-21 00:33:34 +08:00
2018-03-21 20:56:56 +08:00
public bool Start()
{
2018-10-29 02:13:54 +08:00
if (!Receiver.IsConnected)
2018-10-24 14:33:05 +08:00
{
2018-10-29 02:13:54 +08:00
if (!Receiver.Connect(Roomid))
2018-10-24 14:33:05 +08:00
{
2018-03-24 02:27:58 +08:00
return false;
2018-10-24 14:33:05 +08:00
}
}
2018-03-21 20:56:56 +08:00
logger.Log(Roomid, LogLevel.Info, "弹幕服务器连接成功");
// Run 96 times a day.
2018-03-24 02:27:58 +08:00
if (TokenSource == null)
{
TokenSource = new CancellationTokenSource();
Repeat.Interval(TimeSpan.FromMinutes(15), HttpCheck, TokenSource.Token);
}
2018-03-21 20:56:56 +08:00
return true;
2018-03-21 00:33:34 +08:00
}
public void Stop()
{
2018-10-29 02:13:54 +08:00
if (Receiver.IsConnected)
2018-10-24 14:33:05 +08:00
{
2018-10-29 02:13:54 +08:00
Receiver.Disconnect();
2018-10-24 14:33:05 +08:00
}
2018-03-21 20:56:56 +08:00
TokenSource?.Cancel();
2018-03-24 02:27:58 +08:00
TokenSource = null;
2018-03-21 00:33:34 +08:00
}
public void Check(TriggerType type = TriggerType.HttpApiRecheck)
2018-03-21 00:33:34 +08:00
{
var info = BililiveAPI.GetRoomInfo(Roomid);
if (info.isStreaming)
{
_StartRecord(type);
2018-03-21 00:33:34 +08:00
}
}
public void CheckAfterSeconeds(int seconds, TriggerType type = TriggerType.HttpApiRecheck)
2018-03-21 00:33:34 +08:00
{
if (seconds < 0)
2018-10-24 14:33:05 +08:00
{
2018-03-21 00:33:34 +08:00
throw new ArgumentOutOfRangeException(nameof(seconds), "不能小于0");
2018-10-24 14:33:05 +08:00
}
2018-03-21 00:33:34 +08:00
Task.Run(() =>
{
Task.Delay(seconds * 1000).Wait();
Check(type);
2018-03-21 00:33:34 +08:00
});
}
2018-03-13 14:23:53 +08:00
}
}