diff --git a/.github/workflows/dotnet-build.yml b/.github/workflows/dotnet-build.yml index 7e77de2f..a8597bd7 100644 --- a/.github/workflows/dotnet-build.yml +++ b/.github/workflows/dotnet-build.yml @@ -1,4 +1,3 @@ - name: Beta releases on: @@ -15,23 +14,33 @@ jobs: - uses: actions/checkout@v2 with: fetch-depth: 0 - - name: 'Get Previous tag' + + - name: "Get Previous tag" id: previoustag uses: "WyriHaximus/github-action-get-previous-tag@master" + - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: dotnet-version: 5.0.100 + - name: Install dependencies run: dotnet restore "AUCapture-WPF\AUCapture-WPF.csproj" + - name: Publish run: | dotnet publish "AUCapture-WPF\AUCapture-WPF.csproj" -p:PublishProfile=DevProfile -p:AssemblyVersion=${{ steps.previoustag.outputs.tag }}.1 + - name: Relocate run: | - mv AUCapture-WPF\\bin\\Release\\netcoreapp3.1\\publish\\AUCapture-WPF.exe AmongUsCapture.exe + mv AUCapture-WPF\\bin\\Release\\netcoreapp3.1\\publish\\AUCapture-WPF.exe ..\AmongUsCapture-Beta.exe + + - name: Zip + run: | + 7z a AmongUsCapture-Beta.zip ..\AmongUsCapture-Beta.exe -mx=9 + - name: AmongUsCapture-beta uses: actions/upload-artifact@v2 with: name: AmongUsCapture-beta - path: AmongUsCapture.exe + path: AmongUsCapture-Beta.zip diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fa38f86e..3aadfc7c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,7 @@ name: goreleaser on: push: tags: - - '*' + - "*" jobs: goreleaser: @@ -13,35 +13,51 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 - + - name: Set up Go uses: actions/setup-go@v2 with: go-version: 1.15 - + - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: dotnet-version: 5.0.100 - - - name: 'Get Previous tag' + + - name: "Get Previous tag" id: previoustag uses: "WyriHaximus/github-action-get-previous-tag@master" - + - name: Install dependencies run: dotnet restore "AUCapture-WPF\AUCapture-WPF.csproj" - name: Publish run: | dotnet publish "AUCapture-WPF\AUCapture-WPF.csproj" -p:PublishProfile=PubProfile -p:AssemblyVersion=${{ steps.previoustag.outputs.tag }}.0 - + - name: Relocate run: | mv AUCapture-WPF\\bin\\Release\\netcoreapp3.1\\publish\\AUCapture-WPF.exe ..\AmongUsCapture.exe - + - name: Zip run: | 7z a ..\AmongUsCapture.zip ..\AmongUsCapture.exe -mx=9 - + + - name: Sign + uses: carbonneuron/GHActionSignHash@v4 + env: + ACTIONS_ALLOW_UNSECURE_COMMANDS: true + id: sign + with: + path: ../AmongUsCapture.zip + key: ${{ secrets.PRIVATE_KEY }} + privateKey: ${{ secrets.PRIVATE_KEY }} + passphrase: ${{ secrets.PASSPHRASE }} + + - name: Output Signature + shell: bash + run: | + echo "${{ steps.sign.outputs.encrypted-text }}" > ../AmongUsCapture.zip.sha256.pgp + - name: Create Release id: create_release uses: actions/create-release@v1 @@ -52,20 +68,29 @@ jobs: release_name: ${{ github.ref }} draft: false prerelease: false - - - name: Upload Release Asset - id: upload-release-asset + + - name: Upload capture zip + id: upload-release-asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps asset_path: ..\AmongUsCapture.zip asset_name: AmongUsCapture.zip asset_content_type: application/zip - - - name: Run GoReleaser + - name: Upload capture zip signature + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ..\AmongUsCapture.zip.sha256.pgp + asset_name: AmongUsCapture.zip.sha256.pgp + asset_content_type: text/plain + + - name: Run GoReleaser uses: goreleaser/goreleaser-action@v2 with: version: latest diff --git a/AUCapture-WPF/AUCapture-WPF.csproj b/AUCapture-WPF/AUCapture-WPF.csproj index 6e0cee3c..8dd0271f 100644 --- a/AUCapture-WPF/AUCapture-WPF.csproj +++ b/AUCapture-WPF/AUCapture-WPF.csproj @@ -43,6 +43,7 @@ + @@ -53,6 +54,10 @@ + + + + @@ -69,6 +74,7 @@ + diff --git a/AUCapture-WPF/App.xaml.cs b/AUCapture-WPF/App.xaml.cs index d5185ace..917cb355 100644 --- a/AUCapture-WPF/App.xaml.cs +++ b/AUCapture-WPF/App.xaml.cs @@ -80,6 +80,7 @@ protected override void OnStartup(StartupEventArgs e) default: throw new ArgumentOutOfRangeException(); } + Console.WriteLine(string.Join(", ",Assembly.GetExecutingAssembly().GetManifestResourceNames())); //Gets all the embedded resources var r = new Random(); var rValue = r.Next(101); var goingToPop = rValue <= 3; diff --git a/AUCapture-WPF/MainWindow.xaml b/AUCapture-WPF/MainWindow.xaml index 780238d2..b8a81314 100644 --- a/AUCapture-WPF/MainWindow.xaml +++ b/AUCapture-WPF/MainWindow.xaml @@ -199,6 +199,9 @@ + + + diff --git a/AUCapture-WPF/MainWindow.xaml.cs b/AUCapture-WPF/MainWindow.xaml.cs index 564a4b1e..65d5df3d 100644 --- a/AUCapture-WPF/MainWindow.xaml.cs +++ b/AUCapture-WPF/MainWindow.xaml.cs @@ -21,6 +21,7 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography; +using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -34,6 +35,7 @@ using HandyControl.Tools; using HandyControl.Tools.Extension; using Humanizer; +using PgpCore; using Microsoft.Win32; using Color = System.Drawing.Color; using PlayerColor = AmongUsCapture.PlayerColor; @@ -67,7 +69,8 @@ public MainWindow() { Updated = true; try - { //Will wait for the other program to exit. + { + //Will wait for the other program to exit. var me = Process.GetCurrentProcess(); Process[] aProcs = Process.GetProcessesByName(me.ProcessName); aProcs = aProcs.Where(x => x.Id != me.Id).ToArray(); @@ -75,19 +78,19 @@ public MainWindow() { aProcs[0].WaitForExit(1000); } + File.Delete(archivePath); } catch (Exception e) { Console.WriteLine("Could not delete old file."); - } } else { Updated = false; } - + try { config = new ConfigurationBuilder() @@ -102,15 +105,12 @@ public MainWindow() .UseJsonFile(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "\\AmongUsCapture\\AmongUsGUI", "Settings.json")).Build(); } - + context = new UserDataContext(DialogCoordinator.Instance, config); DataContext = context; - App.handler.OnReady += (sender, args) => - { - App.socket.AddHandler(App.handler); - }; - context.ConnectionStatuses.Add(new ConnectionStatus{Connected = false, ConnectionName = "AutoMuteUs"}); - context.ConnectionStatuses.Add(new ConnectionStatus{Connected = false, ConnectionName = "User bot"}); + App.handler.OnReady += (sender, args) => { App.socket.AddHandler(App.handler); }; + context.ConnectionStatuses.Add(new ConnectionStatus {Connected = false, ConnectionName = "AutoMuteUs"}); + context.ConnectionStatuses.Add(new ConnectionStatus {Connected = false, ConnectionName = "User bot"}); window.Topmost = context.Settings.alwaysOnTop; GameMemReader.getInstance().GameStateChanged += GameStateChangedHandler; GameMemReader.getInstance().ProcessHook += OnProcessHook; @@ -142,12 +142,13 @@ public MainWindow() w.Focus(); // important }); }; - + if (!context.Settings.discordTokenEncrypted) //Encrypt discord token if it is not encrypted. { context.Settings.discordToken = JsonConvert.SerializeObject(encryptToken(context.Settings.discordToken)); context.Settings.discordTokenEncrypted = true; } + byte[] encryptedBuff = JsonConvert.DeserializeObject(context.Settings.discordToken); discordTokenBox.Password = decryptToken(encryptedBuff); @@ -166,6 +167,7 @@ public MainWindow() { BaseColor = ThemeManager.BaseColorLight; } + Theme newTheme = new Theme(name: "CustomTheme", displayName: "CustomTheme", baseColorScheme: BaseColor, @@ -178,13 +180,15 @@ public MainWindow() ThemeManager.Current.ChangeTheme(this, newTheme); } catch (Exception e) - { } + { + } + //ApplyDarkMode(); } - + private void PlayersOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { - AmongUsCapture.Settings.conInterface.WriteModuleTextColored("Players", Color.Aqua, JsonConvert.SerializeObject(e, Formatting.None,new StringEnumConverter())); + AmongUsCapture.Settings.conInterface.WriteModuleTextColored("Players", Color.Aqua, JsonConvert.SerializeObject(e, Formatting.None, new StringEnumConverter())); } private void OnPlayerCosmeticChanged(object? sender, PlayerCosmeticChangedEventArgs e) @@ -192,7 +196,7 @@ private void OnPlayerCosmeticChanged(object? sender, PlayerCosmeticChangedEventA if (context.Players.Any(x => x.Name == e.Name)) { var player = context.Players.First(x => x.Name == e.Name); - Console.WriteLine("Cosmetic change "+JsonConvert.SerializeObject(e)); + Console.WriteLine("Cosmetic change " + JsonConvert.SerializeObject(e)); Dispatcher.Invoke((Action) (() => { player.HatID = e.HatId; @@ -200,7 +204,6 @@ private void OnPlayerCosmeticChanged(object? sender, PlayerCosmeticChangedEventA player.PetID = e.PetId; })); } - } private void SocketOnOnDisconnected(object? sender, EventArgs e) @@ -219,7 +222,6 @@ private void HandlerOnOnReady(object? sender, DiscordHandler.ReadyEventArgs e) } - private void OnProcessHook(object? sender, ProcessHookArgs e) { context.Connected = true; @@ -237,13 +239,74 @@ private void ProcessOnExited(object? sender, EventArgs e) ProcessMemory.getInstance().process.Exited -= ProcessOnExited; } + public bool VerifySignature(string pathToSig) + { + try + { + Stream AutoMuteUsPublicKeyStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("AUCapture_WPF.Resources.AutoMuteUs_PK.asc"); + using PGP pgp = new PGP(); + // Verify clear stream + using FileStream inputFileStream = new FileStream(pathToSig, FileMode.Open); + return pgp.VerifyClearStream(inputFileStream, AutoMuteUsPublicKeyStream); + } + catch (Exception e) + { + return false; + } + + } + + public bool VerifyHashFromSig(string pathToFile, string pathToSignature) //Does not care if the signature is correct or not + { + try + { + string HashInSig = File.ReadAllLines(pathToSignature).First(x => x.Length == 64); //First line with 64 characters in it + using SHA256Managed sha256 = new SHA256Managed(); + using FileStream fs = new FileStream(pathToFile, FileMode.Open, FileAccess.Read); + using var bs = new BufferedStream(fs); + var hash = sha256.ComputeHash(bs); + StringBuilder CaptureHashSB = new StringBuilder(2 * hash.Length); + foreach (byte byt in hash) + { + CaptureHashSB.AppendFormat("{0:X2}", byt); + } + + string CaptureHash = CaptureHashSB.ToString(); + Console.WriteLine($"Got SigHash: {HashInSig}, Downloaded Hash: {CaptureHash}"); + return String.Equals(HashInSig, CaptureHash, StringComparison.CurrentCultureIgnoreCase); + } + catch (Exception e) + { + return false; + } + + } + + public async void ShowErrorBox(string errorMessage, string title="ERROR") + { + var errorBox = await context.DialogCoordinator.ShowMessageAsync(context, title, + errorMessage, MessageDialogStyle.AffirmativeAndNegative, + new MetroDialogSettings + { + AffirmativeButtonText = "retry", + NegativeButtonText = "cancel", + DefaultButtonFocus = MessageDialogResult.Affirmative, + AnimateShow = false + }); + if (errorBox == MessageDialogResult.Affirmative) + { + await Task.Factory.StartNew(Update, TaskCreationOptions.LongRunning); + } + } + public async void Update() { Version version = new Version(); Version latestVersion = new Version(); + context.AutoUpdaterEnabled = false; try { - version = new Version(context.Version); + version = new Version(context.Version); latestVersion = new Version(context.LatestVersion); } catch (Exception e) @@ -253,126 +316,193 @@ public async void Update() #if PUBLISH - if (latestVersion.CompareTo(version) > 0) + try { - var selection = await context.DialogCoordinator.ShowMessageAsync(context, "Caution", - $"We've detected you're using an older version of AmongUsCapture!\nYour version: {version}\nLatest version: {latestVersion}", - MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings - { - AffirmativeButtonText = - "Update", - NegativeButtonText = "No thanks", DefaultButtonFocus = MessageDialogResult.Affirmative - }); - if (selection == MessageDialogResult.Negative) + var PublicKey = Assembly.GetExecutingAssembly().GetManifestResourceStream("AUCapture_WPF.Resources.AutoMuteUs_PK.asc"); + context.AutoUpdaterEnabled = PublicKey is not null; + } + catch (Exception) + { + context.AutoUpdaterEnabled = false; + return; + } + if(!context.AutoUpdaterEnabled) + { + return; + } + + try + { + int maxStep = 6; + if (latestVersion.CompareTo(version) > 0) { - selection = await context.DialogCoordinator.ShowMessageAsync(context, "Warning", - $"Having an older version could cause compatibility issues with AutoMuteUs.\nWe can automagically update you to {latestVersion}.", + if (Assembly.GetExecutingAssembly().GetManifestResourceNames().All(x => x != "AUCapture_WPF.Resources.AutoMuteUs_PK.asc")) + { + ShowErrorBox($"We detected an update to {latestVersion}, But there is no public key in this capture so we will not be able to verify integrity. Please download the latest release off the github page.","AutoUpdater failed"); + return; + } + var selection = await context.DialogCoordinator.ShowMessageAsync(context, "Caution", + $"We've detected you're using an older version of AmongUsCapture!\nYour version: {version}\nLatest version: {latestVersion}", MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings { AffirmativeButtonText = "Update", - NegativeButtonText = "no ty", DefaultButtonFocus = MessageDialogResult.Affirmative + NegativeButtonText = "No thanks", DefaultButtonFocus = MessageDialogResult.Affirmative }); - } - if (selection == MessageDialogResult.Affirmative) - { - var DownloadProgress = - await context.DialogCoordinator.ShowProgressAsync(context, "Step 1/3 - Downloading", "Percent: 0% (0/0)", isCancelable:false); - DownloadProgress.Maximum = 100; - using (var client = new WebClient()) + if (selection == MessageDialogResult.Negative) { - var downloadPath = Path.GetTempFileName(); - client.DownloadProgressChanged += (sender, args) => - { - DownloadProgress.SetProgress(args.ProgressPercentage); - DownloadProgress.SetMessage($"Percent: {args.ProgressPercentage}% ({args.BytesReceived.Bytes().Humanize("#.##")}/{args.TotalBytesToReceive.Bytes().Humanize("#.##")})"); - }; - client.DownloadFileCompleted += async (sender, args) => + selection = await context.DialogCoordinator.ShowMessageAsync(context, "Warning", + $"Having an older version could cause compatibility issues with AutoMuteUs.\nWe can automagically update you to {latestVersion}.", + MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings + { + AffirmativeButtonText = + "Update", + NegativeButtonText = "no ty", DefaultButtonFocus = MessageDialogResult.Affirmative + }); + } + + if (selection == MessageDialogResult.Affirmative) + { + var DownloadProgress = + await context.DialogCoordinator.ShowProgressAsync(context, $"Step 1/{maxStep} - Downloading", "Percent: 0% (0/0)", isCancelable: false, new MetroDialogSettings{AnimateHide = false}); + DownloadProgress.Maximum = 100; + using (var client = new WebClient()) { - if (args.Error is not null) + var downloadPath = Path.GetTempFileName(); + client.DownloadProgressChanged += (sender, args) => { - await DownloadProgress.CloseAsync(); - var errorBox = await context.DialogCoordinator.ShowMessageAsync(context, "ERROR", - args.Error.Message, MessageDialogStyle.AffirmativeAndNegative, - new MetroDialogSettings - { - AffirmativeButtonText = "retry", - NegativeButtonText = "cancel", - DefaultButtonFocus = MessageDialogResult.Affirmative - }); - if (errorBox == MessageDialogResult.Affirmative) - { - await Task.Factory.StartNew(Update, TaskCreationOptions.LongRunning); - } - } - else + DownloadProgress.SetProgress(args.ProgressPercentage); + DownloadProgress.SetMessage($"Percent: {args.ProgressPercentage}% ({args.BytesReceived.Bytes().Humanize("#.##")}/{args.TotalBytesToReceive.Bytes().Humanize("#.##")})"); + }; + client.DownloadFileCompleted += async (sender, args) => { - DownloadProgress.SetTitle("Step 2/3 - Extracting"); - DownloadProgress.SetMessage("Please wait, we may go unresponsive but don't close the window, we will restart the program after."); - DownloadProgress.SetIndeterminate(); - if (!Directory.Exists(Path.Join( - Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - "\\AmongUsCapture\\AmongUsGUI\\Update"))) + if (args.Error is not null) { - Directory.CreateDirectory(Path.Join( - Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - "\\AmongUsCapture\\AmongUsGUI\\Update")); + await DownloadProgress.CloseAsync(); } - - using (ZipArchive archive = ZipFile.OpenRead(downloadPath)) + else { - try + DownloadProgress.SetTitle($"Step 2/{maxStep} - Downloading signature"); + using var client2 = new WebClient(); + var downloadPathSignedHash = Path.GetTempFileName(); + client2.DownloadProgressChanged += (sender, args) => { - var entry = archive.Entries.First(x => x.FullName.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)); - entry.ExtractToFile(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - "\\AmongUsCapture\\AmongUsGUI\\Update", "AmongUsCapture.exe"), true); - - } - catch (Exception e) + DownloadProgress.SetProgress(args.ProgressPercentage); + DownloadProgress.SetMessage($"Percent: {args.ProgressPercentage}% ({args.BytesReceived.Bytes().Humanize("#.##")}/{args.TotalBytesToReceive.Bytes().Humanize("#.##")})"); + }; + client2.DownloadFileCompleted += async (sender, args) => { - var errorBox = await context.DialogCoordinator.ShowMessageAsync(context, "ERROR", - e.Message, MessageDialogStyle.AffirmativeAndNegative, - new MetroDialogSettings + if (args.Error is not null) + { + await DownloadProgress.CloseAsync(); + ShowErrorBox(args.Error.Message); + } + else + { + DownloadProgress.SetTitle($"Step 3/{maxStep} - Verifying signature"); + DownloadProgress.SetMessage(""); + DownloadProgress.SetIndeterminate(); + bool SignatureValid = VerifySignature(downloadPathSignedHash); + if (!SignatureValid) + { + await DownloadProgress.CloseAsync(); + ShowErrorBox("File signature invalid. If you get this after retrying tell us on discord. It is potentially a security risk."); + return; + } + + DownloadProgress.SetTitle($"Step 4/{maxStep} - Verifying hash"); + DownloadProgress.SetMessage(""); + DownloadProgress.SetIndeterminate(); + bool HashValid = VerifyHashFromSig(downloadPath, downloadPathSignedHash); + if (!HashValid) + { + await DownloadProgress.CloseAsync(); + ShowErrorBox("Capture hash invalid. If you get this after retrying tell us on discord. It is potentially a security risk."); + return; + } + + DownloadProgress.SetTitle($"Step 5/{maxStep} - Extracting"); + DownloadProgress.SetMessage("Please wait, we may go unresponsive but don't close the window, we will restart the program after."); + DownloadProgress.SetIndeterminate(); + if (!Directory.Exists(Path.Join( + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + "\\AmongUsCapture\\AmongUsGUI\\Update"))) + { + Directory.CreateDirectory(Path.Join( + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + "\\AmongUsCapture\\AmongUsGUI\\Update")); + } + + using (ZipArchive archive = ZipFile.OpenRead(downloadPath)) + { + try + { + var entry = archive.Entries.First(x => x.FullName.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)); + entry.ExtractToFile(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + "\\AmongUsCapture\\AmongUsGUI\\Update", "AmongUsCapture.exe"), true); + } + catch (Exception e) + { + var errorBox = await context.DialogCoordinator.ShowMessageAsync(context, "ERROR", + e.Message, MessageDialogStyle.AffirmativeAndNegative, + new MetroDialogSettings + { + AffirmativeButtonText = "retry", + NegativeButtonText = "cancel", + DefaultButtonFocus = MessageDialogResult.Affirmative + }); + if (errorBox == MessageDialogResult.Affirmative) + { + await Task.Factory.StartNew(Update, TaskCreationOptions.LongRunning); + } + } + } + + + //You can't delete a running application. But you can rename it. + string appFolder = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName); + string appName = Path.GetFileNameWithoutExtension(Process.GetCurrentProcess().MainModule.FileName); + string appExtension = Path.GetExtension(Process.GetCurrentProcess().MainModule.FileName); + string archivePath = Path.Combine(appFolder, appName + "_Old" + appExtension); + + DownloadProgress.SetTitle($"Step 6/{maxStep} - Copying files"); + DownloadProgress.SetMessage("Finishing up.."); + File.Move(Process.GetCurrentProcess().MainModule.FileName, archivePath); + + File.Move(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "\\AmongUsCapture\\AmongUsGUI\\Update", "AmongUsCapture.exe"), + Path.Combine(appFolder, appName + appExtension), true); + Application.Current.Invoke(() => { - AffirmativeButtonText = "retry", - NegativeButtonText = "cancel", - DefaultButtonFocus = MessageDialogResult.Affirmative + IPCAdapter.getInstance().mutex.ReleaseMutex(); //Release the mutex so the other app does not see us. + Process.Start(Path.Combine(appFolder, appName + appExtension)); + Environment.Exit(0); }); - if (errorBox == MessageDialogResult.Affirmative) - { - await Task.Factory.StartNew(Update, TaskCreationOptions.LongRunning); } + }; + if (!string.IsNullOrEmpty(context.LatestReleaseAssetSignedHashURL)) + { + var signatureDownloader = client2.DownloadFileTaskAsync(context.LatestReleaseAssetSignedHashURL, downloadPathSignedHash); + } + else + { + ShowErrorBox("Release does not have a signature. Not downloading, please retry later."); } + } - - - //You can't delete a running application. But you can rename it. - string appFolder = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName); - string appName = Path.GetFileNameWithoutExtension(Process.GetCurrentProcess().MainModule.FileName); - string appExtension = Path.GetExtension(Process.GetCurrentProcess().MainModule.FileName); - string archivePath = Path.Combine(appFolder, appName + "_Old" + appExtension); - - DownloadProgress.SetTitle("Step 3/3 - Copying files"); - DownloadProgress.SetMessage("Finishing up.."); - File.Move(Process.GetCurrentProcess().MainModule.FileName, archivePath); - - File.Move(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "\\AmongUsCapture\\AmongUsGUI\\Update", "AmongUsCapture.exe"), - Path.Combine(appFolder, appName + appExtension), true); - Application.Current.Invoke(()=> - { - IPCAdapter.getInstance().mutex.ReleaseMutex(); //Release the mutex so the other app does not see us. - Process.Start(Path.Combine(appFolder, appName + appExtension)); - Environment.Exit(0); - }); - - } - }; - var downloaderClient = client.DownloadFileTaskAsync(context.LatestReleaseAssetURL, downloadPath); + }; + var downloaderClient = client.DownloadFileTaskAsync(context.LatestReleaseAssetURL, downloadPath); + } } } } + catch (Exception e) + { + ShowErrorBox(e.Message); + } + #endif } + private string decryptToken(byte[] EncryptedBytes) { byte[] protectedBytes = ProtectedData.Unprotect(EncryptedBytes, null, DataProtectionScope.CurrentUser); @@ -385,6 +515,7 @@ private byte[] encryptToken(string token) byte[] protectedBytes = ProtectedData.Protect(buffer, null, DataProtectionScope.CurrentUser); return protectedBytes; } + private void OnGameOver(object? sender, GameOverEventArgs e) { Dispatcher.Invoke((Action) (() => @@ -403,14 +534,14 @@ private void UserForm_PlayerChanged(object sender, PlayerChangedEventArgs e) { if (context.Players.Any(x => x.Name == e.Name)) { - DeadMessages.Enqueue(context.Players.First(x=>x.Name == e.Name)); + DeadMessages.Enqueue(context.Players.First(x => x.Name == e.Name)); } } else { if (e.Action != PlayerAction.Joined && context.Players.Any(x => String.Equals(x.Name, e.Name, StringComparison.CurrentCultureIgnoreCase))) { - var player = context.Players.First(x => String.Equals(x.Name, e.Name, StringComparison.CurrentCultureIgnoreCase)); + var player = context.Players.First(x => String.Equals(x.Name, e.Name, StringComparison.CurrentCultureIgnoreCase)); Dispatcher.Invoke((Action) (() => { switch (e.Action) @@ -435,13 +566,8 @@ private void UserForm_PlayerChanged(object sender, PlayerChangedEventArgs e) { if (e.Action == PlayerAction.Joined) { - Dispatcher.Invoke((Action) (() => - { - context.Players.Add(new Player(e.Name, e.Color, !e.IsDead, 0, 0)); - - })); + Dispatcher.Invoke((Action) (() => { context.Players.Add(new Player(e.Name, e.Color, !e.IsDead, 0, 0)); })); } - } } @@ -455,7 +581,7 @@ private void OnChatMessageAdded(object sender, ChatMessageEventArgs e) $"{PlayerColorToColorOBJ(e.Color).ToTextColor()}{e.Sender}{NormalTextColor.ToTextColor()}: {e.Message}"); //WriteLineToConsole($"[CHAT] {e.Sender}: {e.Message}"); } - + private void OnJoinedLobby(object sender, LobbyEventArgs e) { @@ -535,7 +661,7 @@ public static void OpenBrowser(string url) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); + Process.Start(new ProcessStartInfo(url) {UseShellExecute = true}); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { @@ -550,13 +676,13 @@ public static void OpenBrowser(string url) // throw } } + private void ApplyDarkMode() { if (config.DarkMode) { ThemeManager.Current.ChangeThemeBaseColor(this, ThemeManager.BaseColorDark); NormalTextColor = Color.White; - } else { @@ -586,7 +712,6 @@ private void ManualConnect_Click(object sender, RoutedEventArgs e) { //Open up the manual connection flyout. ManualConnectionFlyout.IsOpen = true; - } private void GameStateChangedHandler(object sender, GameStateChangedEventArgs e) @@ -608,7 +733,6 @@ private void GameStateChangedHandler(object sender, GameStateChangedEventArgs e) setGameCode(""); Dispatcher.Invoke((Action) (() => { - context.GameState = e.NewState; foreach (var player in context.Players) { @@ -627,6 +751,7 @@ private void GameStateChangedHandler(object sender, GameStateChangedEventArgs e) } })); } + //Program.conInterface.WriteModuleTextColored("GameMemReader", Color.Green, "State changed to " + e.NewState); } @@ -648,7 +773,6 @@ private void MetroWindow_Loaded(object sender, RoutedEventArgs e) this.ShowMessageAsync("Update successful!", "The update was successful. Happy auto-muting", MessageDialogStyle.Affirmative); } - } public void PlayGotEm() @@ -658,8 +782,6 @@ public void PlayGotEm() //win.MemeFlyout.IsOpen = true; //win.MemePlayer.Position = TimeSpan.Zero; }); - - } private void MainWindow_OnContentRendered(object? sender, EventArgs e) @@ -697,34 +819,35 @@ private void MemePlayer_OnMediaEnded(object sender, RoutedEventArgs e) //private void MemeFlyout_OnIsOpenChanged(object sender, RoutedEventArgs e) //{ - //if (MemeFlyout.IsOpen) - //{ - // MemePlayer.Play(); - // Task.Factory.StartNew(() => - // { - // Thread.Sleep(5000); - // MemeFlyout.Invoke(new Action(() => - // { - // if (MemeFlyout.IsOpen) - // { - // MemeFlyout.CloseButtonVisibility = Visibility.Visible; - // } - // })); + //if (MemeFlyout.IsOpen) + //{ + // MemePlayer.Play(); + // Task.Factory.StartNew(() => + // { + // Thread.Sleep(5000); + // MemeFlyout.Invoke(new Action(() => + // { + // if (MemeFlyout.IsOpen) + // { + // MemeFlyout.CloseButtonVisibility = Visibility.Visible; + // } + // })); // - // }); - // } - // else - // { - // MemeFlyout.CloseButtonVisibility = Visibility.Hidden; - // MemePlayer.Close(); - // GC.Collect(); - // } + // }); + // } + // else + // { + // MemeFlyout.CloseButtonVisibility = Visibility.Hidden; + // MemePlayer.Close(); + // GC.Collect(); + // } //} private async void SubmitDiscordButton_OnClick(object sender, RoutedEventArgs e) { if (discordTokenBox.Password != "") { - var progressController = await context.DialogCoordinator.ShowProgressAsync(context, "Token Validation", "Validating discord token", false, new MetroDialogSettings{AnimateShow = true, AnimateHide = false, NegativeButtonText = "OK"}); + var progressController = await context.DialogCoordinator.ShowProgressAsync(context, "Token Validation", "Validating discord token", false, + new MetroDialogSettings {AnimateShow = true, AnimateHide = false, NegativeButtonText = "OK"}); progressController.SetIndeterminate(); try { @@ -742,12 +865,12 @@ private async void SubmitDiscordButton_OnClick(object sender, RoutedEventArgs e) progressController.SetProgress(0); discordTokenBox.Password = decryptToken(JsonConvert.DeserializeObject(context.Settings.discordToken)); //Roll back changes } + progressController.SetCancelable(true); progressController.Canceled += delegate(object? o, EventArgs args) { progressController.CloseAsync(); //Close the dialog. }; - } else if (discordTokenBox.Password == string.Empty) { @@ -762,7 +885,6 @@ private async void SubmitDiscordButton_OnClick(object sender, RoutedEventArgs e) context.Settings.discordToken = JsonConvert.SerializeObject(encryptToken(discordTokenBox.Password)); App.handler.Close(); //Close connection because token cleared. await this.ShowMessageAsync("Success!", "Discord token cleared!", MessageDialogStyle.Affirmative); - } } @@ -779,7 +901,6 @@ private async void ReloadOffsetsButton_OnClick(object sender, RoutedEventArgs e) else { //WriteConsoleLineFormatted("GameMemReader", Color.Lime, $"No offsets found for: {Color.Aqua.ToTextColor()}{GameMemReader.getInstance().GameHash.ToString()}."); - } } @@ -811,7 +932,6 @@ private async void AccentColorPicker_OnSelectedColorChanged(object sender, Route { if (e.NewValue.HasValue) { - string BaseColor; if (context.Settings.DarkMode) { @@ -842,7 +962,7 @@ private async void ResetConfigButton_OnClick(object sender, RoutedEventArgs e) { var result = await this.ShowMessageAsync("Are you sure?", "This action will reset your config.\nThis cannot be undone.", - MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings{AnimateShow = true, AnimateHide = false}); + MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings {AnimateShow = true, AnimateHide = false}); if (result == MessageDialogResult.Affirmative) { var progressBar = await this.context.DialogCoordinator.ShowProgressAsync(context, "Resetting config", @@ -860,6 +980,7 @@ private async void ResetConfigButton_OnClick(object sender, RoutedEventArgs e) { File.Delete(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AmongUsCapture", "Settings.json")); } + for (int i = 0; i < 100; i++) //Useless loading to make the user think we are doing a big task { var currentPercent = i / 100d; @@ -870,21 +991,17 @@ private async void ResetConfigButton_OnClick(object sender, RoutedEventArgs e) await progressBar.CloseAsync(); var selection = await this.ShowMessageAsync("Config reset", "Your config was reset successfully.", - MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings{AnimateHide = true, AffirmativeButtonText = "Restart", NegativeButtonText = "Exit"}); + MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings {AnimateHide = true, AffirmativeButtonText = "Restart", NegativeButtonText = "Exit"}); if (selection == MessageDialogResult.Affirmative) { IPCAdapter.getInstance().mutex.ReleaseMutex(); //Release the mutex so the other app does not see us. - Process.Start(Process.GetCurrentProcess().MainModule.FileName); + Process.Start(Process.GetCurrentProcess().MainModule.FileName); Application.Current.Shutdown(0); } else { - Application.Current.Shutdown(0); } - - - } } diff --git a/AUCapture-WPF/Resources/AutoMuteUs_PK.asc b/AUCapture-WPF/Resources/AutoMuteUs_PK.asc new file mode 100644 index 00000000..3f5d1c33 --- /dev/null +++ b/AUCapture-WPF/Resources/AutoMuteUs_PK.asc @@ -0,0 +1,51 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGAJmN8BEACqn5BdE8uktQHT/mjrSoL/TUr9A7KfqSkDOoHb69PwKDOwNuF8 +MdOtxLv2c3llIiKG5+D8KFoM+uCoX/mAd1pvr+zPNQ9xVftWasSYjErOkBzzuwlK +9XTAJg8UF8jiaXRBM7J+grBslAaVzeJrtAO7HCvSxdTWOJKC0ylZrhyrTLlKTypt +seeWdiESWp00VibzRvuDpnkxrdKYrjtDyh/bEsGt9kIoZF0oojz5VtyIzX3Fi2gS +To7mGkWHiQdRAmpEZH+g6p/LlzIP7wERcdIbC/I/41Nz1gW0yNRhaIa+J6zPv9Q3 +4ch8WeD+OIerXOP0lM5kZiShn4oW3AxSIRB4apTCrpzx6wqtEGjVfZFXjBaBiDAv +HkwH/AmopSc91Qk3iThcE1hRNcHhx5FoRqNo0VtMDEgKEnb4tyRo9/5E8GWidaA0 ++f+w8ZBeeJaUFKbkKD5lEESV+UIbEpipkPadoRO7rnK7+Vb+rYmOogut4hUExdJZ +nMKFoxl/3rvUd9AYrHuosNrWddsDMtWWhknHGlFaF6YcvZVANskQkj9zovVObzjB +rgrvxsMuDm/uIvOvjaEDlaXQII7Fm3TNMcD4bvcCupQ0jEeEK3ABgPoDySRuPKXy +ewK79ZnlbP9QsePQCubuSblI64+YaQAUCb8OBn/G64sNS1KqeFtlXfgWcwARAQAB +tApBdXRvTXV0ZVVziQJOBBMBCAA4FiEEJEN9rQLpYCzPlzkTeV8WGgZjdeYFAmAJ +mN8CGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQeV8WGgZjdeZ4gw/7BXqJ +eTyqaL7tKAAAUGOOt28mGOAQH9eRGNa+V8u4ciFOv08LujwtMu69rPHzFWayJthH +br51RLS5yWf4ppjc3LW05Z4fl2pWkl6AXUH/7Sl+yCieHY+/1kniveQ6g4sHyz8E +UQkzI8fJ7nkqF7bZXHWnnmhNp05j30E8B08g3pvIUl6Y6zkaNtj6G1oAYGwj+sf8 +GV9yx21ova4P1582CeAFx6e5Nwhs54GiYvtfoS3pDDSpbTuuD8emqFC84ky9O9Gl +YGwjmV9r4WKOApcKz6saC0B3VmPPQm+dlQIvcUYfKkRwV+1LiM8Z8zdrwWHiON8y +SuVnwFiFtwFZUDZvlbSrrPDueoGgqjFgAehCeZiZWyuFYhrXhA8uLP28ewp69oIH +w3Q57oiJBt/iDy9KtqupHoogWMCg4O2qFaYSkV7lG7xovUOaMvmimsDi/smJSkbP +wergw+JBlCU8CLVZJIBp4f+x7xWSmBXeigf5q53/cfxLiBovn6lEbqbMqWfan+AL +shdMFInAVYI0U0rQUn65sR1LjF5xYqdkC5jybO3zuKlJgQMPBs1v8FHPxvNlvMR9 +cCPDpGB+HO0b4si/CQxQbixC07qo28J2tbw4oLVZRCE1a4olPnjf1eG66isWO3sp +X7kKmU+fN9Jm48+/jgfzYM5M5Z73JUV6mp0CNZS5Ag0EYAmY3wEQANEyh4deQwt9 +Tin3ZNUj4MMct1hDnj85UrsbuSlDtkBK0gA5g0/mtdOQO9ggsFqVs14jVlwljW6V +trN08JnPGcYgIsWL37RysEUqo0Lh7Uz0Wc5KU2949ZXUVjeZ8wb69/zpm/oMkY0+ +UhkLG79XJwAYiXNxt8kI/L0iHFIl+DVneAg1DSBbf5UXlvpgVVcrlrj9sXiUY+5P +6ddnVmdt0v1K/m1GNoiBom9Y5cDG58PHMc//eQ0XwTFxHSZCDSGM+ZvcELjgxYWp +GgwT6wNETR8y3lByRTBFF7C4tAR0eNpcm/T0zkamL7VbNhaQADHUc6LyyPIPYZpd +uBuyMoMmdZVfZUqoyWU0sumfAtWBNsQj6D4JB9XbNmYpiX6sr7nE9IppWsiPT/P5 +zZsHWBVQh6Y1InJnIKb8Bmt0vtR2QOa9UBGeb1wZHpqbguRt7SF27H247xFVhcK8 +ROJfVOPFSpEOWUPABnDmGuzAxQHPoKGizJ8g/zEFMMDMUvH8J/SNoxQEMZ3frBqR +lYVl222M3hqvfyepVV1jQIDY/IoHnCK+y9mUcgOn2SiXyCeFynjZMVChqyacuXrG +mI9v6IdVrR2Omj+uFUxoeE2TWPSZTE8O0/Im3cYUoB6vDVETW1jSJ0IJzVbzmprp +Pk5Bht4qOf4V5ElqRLuQNpeRng/85OrZABEBAAGJAjYEGAEIACAWIQQkQ32tAulg +LM+XORN5XxYaBmN15gUCYAmY3wIbDAAKCRB5XxYaBmN15u8uD/4/Ibh8hLBCElw7 +RFInCMC63lxPUBPIKv7RNObQMizhSNTYXe7RYMMFyQaGRGXvAWYfJK0fsXEYMDn1 +8x2p9+ZsVbvQeJeOt7T2RZETkZgXguAai0H59lb9bRn1YLgpsUY6Zd9+tOb0T2Ob +mP3tT2hr14D4je68XNRoiwmofanQmvihssjOPk7QzAXglntmcR/sYsiPDqZiZv5K +Q5jvocYuCnhXnxvnBdA37D9Xk7FzLH8xvRH5UHqsSiRNcNGmsajO51TzH6zcbr0T +zPn1arahj6MgDmBON2w7IurRNDEHLlQcH4+wGSeEcNBpYNJw6WLi94upvmK0dO2f +FvniY9oAPassm7qLGx8lWxHYefi7mhvzD9RZVS3TLiDlZWKdrOmo5dyupjdcFZBt +Z8BNLM8V8HIblv9tZEm2RmyLmvvOLSWqY8sMoLHVWCQYuTbrlixchLv0cqoqNVYN +30FQg7deJ3bRsyluBHCYAVJVtyhSa2XEQhwNsqWYyEXYvFIvqo3jAfn3ewAQuQnM +kTUfplxR5a7WYhwsiXjns8qGRqCmlwTIMgbJJpLj+alt0uRRLK6ht1vSf8ZTi65O +OiKfubUCyUf87euIHKKrSJubUKuME4tusfVLZoIcMyxuDG+SR2MYPeleJQi4Js2l +vWkou7PLSJdCRqPHtup1XVTwgI29UA== +=4pt9 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/AUCapture-WPF/UserDataContext.cs b/AUCapture-WPF/UserDataContext.cs index 496a4a57..1cc18ea4 100644 --- a/AUCapture-WPF/UserDataContext.cs +++ b/AUCapture-WPF/UserDataContext.cs @@ -31,6 +31,7 @@ public class UserDataContext : INotifyPropertyChanged public string Version { get; set; } public string LatestReleaseAssetURL { get; set; } + public string LatestReleaseAssetSignedHashURL { get; set; } public string LatestVersion { get; set; } private ICommand textBoxButtonCopyCmd; private ICommand textBoxButtonHelpCmd; @@ -228,6 +229,17 @@ public GameState? GameState } } + private bool _autoUpdaterEnabled; + + public bool AutoUpdaterEnabled + { + get => _autoUpdaterEnabled; + set + { + _autoUpdaterEnabled = value; + OnPropertyChanged(); + } + } private static void Shuffle(List list) { Random rng = new Random(); @@ -271,7 +283,7 @@ public UserDataContext(IDialogCoordinator dialogCoordinator, IAppSettings settin try { latest = client.Repository.Release.GetLatest("automuteus", "amonguscapture").Result; - + } catch (Exception e) { @@ -279,6 +291,9 @@ public UserDataContext(IDialogCoordinator dialogCoordinator, IAppSettings settin } LatestReleaseAssetURL = latest.Assets.First(x => x.Name == "AmongUsCapture.zip").BrowserDownloadUrl; + if (latest.Assets.Any(x => x.Name == "AmongUsCapture.zip.sha256.pgp")) + LatestReleaseAssetSignedHashURL = latest.Assets.First(x => x.Name == "AmongUsCapture.zip.sha256.pgp").BrowserDownloadUrl; + LatestVersion = $"{latest.TagName}"; } catch (Exception e)