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,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
@@ -348,3 +348,7 @@ MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
|
||||
# Ignored for token reasons (see template in the repo for correct usage)
|
||||
launchSettings.json
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Policy;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace Discord_Client_Custom.Channels
|
||||
{
|
||||
internal class ChannelMsgGroup
|
||||
{
|
||||
internal class message
|
||||
{
|
||||
internal class Author
|
||||
{
|
||||
private string id;
|
||||
private string username;
|
||||
private string discriminator;
|
||||
private string avatar;
|
||||
|
||||
public string getId() { return id; }
|
||||
public string getTag() { return username + discriminator; }
|
||||
public string getAvatar() { return avatar; }
|
||||
|
||||
|
||||
|
||||
public Author(JsonNode inp)
|
||||
{
|
||||
id = inp["id"].ToString();
|
||||
username = inp["username"].ToString();
|
||||
discriminator = inp["discriminator"].ToString();
|
||||
|
||||
//Check for deleted user
|
||||
if ((string)inp["avatar"] != "")
|
||||
{
|
||||
avatar = inp["avatar"].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public string toString()
|
||||
{
|
||||
return "[\n\tid: " + id + "\n\ttag: " + username + "#" + discriminator + "\n\tavatar: " + getAvatar() + "\n]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string id;
|
||||
private string content;
|
||||
private Author msgAuthor;
|
||||
private string url;
|
||||
private DateTime timestamp;
|
||||
|
||||
public message(JsonNode inp)
|
||||
{
|
||||
id = (string)inp["id"];
|
||||
url = "https://discord.com/channels/@me/" + inp["channel_id"] + "/" + inp["id"];
|
||||
content = (string)inp["content"];
|
||||
msgAuthor = new Author(inp["author"]);
|
||||
timestamp = DateTime.Parse((string)inp["timestamp"]);
|
||||
|
||||
|
||||
if (id == null || content == null || msgAuthor == null)
|
||||
{
|
||||
Debug.WriteLine("id, content, or author is null");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string getId() { return id; }
|
||||
public string getUrl() { return url; }
|
||||
public DateTime getTimestamp() { return timestamp; }
|
||||
|
||||
public string toString()
|
||||
{
|
||||
return "id: " + id + "\ncontent: " + content + "\nauthor: " + msgAuthor.toString();
|
||||
}
|
||||
|
||||
|
||||
public string getContent() { return content; }
|
||||
}
|
||||
|
||||
|
||||
private ContextMenuStrip createContextMenu(bool isIcon, string iconUrl)
|
||||
{
|
||||
//see profile, see icon
|
||||
|
||||
//delete message, copy link, edit message
|
||||
|
||||
ContextMenuStrip menu = new ContextMenuStrip();
|
||||
menu.Text = "right-click";
|
||||
|
||||
if (isIcon)
|
||||
{
|
||||
var item1 = new ToolStripMenuItem("see profile");
|
||||
var item2 = new ToolStripMenuItem("see icon");
|
||||
item2.Click += new EventHandler((sender, args) =>
|
||||
{
|
||||
|
||||
//Horrid resolution, try just opening the web page
|
||||
var icon = (PictureBox)((ContextMenuStrip)((ToolStripMenuItem)sender).Owner).SourceControl;
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = iconUrl.Remove(iconUrl.IndexOf("?size=")),
|
||||
UseShellExecute = true
|
||||
});
|
||||
});
|
||||
|
||||
menu.Items.Add(item1);
|
||||
menu.Items.Add(item2);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var item1 = new ToolStripMenuItem("delete message");
|
||||
var item2 = new ToolStripMenuItem("edit message");
|
||||
var item3 = new ToolStripMenuItem("copy link");
|
||||
item3.Click += new EventHandler(async (sender, args) =>
|
||||
{
|
||||
Clipboard.SetText(iconUrl);
|
||||
var parent = (Label)((ContextMenuStrip)((ToolStripMenuItem)sender).Owner).SourceControl;
|
||||
var oldCol = parent.ForeColor;
|
||||
parent.ForeColor = Color.Blue;
|
||||
ManualResetEvent resetEvent = new ManualResetEvent(false);
|
||||
await Task.Delay(2000);
|
||||
parent.ForeColor = oldCol;
|
||||
});
|
||||
|
||||
menu.Items.Add(item1);
|
||||
menu.Items.Add(item2);
|
||||
menu.Items.Add(item3);
|
||||
}
|
||||
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
private message[] msgs;
|
||||
private Label[] msglabels;
|
||||
|
||||
public ChannelMsgGroup(JsonNode inpMsgs, TableLayoutPanel dmFlowContent, Image uIcon, int rowNumber)
|
||||
{
|
||||
//msgs = new message[inpMsgs.Length];
|
||||
//msglabels = new Label[inpMsgs.Length];
|
||||
|
||||
//dmFlowContent.SuspendLayout();
|
||||
//Add the user icon
|
||||
var uBtn = new PictureBox
|
||||
{
|
||||
Image = uIcon,
|
||||
Tag = uIcon.Tag,
|
||||
};
|
||||
|
||||
uBtn.ContextMenuStrip = createContextMenu(true, (string)uIcon.Tag);
|
||||
uBtn.Size = uIcon.Size;
|
||||
uBtn.Padding = new Padding(0, 0, 0, 50);
|
||||
dmFlowContent.Controls.Add(uBtn, 0, rowNumber);
|
||||
|
||||
|
||||
var msg = new message(inpMsgs);
|
||||
|
||||
Label txt = new Label();
|
||||
txt.Text = msg.getContent();
|
||||
txt.Tag = msg.getId();
|
||||
|
||||
txt.MaximumSize = new Size(dmFlowContent.Width - 70, 100000000);
|
||||
txt.AutoSize = true;
|
||||
txt.Visible = true;
|
||||
|
||||
txt.ContextMenuStrip = createContextMenu(false, msg.getUrl());
|
||||
dmFlowContent.Controls.Add(txt, 1, rowNumber);
|
||||
|
||||
|
||||
/* FOR MULTIPLE MESSAGES
|
||||
for (int i = 0; i < msgs.Length; i++)
|
||||
{
|
||||
//if ((string)inpMsgs[i]["content"] == "") continue;
|
||||
msgs[i] = new message(inpMsgs[i]);
|
||||
|
||||
Label txt = new Label();
|
||||
txt.Text = msgs[i].getContent();
|
||||
txt.Tag = msgs[i].getId();
|
||||
|
||||
txt.MaximumSize = new Size(dmFlowContent.Width - 70, 100000000);
|
||||
txt.AutoSize = true;
|
||||
txt.Visible = true;
|
||||
|
||||
txt.ContextMenuStrip = createContextMenu(false, msgs[i].getUrl());
|
||||
|
||||
dmFlowContent.Controls.Add(txt, 1, rowNumber + i - 1);
|
||||
|
||||
//dmFlowContent.RowStyles.Add(new RowStyle(SizeType.Absolute));
|
||||
//dmFlowContent.RowStyles[rowNumber + i].Height = txt.Height;
|
||||
//dmFlowContent.SetFlowBreak(txt, true);
|
||||
}*/
|
||||
|
||||
//dmFlowContent.ResumeLayout();
|
||||
}
|
||||
|
||||
public Label[] getLabels()
|
||||
{
|
||||
return msglabels;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
using Discord_Client_Custom.client_internals;
|
||||
using Discord_Client_Custom.Connections;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text.Json.Nodes;
|
||||
using static Discord_Client_Custom.client_internals.Client;
|
||||
|
||||
namespace Discord_Client_Custom.Channels
|
||||
{
|
||||
public class ChannelObj
|
||||
{
|
||||
public static async Task<Image> getIconStream(string imageUrl)
|
||||
{
|
||||
Image image = null;
|
||||
|
||||
try
|
||||
{
|
||||
HttpClient client = new HttpClient();
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, imageUrl);
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
Stream stream = await response.Content.ReadAsStreamAsync();
|
||||
|
||||
image = Image.FromStream(stream);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("=======================================================");
|
||||
Debug.Write(ex.StackTrace);
|
||||
Debug.WriteLine(ex.Message);
|
||||
Debug.WriteLine("Using URL: " + imageUrl);
|
||||
Debug.WriteLine("=======================================================");
|
||||
return null;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
private static List<user> users = new List<user>();
|
||||
private static List<ChannelMsgGroup> groupedMsgs = new List<ChannelMsgGroup>();
|
||||
private static string cid;
|
||||
private static int ctype = 1;
|
||||
private static string? cname;
|
||||
private static string? cicon;
|
||||
private static string? cownerId;
|
||||
private string lastSent;
|
||||
|
||||
|
||||
public ChannelObj() { }
|
||||
|
||||
//For displaying information
|
||||
public ChannelObj(JsonNode contents)
|
||||
{
|
||||
cid = contents["id"].ToString();
|
||||
ctype = (int)contents["type"];
|
||||
|
||||
if (ctype == 3)
|
||||
{
|
||||
cname = contents["name"].ToString();
|
||||
cicon = contents["icon"].ToString();
|
||||
cownerId = contents["owner_id"].ToString();
|
||||
}
|
||||
|
||||
//Add the users to the DM
|
||||
Array recipients = contents["recipients"].AsArray().ToArray();
|
||||
|
||||
for (int i = 0; i < recipients.Length; i++)
|
||||
{
|
||||
JsonNode uObj = (JsonNode)recipients.GetValue(i);
|
||||
users.Add(new user(uObj));
|
||||
//users.Append(new user(uObj));
|
||||
}
|
||||
|
||||
//Console.WriteLine(recipients.GetValue(0).ToString() + " NUM: " + recipients.Length.ToString());
|
||||
}
|
||||
|
||||
|
||||
//Creating Messages
|
||||
internal ChannelObj(JsonNode contents, string cid2, TableLayoutPanel dmFlowContent, Image uicon, userMain uMain)
|
||||
{
|
||||
dmFlowContent.Controls.Clear();
|
||||
|
||||
//Begin message section
|
||||
Image uMainIcon = uMain.getAvatar();
|
||||
string uMainId = uMain.getId();
|
||||
|
||||
//There's gonna be a faster way
|
||||
var arr = contents.AsArray().ToArray().Reverse().ToArray();
|
||||
string id_current = (string)arr.Last()["id"];
|
||||
int startInd = 0;
|
||||
|
||||
//Make sure the first column is consitant
|
||||
dmFlowContent.ColumnStyles.Clear();
|
||||
dmFlowContent.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, uicon.Width));
|
||||
dmFlowContent.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
|
||||
//dmFlowContent.ColumnStyles[1].Width = 500;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < arr.Length; i++)
|
||||
{
|
||||
if ((string)arr[i]["content"] == "") continue;
|
||||
|
||||
string authorName = (string)arr[i]["author"]["id"];
|
||||
//Removed for spacing reasons
|
||||
//if (authorName != id_current)
|
||||
//{
|
||||
Debug.WriteLine(arr[i]["content"]);
|
||||
if (authorName == uMainId)
|
||||
{
|
||||
groupedMsgs.Add(new ChannelMsgGroup(arr[i], dmFlowContent, uMainIcon, i));
|
||||
}
|
||||
else
|
||||
{
|
||||
groupedMsgs.Add(new ChannelMsgGroup(arr[i], dmFlowContent, uicon, i));
|
||||
}
|
||||
|
||||
startInd = i;
|
||||
id_current = authorName;
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (i != startInd)
|
||||
{
|
||||
if ((string)arr[startInd]["author"]["id"] == uMainId)
|
||||
{
|
||||
groupedMsgs[groupedMsgs.Count - 1] = new ChannelMsgGroup(arr[startInd..i], dmFlowContent, uMainIcon, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
groupedMsgs[groupedMsgs.Count - 1] = new ChannelMsgGroup(arr[startInd..i], dmFlowContent, uicon, i);
|
||||
}
|
||||
}*/
|
||||
|
||||
lastSent = id_current;
|
||||
|
||||
//Add the text box
|
||||
var txtbx = new RichTextBox();
|
||||
txtbx.AutoWordSelection = true;
|
||||
txtbx.Size = new Size(dmFlowContent.Width - 50, 50);
|
||||
txtbx.KeyDown += async (object o, KeyEventArgs k) =>
|
||||
{
|
||||
if (k.KeyCode == Keys.Enter)
|
||||
{
|
||||
string ep;
|
||||
if (ctype == 1)
|
||||
{
|
||||
ep = "https://discord.com/api/channels/" + cid2 + "/messages";
|
||||
} else
|
||||
{
|
||||
//Deal with group message stuff here.....
|
||||
Debug.WriteLine("Message Sending has not been implemented for group DMs (yet)");
|
||||
return;
|
||||
}
|
||||
|
||||
var response = await MsgRequests.sendMessage(txtbx.Text, ep);
|
||||
JsonNode[] arr = new JsonNode[1];
|
||||
//arr[0] = response;
|
||||
|
||||
//Add the message to chat in the app
|
||||
groupedMsgs.Add(new ChannelMsgGroup(response, dmFlowContent, uMainIcon, i + 1));
|
||||
txtbx.Clear();
|
||||
|
||||
i++;
|
||||
dmFlowContent.Controls.Remove(txtbx);
|
||||
dmFlowContent.Controls.Add(txtbx, 1, i + 1);
|
||||
dmFlowContent.SetColumnSpan(txtbx, 2);
|
||||
} else
|
||||
{
|
||||
//Do typing intent stuff here
|
||||
//Connection
|
||||
}
|
||||
};
|
||||
|
||||
dmFlowContent.Controls.Add(txtbx, 0, i+1);
|
||||
dmFlowContent.SetColumnSpan(txtbx, 2);
|
||||
}
|
||||
|
||||
|
||||
public string getName()
|
||||
{
|
||||
if (cname != null)
|
||||
{
|
||||
return cname;
|
||||
}
|
||||
|
||||
return users[0].getUserName();
|
||||
}
|
||||
|
||||
|
||||
public string getId()
|
||||
{
|
||||
return cid;
|
||||
}
|
||||
|
||||
|
||||
public async Task<Image> getIcon()
|
||||
{
|
||||
string iconUrl;
|
||||
|
||||
if (ctype == 1)
|
||||
{
|
||||
iconUrl = "https://cdn.discordapp.com/avatars/" + users[0].getId() + "/";
|
||||
string uAvatar = users[0].getAvatar();
|
||||
|
||||
//null user
|
||||
if (uAvatar != null)
|
||||
{
|
||||
iconUrl += uAvatar;
|
||||
}
|
||||
else
|
||||
{
|
||||
iconUrl = "https://discord.com/assets/1f0bfc0865d324c2587920a7d80c609b";
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
iconUrl = "https://cdn.discordapp.com/channel-icons/" + cid + "/" + cicon;
|
||||
}
|
||||
|
||||
iconUrl += ".png?size=32";
|
||||
|
||||
|
||||
var imgRaw = await getIconStream(iconUrl);
|
||||
imgRaw.Tag = iconUrl;
|
||||
return imgRaw;
|
||||
|
||||
//string rootPath = @"C:\DownloadedImageFromUrl";
|
||||
//string fileName = System.IO.Path.Combine(rootPath, "test.gif");
|
||||
//image.Save(fileName);
|
||||
}
|
||||
|
||||
|
||||
public string toString()
|
||||
{
|
||||
string totalString = "cid: " + cid;
|
||||
|
||||
if (cname != null) { totalString += ", cname: " + cname; }
|
||||
|
||||
totalString += "\nusers: [";
|
||||
for (int i = 0; i < users.Count; i++)
|
||||
{
|
||||
totalString += users[i].toString();
|
||||
}
|
||||
|
||||
return totalString + "]\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<RootNamespace>Discord_Client_Custom</RootNamespace>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Websocket.Client" Version="4.6.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Form1.resx">
|
||||
<Generator></Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Debug_Utils\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.4.33213.308
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord-Client-Custom", "Discord-Client-Custom.csproj", "{432C8EE8-FCDB-46D6-B532-057706469037}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{432C8EE8-FCDB-46D6-B532-057706469037}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{432C8EE8-FCDB-46D6-B532-057706469037}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{432C8EE8-FCDB-46D6-B532-057706469037}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{432C8EE8-FCDB-46D6-B532-057706469037}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {8E65987B-E6C1-4431-B6C5-485FA5A7006B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Generated
+63
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Discord_Client_Custom {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Form1 {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Form1() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Discord_Client_Custom.Form1", typeof(Form1).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using System.Diagnostics;
|
||||
using static Discord_Client_Custom.Connections.MsgRequests;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Drawing.Imaging;
|
||||
using Discord_Client_Custom.Channels;
|
||||
using Discord_Client_Custom.Connections;
|
||||
using Discord_Client_Custom.client_internals;
|
||||
|
||||
namespace Discord_Client_Custom
|
||||
{
|
||||
public partial class mainPage : Form
|
||||
{
|
||||
private Connection con;
|
||||
public Client clientMain;
|
||||
|
||||
public mainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
private async static void dm_btn_click(object sender, EventArgs e)
|
||||
{
|
||||
string cid = (string)((Button)sender).Tag;
|
||||
|
||||
//Format and present messages
|
||||
//MessageBox.Show(cid);
|
||||
var o = await MsgRequests.getMessages(cid);
|
||||
var p = (mainPage)((Button)sender).Parent.Parent;
|
||||
|
||||
ChannelObj c = new ChannelObj(o, cid, p.dmFlowContent, ((Button)sender).Image, p.clientMain.getUserMain());
|
||||
}
|
||||
|
||||
|
||||
private async void dmFlowPannel_Paint(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
private async void dmFlowContent_Paint(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
private async void mainPage_Load(object sender, EventArgs e)
|
||||
{
|
||||
//Console.WriteLine("ok");
|
||||
var c = new Connection();
|
||||
var uInfoRaw = await c.connect(dmFlowPannel);
|
||||
|
||||
clientMain = new Client(uInfoRaw);
|
||||
var dmsRaw = c.uInfoRaw["private_channels"].AsArray().ToArray(); // (await getChannels()).AsArray().ToArray();
|
||||
if (dmsRaw == null) { throw new NotImplementedException(); }
|
||||
|
||||
|
||||
for (int i = 0; i < dmsRaw.Length; i++)
|
||||
{
|
||||
var o = dmsRaw[i];
|
||||
if ((int)o["type"] == 3) { continue; }
|
||||
|
||||
|
||||
var co = new ChannelObj(dmsRaw[i]);
|
||||
|
||||
Label lab = new Label();
|
||||
lab.Text = co.getName();
|
||||
lab.Location = new Point(30, 30 * i);
|
||||
lab.Tag = co.getId();
|
||||
|
||||
//Button
|
||||
Button btn = new Button();
|
||||
btn.Location = new Point(50, 50 + 30 * i);
|
||||
btn.Tag = co.getId();
|
||||
|
||||
var s = new Size(175, 40);
|
||||
btn.Size = s;
|
||||
|
||||
btn.Image = await co.getIcon();
|
||||
btn.Text = co.getName();
|
||||
btn.ImageAlign = ContentAlignment.MiddleLeft;
|
||||
btn.TextImageRelation = TextImageRelation.ImageBeforeText;
|
||||
btn.TextAlign = ContentAlignment.MiddleCenter;
|
||||
btn.Click += dm_btn_click;
|
||||
|
||||
//dmFlowPannel.Controls.Add(lab);
|
||||
dmFlowPannel.Controls.Add(btn);
|
||||
}
|
||||
|
||||
//*/
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord_Client_Custom
|
||||
{
|
||||
internal class GuildObj
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
namespace Discord_Client_Custom
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
// To customize application configuration such as set high DPI settings or default font,
|
||||
// see https://aka.ms/applicationconfiguration.
|
||||
ApplicationConfiguration.Initialize();
|
||||
Application.Run(new mainPage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord_Client_Custom
|
||||
{
|
||||
internal class user
|
||||
{
|
||||
private static string uid;
|
||||
private static string username;
|
||||
private static string discriminator;
|
||||
private static string avatar;
|
||||
private static string? nickname = null;
|
||||
|
||||
public user(JsonNode specs)
|
||||
{
|
||||
uid = (string)specs["id"];
|
||||
username = (string)specs["username"];
|
||||
discriminator = (string)specs["discriminator"];
|
||||
avatar = (string)specs["avatar"];
|
||||
}
|
||||
|
||||
public string getUserName()
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
|
||||
public string getAvatar()
|
||||
{
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public string getId() { return uid; }
|
||||
|
||||
|
||||
public string toString()
|
||||
{
|
||||
return "{\n\tuid: " + uid + "\n\tusername: " + username + "\n\tdiscriminator: " + discriminator + "\n\tavatar: " + avatar + "\n}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
using Discord_Client_Custom.Channels;
|
||||
using System.Configuration.Internal;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord_Client_Custom.client_internals
|
||||
{
|
||||
public partial class Client
|
||||
{
|
||||
internal class userMain {
|
||||
JsonNode customStatus;
|
||||
string locale;
|
||||
string theme;
|
||||
|
||||
bool verified;
|
||||
string username;
|
||||
string discriminator;
|
||||
int flags;
|
||||
string phone;
|
||||
string email;
|
||||
string id;
|
||||
string bio;
|
||||
string? banner; //Move these to config file maybe?
|
||||
string banner_color;
|
||||
Image avatar;
|
||||
string accent_color;
|
||||
|
||||
JsonNode[] channels;
|
||||
user[] relationships;
|
||||
|
||||
private async void getAvatarHelper(string? avatarUrl) {
|
||||
string iconUrl = "https://cdn.discordapp.com/avatars/" + id + "/" + avatarUrl + ".png?size=32";
|
||||
|
||||
//null user
|
||||
if (avatarUrl == null)
|
||||
{
|
||||
iconUrl = "https://discord.com/assets/1f0bfc0865d324c2587920a7d80c609b";
|
||||
}
|
||||
|
||||
avatar = await ChannelObj.getIconStream(iconUrl);
|
||||
avatar.Tag = iconUrl;
|
||||
}
|
||||
|
||||
|
||||
public userMain(JsonNode uConfigs, JsonNode uObj, JsonNode[] chnls, user[] relshnshps) {
|
||||
customStatus = uConfigs["custom_status"];
|
||||
locale = uConfigs["locale"].ToString();
|
||||
theme = uConfigs["theme"].ToString();
|
||||
|
||||
verified = (bool)uObj["verified"];
|
||||
username = uObj["username"].ToString();
|
||||
discriminator = uObj["discriminator"].ToString();
|
||||
flags = (int)uObj["flags"];
|
||||
phone = uObj["phone"].ToString();
|
||||
email = uObj["email"].ToString();
|
||||
id = uObj["id"].ToString();
|
||||
bio = uObj["bio"].ToString();
|
||||
banner_color = uObj["banner_color"].ToString();
|
||||
//banner = uObj["banner"].ToString();
|
||||
|
||||
accent_color = uObj["accent_color"].ToString();
|
||||
channels = chnls;
|
||||
relationships = relshnshps;
|
||||
getAvatarHelper(uObj["avatar"].ToString());
|
||||
}
|
||||
|
||||
|
||||
public Image getAvatar() { return avatar; }
|
||||
public string getId() { return id; }
|
||||
}
|
||||
|
||||
userMain uMain;
|
||||
|
||||
internal userMain getUserMain()
|
||||
{
|
||||
return this.uMain;
|
||||
}
|
||||
|
||||
private void printAll(JsonNode us, JsonNode um, user[] rel, JsonNode[] channels)
|
||||
{
|
||||
Console.WriteLine("===============User Settings================");
|
||||
Console.WriteLine(us);
|
||||
|
||||
Console.WriteLine("================User Main===============");
|
||||
Console.WriteLine(um);
|
||||
|
||||
Console.WriteLine("===============Relationships================");
|
||||
Console.WriteLine(rel.Length);
|
||||
|
||||
Console.WriteLine("================Channels===============");
|
||||
Console.WriteLine(channels);
|
||||
}
|
||||
|
||||
//configs is the "d" part of the READY event
|
||||
public Client(JsonNode configs) {
|
||||
var userSettings = configs["user_settings"];
|
||||
//var user_guild_settings = configs["user_guild_settings"];
|
||||
var uObj = configs["user"];
|
||||
var relationships = Array.ConvertAll<JsonNode, user>(configs["relationships"].AsArray().ToArray(), (item) => { return new user(item); });
|
||||
var channels = configs["private_channels"].AsArray().ToArray();
|
||||
Debug.WriteLine("\n\n\noh\n\n\n");
|
||||
|
||||
|
||||
uMain = new userMain(userSettings, uObj, channels, relationships);
|
||||
//printAll(userSettings, userMain, relationships, channels);
|
||||
}
|
||||
|
||||
public static explicit operator Client(Control v)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+98
@@ -0,0 +1,98 @@
|
||||
namespace Discord_Client_Custom
|
||||
{
|
||||
partial class mainPage
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
//this.testbtn = new System.Windows.Forms.Button();
|
||||
this.dmFlowPannel = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.dmFlowContent = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// testbtn
|
||||
/*/
|
||||
this.testbtn.Location = new System.Drawing.Point(320, 147);
|
||||
this.testbtn.Name = "testbtn";
|
||||
this.testbtn.Size = new System.Drawing.Size(75, 23);
|
||||
this.testbtn.TabIndex = 0;
|
||||
this.testbtn.Text = "AUR NAUR";
|
||||
this.testbtn.UseVisualStyleBackColor = true;
|
||||
this.testbtn.Click += new System.EventHandler(this.testBtn_click);
|
||||
*/
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(800, 450);
|
||||
//this.Controls.Add(this.testbtn);
|
||||
this.Name = "Form1";
|
||||
this.Text = "Form1";
|
||||
this.Load += new System.EventHandler(this.mainPage_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
|
||||
//
|
||||
// TableLayoutPanel1
|
||||
//
|
||||
this.SuspendLayout();
|
||||
this.dmFlowPannel.AutoScroll = true;
|
||||
this.dmFlowPannel.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;
|
||||
this.dmFlowPannel.Location = new System.Drawing.Point(1, 2);
|
||||
this.dmFlowPannel.Name = "dmFlowPannel";
|
||||
this.dmFlowPannel.Size = new System.Drawing.Size(200, 400);
|
||||
this.dmFlowPannel.TabIndex = 0;
|
||||
this.dmFlowPannel.Paint += new System.Windows.Forms.PaintEventHandler(this.dmFlowPannel_Paint);
|
||||
this.Controls.Add(this.dmFlowPannel);
|
||||
|
||||
|
||||
//
|
||||
// dmFlowContent
|
||||
//
|
||||
this.SuspendLayout();
|
||||
this.dmFlowContent.AutoScroll = true;
|
||||
//this.dmFlowContent.FlowDirection = System.Windows.Forms.FlowDirection.LeftToRight;
|
||||
this.dmFlowContent.Location = new System.Drawing.Point(210, 5);
|
||||
this.dmFlowContent.Name = "dmFlowContent";
|
||||
this.dmFlowContent.Size = new System.Drawing.Size(575, 400);
|
||||
this.dmFlowContent.TabIndex = 0;
|
||||
this.dmFlowContent.BackColor = Color.DarkGray;
|
||||
this.dmFlowContent.Paint += new System.Windows.Forms.PaintEventHandler(this.dmFlowContent_Paint);
|
||||
|
||||
//this.dmFlowContent.WrapContents = true;
|
||||
this.Controls.Add(this.dmFlowContent);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private FlowLayoutPanel dmFlowPannel;
|
||||
|
||||
//FFS find a way to fix this ASAP
|
||||
public TableLayoutPanel dmFlowContent;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user