Param( [string]$Java = 'java', [switch]$NoDeploy ) Add-Type -AssemblyName System.Windows.Forms Add-type -AssemblyName System.Drawing $ProgressPreference = 'SilentlyContinue' $ErrorActionPreference = 'Stop' function execJava { <# .Description execJava was created to additionally allow providing an array of strings to java arguments if the first argument is a string array, it will launch with arguments in that array otherwise it will launch with all provided arguments #> $SavedErrorActionPreference = $ErrorActionPreference $ErrorActionPreference = 'Continue' if ($args[0].getType().Name -ne "String") { & $Java $args[0] 2>&1 | ForEach-Object{ "$_" } } else { & $Java $args 2>&1 | ForEach-Object{ "$_" } } $ErrorActionPreference = $SavedErrorActionPreference } function renderForm([String[]]$items, [String]$label, [String]$title, [System.Windows.Forms.SelectionMode]$mode, [System.Collections.ArrayList]$selected) { # https://docs.microsoft.com/en-us/powershell/scripting/samples/multiple-selection-list-boxes?view=powershell-7.2 # https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.anchorstyles $form = New-Object System.Windows.Forms.Form $form.Text = $title $form.Size = New-Object System.Drawing.Size(300,200) $form.StartPosition = 'CenterScreen' $OKButton = New-Object System.Windows.Forms.Button $OKButton.Anchor = 2 $OKButton.Location = New-Object System.Drawing.Point(102,120) $OKButton.Size = New-Object System.Drawing.Size(75,23) $OKButton.Text = 'OK' $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK $form.AcceptButton = $OKButton $form.Controls.Add($OKButton) $_label = New-Object System.Windows.Forms.Label $_label.Anchor = 1+4+8 $_label.Location = New-Object System.Drawing.Point(10,20) $_label.Size = New-Object System.Drawing.Size(280,20) $_label.Text = $label $form.Controls.Add($_label) $listBox = New-Object System.Windows.Forms.Listbox $listBox.Anchor = 15 $listBox.Location = New-Object System.Drawing.Point(10,40) $listBox.Size = New-Object System.Drawing.Size(260,20) $listBox.SelectionMode = $mode foreach ($entry in $items) { [void] $listBox.Items.Add($entry) } if ($null -ne $selected) { for($i = 0; ($i -lt $selected.Count) -and ($i -lt $items.Length); $i++) { if ($selected[$i]) {$listBox.SetSelected($i, $true) | Out-Null} } } $listBox.Height = 70 $form.Controls.Add($listBox) $form.Topmost = $true if ($form.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { return $listbox.selectedItems } return $false } class config { [hashtable]$version = @{} [System.Collections.ArrayList]$excluded = (New-Object System.Collections.ArrayList) } class configFile { [String]$path = ".\config.json" [config]$config = [config]::new() [void] load() { $fileContent = ConvertFrom-Json ((Get-Content $this.path) -Join ' ').ToString() $version = @{} foreach ($prop in $fileContent.version.PsObject.Properties) { $version.Add($prop.Name, $prop.Value) } $fileContent.version = $null $this.config = $fileContent $this.config.version = $version } [void] save() { Out-File $this.path -InputObject (ConvertTo-Json $this.config) } } function UpdateFromGithub { param ( [Parameter(Mandatory)][String]$Repository, [Parameter(Mandatory)][configFile]$Config, [scriptblock]$AssetsFilter = {$true}, [Parameter(Mandatory)][String]$OutFile ) [String]$InstalledTag = $Config.config.version[$Repository] $LatestRelease try { $LatestRelease = ConvertFrom-Json (Invoke-WebRequest "https://api.github.com/repos/$Repository/releases/latest").Content } catch [System.Net.WebException] { Write-Host "Couldn't check for update $Repository" return $false } [String]$UpdateTag = $LatestRelease.tag_name if ($InstalledTag -eq $UpdateTag) { Write-Host "$Repository up to date! ($InstalledTag)" return $false } $Assets = $LatestRelease.assets | Where-Object -FilterScript $AssetsFilter Write-Host "Downloading $Repository ($InstalledTag -> $UpdateTag)" Write-Host "Changelog: https://github.com/$Repository/compare/$InstalledTag...$UpdateTag" Invoke-WebRequest $Assets[0].browser_download_url -OutFile $OutFile $Config.config.version[$Repository] = $UpdateTag $Config.save() return $true } function main { $config = [configFile]::new() try { $config.load() } catch [System.IO.FileNotFoundException] { Write-Host ".\config.json not found" $config.save() } # Update UpdateFromGithub -Repository "revanced/revanced-patches" -Config $config -AssetsFilter {$_.content_type -like "application/*"} -OutFile ".\app\revanced-patches.jar" | Out-Null UpdateFromGithub -Repository "revanced/revanced-integrations" -Config $config -AssetsFilter {$_.content_type -like "application/*"} -OutFile ".\app\app-release-unsigned.apk" | Out-Null UpdateFromGithub -Repository "revanced/revanced-cli" -Config $config -AssetsFilter {$_.content_type -like "application/*"} -OutFile ".\app\revanced-cli.jar" | Out-Null if ($NoDeploy) {return} # Select Youtube app $apks = (Get-ChildItem *.apk).Name [String]$selectedApk = '' if ($apks.Length -eq 0) {throw "No YouTube apk files found!"} elseif ($apks.getType().Name -eq 'String') {$selectedApk = $apks} else { $selectedApk = (renderForm -items $apks -label "Select apk file to patch" -title "Installer for ReVanced - apk selector" -mode One) } if (-not $selectedApk) {throw "No apk selected!"} # Get available integrations $integrationsList = New-Object System.Collections.ArrayList class Integration { [String] $id [String] $description Integration([String] $_id, [String] $_description) { $this.id = $_id $this.description = $_description } [String] ToString() { return "$($this.id) - $($this.description)" } } foreach ($i in (execJava -jar .\app\revanced-cli.jar -a $selectedApk -b .\app\revanced-patches.jar -l)) { $i = $i.ToString().substring(6).split("`t") [void] $integrationsList.Add([Integration]::new($i[0].TrimStart(), $i[1])) } # integrations selector $excludedIntegrations = New-Object System.Collections.ArrayList [System.Collections.ArrayList]$savedExclusions = New-Object System.Collections.ArrayList $savedExclusionsNames = $config.config.excluded foreach ($i in $integrationsList) { if (($savedExclusionsNames.Count -gt 1) -and $savedExclusionsNames.Contains($i.id)) { [void] $savedExclusions.Add($true) [void] $savedExclusionsNames.Remove($integrationID) } else { [void] $savedExclusions.Add($false) } } foreach ($i in (renderForm -items $integrationsList -label "Select integrations to exclude" -title "Installer for ReVanced - integrations" -mode MultiExtended -selected $savedExclusions)) { [void] $excludedIntegrations.Add($i.Split(' ')[0]) #FIXME: hacky way to do this, but it works } $config.config.excluded = $excludedIntegrations $config.save() # devices $devices = adb devices if ($devices.Length -eq 2) { throw "No devices found" } $devices = $devices[1..($devices.length-2)] [String]$selectedDevice = '' if ($devices.Length -eq 1) { $selectedDevice = ($devices | ForEach-Object {$_.split()[0]}) } else { $selectedDevice = (renderForm -items ($devices | ForEach-Object {$_.split()[0]}) -label "Select deployment target" -title "Installer for ReVanced - target" -mode One) } if (-not $selectedDevice) {throw "No device selected"} # install to device $patcherArgs = "-jar", ".\app\revanced-cli.jar", "-a", ".\$selectedApk", "-c", "-d", "$selectedDevice", "-o", "$env:tmp\revanced.apk", "-m", ".\app\app-release-unsigned.apk", "-b", ".\app\revanced-patches.jar" # is microg patch excluded? if ($excludedIntegrations.Contains("microg-support")) { $patcherArgs += "--mount" } foreach ($i in $excludedIntegrations) { $patcherArgs += "-e" $patcherArgs += $i Write-Output "Excluded: $i" } Write-Output "Logs below are from the cli" execJava $patcherArgs } main