Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # MTG Arena Account Switcher by /u/rentar
- # See https://www.reddit.com/r/MagicArena/comments/1m5vnz5/i_built_a_little_tool_to_switch_between_arena/
- param(
- [Parameter(Mandatory=$false)]
- [String]$Account
- )
- $ErrorActionPreference="Stop"
- $SteamExe="${Env:Programfiles(x86)}\Steam\steam.exe"
- $PathMtga="HKCU:\Software\Wizards Of The Coast\MTGA"
- $PathMtgaAccounts="HKCU:\Software\Wizards Of The Coast\MTGA-Accounts"
- # I previously thought the _h123456789 part of the keys was somehow dynamic, but it seems those are just Unity PlayerPrefs, which means they are static.
- # This function was used before but seem unnecessary now.
- #function Get-RefreshTokenName {
- # (reg query "HKCU\Software\Wizards Of The Coast\MTGA" | Where-Object { $_ -match "WAS-RefreshToken"}).Trim().Split(" ")[0]
- #}
- $PropertyWASRefreshToken = "WAS-RefreshTokenE_h2698947118"
- $PropertyWASRememberMe = "WAS-RememberMe_h1678977314"
- $PropertyLastLoginString = "LastLoginString_h2517025721"
- function ConvertFrom-Base64 {
- param([byte[]] $bytes)
- ConvertFrom-Base64String([System.Text.Encoding]::ASCII.GetString($bytes))
- }
- function ConvertFrom-Base64String {
- param([string] $string)
- # Base64 strings seem to sometimes be 0-terminated and sometimes have 0x1D at the end, just remove those.
- $string = $string.TrimEnd("`u{0}`u{1d}".ToCharArray())
- while ($string.Length % 4 -ne 0) {
- $string += "="
- }
- $decoded = [System.Convert]::FromBase64String($string)
- [System.Text.Encoding]::UTF8.GetString($decoded)
- }
- function Get-RefreshToken {
- Get-ItemPropertyValue -Path $PathMtga -Name $PropertyWASRefreshToken
- }
- function Get-BackupValue {
- param(
- [string] $account,
- [string] $property)
- try {
- Get-ItemPropertyValue -Path "$PathMtgaAccounts/$account" -Name $property
- } catch {
- # Get-ItemPropertyValue throws an unchangable exception when the property doesn't exist.
- # I'm not alone in thinking this is silly https://github.com/PowerShell/PowerShell/issues/5906
- }
- }
- function ConvertFrom-JWT {
- param([byte[]] $refreshToken)
- $rtDecoded = ConvertFrom-Base64($refreshToken)
- $rtParts = $rtDecoded.Split('.')
- # Refresh Token seems to be a JWT. The first part is the header, the second the payload, the third the signature.
- # Since we don't verify anthing, we only care about the payload.
- $payload = ConvertFrom-Base64String($rtParts[1])
- $payload | ConvertFrom-Json
- }
- function Backup-CurrentRefreshToken {
- $refreshToken = Get-RefreshToken
- $payload = ConvertFrom-JWT($refreshToken)
- $account = $payload.sub
- $refreshTokenBackup = Get-BackupValue $account $PropertyWASRefreshToken
- if (-not $refreshTokenBackup) {
- Write-Output "Account ${account}: not seen before, backing up."
- $null = New-Item -Path $PathMtgaAccounts -Name $account -ErrorAction Ignore
- Copy-ItemProperty -Path $PathMtga -Destination "$PathMtgaAccounts/$account" -Name $PropertyLastLoginString
- Copy-ItemProperty -Path $PathMtga -Destination "$PathMtgaAccounts/$account" -Name $PropertyWASRefreshToken
- } else {
- $payloadBackup = ConvertFrom-JWT($refreshTokenBackup)
- if ($payloadBackup.exp -lt $payload.exp) {
- Write-Output "Account ${account}: New refresh token found, backing up ($($payloadBackup.exp) < $($payload.exp))."
- Copy-ItemProperty -Path $PathMtga -Destination "$PathMtgaAccounts/$account" -Name $PropertyWASRefreshToken
- }
- }
- }
- function Get-AccountDetails {
- param([string]$account)
- $refreshToken = Get-BackupValue $account $PropertyWASRefreshToken
- $lastLoginString = [System.Text.Encoding]::UTF8.GetString((Get-backupValue $account $PropertyLastLoginString)).Trim("`u{0}".ToCharArray())
- $payload = ConvertFrom-JWT $refreshToken
- [pscustomobject]@{ ID=$account; Email=$lastLoginString; RefreshedAt=(Get-Date -UnixTimeSeconds $payload.iat); Expiration=(Get-Date -UnixTimeSeconds $payload.exp)}
- }
- function Show-KnownAccounts {
- Get-ChildItem -Path $PathMtgaAccounts -Name | ForEach-Object { Get-AccountDetails $_ } | Format-Table
- }
- function Wait-ForKey {
- Write-Output 'Press any key to continue...'
- $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
- }
- # Create Key to store the various accounts
- New-Item -Path PathMtgaAccounts -ErrorAction Ignore
- Backup-CurrentRefreshToken
- if ($Account) {
- $accountRefreshToken = Get-BackupValue $Account $PropertyWASRefreshToken
- if (-not $accountRefreshToken) {
- Write-Output "Account ${Account} not found."
- Show-KnownAccounts
- Wait-ForKey
- exit 0
- }
- Copy-ItemProperty -Path "$PathMtgaAccounts/$Account" -Destination $PathMtga -Name $PropertyWASRefreshToken
- Set-ItemProperty -Path $PathMtga -Name $PropertyWASRememberMe -Value ([System.Text.Encoding]::ASCII).GetBytes("True`u{0}")
- # Launch Arena if it's not already running.
- $arenaProc = Get-Process -Name "MTGA" -ErrorAction SilentlyContinue
- if (-Not $arenaProc) {
- & $SteamExe steam://rungameid/2141910
- }
- } else {
- Write-Output "No account parameter specified. Specify account ID to launch Arena with that account."
- Show-KnownAccounts
- Wait-ForKey
- }
Add Comment
Please, Sign In to add comment