diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -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 diff --git a/.gitignore b/.gitignore index dfcfd56..9e8b0d5 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/Channels/ChannelMsgGroup.cs b/Channels/ChannelMsgGroup.cs new file mode 100644 index 0000000..ef5b19f --- /dev/null +++ b/Channels/ChannelMsgGroup.cs @@ -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; + } + } +} diff --git a/Channels/ChannelObj.cs b/Channels/ChannelObj.cs new file mode 100644 index 0000000..cc34956 --- /dev/null +++ b/Channels/ChannelObj.cs @@ -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 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 users = new List(); + private static List groupedMsgs = new List(); + 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 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"; + } + } +} diff --git a/Connections/Connection-Old.cs b/Connections/Connection-Old.cs new file mode 100644 index 0000000..fbdf35d --- /dev/null +++ b/Connections/Connection-Old.cs @@ -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 SendMessageAsync(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(); + + } +} diff --git a/Connections/Connection.cs b/Connections/Connection.cs new file mode 100644 index 0000000..5b6da9a --- /dev/null +++ b/Connections/Connection.cs @@ -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 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() { + + } + } +} diff --git a/Connections/GateWayIntents.cs b/Connections/GateWayIntents.cs new file mode 100644 index 0000000..b5cb5b9 --- /dev/null +++ b/Connections/GateWayIntents.cs @@ -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(); + } + } + } +} diff --git a/Connections/MsgRequests.cs b/Connections/MsgRequests.cs new file mode 100644 index 0000000..34d7073 --- /dev/null +++ b/Connections/MsgRequests.cs @@ -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 sendMessage(string content, string ep) + { + Debug.WriteLine(ep); + + try + { + var client = new HttpClient(); + + var toSend = new Dictionary + { + { "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 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 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; + } + } +} diff --git a/Discord-Client-Custom.csproj b/Discord-Client-Custom.csproj new file mode 100644 index 0000000..b25b299 --- /dev/null +++ b/Discord-Client-Custom.csproj @@ -0,0 +1,27 @@ + + + + WinExe + net6.0-windows + Discord_Client_Custom + enable + true + enable + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Discord-Client-Custom.sln b/Discord-Client-Custom.sln new file mode 100644 index 0000000..cde6e05 --- /dev/null +++ b/Discord-Client-Custom.sln @@ -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 diff --git a/Form1.Designer.cs b/Form1.Designer.cs new file mode 100644 index 0000000..932810b --- /dev/null +++ b/Form1.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Discord_Client_Custom { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [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; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Form1.cs b/Form1.cs new file mode 100644 index 0000000..9ed6ffb --- /dev/null +++ b/Form1.cs @@ -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); + } + + //*/ + } + } +} \ No newline at end of file diff --git a/Form1.resx b/Form1.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/Form1.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GuildObj.cs b/GuildObj.cs new file mode 100644 index 0000000..4d5da2d --- /dev/null +++ b/GuildObj.cs @@ -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 + { + + } +} diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE.txt @@ -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. diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..b40c366 --- /dev/null +++ b/Program.cs @@ -0,0 +1,17 @@ +namespace Discord_Client_Custom +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [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()); + } + } +} \ No newline at end of file diff --git a/Properties/userConfigns.json b/Properties/userConfigns.json new file mode 100644 index 0000000..077404a --- /dev/null +++ b/Properties/userConfigns.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/User.cs b/User.cs new file mode 100644 index 0000000..3c782e5 --- /dev/null +++ b/User.cs @@ -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}"; + } + } +} diff --git a/client_internals/Client.cs b/client_internals/Client.cs new file mode 100644 index 0000000..43330cb --- /dev/null +++ b/client_internals/Client.cs @@ -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(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(); + } + } +} diff --git a/mainPage.Designer.cs b/mainPage.Designer.cs new file mode 100644 index 0000000..465f0b2 --- /dev/null +++ b/mainPage.Designer.cs @@ -0,0 +1,98 @@ +namespace Discord_Client_Custom +{ + partial class mainPage + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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; + } +} \ No newline at end of file