using Octokit; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Windows.Forms; using TGS.Interface; using TGS.Interface.Components; namespace TGS.ControlPanel { partial class ControlPanel { bool updatingFields = false; /// /// used for checking the merged state of s /// GitHubClient ghclient; void InitServerPage() { projectNameText.LostFocus += ProjectNameText_LostFocus; projectNameText.KeyDown += ProjectNameText_KeyDown; ServerStartBGW.RunWorkerCompleted += ServerStartBGW_RunWorkerCompleted; ghclient = new GitHubClient(new ProductHeaderValue(Assembly.GetExecutingAssembly().GetName().Name)); var config = Properties.Settings.Default; if (!String.IsNullOrWhiteSpace(config.GitHubAPIKey)) ghclient.Credentials = new Credentials(Helpers.DecryptData(config.GitHubAPIKey, config.GitHubAPIKeyEntropy)); } private void ServerStartBGW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Result != null) MessageBox.Show((string)e.Result); LoadServerPage(); } private void ProjectNameText_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) UpdateProjectName(); } private void CompileCancelButton_Click(object sender, EventArgs e) { var res = Interface.GetComponent().Cancel(); if (res != null) MessageBox.Show(res); LoadServerPage(); } void LoadServerPage() { var RepoExists = Interface.GetComponent().Exists(); compileButton.Visible = RepoExists; AutoUpdateCheckbox.Visible = RepoExists; initializeButton.Visible = RepoExists; AutostartCheckbox.Visible = RepoExists; WebclientCheckBox.Visible = RepoExists; PortSelector.Visible = RepoExists; projectNameText.Visible = RepoExists; CompilerStatusLabel.Visible = RepoExists; CompileCancelButton.Visible = RepoExists; CompilerLabel.Visible = RepoExists; ProjectPathLabel.Visible = RepoExists; ServerGStopButton.Visible = RepoExists; ServerStartButton.Visible = RepoExists; ServerGRestartButton.Visible = RepoExists; ServerRestartButton.Visible = RepoExists; PortLabel.Visible = RepoExists; ServerStopButton.Visible = RepoExists; TestMergeManagerButton.Visible = RepoExists; UpdateServerButton.Visible = RepoExists; RemoveAllTestMergesButton.Visible = RepoExists; WorldAnnounceField.Visible = RepoExists; WorldAnnounceButton.Visible = RepoExists; WorldAnnounceLabel.Visible = RepoExists; SyncCommitsCheckBox.Visible = RepoExists; if (updatingFields) return; var DM = Interface.GetComponent(); var DD = Interface.GetComponent(); var Config = Interface.GetComponent(); var Repo = Interface.GetComponent(); try { updatingFields = true; ServerPathLabel.Text = "Server Path: " + Interface.GetComponent().ServerDirectory(); SecuritySelector.SelectedIndex = (int)DD.SecurityLevel(); if (!RepoExists) return; var interval = Repo.AutoUpdateInterval(); var interval_not_zero = interval != 0; AutoUpdateCheckbox.Checked = interval_not_zero; AutoUpdateInterval.Visible = interval_not_zero; AutoUpdateMLabel.Visible = interval_not_zero; if (interval_not_zero) AutoUpdateInterval.Value = interval; var DaeStat = DD.DaemonStatus(); var Online = DaeStat == DreamDaemonStatus.Online; ServerStartButton.Enabled = !Online; ServerGStopButton.Enabled = Online; ServerGRestartButton.Enabled = Online; ServerStopButton.Enabled = Online; ServerRestartButton.Enabled = Online; switch (DaeStat) { case DreamDaemonStatus.HardRebooting: ServerStatusLabel.Text = "REBOOTING"; break; case DreamDaemonStatus.Offline: ServerStatusLabel.Text = "OFFLINE"; break; case DreamDaemonStatus.Online: ServerStatusLabel.Text = "ONLINE"; var pc = DD.PlayerCount(); if (pc != -1) ServerStatusLabel.Text += " (" + pc + " players)"; break; } ServerGStopButton.Checked = DD.ShutdownInProgress(); AutostartCheckbox.Checked = DD.Autostart(); WebclientCheckBox.Checked = DD.Webclient(); if (!PortSelector.Focused) PortSelector.Value = DD.Port(); if (!projectNameText.Focused) projectNameText.Text = DM.ProjectName(); UpdateServerButton.Enabled = false; TestMergeManagerButton.Enabled = false; RemoveAllTestMergesButton.Enabled = false; switch (DM.GetStatus()) { case CompilerStatus.Compiling: CompilerStatusLabel.Text = "Compiling..."; compileButton.Enabled = false; initializeButton.Enabled = false; CompileCancelButton.Enabled = true; break; case CompilerStatus.Initializing: CompilerStatusLabel.Text = "Initializing..."; compileButton.Enabled = false; initializeButton.Enabled = false; CompileCancelButton.Enabled = false; break; case CompilerStatus.Initialized: CompilerStatusLabel.Text = "Idle"; initializeButton.Enabled = true; compileButton.Enabled = true; CompileCancelButton.Enabled = false; UpdateServerButton.Enabled = true; TestMergeManagerButton.Enabled = true; RemoveAllTestMergesButton.Enabled = true; break; case CompilerStatus.Uninitialized: CompilerStatusLabel.Text = "Uninitialized"; compileButton.Enabled = false; initializeButton.Enabled = true; CompileCancelButton.Enabled = false; break; default: CompilerStatusLabel.Text = "Unknown!"; initializeButton.Enabled = true; compileButton.Enabled = true; CompileCancelButton.Enabled = true; break; } var error = DM.CompileError(); if (error != null) MessageBox.Show("Error: " + error); } finally { updatingFields = false; } } private void ProjectNameText_LostFocus(object sender, EventArgs e) { UpdateProjectName(); } void UpdateProjectName() { if (!updatingFields) Interface.GetComponent().SetProjectName(projectNameText.Text); } private void PortSelector_ValueChanged(object sender, EventArgs e) { if (!updatingFields) Interface.GetComponent().SetPort((ushort)PortSelector.Value); } private void ServerPageRefreshButton_Click(object sender, EventArgs e) { LoadServerPage(); } private void InitializeButton_Click(object sender, EventArgs e) { if (!Interface.GetComponent().Initialize()) MessageBox.Show("Unable to start initialization!"); LoadServerPage(); } private void CompileButton_Click(object sender, EventArgs e) { if (!Interface.GetComponent().Compile()) MessageBox.Show("Unable to start compilation!"); LoadServerPage(); } private void AutostartCheckbox_CheckedChanged(object sender, System.EventArgs e) { if (!updatingFields) Interface.GetComponent().SetAutostart(AutostartCheckbox.Checked); } private void ServerStartButton_Click(object sender, System.EventArgs e) { if (!ServerStartBGW.IsBusy) ServerStartBGW.RunWorkerAsync(); } private void ServerStartBGW_DoWork(object sender, DoWorkEventArgs e) { try { e.Result = Interface.GetComponent().Start(); } catch (Exception ex) { e.Result = ex.ToString(); } } private void ServerStopButton_Click(object sender, EventArgs e) { var DialogResult = MessageBox.Show("This will immediately shut down the server. Continue?", "Confim", MessageBoxButtons.YesNo); if (DialogResult == DialogResult.No) return; var res = Interface.GetComponent().Stop(); if (res != null) MessageBox.Show(res); } private void ServerRestartButton_Click(object sender, EventArgs e) { var DialogResult = MessageBox.Show("This will immediately restart the server. Continue?", "Confim", MessageBoxButtons.YesNo); if (DialogResult == DialogResult.No) return; var res = Interface.GetComponent().Restart(); if (res != null) MessageBox.Show(res); } private void ServerGStopButton_Checked(object sender, EventArgs e) { if (updatingFields) return; var DialogResult = MessageBox.Show("This will shut down the server when the current round ends. Continue?", "Confim", MessageBoxButtons.YesNo); if (DialogResult == DialogResult.No) return; Interface.GetComponent().RequestStop(); LoadServerPage(); } private void ServerGRestartButton_Click(object sender, EventArgs e) { var DialogResult = MessageBox.Show("This will restart the server when the current round ends. Continue?", "Confim", MessageBoxButtons.YesNo); if (DialogResult == DialogResult.No) return; Interface.GetComponent().RequestRestart(); } /// /// Launches the /// /// The sender of the event /// The void TestMergeManagerButton_Click(object sender, System.EventArgs e) { using (var TMM = new TestMergeManager(Interface, ghclient)) TMM.ShowDialog(); LoadServerPage(); } /// /// Calls /// /// The sender of the event /// The void UpdateServerButton_Click(object sender, EventArgs e) { UpdateServer(); } /// /// Calls with a parameter, re-merging any current s at their current commit, calls and , and starts the prompting the user with any errors that may occur. Merged s are not remerged /// async void UpdateServer() { try { UseWaitCursor = true; Enabled = false; try { string res = null; var repo = Interface.GetComponent(); var pulls = await Task.Run(() => repo.MergedPullRequests(out res)); if (pulls == null) { MessageBox.Show(res); return; } List> pullsRequests = null; if (Program.GetRepositoryRemote(repo, out string remoteOwner, out string remoteName)) { //find out which of the PRs have been merged pullsRequests = new List>(); foreach (var I in pulls) pullsRequests.Add(ghclient.PullRequest.Get(remoteOwner, remoteName, I.Number)); } res = await Task.Run(() => repo.Update(true)); if (res != null) { MessageBox.Show(res, "Error updating repository"); return; } await Task.Run(() => repo.GenerateChangelog(out res)); if (res != null) MessageBox.Show(res, "Error generating changelog"); res = await Task.Run(() => repo.SynchronizePush()); if (res != null) MessageBox.Show(res, "Error synchronizing commits"); if (pullsRequests != null) Task.WaitAll(pullsRequests.ToArray()); foreach (var I in pullsRequests) if (I.Result.Merged) pulls.RemoveAll(x => x.Number == I.Result.Number); var mergeResults = await Task.Run(() => repo.MergePullRequests(pulls, true)); var compileStartResult = await Task.Run(() => Interface.GetComponent().Compile(true)); //Show any errors for (var I = 0; I < mergeResults.Count(); ++I) { var err = mergeResults.ElementAt(I); if (err != null) MessageBox.Show(err, String.Format("Error re-merging PR #{0}", pulls[I].Number)); } if (!compileStartResult) MessageBox.Show(res, "Error starting compile!"); } finally { UseWaitCursor = false; Enabled = true; } } catch (ForbiddenException) { if (ghclient.Credentials.AuthenticationType == AuthenticationType.Anonymous) { if (Program.RateLimitPrompt(ghclient)) UpdateServer(); return; } else throw; } LoadServerPage(); } /// /// Calls with a parameter, calls , and starts the prompting the user with any errors that may occur. /// /// The sender of the event /// The async void RemoveAllTestMergesButton_Click(object sender, EventArgs e) { try { UseWaitCursor = true; Enabled = false; try { var repo = Interface.GetComponent(); var res = await Task.Run(() => repo.Reset(true)); if (res != null) { MessageBox.Show(res, "Error resetting repository"); return; } await Task.Run(() => repo.GenerateChangelog(out res)); if (res != null) MessageBox.Show(res, "Error generating changelog"); await Task.Run(() => Interface.GetComponent().Compile(false)); if (res != null) MessageBox.Show(res, "Error starting compile!"); } finally { UseWaitCursor = false; Enabled = true; } } catch (ForbiddenException) { if (ghclient.Credentials.AuthenticationType == AuthenticationType.Anonymous) { if (Program.RateLimitPrompt(ghclient)) UpdateServer(); return; } else throw; } LoadServerPage(); } private void SecuritySelector_SelectedIndexChanged(object sender, EventArgs e) { if (!updatingFields) if (!Interface.GetComponent().SetSecurityLevel((DreamDaemonSecurity)SecuritySelector.SelectedIndex)) MessageBox.Show("Security change will be applied after next server reboot."); } private void WorldAnnounceButton_Click(object sender, EventArgs e) { var msg = WorldAnnounceField.Text; if (!String.IsNullOrWhiteSpace(msg)) { var res = Interface.GetComponent().WorldAnnounce(msg); if (res != null) { MessageBox.Show(res); return; } } WorldAnnounceField.Text = ""; } private void WebclientCheckBox_CheckedChanged(object sender, EventArgs e) { if (!updatingFields) Interface.GetComponent().SetWebclient(WebclientCheckBox.Checked); } private void AutoUpdateInterval_ValueChanged(object sender, EventArgs e) { if (!updatingFields) Interface.GetComponent().SetAutoUpdateInterval((ulong)AutoUpdateInterval.Value); } private void AutoUpdateCheckbox_CheckedChanged(object sender, EventArgs e) { if (updatingFields) return; var on = AutoUpdateCheckbox.Visible && AutoUpdateCheckbox.Checked; AutoUpdateInterval.Visible = on; AutoUpdateMLabel.Visible = on; if (!on) Interface.GetComponent().SetAutoUpdateInterval(0); else Interface.GetComponent().SetAutoUpdateInterval((ulong)AutoUpdateInterval.Value); } } }