Gateway client basics
This commit is contained in:
parent
bc58ae98ea
commit
6df9346de1
76
Discord.API/Gateway/GatewayClient.cs
Normal file
76
Discord.API/Gateway/GatewayClient.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Text.Json;
|
||||
using Serilog;
|
||||
using Websocket.Client;
|
||||
|
||||
namespace Discord.API;
|
||||
|
||||
public class GatewayClient {
|
||||
|
||||
private const int ApiVersion = 10;
|
||||
|
||||
private string ApiKey;
|
||||
private WebsocketClient Websocket;
|
||||
private CancellationTokenSource? heartbeat_cts;
|
||||
private ulong? Sequence = null;
|
||||
|
||||
public GatewayClient(string url, string api_key){
|
||||
this.ApiKey=api_key;
|
||||
UriBuilder uriBuilder = new(url);
|
||||
NameValueCollection query = System.Web.HttpUtility.ParseQueryString("");
|
||||
query.Add("v", ApiVersion.ToString());
|
||||
query.Add("encoding", "json");
|
||||
uriBuilder.Query=query.ToString();
|
||||
Websocket = new WebsocketClient(uriBuilder.Uri);
|
||||
Websocket.DisconnectionHappened.Subscribe(DisconnectionHandler);
|
||||
Websocket.ReconnectionHappened.Subscribe(ReconnectionHandler);
|
||||
Websocket.MessageReceived.Subscribe(MessageReceivedHandler);
|
||||
|
||||
Log.Debug("GATEWAY: Created new gateway, with url: {url}", uriBuilder.ToString());
|
||||
}
|
||||
|
||||
private void DisconnectionHandler(DisconnectionInfo info){
|
||||
Log.Information("GATEWAY: Disconnected. Type: {DisconnectionType}", info.Type);
|
||||
}
|
||||
private void ReconnectionHandler(ReconnectionInfo info){
|
||||
Log.Information("GATEWAY: (Re)Connected to server. Url: {url}, Type: {Type}", Websocket.Url, info.Type);
|
||||
}
|
||||
private void MessageReceivedHandler(ResponseMessage msg){
|
||||
if(msg.MessageType != System.Net.WebSockets.WebSocketMessageType.Text) return;
|
||||
try{
|
||||
GatewayPacket packet = JsonSerializer.Deserialize(msg.Text!, SourceGenerationContext.Default.GatewayPacket)
|
||||
?? throw new Exception("Failed to deserialize packet"); // This can be optimized //TODO
|
||||
|
||||
switch(packet){
|
||||
case HelloPacket helloPacket:
|
||||
HelloPacketHandler(helloPacket);
|
||||
break;
|
||||
}
|
||||
}catch(Exception ex){
|
||||
Log.Warning(ex, "GATEWAY: Error processing gateway event");
|
||||
}
|
||||
}
|
||||
|
||||
private void HelloPacketHandler(HelloPacket packet){
|
||||
StartHeartbeat((int)packet.Data.HeartbeatInterval);
|
||||
}
|
||||
|
||||
private void StartHeartbeat(int heartbeat_interval){
|
||||
heartbeat_cts?.Cancel();
|
||||
heartbeat_cts = new CancellationTokenSource();
|
||||
CancellationToken ct = heartbeat_cts.Token;
|
||||
Task.Run(async ()=>{
|
||||
await Task.Delay(Random.Shared.Next(1, heartbeat_interval));
|
||||
using PeriodicTimer pd = new(TimeSpan.FromMilliseconds(heartbeat_interval));
|
||||
do{
|
||||
HeartbeatPacket packet = new HeartbeatPacket(){
|
||||
Sequence=this.Sequence
|
||||
};
|
||||
if(Websocket.IsRunning)
|
||||
if(!Websocket.Send(JsonSerializer.Serialize(packet, SourceGenerationContext.Default.HeartbeatPacket))){
|
||||
Log.Warning("GATEWAY: Failed to queue heartbeat message");
|
||||
}
|
||||
}while(await pd.WaitForNextTickAsync(ct) && !ct.IsCancellationRequested);
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user