-
Notifications
You must be signed in to change notification settings - Fork 272
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[OneBot] Forward Websocket Supported
- Loading branch information
Linwenxuan
authored and
Linwenxuan
committed
Oct 25, 2023
1 parent
42ce36d
commit 28565ea
Showing
11 changed files
with
204 additions
and
103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
using System.Net.NetworkInformation; | ||
using System.Text.Json; | ||
using Fleck; | ||
using Lagrange.OneBot.Core.Entity.Meta; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Lagrange.OneBot.Core.Network.Service; | ||
|
||
public sealed class ForwardWSService : LagrangeWSService | ||
{ | ||
private const string Tag = nameof(ForwardWSService); | ||
public override event EventHandler<MsgRecvEventArgs>? OnMessageReceived = delegate { }; | ||
|
||
private readonly WebSocketServer _server; | ||
|
||
private IWebSocketConnection? _connection; | ||
|
||
private readonly Timer _timer; | ||
|
||
public ForwardWSService(IConfiguration config, ILogger<LagrangeApp> logger) : base(config, logger) | ||
{ | ||
var ws = config.GetSection("Implementation").GetSection("ForwardWebSocket"); | ||
string url = $"ws://{ws["Host"]}:{ws["Port"]}"; | ||
|
||
_server = new WebSocketServer(url) | ||
{ | ||
RestartAfterListenError = true | ||
}; | ||
|
||
_timer = new Timer(OnHeartbeat, null, int.MaxValue, ws.GetValue<int>("HeartBeatInterval")); | ||
} | ||
|
||
public override Task StartAsync(CancellationToken cancellationToken) | ||
{ | ||
return Task.Run(() => | ||
{ | ||
_server.Start(conn => | ||
{ | ||
_connection = conn; | ||
|
||
conn.OnMessage = s => | ||
{ | ||
Logger.LogTrace($"[{Tag}] Receive: {s}"); | ||
OnMessageReceived?.Invoke(this, new MsgRecvEventArgs(s)); | ||
}; | ||
|
||
conn.OnOpen = () => | ||
{ | ||
Logger.LogInformation($"[{Tag}]: Connected"); | ||
|
||
var lifecycle = new OneBotLifecycle(Config.GetValue<uint>("Account:Uin"), "connect"); | ||
SendJsonAsync(lifecycle, cancellationToken).GetAwaiter().GetResult(); | ||
}; | ||
}); | ||
}, cancellationToken); | ||
} | ||
|
||
public override Task StopAsync(CancellationToken cancellationToken) | ||
{ | ||
_timer.Dispose(); | ||
_server.ListenerSocket.Close(); | ||
_server.Dispose(); | ||
|
||
return Task.CompletedTask; | ||
} | ||
|
||
public override Task SendJsonAsync<T>(T json, CancellationToken cancellationToken = default) | ||
{ | ||
string payload = JsonSerializer.Serialize(json); | ||
|
||
Logger.LogTrace($"[{Tag}] Send: {payload}"); | ||
return _connection?.Send(payload) ?? Task.CompletedTask; | ||
} | ||
|
||
private static bool IsPortInUse(uint port) | ||
{ | ||
return IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners().Any(endpoint => endpoint.Port == port); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...neBot/Core/Network/ILagrangeWebService.cs → ...re/Network/Service/ILagrangeWebService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
using Lagrange.OneBot.Core.Entity.Meta; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Lagrange.OneBot.Core.Network.Service; | ||
|
||
public abstract class LagrangeWSService(IConfiguration config, ILogger<LagrangeApp> logger) : ILagrangeWebService | ||
{ | ||
protected readonly ILogger Logger = logger; | ||
|
||
protected readonly IConfiguration Config = config; | ||
|
||
protected 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); | ||
} | ||
|
||
public abstract Task StartAsync(CancellationToken cancellationToken); | ||
|
||
public abstract Task StopAsync(CancellationToken cancellationToken); | ||
|
||
public abstract event EventHandler<MsgRecvEventArgs>? OnMessageReceived; | ||
public abstract Task SendJsonAsync<T>(T json, CancellationToken cancellationToken = default); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
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.Service; | ||
|
||
public sealed class ReverseWSService : LagrangeWSService | ||
{ | ||
private const string Tag = nameof(ReverseWSService); | ||
public override event EventHandler<MsgRecvEventArgs>? OnMessageReceived = delegate { }; | ||
|
||
private readonly WebsocketClient _socket; | ||
|
||
private readonly Timer _timer; | ||
|
||
public ReverseWSService(IConfiguration config, ILogger<LagrangeApp> logger) : base(config, 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, ws.GetValue<int>("HeartBeatInterval")); | ||
_socket.MessageReceived.Subscribe(resp => | ||
{ | ||
Logger.LogTrace($"[{Tag}] Receive: {resp.Text}"); | ||
OnMessageReceived?.Invoke(this, new MsgRecvEventArgs(resp.Text ?? "")); | ||
}); | ||
} | ||
|
||
public override async Task StartAsync(CancellationToken cancellationToken) | ||
{ | ||
await _socket.Start(); | ||
|
||
var lifecycle = new OneBotLifecycle(Config.GetValue<uint>("Account:Uin"), "connect"); | ||
await SendJsonAsync(lifecycle, cancellationToken); | ||
} | ||
|
||
public override Task StopAsync(CancellationToken cancellationToken) | ||
{ | ||
_timer.Dispose(); | ||
_socket.Dispose(); | ||
|
||
return Task.CompletedTask; | ||
} | ||
|
||
public override Task SendJsonAsync<T>(T json, CancellationToken cancellationToken = default) | ||
{ | ||
string payload = JsonSerializer.Serialize(json); | ||
|
||
Logger.LogTrace($"[{Tag}] Send: {payload}"); | ||
return _socket.SendInstant(payload); | ||
} | ||
|
||
private static void SetRequestHeader(ClientWebSocket webSocket, Dictionary<string, string> headers) | ||
{ | ||
foreach (var (key, value) in headers) webSocket.Options.SetRequestHeader(key, value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters