96 lines
3.2 KiB
C#
96 lines
3.2 KiB
C#
using System.Net.WebSockets;
|
|
using System.Text.Json;
|
|
using Lagrange.OneBot.Core.Entity.Meta;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Logging;
|
|
using Websocket.Client;
|
|
using Timer = System.Threading.Timer;
|
|
|
|
namespace Lagrange.OneBot.Core.Network;
|
|
|
|
public sealed class ReverseWSService : ILagrangeWebService
|
|
{
|
|
private const string Tag = nameof(ReverseWSService);
|
|
|
|
public event EventHandler<MsgRecvEventArgs> OnMessageReceived = delegate { };
|
|
|
|
private readonly WebsocketClient _socket;
|
|
|
|
private readonly IConfiguration _config;
|
|
|
|
private readonly ILogger _logger;
|
|
|
|
private readonly Timer _timer;
|
|
|
|
public ReverseWSService(IConfiguration config, ILogger<LagrangeApp> logger)
|
|
{
|
|
_config = config;
|
|
_logger = logger;
|
|
|
|
var ws = _config.GetSection("Implementation").GetSection("ReverseWebSocket");
|
|
string url = $"ws://{ws["Host"]}:{ws["Port"]}{ws["Suffix"]}";
|
|
|
|
_socket = new WebsocketClient(new Uri(url), () =>
|
|
{
|
|
var socket = new ClientWebSocket();
|
|
|
|
SetRequestHeader(socket, new Dictionary<string, string>
|
|
{
|
|
{ "X-Client-Role", "Universal" },
|
|
{ "X-Self-ID", _config.GetValue<uint>("Account:Uin").ToString() },
|
|
{ "User-Agent", Constant.OneBotImpl }
|
|
});
|
|
socket.Options.KeepAliveInterval = TimeSpan.FromSeconds(5);
|
|
if (_config["AccessToken"] != null) socket.Options.SetRequestHeader("Authorization", $"Bearer {_config["AccessToken"]}");
|
|
|
|
return socket;
|
|
});
|
|
|
|
_timer = new Timer(OnHeartbeat, null, int.MaxValue, config.GetValue<int>("Implementation:ReverseWebSocket:HeartBeatInterval"));
|
|
_socket.MessageReceived.Subscribe(resp =>
|
|
{
|
|
_logger.LogTrace($"[{Tag}] Receive: {resp.Text}");
|
|
OnMessageReceived.Invoke(this, new MsgRecvEventArgs(resp.Text ?? ""));
|
|
});
|
|
}
|
|
|
|
public async Task StartAsync(CancellationToken cancellationToken)
|
|
{
|
|
await _socket.Start();
|
|
|
|
var lifecycle = new OneBotLifecycle(_config.GetValue<uint>("Account:Uin"), "connect");
|
|
await SendJsonAsync(lifecycle, cancellationToken);
|
|
}
|
|
|
|
public Task StopAsync(CancellationToken cancellationToken)
|
|
{
|
|
_timer.Dispose();
|
|
_socket.Dispose();
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SendJsonAsync<T>(T json, CancellationToken cancellationToken = default)
|
|
{
|
|
string payload = JsonSerializer.Serialize(json);
|
|
|
|
_logger.LogTrace($"[{Tag}] Send: {payload}");
|
|
return _socket.SendInstant(payload);
|
|
}
|
|
|
|
private void OnHeartbeat(object? sender)
|
|
{
|
|
var status = new OneBotStatus(true, true);
|
|
var heartBeat = new OneBotHeartBeat(
|
|
_config.GetValue<uint>("Account:Uin"),
|
|
_config.GetValue<int>("Implementation:ReverseWebSocket:HeartBeatInterval"),
|
|
status);
|
|
|
|
SendJsonAsync(heartBeat);
|
|
}
|
|
|
|
private static void SetRequestHeader(ClientWebSocket webSocket, Dictionary<string, string> headers)
|
|
{
|
|
foreach (var (key, value) in headers) webSocket.Options.SetRequestHeader(key, value);
|
|
}
|
|
} |