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-11-10 12:17:41 +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-10-31 06:22:38 +08:00
|
|
|
|
logger.Warn(e.Error, "弹幕连接被断开,将每15秒尝试重连一次"); // TODO: 设置重连时间间隔
|
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-10-31 06:22:38 +08:00
|
|
|
|
Thread.Sleep(1000 * 15); // 备注:这是运行在 ReceiveMessageLoop 线程上的
|
2018-03-21 20:56:56 +08:00
|
|
|
|
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
|
|
|
|
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, "弹幕服务器连接成功");
|
|
|
|
|
|
2018-03-24 02:27:58 +08:00
|
|
|
|
if (TokenSource == null)
|
|
|
|
|
{
|
|
|
|
|
TokenSource = new CancellationTokenSource();
|
2018-10-31 06:22:38 +08:00
|
|
|
|
Repeat.Interval(TimeSpan.FromMinutes(5), () => // TODO: 设置查询时间间隔
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Check(TriggerType.HttpApi);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
logger.Log(Roomid, LogLevel.Warn, "获取直播间开播状态出错", ex);
|
|
|
|
|
}
|
|
|
|
|
}, TokenSource.Token);
|
2018-03-24 02:27:58 +08:00
|
|
|
|
}
|
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
|
|
|
|
}
|
|
|
|
|
|
2018-03-26 04:50:08 +08:00
|
|
|
|
public void Check(TriggerType type = TriggerType.HttpApiRecheck)
|
2018-03-21 00:33:34 +08:00
|
|
|
|
{
|
2018-10-31 06:22:38 +08:00
|
|
|
|
if (BililiveAPI.GetRoomInfo(Roomid).isStreaming)
|
2018-03-21 00:33:34 +08:00
|
|
|
|
{
|
2018-03-26 04:50:08 +08:00
|
|
|
|
_StartRecord(type);
|
2018-03-21 00:33:34 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-26 04:50:08 +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();
|
2018-03-26 04:50:08 +08:00
|
|
|
|
Check(type);
|
2018-03-21 00:33:34 +08:00
|
|
|
|
});
|
|
|
|
|
}
|
2018-03-13 14:23:53 +08:00
|
|
|
|
}
|
|
|
|
|
}
|