private void btnUpload_Click(object sender, EventArgs e)
        {
            if (CurrentlyUploadingSlices > 0 && e != null)
            {
                return;
            }
            var dialog = new OpenFileDialog();

            dialog.InitialDirectory = "C:\\";
            dialog.Title            = "Select Image to Upload";
            dialog.Filter           = "Image files|*.jpg;*.jpeg;*.png;*.gif;*.bmp";
            dialog.CheckFileExists  = true;
            dialog.CheckPathExists  = true;
            dialog.ShowDialog(this);
            if (string.IsNullOrWhiteSpace(dialog.FileName))
            {
                return;
            }
            var path  = System.IO.Path.GetFileName(dialog.FileName);
            var image = new Classes.Image(path, Client.CurrentUser);

            image.Id = _imageInProgressId++;
            if (!Directory.Exists("Images"))
            {
                Directory.CreateDirectory("Images");
            }

            if (!Directory.Exists($"Images/{image.UploadedBy.Id}"))
            {
                Directory.CreateDirectory($"Images/{image.UploadedBy.Id}");
            }

            if (!Directory.Exists($"Images/{image.UploadedBy.Id}/{image.Id}"))
            {
                Directory.CreateDirectory($"Images/{image.UploadedBy.Id}/{image.Id}");
            }

            File.Copy(dialog.FileName, image.Path, true);
            image.LoadImageIntoString();
            CurrentlyUploadingSlices = image.Slices.Count;
            var packet = new Packet(PacketId.RequestUploadImage, image.ToJson(true));

            Client.Send(packet.ToString());
            Common.AddImage(image);
        }
        private void HandleConnMessage(Connection connection, User user, Packet packet)
        {
            if (packet.Id == PacketId.SendMessage)
            {
                var msg = new Message();
                msg.FromJson(packet.Information);
                if (msg.Content.Length > 256)
                {
                    msg         = new Message();
                    msg.Content = $"Error: Message was too long";
                    msg.Author  = Menu.Server.SERVERUSER;
                    msg.Colour  = System.Drawing.Color.Red;
                    SendTo(user, new Packet(PacketId.NewMessage, msg.ToJson()));
                    return;
                }
                if (string.IsNullOrWhiteSpace(msg.Content))
                {
                    msg         = new Message();
                    msg.Content = $"Error: Message was empty, whitespace or null.";
                    msg.Author  = Menu.Server.SERVERUSER;
                    msg.Colour  = System.Drawing.Color.Red;
                    SendTo(user, new Packet(PacketId.NewMessage, msg.ToJson()));
                    return;
                }
                if (user.SavedValues.TryGetValue("muted", out var val) && bool.TryParse(val, out var muted) && muted)
                {
                    msg         = new Message();
                    msg.Content = $"Error: you are muted";
                    msg.Author  = Menu.Server.SERVERUSER;
                    msg.Colour  = System.Drawing.Color.Red;
                    SendTo(user, new Packet(PacketId.NewMessage, msg.ToJson()));
                    return;
                }


                msg.Id = Common.IterateMessageId();
                Common.AddMessage(msg);
                NewMessage?.Invoke(this, msg); // so Server can see all messages
                if (msg.Content.StartsWith("/"))
                {                              // command, so we dont broadcast to all users
                    try
                    {
                        Menu.Server.Commands.Execute(msg);
                    } catch (Exception ex)
                    {
                        Logger.LogMsg(ex.ToString(), LogSeverity.Error);
                        var reply = new Classes.Message();
                        reply.Author = Menu.Server.SERVERUSER;
                        reply.Id     = Common.IterateMessageId();
                        reply.Colour = System.Drawing.Color.Red;
                        SendTo(user, new Packet(PacketId.NewMessage, reply.ToJson()));
                    }
                }
                else
                { // non-command, so we broadcast
                    var pong = new Packet(PacketId.NewMessage, msg.ToJson());
                    Broadcast(pong);
                }
            }
            else if (packet.Id == PacketId.Disconnect)
            {
                HandleConnDisconnect(connection, new Exception("User self-disconnected"));
            }
            else if (packet.Id == PacketId.RequestDeleteMessage)
            {
                var id = packet.Information["id"].ToObject <uint>();
                if (Common.TryGetMessage(id, out var msg))
                {
                    if (msg.Author.Id != user.Id && user.Id != Menu.Server.SERVERUSER.Id)
                    {
                        var errMsg = new Message();
                        errMsg.Author  = Menu.Server.SERVERUSER;
                        errMsg.Id      = 0;
                        errMsg.Content = $"Error: Cannot delete message since you are not the author";
                        errMsg.Colour  = Color.Red;
                        SendTo(user, new Packet(PacketId.NewMessage, errMsg.ToJson()));
                        return;
                    }
                    var jobj = new JObject();
                    jobj["id"] = id;
                    var pong = new Packet(PacketId.MessageDeleted, jobj);
                    Broadcast(pong);
                }
            }
            else if (packet.Id == PacketId.RequestEditMessage)
            {
            }
            else if (packet.Id == PacketId.RequestUploadImage)
            {
                var image = new Classes.Image();
                image.FromJson(packet.Information);
                if ((Menu.Client?.Client?.CurrentUser?.Id ?? (uint)0) == user.Id)
                { // Local user, so no need to upload image (since its already there)
                    if (Common.TryGetImage(image.Id, out var old))
                    {
                        Common.Images.Remove(image.Id);
                        old.Id = Common.IterateImageId();
                        Common.AddImage(old);
                        image = old;
                    }
                    var otherPacket = new Packet(PacketId.ImageInitialInformation, image.ToJson(true));
                    Broadcast(otherPacket);
                    return;
                }
                var jobj = new JObject();
                jobj["slice"]      = 0;
                jobj["originalId"] = image.Id;
                image.Id           = Common.IterateImageId();
                Common.AddImage(image);
                jobj["id"] = image.Id;
                var pongPacket = new Packet(PacketId.ImageNeedSlice, jobj);
                SendTo(user, pongPacket);
            }
            else if (packet.Id == PacketId.ImageSlice)
            {
                var id       = packet.Information["id"].ToObject <uint>();
                var sliceNum = packet.Information["slice"].ToObject <int>();
                var done     = packet.Information["done"].ToObject <bool>();
                var content  = packet.Information["data"].ToObject <string>();
                if (Common.TryGetImage(id, out var image))
                {
                    image.SetSlice(sliceNum, content);
                    if (done)
                    {
                        var      loadedImage = System.Drawing.Image.FromStream(image.GetStream());
                        string[] pathDirs    = image.Path.Split('/');
                        pathDirs = pathDirs.Reverse().Skip(1).Reverse().ToArray();
                        string temp = "";
                        foreach (var path in pathDirs)
                        {
                            temp += path + "/";
                            if (!Directory.Exists(temp))
                            {
                                Directory.CreateDirectory(temp);
                            }
                        }
                        loadedImage.Save(image.Path);
                        var otherPacket = new Packet(PacketId.ImageInitialInformation, image.ToJson(true));
                        Broadcast(otherPacket);
                    }
                    else
                    {
                        var jobj = new JObject();
                        jobj["id"]    = image.Id;
                        jobj["slice"] = sliceNum + 1;
                        var pongPacket = new Packet(PacketId.ImageNeedSlice, jobj);
                        SendTo(user, pongPacket);
                    }
                }
            }
            else if (packet.Id == PacketId.ImageNeedSlice)
            {
                var id       = packet.Information["id"].ToObject <uint>();
                var sliceNum = packet.Information["slice"].ToObject <int>();
                if (Common.TryGetImage(id, out var image))
                {
                    var slice = image.Slices[sliceNum];
                    var jobj  = new JObject(packet.Information);
                    jobj["done"] = (sliceNum == image.Slices.Count - 1);
                    jobj["data"] = slice;
                    var pongPacket = new Packet(PacketId.ImageSlice, jobj);
                    SendTo(user, pongPacket);
                }
            }
            else if (packet.Id == PacketId.NeedUserInfo)
            {
                var id   = packet.Information["id"].ToObject <uint>();
                var usr  = Common.GetUser(id);
                var pong = new Packet(PacketId.RespondUserInfo, usr.ToJson());
                SendTo(user, pong);
            }
        }