BililiveRecorder/BililiveRecorder.Core/StreamMonitor.cs
2018-10-31 06:22:38 +08:00

132 lines
4.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using NLog;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace BililiveRecorder.Core
{
public class StreamMonitor : IStreamMonitor
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public int Roomid { get; private set; } = 0;
public event StreamStatusChangedEvent StreamStatusChanged;
public IDanmakuReceiver Receiver { get; }
private CancellationTokenSource TokenSource = null;
public StreamMonitor(int roomid, IDanmakuReceiver danmakuReceiver)
{
Receiver = danmakuReceiver;
Roomid = roomid;
Receiver.Disconnected += Receiver_Disconnected;
Receiver.ReceivedDanmaku += Receiver_ReceivedDanmaku;
Receiver.ReceivedRoomCount += Receiver_ReceivedRoomCount;
}
private void Receiver_ReceivedRoomCount(object sender, ReceivedRoomCountArgs e)
{
logger.Log(Roomid, LogLevel.Trace, "直播间人气: " + e.UserCount.ToString());
}
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)
{
logger.Warn(e.Error, "弹幕连接被断开将每15秒尝试重连一次"); // TODO: 设置重连时间间隔
bool connect_result = false;
while (!Receiver.IsConnected && !TokenSource.Token.IsCancellationRequested)
{
Thread.Sleep(1000 * 15); // 备注:这是运行在 ReceiveMessageLoop 线程上的
logger.Log(Roomid, LogLevel.Info, "重连弹幕服务器...");
connect_result = Receiver.Connect(Roomid);
}
if (connect_result)
{
logger.Log(Roomid, LogLevel.Info, "弹幕服务器重连成功");
}
}
private void _StartRecord(TriggerType status)
{
Task.Run(() => StreamStatusChanged?.Invoke(this, new StreamStatusChangedArgs() { type = status }));
}
public bool Start()
{
if (!Receiver.IsConnected)
{
if (!Receiver.Connect(Roomid))
{
return false;
}
}
logger.Log(Roomid, LogLevel.Info, "弹幕服务器连接成功");
if (TokenSource == null)
{
TokenSource = new CancellationTokenSource();
Repeat.Interval(TimeSpan.FromMinutes(5), () => // TODO: 设置查询时间间隔
{
try
{
Check(TriggerType.HttpApi);
}
catch (Exception ex)
{
logger.Log(Roomid, LogLevel.Warn, "获取直播间开播状态出错", ex);
}
}, TokenSource.Token);
}
return true;
}
public void Stop()
{
if (Receiver.IsConnected)
{
Receiver.Disconnect();
}
TokenSource?.Cancel();
TokenSource = null;
}
public void Check(TriggerType type = TriggerType.HttpApiRecheck)
{
if (BililiveAPI.GetRoomInfo(Roomid).isStreaming)
{
_StartRecord(type);
}
}
public void CheckAfterSeconeds(int seconds, TriggerType type = TriggerType.HttpApiRecheck)
{
if (seconds < 0)
{
throw new ArgumentOutOfRangeException(nameof(seconds), "不能小于0");
}
Task.Run(() =>
{
Task.Delay(seconds * 1000).Wait();
Check(type);
});
}
}
}