public static void ProcessDiscordPresence(g_Instance frame)
        {
            lastDiscordPresenceTime = DateTime.Now;

            if (Settings.Default.discordRichPresence)
            {
                if (discordClient == null || discordClient.IsDisposed)
                {
                    //InitializeDiscord();
                    LogRow(LogType.Error, "Discord RP client disposed while in normal thread.");
                }

                RichPresence rp = new RichPresence();

                if (frame == null)
                {
                    discordClient.SetPresence(null);
                    return;
                }

                StringBuilder details = new StringBuilder();
                if (frame.map_name == "mpl_arena_a")
                {
                    if (frame.teams[2].players.Find(p => p.name == frame.client_name) != null)
                    {
                        details.Append("Spectating ");
                    }
                    else
                    {
                        details.Append("Playing ");
                    }

                    details.Append("Arena ");

                    if (frame.private_match)
                    {
                        details.Append("pvt.");

                        rp.WithSecrets(new Secrets
                        {
                            JoinSecret     = "spark://c/" + frame.sessionid,
                            SpectateSecret = "spark://s/" + frame.sessionid,
                        });
                    }
                    else
                    {
                        details.Append("pub.");
                    }

                    rp.State      = "Score: " + frame.orange_points + " - " + frame.blue_points;
                    rp.Timestamps = new Timestamps
                    {
                        End = frame.game_status == "post_match" ? DateTime.UtcNow : DateTime.UtcNow.AddSeconds(frame.game_clock)
                    };
                    rp.WithParty(new Party
                    {
                        ID   = frame.sessionid,
                        Size = frame.GetAllPlayers().Count,
                        Max  = frame.private_match ? 15 : 8
                    });
                }
                else if (frame.map_name == "mpl_lobby_b2")
                {
                    details.Append("in EchoVR Lobby");

                    // how long have we been in the lobby?
                    if (!inLobby)
                    {
                        inLobby        = true;
                        lobbyEntryTime = DateTime.UtcNow;
                    }
                    rp.Timestamps = new Timestamps
                    {
                        Start = lobbyEntryTime
                    };
                }
                else                 // if (frame.map_name == "whatever combat is")
                {
                    details.Append("Playing Combat");
                }

                rp.Details = details.ToString();
                rp.Assets  = new Assets
                {
                    LargeImageKey  = "echo_arena_store_icon",
                    LargeImageText = "Rich presence from Spark"
                };


                discordClient.SetPresence(rp);
            }
            else
            {
                if (discordClient != null && !discordClient.IsDisposed)
                {
                    discordClient.Dispose();
                }
            }
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (m_Client != null)
            {
                m_Client.Invoke();

                var has = false;
                var rp  = new RichPresence();

                if (checkBox_Details.Checked &&
                    textBox_Details.Text.Length >= 2)
                {
                    rp.Details = textBox_Details.Text;
                    has        = true;
                }

                if (checkBox_State.Checked &&
                    textBox_State.Text.Length >= 2)
                {
                    rp.State = textBox_State.Text;
                    has      = true;
                }

                if (checkBox_LargeImageKey.Checked ||
                    checkBox_LargeImageText.Checked ||
                    checkBox_SmallImageKey.Checked ||
                    checkBox_SmallImageText.Checked)
                {
                    var a = new Assets();
                    if (checkBox_LargeImageKey.Checked)
                    {
                        a.LargeImageKey = textBox_LargeImageKey.Text;
                    }
                    if (checkBox_LargeImageText.Checked)
                    {
                        a.LargeImageText = textBox_LargeImageText.Text;
                    }
                    if (checkBox_SmallImageKey.Checked)
                    {
                        a.SmallImageKey = textBox_SmallImageKey.Text;
                    }
                    if (checkBox_SmallImageText.Checked)
                    {
                        a.SmallImageText = textBox_SmallImageText.Text;
                    }
                    rp.Assets = a;
                    has       = true;
                }

                // Details나 State가 설정되어야 값이 나옴
                // PC는 상관이 없는데 MOBILE에서 그럼
                if (checkBox_Start.Checked ||
                    checkBox_End.Checked)
                {
                    var timestamps = new Timestamps();
                    if (checkBox_Start.Checked)
                    {
                        timestamps.Start = dtp_Start.Value.ToUniversalTime();
                    }
                    // Start가 설정되어야 함.
                    // 안그럼 디코가 터짐
                    if (checkBox_Start.Checked &&
                        checkBox_End.Checked)
                    {
                        timestamps.End = dtp_End.Value.ToUniversalTime();
                    }
                    rp.Timestamps = timestamps;
                    has           = true;
                }

                if (checkBox_Party.Checked &&
                    nud_PartySize.Value < nud_PartyMax.Value)
                {
                    rp.WithParty(new Party
                    {
                        ID   = "pypy",
                        Size = (int)nud_PartySize.Value,
                        Max  = (int)nud_PartyMax.Value
                    });
                    has = true;
                }

                if (has)
                {
                    m_Client.SetPresence(rp);
                }
                else
                {
                    m_Client.SetPresence(null);
                }
            }
        }