mirror of
https://github.com/ION606/Discord-Client.git
synced 2026-05-14 21:06:55 +00:00
Initial code commit
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.WebSockets;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
|
||||
namespace Discord_Client_Custom.Connections
|
||||
{
|
||||
internal class ConnectionOld
|
||||
{
|
||||
private static string gateWayUrl = "wss://gateway.discord.gg/?v=10&encoding=json";
|
||||
private static string baseUrl = "discord.com/api/gateway";
|
||||
public int ReceiveBufferSize { get; set; } = 8192;
|
||||
|
||||
private static int heartBeatSequence = 0;
|
||||
int heartBeatCounter = 0;
|
||||
|
||||
private ClientWebSocket WS;
|
||||
private CancellationTokenSource CTS;
|
||||
|
||||
private async void heartBeat(object o)
|
||||
{
|
||||
if (heartBeatCounter == 3)
|
||||
{
|
||||
Debug.WriteLine("\n\n\njDHsfKJdshfLK<DShflKJDSHflKJDSn\n\n\n");
|
||||
var idObj = new
|
||||
{
|
||||
op = 2,
|
||||
d = new
|
||||
{
|
||||
token = MsgRequests.userToken,
|
||||
intents = 513, //61440,
|
||||
properties = new {
|
||||
os = "linux",
|
||||
browser = "my_library",
|
||||
device = "my_library"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
byte[] idData = Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(idObj));
|
||||
await WS.SendAsync(idData, WebSocketMessageType.Text, false, CancellationToken.None);
|
||||
|
||||
var buffer = new byte[ReceiveBufferSize];
|
||||
await WS.ReceiveAsync(buffer, CancellationToken.None);
|
||||
|
||||
}
|
||||
|
||||
var obj = new { op = 1, d = heartBeatSequence };
|
||||
var toSend = System.Text.Json.JsonSerializer.Serialize(obj);
|
||||
|
||||
byte[] data = Encoding.ASCII.GetBytes(toSend);
|
||||
await WS.SendAsync(data, WebSocketMessageType.Text, false, CancellationToken.None);
|
||||
Debug.WriteLine("PING");
|
||||
heartBeatCounter++;
|
||||
}
|
||||
|
||||
|
||||
public async Task ConnectAsync()
|
||||
{
|
||||
Debug.WriteLine("CONNECTING....");
|
||||
|
||||
if (WS != null)
|
||||
{
|
||||
if (WS.State == WebSocketState.Open) return;
|
||||
else WS.Dispose();
|
||||
}
|
||||
|
||||
WS = new ClientWebSocket();
|
||||
|
||||
if (CTS != null) CTS.Dispose();
|
||||
CTS = new CancellationTokenSource();
|
||||
|
||||
await WS.ConnectAsync(new Uri(gateWayUrl), CTS.Token);
|
||||
await Task.Factory.StartNew(ReceiveLoop, CTS.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
||||
}
|
||||
|
||||
|
||||
public async Task DisconnectAsync()
|
||||
{
|
||||
if (WS is null) return;
|
||||
// TODO: requests cleanup code, sub-protocol dependent.
|
||||
if (WS.State == WebSocketState.Open)
|
||||
{
|
||||
CTS.CancelAfter(TimeSpan.FromSeconds(2));
|
||||
await WS.CloseOutputAsync(WebSocketCloseStatus.Empty, "", CancellationToken.None);
|
||||
await WS.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
|
||||
}
|
||||
WS.Dispose();
|
||||
WS = null;
|
||||
CTS.Dispose();
|
||||
CTS = null;
|
||||
}
|
||||
|
||||
|
||||
private async Task ReceiveLoop()
|
||||
{
|
||||
var loopToken = CTS.Token;
|
||||
MemoryStream outputStream = null;
|
||||
WebSocketReceiveResult receiveResult = null;
|
||||
var buffer = new byte[ReceiveBufferSize];
|
||||
try
|
||||
{
|
||||
while (!loopToken.IsCancellationRequested)
|
||||
{
|
||||
outputStream = new MemoryStream(ReceiveBufferSize);
|
||||
do
|
||||
{
|
||||
receiveResult = await WS.ReceiveAsync(buffer, CTS.Token);
|
||||
if (receiveResult.MessageType != WebSocketMessageType.Close)
|
||||
outputStream.Write(buffer, 0, receiveResult.Count);
|
||||
}
|
||||
while (!receiveResult.EndOfMessage);
|
||||
|
||||
if (receiveResult.MessageType == WebSocketMessageType.Close) break;
|
||||
outputStream.Position = 0;
|
||||
ResponseReceived(outputStream);
|
||||
}
|
||||
}
|
||||
catch (TaskCanceledException e) { Debug.WriteLine(e); }
|
||||
finally
|
||||
{
|
||||
outputStream?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private async Task<JsonNode> SendMessageAsync<RequestType>(RequestType message)
|
||||
{
|
||||
// TODO: handle serializing requests and deserializing responses, handle matching responses to the requests.
|
||||
}*/
|
||||
|
||||
private async void ResponseReceived(Stream inputStream)
|
||||
{
|
||||
var responseJson = JsonNode.Parse(inputStream);
|
||||
int opCode = (int)responseJson["op"];
|
||||
|
||||
Debug.WriteLine("=======================================================\nREADY\n");
|
||||
Debug.WriteLine(responseJson);
|
||||
Debug.WriteLine("=======================================================");
|
||||
|
||||
//Heartbeat stuff
|
||||
if (opCode == 0) {
|
||||
Debug.WriteLine("=======================================================\nREADY\n");
|
||||
Debug.WriteLine(responseJson);
|
||||
Debug.WriteLine("=======================================================");
|
||||
}
|
||||
else if (opCode == 11)
|
||||
{
|
||||
int hinterval = (int)responseJson["d"];
|
||||
var toSend = "op: 1\r\nd: " + responseJson["d"];
|
||||
|
||||
Debug.WriteLine(responseJson);
|
||||
byte[] data = Encoding.ASCII.GetBytes(toSend);
|
||||
await WS.SendAsync(data, WebSocketMessageType.Text, false, CancellationToken.None);
|
||||
}
|
||||
else if (opCode == 10) {
|
||||
Debug.WriteLine("=======================================================");
|
||||
Debug.WriteLine("CONNECTION ESTABLISHED");
|
||||
Debug.WriteLine("=======================================================");
|
||||
|
||||
int heartBeatInterval = (int)responseJson["d"]["heartbeat_interval"];
|
||||
|
||||
var autoEvent = new AutoResetEvent(false);
|
||||
var stateTimer = new System.Threading.Timer(heartBeat, autoEvent, 0, heartBeatInterval);
|
||||
autoEvent.WaitOne();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("=======================================================");
|
||||
Debug.WriteLine(responseJson);
|
||||
Debug.WriteLine("=======================================================");
|
||||
}
|
||||
|
||||
// TODO: handle deserializing responses and matching them to the requests.
|
||||
// IMPORTANT: DON'T FORGET TO DISPOSE THE inputStream!
|
||||
inputStream.DisposeAsync();
|
||||
}
|
||||
|
||||
|
||||
public ConnectionOld()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void Dispose() => DisconnectAsync().Wait();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text.Json.Nodes;
|
||||
using Websocket.Client;
|
||||
using Discord_Client_Custom.client_internals;
|
||||
|
||||
|
||||
|
||||
namespace Discord_Client_Custom.Connections
|
||||
{
|
||||
internal class Connection
|
||||
{
|
||||
private static Uri gateWayUrl = new Uri("wss://gateway.discord.gg/?v=10&encoding=json");
|
||||
private static ManualResetEvent exitEvent = new ManualResetEvent(false);
|
||||
private static int heartBeatSequence = 0;
|
||||
private int heartBeatInterval = 0;
|
||||
int heartBeatCounter = 0;
|
||||
private WebsocketClient WS;
|
||||
private GateWayIntents intents;
|
||||
public JsonNode uInfoRaw;
|
||||
|
||||
|
||||
private async void heartBeat(object o)
|
||||
{
|
||||
var obj = new { op = 1, d = heartBeatSequence };
|
||||
var toSend = System.Text.Json.JsonSerializer.Serialize(obj);
|
||||
|
||||
WS.Send(toSend);
|
||||
heartBeatCounter++;
|
||||
}
|
||||
|
||||
|
||||
private void startHeartBeat(object o)
|
||||
{
|
||||
var confObj = JsonNode.Parse(o.ToString());
|
||||
heartBeatInterval = (int)confObj["d"]["heartbeat_interval"];
|
||||
Debug.WriteLine("INTERVAL SET TO: " + heartBeatInterval.ToString());
|
||||
|
||||
var idObj = new
|
||||
{
|
||||
op = 2,
|
||||
d = new
|
||||
{
|
||||
token = MsgRequests.userToken,
|
||||
intents = intents.value, //61440,
|
||||
properties = new
|
||||
{
|
||||
os = "linux",
|
||||
browser = "my_library",
|
||||
device = "my_library"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
WS.Send(System.Text.Json.JsonSerializer.Serialize(idObj));
|
||||
|
||||
var autoEvent = new AutoResetEvent(false);
|
||||
var stateTimer = new System.Threading.Timer(heartBeat, autoEvent, 0, heartBeatInterval);
|
||||
}
|
||||
|
||||
|
||||
private static void statusUpdate(object statusObj)
|
||||
{
|
||||
//Console.WriteLine(statusObj.ToString() + "\n\n");
|
||||
}
|
||||
|
||||
|
||||
private static void messageEvent(object msgObj)
|
||||
{
|
||||
Console.WriteLine(msgObj.ToString() + "\n\n");
|
||||
}
|
||||
|
||||
public async Task<JsonNode> connect(FlowLayoutPanel dmFlowPannel)
|
||||
{
|
||||
using (var client = new WebsocketClient(gateWayUrl))
|
||||
{
|
||||
client.ReconnectTimeout = TimeSpan.FromSeconds(30);
|
||||
client.ReconnectionHappened.Subscribe(info =>
|
||||
Debug.WriteLine($"Reconnection happened, type: {info.Type}"));
|
||||
|
||||
|
||||
//"READY" info dump handling
|
||||
client.MessageReceived.Where((msg) =>
|
||||
{
|
||||
var msgObj = JsonNode.Parse(msg.Text);
|
||||
return (int)msgObj["op"] == 0 && msgObj["t"].ToString() == "READY";
|
||||
}).Subscribe((msg) =>
|
||||
{
|
||||
var configs = JsonNode.Parse(msg.Text);
|
||||
//var c = new Client(configs["d"], dmFlowPannel);
|
||||
uInfoRaw = configs["d"];
|
||||
});
|
||||
|
||||
|
||||
client.MessageReceived.Where((msg) =>
|
||||
{
|
||||
var msgObj = JsonNode.Parse(msg.Text);
|
||||
return ((string)msgObj["t"] == "PRESENCE_UPDATE");
|
||||
}).Subscribe(statusUpdate);
|
||||
|
||||
|
||||
// client.MessageReceived.Subscribe(msg => Debug.WriteLine($"Message received: {msg}"));
|
||||
|
||||
client.MessageReceived.Where((msg) =>
|
||||
{
|
||||
var msgObj = JsonNode.Parse(msg.Text);
|
||||
return ((int)msgObj["op"] == 10);
|
||||
}).Subscribe((object o) =>
|
||||
{
|
||||
intents = new GateWayIntents(true);
|
||||
//throw new Exception(intents.ToString());
|
||||
startHeartBeat(o);
|
||||
});
|
||||
|
||||
|
||||
client.MessageReceived.Where((msg) =>
|
||||
{
|
||||
var msgObj = JsonNode.Parse(msg.Text);
|
||||
return ((string)msgObj["t"] == "PRESENCE_UPDATE");
|
||||
}).Subscribe(statusUpdate);
|
||||
|
||||
client.MessageReceived.Where((msg) =>
|
||||
{
|
||||
var msgObj = JsonNode.Parse(msg.Text);
|
||||
return ((int)msgObj["op"] == 0) && (string)msgObj["t"] == "MESSAGE_CREATE";
|
||||
}).Subscribe(messageEvent);
|
||||
|
||||
|
||||
client.Start();
|
||||
|
||||
Task.Run(() => client.Send("{ message }"));
|
||||
WS = client;
|
||||
|
||||
//exitEvent.WaitOne();
|
||||
|
||||
while (uInfoRaw == null) { }
|
||||
return uInfoRaw;
|
||||
}
|
||||
}
|
||||
|
||||
public Connection() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord_Client_Custom.Connections
|
||||
{
|
||||
internal partial class GateWayIntents
|
||||
{
|
||||
public enum GatewayIntent
|
||||
{
|
||||
Guilds = 1 << 0,
|
||||
GuildMembers = 1 << 1,
|
||||
GuildModeration = 1 << 2,
|
||||
GuildEmojisStickers = 1 << 3,
|
||||
GuildIntegrations = 1 << 4,
|
||||
GuildWebhooks = 1 << 5,
|
||||
GuildInvites = 1 << 6,
|
||||
GuildVoiceStates = 1 << 7,
|
||||
GuildPresences = 1 << 8,
|
||||
GuildMessages = 1 << 9,
|
||||
GuildMessageReactions = 1 << 10,
|
||||
GuildMessageTyping = 1 << 11,
|
||||
DirectMessages = 1 << 12,
|
||||
DirectMessageReactions = 1 << 13,
|
||||
DirectMessageTyping = 1 << 14,
|
||||
MessageContent = 1 << 15,
|
||||
GuildScheduledEvents = 1 << 16,
|
||||
AutoModerationConfiguration = 1 << 20,
|
||||
AutoModerationExecution = 1 << 21,
|
||||
}
|
||||
|
||||
public static int sum(GatewayIntent[] intents)
|
||||
{
|
||||
int sum = 0;
|
||||
foreach (var i in intents) sum += (int)i;
|
||||
return sum;
|
||||
}
|
||||
|
||||
public int value;
|
||||
public GatewayIntent[] intents;
|
||||
|
||||
//Initializes for DMs ONLY (so far...)
|
||||
public GateWayIntents(bool isDmOnly)
|
||||
{
|
||||
if (isDmOnly)
|
||||
{
|
||||
GatewayIntent[] intentsTemp = { GatewayIntent.DirectMessages, GatewayIntent.DirectMessageReactions, GatewayIntent.DirectMessageTyping };
|
||||
this.intents = intentsTemp;
|
||||
this.value = sum(intents);
|
||||
} else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
||||
namespace Discord_Client_Custom.Connections
|
||||
{
|
||||
internal class MsgRequests
|
||||
{
|
||||
private static string dmMePath = "https://discord.com/api/users/@me/channels";
|
||||
private static string dmGetMsgsBasepath = "https://discord.com/api/channels/{{id}}/messages?limit=10";
|
||||
public static string userToken = System.Environment.GetEnvironmentVariable("userToken");
|
||||
|
||||
public MsgRequests(string url, string reqType)
|
||||
{
|
||||
//userToken = System.Environment.GetEnvironmentVariable("userToken");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async static Task<JsonNode> sendMessage(string content, string ep)
|
||||
{
|
||||
Debug.WriteLine(ep);
|
||||
|
||||
try
|
||||
{
|
||||
var client = new HttpClient();
|
||||
|
||||
var toSend = new Dictionary<string, string>
|
||||
{
|
||||
{ "content", content },
|
||||
};
|
||||
|
||||
var request = new HttpRequestMessage()
|
||||
{
|
||||
RequestUri = new Uri(ep),
|
||||
Method = HttpMethod.Post,
|
||||
Content = new FormUrlEncodedContent(toSend)
|
||||
};
|
||||
|
||||
request.Headers.Clear();
|
||||
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
//CHANGE THIS TO CONFIG LATER
|
||||
request.Headers.Add("Authorization", userToken);
|
||||
request.Headers.Add("User-Agent", ".NET Foundation Repository Reporter");
|
||||
|
||||
|
||||
var taskResponse = await client.SendAsync(request);
|
||||
var responseContent = await taskResponse.Content.ReadAsStringAsync();
|
||||
JsonNode responseJSON = JsonNode.Parse(responseContent);
|
||||
|
||||
if (taskResponse.StatusCode != System.Net.HttpStatusCode.OK)
|
||||
{
|
||||
Debug.Write(responseJSON["message"]);
|
||||
return null;
|
||||
}
|
||||
|
||||
return responseJSON;
|
||||
} catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static async Task<JsonNode> getChannels()
|
||||
{
|
||||
var client = new HttpClient();
|
||||
var request = new HttpRequestMessage()
|
||||
{
|
||||
RequestUri = new Uri(dmMePath),
|
||||
Method = HttpMethod.Get,
|
||||
};
|
||||
|
||||
request.Headers.Clear();
|
||||
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
//CHANGE THIS TO CONFIG LATER
|
||||
request.Headers.Add("Authorization", userToken);
|
||||
request.Headers.Add("User-Agent", ".NET Foundation Repository Reporter");
|
||||
|
||||
var taskResponse = await client.SendAsync(request);
|
||||
var responseContent = await taskResponse.Content.ReadAsStringAsync();
|
||||
|
||||
if (responseContent == null) { return null; }
|
||||
|
||||
JsonNode responseJSON = JsonNode.Parse(responseContent);
|
||||
|
||||
if (taskResponse.StatusCode != System.Net.HttpStatusCode.OK)
|
||||
{
|
||||
Debug.Write(responseJSON["message"]);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return responseJSON;
|
||||
}
|
||||
|
||||
//Returns the
|
||||
public static async Task<JsonNode> getMessages(string cid, string? lastId = null)
|
||||
{
|
||||
string newUrl = dmGetMsgsBasepath.Replace("{{id}}", cid);
|
||||
if (lastId != null)
|
||||
{
|
||||
newUrl += "&before=" + lastId;
|
||||
}
|
||||
|
||||
var client = new HttpClient();
|
||||
var request = new HttpRequestMessage()
|
||||
{
|
||||
RequestUri = new Uri(newUrl),
|
||||
Method = HttpMethod.Get,
|
||||
};
|
||||
|
||||
request.Headers.Clear();
|
||||
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
request.Headers.Add("Authorization", userToken);
|
||||
request.Headers.Add("User-Agent", ".NET Foundation Repository Reporter");
|
||||
|
||||
var taskResponse = await client.SendAsync(request);
|
||||
var responseContent = await taskResponse.Content.ReadAsStringAsync();
|
||||
|
||||
if (responseContent == null) { return null; }
|
||||
|
||||
JsonNode responseJSON = JsonNode.Parse(responseContent);
|
||||
|
||||
if (taskResponse.StatusCode != System.Net.HttpStatusCode.OK)
|
||||
{
|
||||
Debug.Write(responseJSON["message"]);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return responseJSON;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user