diff --git a/revanced.ps1 b/revanced.ps1 index 82ba1d9..6e9a5c7 100644 --- a/revanced.ps1 +++ b/revanced.ps1 @@ -27,7 +27,46 @@ otherwise it will launch with all provided arguments $ErrorActionPreference = $SavedErrorActionPreference } -function renderForm([String[]]$items, [String]$label, [String]$title, [System.Windows.Forms.SelectionMode]$mode, [System.Collections.ArrayList]$selected) { +class FormItem { + $value + [String] $displayText + [Bool] $selected = $false + + FormItem ($_value, [String] $_displayText, [Bool] $_selected = $false) { + $this.value = $_value + $this.displayText = $_displayText + $this.selected = $_selected + } + + FormItem ($_value, [String] $_displayText) { + $this.value = $_value + $this.displayText = $_displayText + } + + [String] ToString() { + return $this.displayText + } +} + +class FormItems : System.Collections.ArrayList<#FormItem#> { + [System.Collections.ArrayList] getSelectedBoolArray() { + $rvalue = [System.Collections.ArrayList]::new() + foreach ($i in $this) { + [void] $rvalue.Add($i.selected) + } + return $rvalue + } + + [System.Collections.ArrayList] getDisplay() { + $rvalue = [System.Collections.ArrayList]::new() + foreach ($i in $this) { + [void] $rvalue.Add($i.displayText) + } + return $rvalue + } +} + +function renderForm([FormItems]$items, [String]$label, [String]$title, [System.Windows.Forms.SelectionMode]$mode) { # 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 @@ -59,29 +98,35 @@ function renderForm([String[]]$items, [String]$label, [String]$title, [System.Wi $listBox.SelectionMode = $mode - foreach ($entry in $items) { - [void] $listBox.Items.Add($entry) + foreach ($i in $items.getDisplay()) { + [void] $listBox.Items.Add($i) } - 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} - } + for ($i = 0; $i -lt $items.Count; $i++) { + [void] $listBox.SetSelected($i, $items[$i].selected) } $listBox.Height = 70 $form.Controls.Add($listBox) $form.Topmost = $true - if ($form.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { - return $listbox.selectedItems + $dialogResult = $form.ShowDialog() + if ($dialogResult -ne [System.Windows.Forms.DialogResult]::OK) { + return $false } - return $false + + $selected = [System.Collections.ArrayList]::new() + foreach ($i in $listbox.selectedIndices) { + [void] $selected.Add($items[$i].value) + } + + $selected.TrimToSize() + return $selected } class config { [hashtable]$version = @{} - [System.Collections.ArrayList]$excluded = (New-Object System.Collections.ArrayList) + [System.Collections.ArrayList]$included = [System.Collections.ArrayList]::new() } class configFile { @@ -142,6 +187,106 @@ function UpdateFromGithub { return $true } +class CompatiblePackage { + [String] $name + [String[]] $versions + + CompatiblePackage([String] $_name, [String[]] $_versions) { + $this.name = $_name + $this.versions = $_versions + } +} + +class Integration { + [String] $name + [String] $description + [String] $version + [Bool] $excluded + [Bool] $deprecated + [String[]] $dependencies + <#[compatiblePackage[]]#> $compatiblePackages = [System.Collections.ArrayList]::new() + + Integration([String] $_name, [String] $_description) { + $this.name = $_name + $this.description = $_description + } + + Integration($integration) { + $this.name = $integration.name + $this.description = $integration.description + $this.version = $integration.version + $this.excluded = $integration.excluded + $this.deprecated = $integration.deprecated + $this.dependencies = $integration.dependencies + + foreach ($i in $integration.compatiblePackages) { + [void] $this.compatiblePackages.Add([CompatiblePackage]::new($i.name, $i.versions)) + } + } + + [String] ToString() { + return "$($this.name) - $($this.description)" + } + + [Bool] Compatible([String] $name, [String] $version) { + if ($this.compatiblePackages.Count -eq 0) { return $true } + [compatiblePackage[]] $compatiblePackage = $this.compatiblePackages | Where-Object {$_.name -eq $name} + if ($compatiblePackage.length -eq 0 ) { return $false } + return $compatiblePackage.Contains($version) + } +} + +class IntegrationList : System.Collections.ArrayList<#Integration#> { + + IntegrationList($path) { + $integration = ConvertFrom-Json(Get-Content $path) + + foreach ($i in $integration) { + [void] $this.add([Integration]::new($i)) + } + } + + [String[]] getDependenciesNames([String] $name) { + foreach ($i in $this) { + if ($i.name -ne $name) { continue } + $rvalue = [System.Collections.ArrayList]::new() + foreach ($j in $i.dependencies) { + if ($rvalue.Contains($j)) { continue } + [void] $rvalue.Add($j) + } + return $rvalue + } + return $null + } + + [System.Collections.ArrayList] getFullIntegrationList([String[]] $integrations) { + <# + .Description + Returns Integration list with all dependencies included + #> + $rvalue = [System.Collections.ArrayList]::new($this.Count) + + foreach ($i in $integrations) { + if ($rvalue.Contains($i)) { continue } + [void] $rvalue.Add($i) + $dependencies = $this.getDependenciesNames($i) + foreach ($j in $this.getFullIntegrationList($dependencies)) { + if ($rvalue.Contains($j)) { continue } + [void] $rvalue.Add($j) + } + } + return $rvalue + } + + [FormItems] getForm() { + $rvalue = [FormItems]::new() + foreach ($i in $this) { + [void] $rvalue.Add([FormItem]::new($i.name, "$($i.name) - for $($i.compatiblePackages[0].name) - $($i.description)")) + } + return $rvalue + } +} + function main { $config = [configFile]::new() try { @@ -154,69 +299,53 @@ function main { # Update - UpdateFromGithub -Repository "revanced/revanced-patches" -Config $config -AssetsFilter {$_.content_type -like "application/*"} -OutFile ".\app\revanced-patches.jar" | Out-Null + $updatedPatches = UpdateFromGithub -Repository "revanced/revanced-patches" -Config $config -AssetsFilter {$_.content_type -like "application/java-archive"} -OutFile ".\app\revanced-patches.jar" + if ($updatedPatches) { + Invoke-WebRequest "https://raw.githubusercontent.com/revanced/revanced-patches/main/patches.json" -OutFile ".\app\revanced-patches.json" + } + 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 + # Select apk to patch $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) + $apkItems = [FormItems]::new() + foreach ($i in $apks) { + [void] $apkItems.Add([FormItem]::new($i, $i)) + } + $selectedApk = renderForm -items $apkItems -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 = [IntegrationList]::new(".\app\revanced-patches.json") # 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) - } + $integrationsToInclude = [System.Collections.ArrayList]::new() + $integrationsForm = $integrations.getForm() + for ($i = 0; $i -lt $integrationsForm.Count; $i++) { + if (-not $config.config.included.Contains($integrationsForm[$i].value)) { continue } + $integrationsForm[$i].selected = $true } - 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 - } + $integrationsToInclude = renderForm -items $integrationsForm -label "Select integrations to include" -title "Installer for ReVanced - integrations" -mode MultiExtended - $config.config.excluded = $excludedIntegrations + $config.config.included = $integrationsToInclude $config.save() + # We save only what user selected, but we still need to include integrations that depends on selected + $integrationsToInclude = $integrations.getFullIntegrationList($integrationsToInclude) + # devices $devices = adb devices @@ -230,25 +359,29 @@ function main { $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) + $devicesForm = [FormItems]::new() + foreach ($i in $devices) { + [void] $devicesForm.Add([FormItem]::new($i.split()[0], $i)) + } + $selectedDevice = (renderForm -items $devicesForm -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" + $patcherArgs = [System.Collections.ArrayList]::new(100) + [void] $patcherArgs.AddRange(("-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", "--exclusive", "--experimental")) # is microg patch excluded? - if ($excludedIntegrations.Contains("microg-support")) { - $patcherArgs += "--mount" + if (-not $integrationsToInclude.Contains("microg-support")) { + [void] $patcherArgs.Add("--mount") } - foreach ($i in $excludedIntegrations) { - $patcherArgs += "-e" - $patcherArgs += $i - Write-Output "Excluded: $i" + foreach ($i in $integrationsToInclude) { + [void] $patcherArgs.AddRange(("-i", $i)) + Write-Output "Included: $i" } Write-Output "Logs below are from the cli"