Skip to content

Commit 9fabb98

Browse files
committed
refractor websocket client
1 parent 02e600f commit 9fabb98

17 files changed

Lines changed: 96 additions & 142 deletions

File tree

Lines changed: 26 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System.Net.WebSockets;
2-
using System.Reactive.Linq;
32
using System.Text;
4-
using Websocket.Client;
3+
using HuaJiBot.NET.Websocket;
4+
using Newtonsoft.Json.Linq;
55

66
namespace HuaJiBot.NET.Adapter.OneBot;
77

@@ -12,81 +12,40 @@ internal class ForwardWebSocketClient
1212
private readonly WebsocketClient _client;
1313
internal readonly OneBotApi Api;
1414

15-
public Task ConnectAsync() => _client.Start();
15+
public ValueTask ConnectAsync()
16+
{
17+
return ValueTask.CompletedTask;
18+
}
1619

1720
public ForwardWebSocketClient(OneBotAdapter service, string wsUrl, string? token)
1821
{
1922
void Send(string text) => _client!.Send(text);
20-
Api = new OneBotApi(service, Send);
21-
_handler = new OneBotMessageHandler(Api, service);
22-
_client = new WebsocketClient(
23-
new Uri(wsUrl),
24-
() =>
23+
Api = new(service, Send);
24+
_handler = new(Api, service);
25+
_client = new(wsUrl, token, service.Logger);
26+
_client.OnMessage += async msg =>
27+
{
28+
try
29+
{
30+
await _handler.ProcessMessageAsync((JObject)msg);
31+
}
32+
catch (Exception e)
2533
{
26-
var cfg = new ClientWebSocket
27-
{
28-
Options =
29-
{
30-
KeepAliveInterval = TimeSpan.FromSeconds(5),
31-
CollectHttpResponseDetails = true,
32-
//Credentials = new NetworkCredential("Bearer", token),
33-
},
34-
};
35-
if (!string.IsNullOrEmpty(token))
36-
cfg.Options.SetRequestHeader("Authorization", "Bearer " + token);
37-
return cfg;
34+
service.LogError("[OneBotWsClient] 处理消息时出现异常:", e);
3835
}
39-
)
36+
};
37+
_client.OnConnected += info =>
4038
{
41-
IsReconnectionEnabled = true,
42-
ReconnectTimeout = null,
43-
MessageEncoding = Encoding.UTF8,
44-
IsTextMessageConversionEnabled = true,
39+
service.Log("[OneBotWsClient] Connection Happened.");
4540
};
46-
_client
47-
.MessageReceived.Where(m => m.MessageType == WebSocketMessageType.Text)
48-
.Select(m => m.Text)
49-
.Subscribe(msg =>
50-
{
51-
try
52-
{
53-
_handler
54-
.ProcessMessageAsync(msg ?? throw new NullReferenceException("msg.Text"))
55-
.ContinueWith(
56-
task =>
57-
{
58-
var ex = task.Exception;
59-
if (ex is not null)
60-
service.LogError(
61-
"[OneBotWsClient] ProcessMessage 处理消息时出现异常:",
62-
ex
63-
);
64-
},
65-
TaskContinuationOptions.OnlyOnFaulted
66-
);
67-
}
68-
catch (Exception e)
69-
{
70-
service.LogError("[OneBotWsClient] 处理消息时出现异常:", e);
71-
}
72-
});
73-
_client.DisconnectionHappened.Subscribe(info =>
41+
_client.OnClosed += e =>
42+
{
7443
service.Log(
7544
"[OneBotWsClient] Disconnection Happened. Type:"
76-
+ info.Type
45+
+ e.Type
7746
+ " Description:"
78-
+ info.CloseStatusDescription
79-
)
80-
);
81-
_client.ReconnectionHappened.Subscribe(info =>
82-
service.Log("[OneBotWsClient] Reconnection Happened " + info.Type)
83-
);
84-
85-
//var timer = new System.Timers.Timer(500);
86-
//timer.Elapsed += (sender, args) =>
87-
//{ //send ping
88-
// _client.Send("{}");
89-
//};
90-
//timer.Start();
47+
+ e.Reason
48+
);
49+
};
9150
}
9251
}

src/HuaJiBot.NET.Adapter.OneBot/HuaJiBot.NET.Adapter.OneBot.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
<ItemGroup>
1010
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
11-
<PackageReference Include="Websocket.Client" Version="5.3.0" />
1211
</ItemGroup>
1312

1413
<ItemGroup>

src/HuaJiBot.NET.Adapter.OneBot/OneBotAdapter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public override void Reconnect()
2121
_client.ConnectAsync();
2222
}
2323

24-
public override Task SetupServiceAsync() => _client.ConnectAsync();
24+
public override async Task SetupServiceAsync() => await _client.ConnectAsync();
2525

2626
public override string[] AllRobots => _client.QQ is not null ? [_client.QQ] : [];
2727

src/HuaJiBot.NET.Adapter.OneBot/OneBotMessageHandler.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ internal class OneBotMessageHandler(OneBotApi api, OneBotAdapter service)
1010
private string? _qq = null;
1111
public string? QQ => _qq;
1212

13-
public async Task ProcessMessageAsync(string data)
13+
public async Task ProcessMessageAsync(JObject json)
1414
{
1515
#if !DEBUG
1616
try
1717
{
1818
#endif
19-
var json = JObject.Parse(data);
2019
if (json.ContainsKey("echo"))
2120
{
2221
await api.ProcessMessageAsync(json);

src/HuaJiBot.NET.Adapter.Satori/HuaJiBot.NET.Adapter.Satori.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
<ItemGroup>
1414
<PackageReference Include="HtmlAgilityPack" Version="1.12.3" />
1515
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
16-
<PackageReference Include="Websocket.Client" Version="5.3.0" />
1716
</ItemGroup>
1817

1918
<ItemGroup>

src/HuaJiBot.NET.Adapter.Satori/Protocol/SatoriEventClient.cs

Lines changed: 39 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
using HuaJiBot.NET.Adapter.Satori.Protocol.Events;
66
using HuaJiBot.NET.Commands;
77
using HuaJiBot.NET.Events;
8+
using HuaJiBot.NET.Websocket;
89
using Newtonsoft.Json;
910
using Newtonsoft.Json.Linq;
1011
using Newtonsoft.Json.Serialization;
11-
using Websocket.Client;
1212
using Timer = System.Timers.Timer;
1313

1414
namespace HuaJiBot.NET.Adapter.Satori.Protocol;
@@ -26,79 +26,63 @@ internal class SatoriEventClient
2626
private readonly Timer _pingTimer;
2727
private readonly SatoriAdapter _service;
2828

29-
public Task ConnectAsync() => _client.Start();
29+
public Task ConnectAsync() => Task.CompletedTask;
3030

3131
public SatoriEventClient(SatoriAdapter service, Uri wsUrl, string token)
3232
{
33-
_client = new WebsocketClient(wsUrl)
34-
{
35-
IsTextMessageConversionEnabled = true,
36-
MessageEncoding = Encoding.UTF8,
37-
ReconnectTimeout = null,
38-
};
33+
_client = new(wsUrl);
3934
_service = service;
40-
_client
41-
.MessageReceived.Where(m => m.MessageType == WebSocketMessageType.Text)
42-
.Select(m => m.Text)
43-
.Subscribe(msg =>
35+
36+
// 订阅消息接收事件
37+
_client.OnMessage += async msg =>
38+
{
39+
try
4440
{
45-
try
46-
{
47-
ProcessMessageAsync(msg ?? throw new NullReferenceException("msg.Text"))
48-
.ContinueWith(
49-
task =>
50-
{
51-
var ex = task.Exception;
52-
if (ex is not null)
53-
service.LogError(
54-
"[SatoriEventClient] ProcessMessage 处理消息时出现异常:",
55-
ex
56-
);
57-
},
58-
TaskContinuationOptions.OnlyOnFaulted
59-
);
60-
}
61-
catch (Exception e)
62-
{
63-
service.LogError("[SatoriEventClient] 处理消息时出现异常:", e);
64-
}
65-
});
66-
_client.DisconnectionHappened.Subscribe(info =>
41+
await ProcessMessageAsync(msg ?? throw new NullReferenceException("msg.Text"));
42+
}
43+
catch (Exception ex)
44+
{
45+
service.LogError("[SatoriEventClient] ProcessMessage 处理消息时出现异常:", ex);
46+
}
47+
};
48+
// 订阅断开连接事件
49+
_client.OnClosed += info =>
6750
{
6851
service.Log(
6952
"[SatoriEventClient] Disconnection Happened. Type:"
7053
+ info.Type
7154
+ " Description:"
72-
+ info.CloseStatusDescription
55+
+ info.Reason
7356
);
7457
_pingTimer?.Stop();
75-
});
76-
_client.ReconnectionHappened.Subscribe(info =>
58+
};
59+
60+
// 订阅重连事件
61+
_client.OnConnected += info =>
7762
{
78-
service.Log("[SatoriEventClient] Reconnection Happened " + info.Type);
63+
service.Log("[SatoriEventClient] Reconnection Happened " + info.IsReconnect);
7964
var identify = new Signal<IdentifySignalBody> //鉴权
8065
{
8166
Op = SignalOperation.Identify,
82-
Body = new IdentifySignalBody { Token = token },
67+
Body = new() { Token = token },
8368
};
8469
SendSignal(identify);
8570
_pingTimer?.Start();
86-
});
71+
};
8772

88-
_pingTimer = new Timer
73+
_pingTimer = new()
8974
{
9075
AutoReset = true,
9176
Interval = TimeSpan.FromSeconds(10).TotalMilliseconds,
9277
};
9378
_pingTimer.Elapsed += (_, _) => SendSignal(new Signal { Op = SignalOperation.Ping });
9479
}
9580

96-
private Task ProcessMessageAsync(string message)
81+
private ValueTask ProcessMessageAsync(JToken json)
9782
{
9883
try
9984
{
10085
//_service.LogDebug($"WebSocket::Process {message}");
101-
var json = JObject.Parse(message);
10286
var op = (SignalOperation)json.Value<int>("op");
10387
switch (op)
10488
{
@@ -169,7 +153,7 @@ out senderId
169153
}
170154
}
171155
yield return new CommonCommandReader.ReaderReply(
172-
new CommandReader.ReplyInfo(
156+
new(
173157
messageId: id,
174158
seqId: messageSeq,
175159
senderId: senderId,
@@ -203,7 +187,7 @@ out senderId
203187
}
204188
}
205189
_service.Events.CallOnGroupMessageReceived(
206-
new GroupMessageEventArgs(
190+
new(
207191
() => new DefaultCommandReader(Parse()),
208192
() => ValueTask.FromResult(groupName ?? string.Empty)
209193
)
@@ -213,7 +197,7 @@ out senderId
213197
GroupId = groupId,
214198
SenderId = senderId,
215199
SenderMemberCard = name ?? string.Empty,
216-
TextMessageLazy = new Lazy<string>(() => msg.Content),
200+
TextMessageLazy = new(() => msg.Content),
217201
Service = _service,
218202
}
219203
);
@@ -231,7 +215,7 @@ out senderId
231215
$"{appName} {account.Status} Features: {string.Join(",", account.Features)}"
232216
);
233217
_service.Events.CallOnBotLogin(
234-
new BotLoginEventArgs
218+
new()
235219
{
236220
Accounts = _service.AllRobots,
237221
ClientName = appName,
@@ -253,7 +237,7 @@ out senderId
253237
_service.Log(e);
254238
}
255239

256-
return Task.CompletedTask;
240+
return ValueTask.CompletedTask;
257241
}
258242

259243
private void SendSignal<T>(T signal)
@@ -263,4 +247,11 @@ private void SendSignal<T>(T signal)
263247
//_service.LogDebug($"WebSocket::SendSignal {text}");
264248
_client.Send(text);
265249
}
250+
251+
public void Dispose()
252+
{
253+
_pingTimer?.Stop();
254+
_pingTimer?.Dispose();
255+
_client?.Dispose();
256+
}
266257
}

src/HuaJiBot.NET.Adapter.Satori/SatoriAdapter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public SatoriAdapter(string url, string token)
2323
new UriBuilder(httpUrl) { Scheme = baseUri.Scheme == "http" ? "ws" : "wss" }.Uri,
2424
new Uri("/v1/events", UriKind.Relative)
2525
);
26-
_apiClient = new SatoriApiClient(this, httpUrl, token);
27-
_eventClient = new SatoriEventClient(this, wsUrl, token);
26+
_apiClient = new(this, httpUrl, token);
27+
_eventClient = new(this, wsUrl, token);
2828
}
2929

3030
public override void Reconnect() => _ = _eventClient.ConnectAsync();

src/HuaJiBot.NET.Plugin.GitHubBridge/PluginMain.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using HuaJiBot.NET.MQ;
1+
using HuaJiBot.NET.Websocket;
22
using HuaJiBot.NET.Plugin.GitHubBridge.EventDispatch;
33
using HuaJiBot.NET.Plugin.GitHubBridge.Types;
44
using HuaJiBot.NET.Plugin.GitHubBridge.Types.IssueCommentEventBody;

src/HuaJiBot.NET.Plugin.MessageBridge/PluginMain.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using HuaJiBot.NET.Bot;
55
using HuaJiBot.NET.Commands;
66
using HuaJiBot.NET.Events;
7-
using HuaJiBot.NET.MQ;
7+
using HuaJiBot.NET.Websocket;
88
using HuaJiBot.NET.Plugin.MessageBridge.Types;
99
using HuaJiBot.NET.Plugin.MessageBridge.Types.Packet;
1010
using Microsoft.Extensions.Logging;

src/HuaJiBot.NET.UnitTest/WebsocketTest.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using HuaJiBot.NET.Logger;
2-
using HuaJiBot.NET.MQ;
1+
using HuaJiBot.NET.Websocket;
32
using Microsoft.Extensions.Logging;
43
using Newtonsoft.Json;
54
using Newtonsoft.Json.Linq;

0 commit comments

Comments
 (0)