This repository has been archived on 2023-10-05. You can view files and clone it, but cannot push or open issues or pull requests.
revanced-ps/revanced.ps1

467 lines
15 KiB
PowerShell
Raw Permalink Normal View History

2022-07-03 01:36:42 +02:00
Param(
2022-07-15 23:47:24 +02:00
[string]$Java = 'java',
2022-11-12 00:55:27 +01:00
[switch]$NoDeploy,
[switch]$NoUpdate
2022-07-03 01:36:42 +02:00
)
Add-Type -AssemblyName System.Windows.Forms
Add-type -AssemblyName System.Drawing
$ProgressPreference = 'SilentlyContinue'
$ErrorActionPreference = 'Stop'
2022-07-19 18:33:03 +02:00
2022-07-03 01:36:42 +02:00
function execJava {
2022-07-19 18:33:03 +02:00
<#
.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
2022-07-03 01:36:42 +02:00
$ErrorActionPreference = 'Continue'
if ($args[0].getType().Name -ne "String") {
& $Java $args[0] 2>&1 | ForEach-Object{ "$_" }
}
else {
& $Java $args 2>&1 | ForEach-Object{ "$_" }
}
2022-07-19 18:33:03 +02:00
$ErrorActionPreference = $SavedErrorActionPreference
2022-07-03 01:36:42 +02:00
}
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
}
FormItems() {}
FormItems([System.Collections.IEnumerable] $list) {
<#
.Description
Creates FormItems list with all items in list
where values are those items
and displaytext as string representation of them
TLDR it converts any list to FormItems
#>
foreach ($i in $list) {
[void] $this.Add([FormItem]::new($i, $i.ToString()))
}
}
}
function renderForm([FormItems]$items, [String]$label, [String]$title, [System.Windows.Forms.SelectionMode]$mode) {
2022-07-03 01:36:42 +02:00
# 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 ($i in $items.getDisplay()) {
[void] $listBox.Items.Add($i)
2022-07-03 01:36:42 +02:00
}
for ($i = 0; $i -lt $items.Count; $i++) {
[void] $listBox.SetSelected($i, $items[$i].selected)
2022-07-03 01:36:42 +02:00
}
$listBox.Height = 70
$form.Controls.Add($listBox)
$form.Topmost = $true
$dialogResult = $form.ShowDialog()
if ($dialogResult -ne [System.Windows.Forms.DialogResult]::OK) {
return $false
}
$selected = [System.Collections.ArrayList]::new()
foreach ($i in $listbox.selectedIndices) {
[void] $selected.Add($items[$i].value)
2022-07-03 01:36:42 +02:00
}
$selected.TrimToSize()
return $selected
2022-07-03 01:36:42 +02:00
}
class config {
2022-11-12 01:59:22 +01:00
[System.Collections.SortedList]$version
[System.Collections.SortedList]$included
2022-07-03 01:36:42 +02:00
}
2022-07-20 00:52:59 +02:00
class configFile {
[String]$path = ".\config.json"
[config]$config = [config]::new()
2022-07-03 01:36:42 +02:00
2022-07-20 00:52:59 +02:00
[void] load() {
$fileContent = ConvertFrom-Json ((Get-Content $this.path) -Join ' ').ToString()
2022-07-03 01:36:42 +02:00
2022-11-12 01:59:22 +01:00
$version = [System.Collections.SortedList]::new()
2022-07-20 00:52:59 +02:00
foreach ($prop in $fileContent.version.PsObject.Properties) {
$version.Add($prop.Name, $prop.Value)
}
$this.config.version = $version
2022-11-12 01:59:22 +01:00
$included = [System.Collections.SortedList]::new()
foreach ($prop in $fileContent.included.PsObject.Properties) {
$included.Add($prop.Name, $prop.Value)
}
$this.config.included = $included
2022-07-20 00:52:59 +02:00
}
2022-07-03 01:36:42 +02:00
2022-07-20 00:52:59 +02:00
[void] save() {
Out-File $this.path -InputObject (ConvertTo-Json $this.config)
}
2022-11-12 01:59:22 +01:00
[void] setIncludesForPackage([String] $packageName, [System.Collections.IEnumerable] $integrationNames) {
$this.config.included[$packageName] = $integrationNames.Clone()
}
[System.Collections.ArrayList] getIncludesForPackage([String] $packageName) {
if (-not $this.config.included.Keys.Contains($packageName)) { return [System.Collections.ArrayList]::new() }
2022-11-12 01:59:22 +01:00
return $this.config.included[$packageName].Clone()
}
2022-07-20 00:52:59 +02:00
}
2022-07-03 01:36:42 +02:00
2022-07-20 00:52:59 +02:00
function UpdateFromGithub {
param (
[Parameter(Mandatory)][String]$Repository,
[Parameter(Mandatory)][configFile]$Config,
[scriptblock]$AssetsFilter = {$true},
[Parameter(Mandatory)][String]$OutFile
)
2022-07-03 01:36:42 +02:00
2022-07-20 00:52:59 +02:00
[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
}
2022-07-03 01:36:42 +02:00
2022-07-20 00:52:59 +02:00
[String]$UpdateTag = $LatestRelease.tag_name
2022-07-03 01:36:42 +02:00
2022-07-20 00:52:59 +02:00
if ($InstalledTag -eq $UpdateTag) {
Write-Host "$Repository up to date! ($InstalledTag)"
return $false
}
2022-07-03 01:36:42 +02:00
2022-07-20 00:52:59 +02:00
$Assets = $LatestRelease.assets | Where-Object -FilterScript $AssetsFilter
2022-07-03 01:36:42 +02:00
2022-07-20 00:52:59 +02:00
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()
2022-07-19 18:33:03 +02:00
2022-07-20 00:52:59 +02:00
return $true
}
2022-07-03 01:36:42 +02:00
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)
}
[System.Collections.ArrayList] compatiblePackageNames() {
$rvalue =[System.Collections.ArrayList]::new($this.compatiblePackages.Count)
foreach ($i in $this.compatiblePackages) {
[void] $rvalue.Add($i.name)
}
return $rvalue
}
}
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
}
[FormItems] getForm([String] $packageName) {
$rvalue = [FormItems]::new()
foreach ($i in $this) {
if (-not $i.compatiblePackageNames().Contains($packageName)) { continue }
2022-11-12 16:25:34 +01:00
[String] $description = "$($i.name) - $($i.description)"
foreach ($j in $this.getFullIntegrationList($i.name)) {
if ( $j -match "setting") {
$description = $description.Replace("$($i.name) - ", "$($i.name) [s] - ")
break
}
}
[void] $rvalue.Add([FormItem]::new($i.name, $description))
}
return $rvalue
}
[System.Collections.ArrayList] getAllCompatiblePackagesNames() {
$rvalue = [System.Collections.ArrayList]::new()
foreach ($i in $this) {
foreach ($j in $i.compatiblePackages) {
if ($rvalue.Contains($j.name)) { continue }
[void] $rvalue.Add($j.name)
}
}
return $rvalue
}
}
2022-07-20 00:52:59 +02:00
function main {
$config = [configFile]::new()
try {
$config.load()
2022-07-03 01:36:42 +02:00
}
2022-07-20 00:52:59 +02:00
catch [System.IO.FileNotFoundException] {
Write-Host ".\config.json not found"
$config.save()
2022-07-03 01:36:42 +02:00
}
2022-07-20 00:52:59 +02:00
# Update
2022-11-12 00:55:27 +01:00
if (-not $NoUpdate) {
$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"
}
2022-11-12 00:55:27 +01:00
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
}
2022-07-20 00:52:59 +02:00
2022-07-15 23:47:24 +02:00
if ($NoDeploy) {return}
# Select apk to patch
2022-07-03 01:36:42 +02:00
$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}
2022-07-03 01:36:42 +02:00
else {
$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
2022-07-03 01:36:42 +02:00
}
if (-not $selectedApk) {throw "No apk selected!"}
2022-07-03 01:36:42 +02:00
# Get available integrations
$integrations = [IntegrationList]::new(".\app\revanced-patches.json")
2022-07-03 01:36:42 +02:00
# get package name
# FIXME: How to extract package name from its apk file?
$packageNamesForm = [FormItems]::new($integrations.getAllCompatiblePackagesNames())
$packageName = renderForm -items $packageNamesForm -label "Which package is it?" -title "Installer for ReVanced - package name" -mode One
2022-07-03 01:36:42 +02:00
# integrations selector
$integrationsToInclude = [System.Collections.ArrayList]::new()
$integrationsForm = $integrations.getForm($packageName)
for ($i = 0; $i -lt $integrationsForm.Count; $i++) {
2022-11-12 01:59:22 +01:00
if (-not $config.getIncludesForPackage($packageName).Contains(($integrationsForm[$i].value))) { continue }
$integrationsForm[$i].selected = $true
2022-07-03 01:36:42 +02:00
}
$integrationsToInclude = renderForm -items $integrationsForm -label "Select integrations to include" -title "Installer for ReVanced - integrations" -mode MultiExtended
2022-07-03 01:36:42 +02:00
2022-11-12 01:59:22 +01:00
$config.setIncludesForPackage($packageName, $integrationsToInclude)
2022-07-20 00:52:59 +02:00
$config.save()
2022-07-03 01:36:42 +02:00
# We save only what user selected, but we still need to include integrations that depends on selected
$integrationsToInclude = $integrations.getFullIntegrationList($integrationsToInclude)
2022-07-03 01:36:42 +02:00
# devices
$devices = adb devices
if ($devices.Length -eq 2) {
throw "No devices found"
}
2022-07-03 01:36:42 +02:00
$devices = $devices[1..($devices.length-2)]
[String]$selectedDevice = ''
if ($devices.Length -eq 1) {
2022-08-04 21:58:06 +02:00
$selectedDevice = ($devices | ForEach-Object {$_.split()[0]})
2022-07-19 18:01:45 +02:00
}
2022-07-03 01:36:42 +02:00
else {
$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)
2022-07-03 01:36:42 +02:00
}
if (-not $selectedDevice) {throw "No device selected"}
2022-07-03 01:36:42 +02:00
# install to device
$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"))
2022-07-03 01:36:42 +02:00
# is microg patch excluded?
if (-not $integrationsToInclude.Contains("microg-support")) {
[void] $patcherArgs.Add("--mount")
2022-07-03 01:36:42 +02:00
}
foreach ($i in $integrationsToInclude) {
[void] $patcherArgs.AddRange(("-i", $i))
Write-Output "Included: $i"
2022-07-03 01:36:42 +02:00
}
2022-07-04 02:38:26 +02:00
Write-Output "Logs below are from the cli"
2022-07-03 01:36:42 +02:00
execJava $patcherArgs
}
main