[
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 ninthwalker\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Saverr\n\n## Developers Note:\nThis script/repo is no longer maintained.  \nWhile it still works as far as i know, I'm not adding/changing to it any longer. I would suggest to check out a project called [PlexRipper](https://github.com/PlexRipper/PlexRipper) if you are interested in something like my Saverr, but with a lot better GUI and feature set. Thanks!\n\n\nPowershell script with a front-end GUI to download media from Plex Servers.  \nAllows you to search and save movies, tv shows, and music for offline/personal use.  \nExpanded from the original non-gui version: [directplexDownloader](https://github.com/ninthwalker/directPlexDownloader).\n\n## Details/Requirements\n1. Windows 7/8/10\n2. Powershell 3.0+\n3. .Net Framework 3.5+ (Usually already on your windows computer)\n4. Plex Server (Can be used on your own server or a remote friends server as well)\n  \nSupports:\n* **Movies, TV Shows, and Music:** Download any and all media. Full TV Series or Albulms as well.\n* **Searching:** Enter the name of what you are looking for to watch what you want, when you want.\n* **Multiple Server support:** Quickly switch between multiple plex servers.\n* **Size/ETA Estimates:** Shows current progress, size of download as well as an estimated time of finishing.\n* **Pause/Resume:** Supports pausing and resuming of downloads.\n\n## Launching Saverr\n\n**Note:**\nDepending on your download method/settings, you may need to 'unblock' the files after downloading them from Github. This is normal behavior for Microsoft Windows to do for files downloaded from the internet.  \n`Right click > Properties > Check 'Unblock'`\n\n**Option One**\n1. Copy the Saverr.lnk shortcut, as well as the Saverr.ps1 file to your computer. Place in the same directory.\n2. Double click the Saverr shortcut to launch the app.\n3. Click the gear icon to configure initial settings. (See settings section below)  \n\n**Option Two**\n1. Copy the Saverr.ps1 file to your desktop.\n2. Open a powershell console (Not ISE) and navigate to the folder you saved the Saverr.ps1 file.\n3. Enter the below command to temporarily set the execution policy:  \n  `Set-ExecutionPolicy -Scope Process Bypass`  \n  Alternatively, set the execution policy to permanently allow powershell scripts:  \n  `Set-ExecutionPolicy -Scope Currentuser Unrestricted`  \n4. Then enter the below command to launch the app:  \n  `.\\Saverr.ps1`  \n\n**Option Three**  \n  \nNot available anymore. Even though the .exe was just the powershell script compiled, windows would flag it as a virus so I removed this option. You can compile it yourself into an executable using this tool here if you would like:  \n(https://gallery.technet.microsoft.com/scriptcenter/PS2EXE-GUI-Convert-e7cb69d5)\n~~If you trust me, I've compiled an .exe here as well.~~\n  ~~source is just the Saverr.ps1 file that is located here converted with the [PS2EXE] tool. You can do it yourself if you want using the Saverr.ps1 file.~~\n~~Save the Saverr.exe to your computer and double click it to launch the app.~~\n\n## How to use  \n1. Launch the script using one of the methods listed above.  \n2. Enter the name of the Movie, TV show or Music artist to search for.  \n3. Select the desired result from the results box.  \n  3a. If a Movie: Just click download.  \n  3b. If a TV Show, select the season or episodes, then click download. (Can also select All seasons or All episodes)  \n  3c. If Music, select the album or tack, then click download. (Can also select All albums or All tracks)  \n\n## Config/Settings  \nAll config is done in the settings menu (Accessed by clicking the orange gear icon)  \n\n* **Plex Username:** Plex Username. Can be an email or a username. (this is not saved)  \n* **Plex Password:** Your Plex password. (this is not saved, only used to retrieve your plex token)  \nNote for 2FA: If 2FA is enabled, please add your 2FA token to the end of your password. ie: MyP@ssword347821\n* **Server:** After a token has been saved from entering a username/password you can select a Plex server to search from.  \n* **Download Path:** Navigate and select a path to save downloads to.\n* **SSL Required:** Select this if the server you are trying to connect to has 'Secure Connections: Required' enabled.\n* **Debug:** Check to enable a log file for debugging issues. (Saves to saverrLog.txt)\n\n## Known Issues    \n\n1. Some plex servers will not work or may act a bit funky.  \nNot much I can do about this. Everyones plex servers are set up a bit differently. Some have firewalls, special routing configuration, or nginx proxy servers in front. However, from my experience using mutiple plex servers, this works the majority of the time and the servers that do not work are outliers.\n\n3. No mimimize button during an active download.  \nThis is intended. Because of the powershell script functions used in the background, a pause is required to prevent hanging of the script. The mimimize button becomes available after you pause a download. Click resume after maximizing the window again. You can also continue to do other things on your computer by opening other windows while the Saverr app downloads. Saverr will remain open behind these windows and can be re-selected again to use it without pausing of downloads.\n\n4. Maximum number of downloads is 200.  \nThis is the default setting within windows for the BITS download function being used.  \nMore than 200 items will automatically be truncated to 200.  \nIf you need to increase the maximum download amount, please set this registry setting below to the value desired:  \n  **Path:** `HKLM\\Software\\Policies\\Microsoft\\Windows\\BITS`  \n  **Dword:** `MaxFilesPerJob`  \n  **Decimal Value:** `Dealers Choice`  \nReference: [Bits](https://docs.microsoft.com/en-us/windows/desktop/bits/group-policies)\n\n\n## Errors  \nSome errors are self explanatory and output to the main app window, others are not. You can enable debugging in the settings menu. This will create a log file (saverrLog.txt) in the current Saverr directory that will give more information on the error or issue.  \n\n## Screenshots  \n\n![](https://raw.githubusercontent.com/ninthwalker/saverr/master/screenshots/Saverr%20-%20Movie%20Search.png)  \n\n![](https://raw.githubusercontent.com/ninthwalker/saverr/master/screenshots/Saverr%20-%20TV%20Search.png)  \n\n![](https://raw.githubusercontent.com/ninthwalker/saverr/master/screenshots/Saverr%20-%20Music.png)  \n\n![](https://raw.githubusercontent.com/ninthwalker/saverr/master/screenshots/Saverr%20-%20Downloading.png)  \n\n![](https://raw.githubusercontent.com/ninthwalker/saverr/master/screenshots/Saverr%20-%20Settings.png)\n"
  },
  {
    "path": "Saverr.ps1",
    "content": "#######################################\r\n# Name:    Saverr                     #\r\n# Desc:    d/l media from Plex        #\r\n# Author:  Ninthwalker                #\r\n# Date:    16NOV2021                  #\r\n# Version: 1.1.2                      #\r\n#######################################\r\n\r\n\r\n###### NOTES FOR USER #######\r\n\r\n# See Instruction online at: https://github.com/ninthwalker/saverr\r\n\r\n# Execution policy may need to be set to run powershell scripts if not using the shortcut from Github\r\n# ie: Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass\r\n\r\n# Enforce TLS 1.1/1.2 if wanting. Uses HTTPS/SSL by default to retrieve plex tokens. May/may not break functionality depending on network setup.\r\n#[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls\r\n\r\n# If you need to increase the maximum downloads, please set this registry setting below to value desired.\r\n# Bitstransfers default limit is 200. see: https://docs.microsoft.com/en-us/windows/desktop/bits/group-policies\r\n# Path: HKLM\\Software\\Policies\\Microsoft\\Windows\\BITS\r\n# Dword: MaxFilesPerJob\r\n# Decimal Value: Dealers Choice\r\n\r\n\r\n#############################\r\n####### DO NOT MODIFY #######\r\n#############################\r\n\r\n### setup environment ###\r\n\r\nif ($MyInvocation.MyCommand.CommandType -eq \"ExternalScript\") {\r\n    $ScriptPath = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition\r\n}\r\nelse {\r\n    $ScriptPath = Split-Path -Parent -Path ([Environment]::GetCommandLineArgs()[0])\r\n    if (!$ScriptPath) {\r\n        $ScriptPath = \".\"\r\n    }\r\n}\r\n\r\n# Set-Location $PSScriptRoot. Changed to above so it works with an .exe as well.\r\nSet-Location $ScriptPath\r\n\r\n#import Bitstransfer if not\r\nif (!(Get-Module BitsTransfer)) {\r\n    Import-Module BitsTransfer\r\n}\r\n\r\n# Set timeout value for how long to wait for download to start before giving up\r\n$timeout = 30\r\n\r\n# Get maximum BITS files value if set\r\n$bitsRegistry =  'HKLM:\\Software\\Policies\\Microsoft\\Windows\\BITS' \r\n$key = Get-Item -LiteralPath $bitsRegistry -ErrorAction SilentlyContinue\r\nif ($key) {\r\n    $limit = $key.GetValue(\"MaxFilesPerJob\", 200)\r\n}\r\n\r\n# diff ways of d/l. invoke-restmethod seems to fail sometimes while webclient method does not.\r\n# Set-Alias -Name plx -Value Invoke-RestMethod -Scope Script\r\n\r\n# download function shortcut\r\nfunction plx {\r\n    \r\n    Param([Parameter(Mandatory=$true)]\r\n    [string]$url\r\n    )\r\n\r\n    # Will timeout after 20sec by default\r\n    [xml](New-Object System.Net.WebClient).DownloadString($url)\r\n}\r\n\r\n# check invalid char's function\r\nFunction Remove-InvalidChars {\r\n\r\n    Param([Parameter(Mandatory=$true)]\r\n    [string]$name\r\n    )\r\n\r\n  $strip = $name -replace('[][]','')\r\n  $invalidChars = [IO.Path]::GetInvalidFileNameChars() -join ''\r\n  $re = \"[{0}]\" -f [RegEx]::Escape($invalidChars)\r\n  return ($strip -replace $re)\r\n}\r\n\r\n# download path function\r\nFunction Get-SavePath($initialDirectory) {\r\n    [System.Reflection.Assembly]::LoadWithPartialName(\"System.windows.forms\")|Out-Null\r\n\r\n    $foldername = New-Object System.Windows.Forms.FolderBrowserDialog\r\n    $foldername.Description = \"Select a folder to save downloads to\"\r\n    $foldername.rootfolder = \"MyComputer\"\r\n\r\n    if($foldername.ShowDialog() -eq \"OK\")\r\n    {\r\n        $folder += $foldername.SelectedPath\r\n    }\r\n    else {\r\n        $folder = $false\r\n    }\r\n    return $folder\r\n}\r\n\r\n# logging function\r\nfunction logIt {\r\n    if ($debug) {\r\n        $e = $_.Exception\r\n        $line = $_.InvocationInfo.ScriptLineNumber\r\n        $msg = $e.Message\r\n\t\r\n        $eMSG = \"$(Get-Date): caught exception: $e at $line. $msg\"\r\n        $eMSG | Out-File \".\\saverrLog.txt\" -Append\r\n    }\r\n}\r\n\r\n# display size function\r\nfunction byteSize($num)\r\n{\r\n    $suffix = \"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"\r\n    $index = 0\r\n    while ($num -gt 1kb) \r\n    {\r\n        $num = $num / 1kb\r\n        $index++\r\n    } \r\n\r\n    \"{0:N1} {1}\" -f $num, $suffix[$index]\r\n}\r\n\r\n# Import settings\r\nif (Test-Path .\\saverrSettings.xml) {\r\n    $script:settings = Import-Clixml .\\saverrSettings.xml\r\n    if ((!($settings.name)) -or (!($settings.server)) -or (!($settings.userToken)) -or (!($settings.serverToken)) -or (!($settings.dlPath))) {\r\n        $errorMsg = \"Settings are not fully configured.`nPlease click the gear icon before searching.\"\r\n    }\r\n    else {\r\n        $errorMsg = \"\"\r\n    }\r\n}\r\nelse {\r\n    $errorMsg = \"Settings file not detected. Please configure settings before searching.\"\r\n}\r\n\r\n# enable/disable debug\r\n$debug = $settings.logging\r\n\r\n# enable/disable ssl\r\n$ssl = $settings.ssl\r\n\r\n# The below is needed when the plex server has 'Secure connections: required' set. \r\n# when SSL is enforced, and the 'SSL Required' is checked on the Saverr settings page we will use HTTPS.\r\n# However, because we have to access by IP, the cert will show as 'invalid' since the CN will not match the IP.\r\n# These settings here, allow us to download from servers that enforce the SSL.\r\n\r\n# also, later on we do a similar 'ignore cert errors' for the bitstransfer job\r\n# using the below command/info:\r\n# https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/bitsadmin-setsecurityflags\r\n# https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc753211(v=ws.10)?redirectedfrom=MSDN\r\n# bitsadmin /SetSecurityFlags myJob 30\r\n\r\nif ($ssl -eq $True) {\r\n\t$scheme = \"https://\"\r\n    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}\r\n}\r\nelse {\r\n\t$scheme = \"http://\"\r\n}\r\n\r\n# Plex signin for token url\r\n$plexSignInUrl = \"https://plex.tv/users/sign_in.xml\"\r\n\r\n# Plex servers list URL\r\n$plexServersUrl = \"https://plex.tv/pms/servers\"\r\n\r\n# init the cancel/pauseLoop variables\r\n$script:cancelLoop = $false\r\n$script:pauseLoop = $false\r\n\r\n\r\n### Load required libraries ###\r\n\r\nAdd-Type -AssemblyName System.Windows.Forms, PresentationFramework, PresentationCore, WindowsBase, System.Drawing\r\n[System.Windows.Forms.Application]::EnableVisualStyles()\r\n\r\n################ Images ##################\r\n\r\n\r\n# load these images inside the script so external calls arents\r\n$plexImg = @'\r\n    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\r\n'@\r\n\r\n$loadingImg = @'\r\n    iVBORw0KGgoAAAANSUhEUgAAAHEAAACmCAYAAADtRWBHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkM\r\n    Ea+wAABC7SURBVHhe7Z0LlFTFncZ5DDCDAiIg4mOAYYZ5dE8/pqe7ZwbQAA4rIIxCQIYguCoqKL5FEZEEBBQTWRE0AopgwPg6RvNAjTGaXTdns48TyZo1iWvM6mbduBqjJhLpqt7v33\r\n    RP/tVTPV0TWovb1HfO79z57nTfrqqv696qupehRzKZdHgc7U6Ht9DudHgL7U6Ht9DudHgL7U6Ht9DudHgL7U6Ht9DudHgL7U6Ht9DudHgL7U6Ht9DuzIeTfSl5cGOKk30peXBjipN9K\r\n    XlwY4qTfSl5cGOKk30peXBjipN9KXlwY4qTfSl5cGOKk30peXBjipN9KXlwY4qTfSl5cGOKk30peXBjipN9KXlwY4qTfSl5cGOKk30peXBjipN9KXlwY4qTfSl5cGOKk30peXBjipN9\r\n    KXlwY4qTfSl5cGOKk30peXBjipN9KXlwY4qTfSl5cGOKk30peXBjipN9KXlwY4qTfSl5cGOKk30peXBjipN9KXlwY4qTfSl5cGOKk30peXBjipN9KXlwY4qTfSl5cGOKk30peXBjipN\r\n    9KXlwY4qTfSl5cGOKk30peXBjilNn+Xy+njU1NQOwDfv9/i/X1dW1V1VVDUr/uuBS8uDGlKNdCKoXGAhGgji4EfyD3+f7IBjwi5ZonQwF/BJh7sf+cQg3/c7CScmDG1OORiGQEvSu4R\r\n    QKmA9/J7b7sf2YgpsQr5VfmjpGLm8/VT547dDEhFitwO/+jNdsQIh90ocpmJQ8uDHlaFF9fX0fhFADFiGQ1djuwvY18El9vV9ScEtnjRR3XnKieOym48V/bC0TH+3tLV+6bWAiHPQl8\r\n    TrqjTtra2uPTx+yYFLy4MaUYhYavRfCG4ntxWA3eBn8Dnxaj1Ci4TqxYGpFYvtVw8SL6wfKN7aVyg/3lMhPHuktDzzSO0nbC9tGCRwjCSjEp9GDR6UPXzApeXBjSrEpHA73RmNXobGv\r\n    x/af0fhvYPt7cBBICmTmxCqx4+phif2b+4u37+8nP9xbQqHJPz/aO8l5c3s/EYvUZkKk3vgKenBL+qMKJiUPbkzxqtCgdIqkbU8E1heNGwPbwG+w71P8LhVYNqGAT77+9VKRHVg2FOr\r\n    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\r\n    gpae6E4FPbBU7Oie+iuKEOk+Id3QPRmMKGJOAUuy6k4UR4hgdiAQKOo78giwF5iXVXfCkyF+LasSLsQCSMmDG1O6IxeiUnfCkyF+NasSLsQCSMmDG1O6IxeiUnfChegVuRCLQC7EIpA\r\n    LsQjkQiwCFVWIqIgLUcWTId6RVQkXYgGk5MGNKd2RC1GpO+FC9IpciEWgYgtxY1YlXIgFkJIHN6Z0Ry5Epe6EC9ErciEWgVyIRaBiC/H2rEq4EAsgJQ9uTOmOXIhK3YniCTEUCvWaM2\r\n    dOj2KFvqRFE6LP57stqxL03Ok6bKeDaUUM/dHe7C+wZ/+59wpNRegP2n6In4sWqh9Q/iwaoKffp6eb5rCk5MGNKd0RQqQ/BJv3j9geDaAdXgdD001zWFLy4MaU7giFp2vDFwD9Pxcm/\r\n    0FJ0YF6f4rLyvPY+ugPNBVCSh7cmOJkX0oe3JjiZF9KHtyY4mRfSh7cmOJkX0oe3JjiZF9KHtyY4mRfSh7cmOJkX0oe3JjiZF9KHtyY4mRfSh7cmOJkX0oe3JjiZF9KHtyY4mRfSh7c\r\n    mOJkX0oe3JjiZF9KHtyY4mRfSh7cmOJkX0oe3JjiZF9KHtyY4mRfSh7cmOJkX0oe3JjiZF9KHtyY4mRfSh7cmOJkX0oe3JjiZF9KHtyY4mRfSh7cmOJkX0oe3JjiZF9KHtyY4mRfSh7\r\n    cmOJkX0oe3JjiZF9KHtyY4mRfSh7cmOJkX0oe3JjiZF9KHtyY4mRfSh7cmOJkX0oe3JjiZF9KHtyY4mRfSh7cOLyJdqfDW2h3OryFdqfDW2h3OryFdqfDW2h3OryFdqfDW2h3OryFdq\r\n    fDW2h3OryFdqfDSyR7/D/88mPYQlLgrwAAAABJRU5ErkJggg==\r\n'@\r\n\r\n\r\n$iconImg = @'\r\nAAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAMMOAADDDgAAAAAAAAAAAAAtLS0ZLS0tyS0tLbQtLS2gLS0toS0tLaEtLS2hLS0toS0tLaEtLS2hLS0toS0\r\ntLaEtLS2hLS0toC0tLbItLS3qLS0tIS0tLcgtLS0yLCwsAi0tLQUtLS0FLS0tBS0tLQUtLS0FLS0tBS0tLQUtLS0FLS0tBSwsLAItLS0xLS0t6C0tLSEtLS3ILS0tLi0tLQAAAAAAAAAAAA\r\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtLS0ALS0tLS0tLegtLS0hLS0tyC0tLS4tLS0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS0tAC0tLS0tLS3oLS0tI\r\nS0tLcgtLS0uLS0tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0tLQAtLS0tLS0t6C0tLSEtLS3JLiopNzQVBggxIRoLLS0sCyMmKwsYHyoLGyEqCykrLAsuKigLMh0T\r\nCzMbEAswIhsILS0tNi0tLektLSwgLS4u1yk5QdAoPUfCKjc9wy0sK8M2My7DQDkvwz03L8MuLi3DKy8ywyg8RsMoPEbDKzM3wi0sK84tLS36LSwsIC0tLtwfWHT/C5LS/w2Myf8iS1//RDw\r\nw/5NtNf+oeTb/b1cy/zA1Nv8XbZX/CZfa/xGAtP8oPEb/LSws/y0tLSEtLCvcLC8w/xpni/QLk9TzEn6w9ig8RfdRRC/3mnE1951zNfdbSjH3KTlA9xR5qPYLktL2GWuS9ysyNfAuKylRKD\r\ntD7yVFVPssMTTEKjY7eydBTk0pNz4/KSosQD04L0JHPjBCQzwwQi8rKUIrMzdCJ0JOQiZDUUMrMzY4LSsrzic+Sf8MkdD/EIO5/ic/S+wuKyq5LS0tbR8kLCYKFCgDERsqAAAAAAAAAAAAA\r\nAAAAAAAAAAAAAAAAAAAAC0tLFgsLzCkGWiN4wqW2P0aZor/MC4s/2RQMv5dSzHmOjUuqSwsLVovKCUbOwMAAjYRBQAAAAAAAAAAAAAAAAAvJyMAMCQeBC4pJyYkSVpqIk1htystL+1sVDL/\r\nuYM2/4ZlNP8xLy37KTg+2Co2PJEvJiJCLiglDk0AAAAsLCwAAAAAAAAAAACEAAAAB0lIADUgHwkqKyw0PzkvfnhcM8iPajX1Qzot/yBRaP8QhLv/HV188ysyNcMtLCtALS0tAAAAAAAAAAA\r\nAAAAAAAAAAAAAAAAAAAEhAAAAAAAVHSwQQDowRDYxLJAoO0TUDorF+Aee5v8jTGD+LikmYS0tLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0tLQAsLS4CLiooHiVFVGMZaI\r\ny9IFNq5C4pJjQtLS0AAAAAAAAAAAAf/AAAH/wAAB/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/AAAADwAAgAMAAPABAAD8AQAA/4EAAA==\r\n'@\r\n\r\n$settingsImg = @'\r\niVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+w\r\nAAALtSURBVEhLtVVPSBRRGJ/V3ZnR3XVllS1rzf4RIWWWVFJ06FZ46Bh08ZS3oGMk1bW6RIHXwpz3ZmZ3dS3QEgLzVJQdoqAo8iIlRaQEIevO+17fPF+5jU93gvrBjx3e9/t+385733xPWw\r\n/lIb2HUd1ixHy14Han5bIAjJ8wGDVfMFsfgpHNJ+VyeECh6TgjsSlOIpwTTZDRukE+3ReTEs1z4qO/Yj6B6pMlq75ThqsDbH0X0NqlSpNlo9hbZsXGGI1+CMZEPJ/pkBbhwJzkrMpoTTpxL\r\nlPDAcYPZRmp/aE0W5MRXnKze6XFapSKbZ18ukvsN4zvNDyiP1IbrU88x0mea9sofN6dMxaLbVv9ZwHsoCnc7xlmRR/g75zKICzRa55R4wnQ6BwWvScKlGmyp7KL/jXBSRzFtzAsVTBIZpu3\r\nIN9yDGyzFfIbDjOn4TqQyKoODJKRuqsas+ufqYKV9OxUn3jtADy3+XS1QtjWgxpMdMSZnRxQCXwyYoxKTyXKxHBVeZzW8LLddErKlsFI9KVKDG7qrJQowXOZPlUejpwBKVkBnk1BJfbcpjN\r\nSooSX392rygOqnZeSFWBl5ajgtn5BSpTwiHlZlYdD9envWccnexs9J/nHsKskHuwsFHe0CnEAy5M4+l6V5xNjFp55Bs/CrNpd2L7PFwtbtktvARg+0IIf3mOVvpLMTb/xt+m2Khgks2q+YX\r\nNQRiI3gNTeBVLzRaUL0rPMK9qSk+z+r198ftMR8er+HQFOfAbwYgJqfFaJwxLsOumjf8JvbEgU8MGLqa0f73fV+88LD9vTuC0jKoNqxIF4k+faE77PfHFfIww3t/jPSoCbTeM0/q4yWovYB\r\nF95ThMFQuNvb0ZWyLyWqeEAww0HmRUprTKi5phnm/3gmBPBGN4fSziCtkmL6ig52T3MSTiVXefZDf0yLIBD9VplEUb0O4t2auUmDAueS3XhP7/EaGICD1SXywL+yPDnHd4vF0s0tV8uK6Bp\r\nPwEAHUcTE+ClVQAAAABJRU5ErkJggg==\r\n'@\r\n\r\n# Image logo function\r\nfunction DecodeBase64Image {\r\n    param ([Parameter(Mandatory=$true)][String]$ImageBase64)\r\n    $ObjBitmapImage = New-Object System.Windows.Media.Imaging.BitmapImage #Provides a specialized BitmapSource that is optimized for loading images using Extensible Application Markup Language (XAML).\r\n    $ObjBitmapImage.BeginInit() #Signals the start of the BitmapImage initialization.\r\n    $ObjBitmapImage.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($ImageBase64) #Creates a stream whose backing store is memory.\r\n    $ObjBitmapImage.EndInit() #Signals the end of the BitmapImage initialization.\r\n    $ObjBitmapImage.Freeze() #Makes the current object unmodifiable and sets its IsFrozen property to true.\r\n    $ObjBitmapImage\r\n}\r\n\r\n$plexImgDecoded = DecodeBase64Image -ImageBase64 $plexImg\r\n$loadingImgDecoded = DecodeBase64Image -ImageBase64 $loadingImg\r\n$settingsImgDecoded = DecodeBase64Image -ImageBase64 $settingsImg\r\n$loading = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($loadingImgDecoded.StreamSource)\r\n$logo = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($plexImgDecoded.StreamSource)\r\n$gear = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($settingsImgDecoded.StreamSource)\r\n\r\n\r\n# Icon\r\n$iconBase64      = $iconImg\r\n$iconBytes       = [Convert]::FromBase64String($IconBase64)\r\n$stream          = New-Object IO.MemoryStream($iconBytes, 0, $iconBytes.Length)\r\n$stream.Write($iconBytes, 0, $iconBytes.Length);\r\n\r\n#################### FORMS ##############################\r\n\r\n#Defaults\r\n$label_mediaTitle_default_xy       = New-Object System.Drawing.Point(140,255)\r\n$label_mediaRating_default_xy      = New-Object System.Drawing.Point(140,275)\r\n$label_mediaScore_default_xy       = New-Object System.Drawing.Point(215,275)\r\n$label_mediaSummary_default_xy     = New-Object System.Drawing.Point(140,295)\r\n$label_mediaSummary_default_height = 110\r\n\r\n# main form\r\n$form                            = New-Object system.Windows.Forms.Form\r\n$form.ClientSize                 = '550,500'\r\n$form.text                       = \"Saverr\"\r\n$form.BackColor                  = \"#4a4a4a\"\r\n$form.TopMost                    = $false\r\n$form.StartPosition              = 'CenterScreen'\r\n$form.Icon                       = [System.Drawing.Icon]::FromHandle((New-Object System.Drawing.Bitmap -Argument $stream).GetHIcon())\r\n$form.FormBorderStyle            = \"FixedDialog\"\r\n$form.MaximizeBox                = $false\r\n\r\n$label_title                     = New-Object system.Windows.Forms.Label\r\n$label_title.text                = \"Saverr\"\r\n$label_title.AutoSize            = $true\r\n$label_title.width               = 30\r\n$label_title.height              = 20\r\n$label_title.location            = New-Object System.Drawing.Point(143,12)\r\n$label_title.Font                = 'Microsoft Sans Serif,15,style=Bold'\r\n$label_title.ForeColor           = \"#f5a623\"\r\n\r\n$pictureBox_logo                 = New-Object system.Windows.Forms.PictureBox\r\n$pictureBox_logo.width           = 75\r\n$pictureBox_logo.height          = 75\r\n$pictureBox_logo.location        = New-Object System.Drawing.Point(15,15)\r\n$pictureBox_logo.image           = $logo\r\n$pictureBox_logo.SizeMode        = [System.Windows.Forms.PictureBoxSizeMode]::normal\r\n\r\n$pictureBox_thumb                = new-object Windows.Forms.PictureBox\r\n$pictureBox_thumb.ImageLocation  = \"\"\r\n$pictureBox_thumb.Visible        = $false\r\n$pictureBox_thumb.Width          = 113 #680\r\n$pictureBox_thumb.Height         = 166 #1000\r\n$pictureBox_thumb.Anchor         = [System.Windows.Forms.AnchorStyles]::Top\r\n$pictureBox_thumb.Location       = New-object System.Drawing.Size(15,250)\r\n$pictureBox_thumb.image          = $loading\r\n$pictureBox_thumb.SizeMode       = [System.Windows.Forms.PictureBoxSizeMode]::Zoom\r\n\r\n$label_search                    = New-Object system.Windows.Forms.Label\r\n$label_search.text               = \"Search Movie:\"\r\n$label_search.AutoSize           = $true\r\n$label_search.width              = 30\r\n$label_search.height             = 15\r\n$label_search.location           = New-Object System.Drawing.Point(15,105)\r\n$label_search.Font               = 'Microsoft Sans Serif,8'\r\n$label_search.ForeColor          = \"#f5a623\"\r\n\r\n$textBox_search                  = New-Object system.Windows.Forms.TextBox\r\n$textBox_search.multiline        = $false\r\n$textBox_search.text             = \"\"\r\n$textBox_search.width            = 300\r\n$textBox_search.height           = 20\r\n$textBox_search.location         = New-Object System.Drawing.Point(15,125)\r\n$textBox_search.Font             = 'Microsoft Sans Serif,10'\r\n\r\n$button_search                   = New-Object system.Windows.Forms.Button\r\n$button_search.BackColor         = \"#f5a623\"\r\n$button_search.text              = \"Search\"\r\n$button_search.width             = 80\r\n$button_search.height            = 25\r\n$button_search.location          = New-Object System.Drawing.Point(345,124)\r\n$button_search.Font              = 'Microsoft Sans Serif,9,style=Bold'\r\n$button_search.FlatStyle         = \"Flat\"\r\n\r\n$button_download                 = New-Object system.Windows.Forms.Button\r\n$button_download.Enabled         = $false\r\n$button_download.BackColor       = \"#f5a623\"\r\n$button_download.text            = \"Download\"\r\n$button_download.width           = 80\r\n$button_download.height          = 25\r\n$button_download.location        = New-Object System.Drawing.Point(345,174)\r\n$button_download.Font            = 'Microsoft Sans Serif,9,style=Bold'\r\n$button_download.FlatStyle       = \"Flat\"\r\n\r\n$button_settings                 = New-Object system.Windows.Forms.Button\r\n$button_settings.width           = 30\r\n$button_settings.height          = 30\r\n$button_settings.location        = New-Object System.Drawing.Point(508,8)\r\n$button_settings.image           = $gear\r\n$button_settings.FlatStyle       = \"Flat\"\r\n$button_settings.BackColor       = \"Transparent\"\r\n$button_settings.FlatAppearance.BorderSize = 0\r\n$button_settings.FlatAppearance.MouseDownBackColor = \"Transparent\"\r\n$button_settings.FlatAppearance.MouseOverBackColor = \"#666666\"\r\n\r\n$groupBox_type                   = New-Object system.Windows.Forms.Groupbox\r\n$groupBox_type.height            = 40\r\n$groupBox_type.width             = 285\r\n$groupBox_type.text              = \"Select Media Type\"\r\n$groupBox_type.location          = New-Object System.Drawing.Point(140,46)\r\n\r\n$RadioButton_movie               = New-Object system.Windows.Forms.RadioButton\r\n$RadioButton_movie.text          = \"Movies\"\r\n$RadioButton_movie.AutoSize      = $true\r\n$RadioButton_movie.Checked       = $true\r\n$RadioButton_movie.width         = 80\r\n$RadioButton_movie.height        = 20\r\n$RadioButton_movie.location      = New-Object System.Drawing.Point(15,16)\r\n$RadioButton_movie.Font          = 'Microsoft Sans Serif,9'\r\n$RadioButton_movie.ForeColor     = \"#ffffff\"\r\n\r\n$RadioButton_tv                  = New-Object system.Windows.Forms.RadioButton\r\n$RadioButton_tv.text             = \"TV Shows\"\r\n$RadioButton_tv.AutoSize         = $true\r\n$RadioButton_tv.width            = 80\r\n$RadioButton_tv.height           = 20\r\n$RadioButton_tv.location         = New-Object System.Drawing.Point(110,16)\r\n$RadioButton_tv.Font             = 'Microsoft Sans Serif,9'\r\n$RadioButton_tv.ForeColor        = \"#ffffff\"\r\n\r\n$RadioButton_music               = New-Object system.Windows.Forms.RadioButton\r\n$RadioButton_music.text          = \"Artists\"\r\n$RadioButton_music.AutoSize      = $true\r\n$RadioButton_music.width         = 80\r\n$RadioButton_music.height        = 20\r\n$RadioButton_music.location      = New-Object System.Drawing.Point(215,16)\r\n$RadioButton_music.Font          = 'Microsoft Sans Serif,9'\r\n$RadioButton_music.ForeColor     = \"#ffffff\"\r\n\r\n$label_results                   = New-Object system.Windows.Forms.Label\r\n$label_results.text              = \"Results:\"\r\n$label_results.AutoSize          = $true\r\n$label_results.width             = 30\r\n$label_results.height            = 15\r\n$label_results.location          = New-Object System.Drawing.Point(15,155)\r\n$label_results.Font              = 'Microsoft Sans Serif,8'\r\n$label_results.ForeColor         = \"#f5a623\"\r\n\r\n$comboBox_results                = New-Object system.Windows.Forms.ComboBox\r\n$comboBox_results.text           = \"\"\r\n$comboBox_results.width          = 300\r\n$comboBox_results.height         = 20\r\n$comboBox_results.location       = New-Object System.Drawing.Point(15,175)\r\n$comboBox_results.Font           = 'Microsoft Sans Serif,10'\r\n\r\n$label_seasons                   = New-Object system.Windows.Forms.Label\r\n$label_seasons.text              = \"\"\r\n$label_seasons.AutoSize          = $true\r\n$label_seasons.width             = 30\r\n$label_seasons.height            = 15\r\n$label_seasons.location          = New-Object System.Drawing.Point(15,225)\r\n$label_seasons.Font              = 'Microsoft Sans Serif,8'\r\n$label_seasons.ForeColor         = \"#f5a623\"\r\n\r\n$comboBox_seasons                = New-Object system.Windows.Forms.ComboBox\r\n$comboBox_seasons.Visible        = $false\r\n$comboBox_seasons.text           = \"\"\r\n$comboBox_seasons.width          = 130\r\n$comboBox_seasons.height         = 20\r\n$comboBox_seasons.location       = New-Object System.Drawing.Point(65,215)\r\n$comboBox_seasons.Font           = 'Microsoft Sans Serif,10'\r\n\r\n$label_episodes                  = New-Object system.Windows.Forms.Label\r\n$label_episodes.text             = \"\"\r\n$label_episodes.AutoSize         = $true\r\n$label_episodes.width            = 30\r\n$label_episodes.height           = 15\r\n$label_episodes.location         = New-Object System.Drawing.Point(215,225)\r\n$label_episodes.Font             = 'Microsoft Sans Serif,8'\r\n$label_episodes.ForeColor        = \"#f5a623\"\r\n\r\n$comboBox_episodes               = New-Object system.Windows.Forms.ComboBox\r\n$comboBox_episodes.Visible       = $false\r\n$comboBox_episodes.text          = \"\"\r\n$comboBox_episodes.width         = 45\r\n$comboBox_episodes.height        = 20\r\n$comboBox_episodes.location      = New-Object System.Drawing.Point(265,215)\r\n$comboBox_episodes.Font          = 'Microsoft Sans Serif,10'\r\n\r\n$label_mediaTitle                = New-Object system.Windows.Forms.Label\r\n$label_mediaTitle.text           = \"\"\r\n$label_mediaTitle.AutoSize       = $false\r\n$label_mediaTitle.AutoEllipsis   = $true\r\n$label_mediaTitle.width          = 400\r\n$label_mediaTitle.height         = 20\r\n$label_mediaTitle.location       = $label_mediaTitle_default_xy\r\n$label_mediaTitle.Font           = 'Microsoft Sans Serif,10,style=Bold'\r\n$label_mediaTitle.ForeColor      = \"#f5a623\"\r\n\r\n$label_mediaRating               = New-Object system.Windows.Forms.Label\r\n$label_mediaRating.text          = \"\"\r\n$label_mediaRating.AutoSize      = $true\r\n$label_mediaRating.width         = 50\r\n$label_mediaRating.height        = 20\r\n$label_mediaRating.location      = $label_mediaRating_default_xy\r\n$label_mediaRating.Font          = 'Microsoft Sans Serif,9,style=Bold'\r\n$label_mediaRating.ForeColor     = \"#ffffff\"\r\n\r\n$label_mediaScore                = New-Object system.Windows.Forms.Label\r\n$label_mediaScore.text           = \"\"\r\n$label_mediaScore.AutoSize       = $true\r\n$label_mediaScore.width          = 50\r\n$label_mediaScore.height         = 20\r\n$label_mediaScore.location       = $label_mediaScore_default_xy\r\n$label_mediaScore.Font           = 'Microsoft Sans Serif,9,style=Bold'\r\n$label_mediaScore.ForeColor      = \"#ffffff\"\r\n\r\n$label_mediaSummary              = New-Object system.Windows.Forms.Label\r\n$label_mediaSummary.text         = $errorMsg\r\n$label_mediaSummary.AutoSize     = $false\r\n$label_mediaSummary.AutoEllipsis = $true\r\n$label_mediaSummary.width        = 400\r\n$label_mediaSummary.height       = $label_mediaSummary_default_height\r\n$label_mediaSummary.location     = $label_mediaSummary_default_xy\r\n$label_mediaSummary.Font         = 'Microsoft Sans Serif,9'\r\n$label_mediaSummary.ForeColor    = \"#ffffff\"\r\n\r\n$label_DLTitle                   = New-Object system.Windows.Forms.Label\r\n$label_DLTitle.text              = \"\"\r\n$label_DLTitle.AutoSize          = $false\r\n$label_DLTitle.AutoEllipsis      = $true\r\n$label_DLTitle.width             = 440\r\n$label_DLTitle.height            = 20\r\n$label_DLTitle.location          = New-Object System.Drawing.Point(15,430)\r\n$label_DLTitle.Font              = 'Microsoft Sans Serif,9'\r\n$label_DLTitle.ForeColor         = \"#f5a623\"\r\n\r\n$label_DLProgress                = New-Object system.Windows.Forms.Label\r\n$label_DLProgress.text           = \"\"\r\n$label_DLProgress.AutoSize       = $false\r\n$label_DLProgress.AutoEllipsis   = $true\r\n$label_DLProgress.width          = 410\r\n$label_DLProgress.height         = 20\r\n$label_DLProgress.location       = New-Object System.Drawing.Point(15,455)\r\n$label_DLProgress.Font           = 'Microsoft Sans Serif,9'\r\n$label_DLProgress.ForeColor      = \"#f5a623\"\r\n\r\n$button_cancel                   = New-Object system.Windows.Forms.Button\r\n$button_cancel.Visible           = $false\r\n$button_cancel.BackColor         = \"#f5a623\"\r\n$button_cancel.text              = \"Cancel\"\r\n$button_cancel.width             = 80\r\n$button_cancel.height            = 25\r\n$button_cancel.location          = New-Object System.Drawing.Point(456,470)\r\n$button_cancel.Font              = 'Microsoft Sans Serif,9,style=Bold'\r\n$button_cancel.FlatStyle         = \"Flat\"\r\n\r\n$checkBoxButton_pause            = New-Object System.Windows.Forms.Checkbox \r\n$checkBoxButton_pause.location   = New-Object System.Drawing.Point(456,440)\r\n$checkBoxButton_pause.Size       = New-Object System.Drawing.Size(80,25)\r\n$checkBoxButton_pause.Appearance = [System.Windows.Forms.Appearance]::Button\r\n$checkBoxButton_pause.Visible    = $false\r\n$checkBoxButton_pause.Text       = \"Pause\"\r\n$checkBoxButton_pause.FlatStyle  = \"Flat\"\r\n$checkBoxButton_pause.BackColor  = \"#f5a623\"\r\n$checkBoxButton_pause.width      = 80\r\n$checkBoxButton_pause.height     = 25\r\n$checkBoxButton_pause.TextAlign  = \"MiddleCenter\"\r\n$checkBoxButton_pause.AllowDrop = $false\r\n$checkBoxButton_pause.Font              = 'Microsoft Sans Serif,9,style=Bold'\r\n$checkBoxButton_pause.FlatAppearance.BorderColor = \"#000000\"\r\n\r\n$progressBar                     = New-Object system.Windows.Forms.ProgressBar\r\n$progressBar.Name                = 'progressBar1'\r\n$progressBar.BackColor           = \"#f5a623\"\r\n$progressBar.ForeColor           = \"#f5a623\"\r\n$progressBar.width               = 430\r\n$progressBar.height              = 12\r\n$progressBar.location            = New-Object System.Drawing.Point(15,480)\r\n$progressBar.Value               = 0\r\n$progressBar.Style               = \"Continuous\" #\"Blocks\"\r\n$progressBar.Visible             = $false\r\n$progressBar.Minimum             = 0\r\n$progressBar.Maximum             = 110\r\n\r\n# add tooltips\r\n$toolTip                         = New-Object System.Windows.Forms.ToolTip\r\n$toolTip.SetToolTip($label_search, \"Searches by first Letter. Excluding 'The' and 'A'\")\r\n\r\n$form.controls.AddRange(@($groupbox_type,$label_title,$pictureBox_logo,$pictureBox_thumb,$label_search,$textBox_search,$progressBar,$button_search,$button_download,$button_settings,$label_mediaTitle,$label_mediaScore,$comboBox_results,$comboBox_seasons,$comboBox_episodes,$label_mediaRating,$label_mediaSummary,$label_results,$label_seasons,$label_episodes,$label_DLTitle,$label_DLProgress,$button_cancel,$checkBoxButton_pause))\r\n$groupBox_type.controls.AddRange(@($RadioButton_movie,$RadioButton_tv,$RadioButton_music))\r\n\r\n\r\n# settings form\r\n$form2                           = New-Object system.Windows.Forms.Form\r\n$form2.ClientSize                = '550,500'\r\n$form2.text                      = \"Saverr Settings\"\r\n$form2.BackColor                 = \"#4a4a4a\"\r\n$form2.TopMost                   = $false\r\n$form2.StartPosition             = 'CenterScreen'\r\n$form2.Icon                      = [System.Drawing.Icon]::FromHandle((New-Object System.Drawing.Bitmap -Argument $stream).GetHIcon())\r\n$form2.FormBorderStyle           = \"FixedDialog\"\r\n$form2.MaximizeBox               = $false\r\n$form2.StartPosition             = \"CenterParent\"\r\n\r\n$label2_title                    = New-Object system.Windows.Forms.Label\r\n$label2_title.text               = \"Settings\"\r\n$label2_title.AutoSize           = $true\r\n$label2_title.width              = 30\r\n$label2_title.height             = 20\r\n$label2_title.location           = New-Object System.Drawing.Point(143,12)\r\n$label2_title.Font               = 'Microsoft Sans Serif,15,style=Bold'\r\n$label2_title.ForeColor          = \"#f5a623\"\r\n\r\n$label2_notice                   = New-Object system.Windows.Forms.Label\r\n$label2_notice.text              = \"Username/password is not saved.`nOnly used to retrieve Plex token\"\r\n$label2_notice.AutoSize          = $true\r\n$label2_notice.width             = 70\r\n$label2_notice.height            = 20\r\n$label2_notice.location          = New-Object System.Drawing.Point(143,50)\r\n$label2_notice.Font              = 'Microsoft Sans Serif,8'\r\n$label2_notice.ForeColor         = \"#ffffff\"\r\n\r\n$pictureBox2_logo                = New-Object system.Windows.Forms.PictureBox\r\n$pictureBox2_logo.width          = 75\r\n$pictureBox2_logo.height         = 75\r\n$pictureBox2_logo.location       = New-Object System.Drawing.Point(15,15)\r\n$pictureBox2_logo.image          = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($plexImgDecoded.StreamSource)\r\n$pictureBox2_logo.SizeMode       = [System.Windows.Forms.PictureBoxSizeMode]::normal\r\n\r\n$label2_username                 = New-Object system.Windows.Forms.Label\r\n$label2_username.text            = \"Plex Username:\"\r\n$label2_username.AutoSize        = $true\r\n$label2_username.width           = 30\r\n$label2_username.height          = 20\r\n$label2_username.location        = New-Object System.Drawing.Point(15,121)\r\n$label2_username.Font            = 'Microsoft Sans Serif,8'\r\n$label2_username.ForeColor       = \"#ffffff\"\r\n\r\n$textBox2_username               = New-Object system.Windows.Forms.TextBox\r\n$textBox2_username.multiline     = $false\r\n$textBox2_username.width         = 225\r\n$textBox2_username.height        = 20\r\n$textBox2_username.location      = New-Object System.Drawing.Point(110,110)\r\n$textBox2_username.Font          = 'Microsoft Sans Serif,10'\r\n\r\n$label2_password                 = New-Object system.Windows.Forms.Label\r\n$label2_password.text            = \"Plex Password:\"\r\n$label2_password.AutoSize        = $true\r\n$label2_password.width           = 70\r\n$label2_password.height          = 20\r\n$label2_password.location        = New-Object System.Drawing.Point(15,166)\r\n$label2_password.Font            = 'Microsoft Sans Serif,8'\r\n$label2_password.ForeColor       = \"#ffffff\"\r\n\r\n$textBox2_password               = New-Object system.Windows.Forms.TextBox\r\n$textBox2_password.PasswordChar  = '*'\r\n$textBox2_password.multiline     = $false\r\n$textBox2_password.width         = 225\r\n$textBox2_password.height        = 20\r\n$textBox2_password.location      = New-Object System.Drawing.Point(110,155)\r\n$textBox2_password.Font          = 'Microsoft Sans Serif,10'\r\n\r\n$button2_getToken                = New-Object system.Windows.Forms.Button\r\n$button2_getToken.BackColor      = \"#f5a623\"\r\n$button2_getToken.text           = \"Get Token\"\r\n$button2_getToken.width          = 95\r\n$button2_getToken.height         = 25\r\n$button2_getToken.location       = New-Object System.Drawing.Point(350,154)\r\n$button2_getToken.Font           = 'Microsoft Sans Serif,9,style=Bold'\r\n$button2_getToken.FlatStyle      = \"Flat\"\r\n\r\n$label2_tokenStatus              = New-Object system.Windows.Forms.Label\r\n$label2_tokenStatus.text         = \"\"\r\n$label2_tokenStatus.AutoSize     = $true\r\n$label2_tokenStatus.width        = 70\r\n$label2_tokenStatus.height       = 20\r\n$label2_tokenStatus.location     = New-Object System.Drawing.Point(350,180)\r\n$label2_tokenStatus.Font         = 'Microsoft Sans Serif,8'\r\n$label2_tokenStatus.ForeColor    = \"#ffff00\"\r\n\r\n$label2_server                   = New-Object system.Windows.Forms.Label\r\n$label2_server.text              = \"Select Server:\"\r\n$label2_server.AutoSize          = $true\r\n$label2_server.width             = 70\r\n$label2_server.height            = 20\r\n$label2_server.location          = New-Object System.Drawing.Point(15,211)\r\n$label2_server.Font              = 'Microsoft Sans Serif,8'\r\n$label2_server.ForeColor         = \"#ffffff\"\r\n\r\n$comboBox2_servers               = New-Object system.Windows.Forms.ComboBox\r\n$comboBox2_servers.text          = $settings.name\r\n$comboBox2_servers.width         = 225\r\n$comboBox2_servers.height        = 20\r\n$comboBox2_servers.location      = New-Object System.Drawing.Point(110,200)\r\n$comboBox2_servers.Font          = 'Microsoft Sans Serif,10'\r\n\r\n$label2_dlPath                   = New-Object system.Windows.Forms.Label\r\n$label2_dlPath.text              = \"Download Path:\"\r\n$label2_dlPath.AutoSize          = $true\r\n$label2_dlPath.width             = 70\r\n$label2_dlPath.height            = 20\r\n$label2_dlPath.location          = New-Object System.Drawing.Point(15,256)\r\n$label2_dlPath.Font              = 'Microsoft Sans Serif,8'\r\n$label2_dlPath.ForeColor         = \"#ffffff\"\r\n\r\n$textBox2_dlPath                 = New-Object system.Windows.Forms.TextBox\r\n$textBox2_dlPath.text            = $settings.dlPath\r\n$textBox2_dlPath.ReadOnly        = $true\r\n$textBox2_dlPath.multiline       = $false\r\n$textBox2_dlPath.width           = 225\r\n$textBox2_dlPath.height          = 20\r\n$textBox2_dlPath.location        = New-Object System.Drawing.Point(110,245)\r\n$textBox2_dlPath.Font            = 'Microsoft Sans Serif,10'\r\n$textBox2_dlPath.Enabled         = $false\r\n\r\n$button2_dlPath                  = New-Object system.Windows.Forms.Button\r\n$button2_dlPath.BackColor        = \"#f5a623\"\r\n$button2_dlPath.text             = \"Select Path\"\r\n$button2_dlPath.width            = 95\r\n$button2_dlPath.height           = 25\r\n$button2_dlPath.location         = New-Object System.Drawing.Point(350,244)\r\n$button2_dlPath.Font             = 'Microsoft Sans Serif,9,style=Bold'\r\n$button2_dlPath.FlatStyle        = \"Flat\"\r\n\r\n$label2_pathStatus               = New-Object system.Windows.Forms.Label\r\n$label2_pathStatus.text          = \"\"\r\n$label2_pathStatus.AutoSize      = $true\r\n$label2_pathStatus.width         = 70\r\n$label2_pathStatus.height        = 20\r\n$label2_pathStatus.location      = New-Object System.Drawing.Point(350,270)\r\n$label2_pathStatus.Font          = 'Microsoft Sans Serif,8'\r\n$label2_pathStatus.ForeColor     = \"#ffff00\"\r\n\r\n$label2_ssl                      = New-Object system.Windows.Forms.Label\r\n$label2_ssl.text                 = \"SSL Required:\"\r\n$label2_ssl.AutoSize             = $true\r\n$label2_ssl.width                = 70\r\n$label2_ssl.height               = 20\r\n$label2_ssl.location             = New-Object System.Drawing.Point(15,290)\r\n$label2_ssl.Font                 = 'Microsoft Sans Serif,8'\r\n$label2_ssl.ForeColor            = \"#ffffff\"\r\n\r\n$checkBox_ssl                    = New-Object System.Windows.Forms.Checkbox \r\n$checkBox_ssl.location           = New-Object System.Drawing.Point(110,285)\r\n$checkBox_ssl.Size               = New-Object System.Drawing.Size(80,25)\r\n$checkBox_ssl.width              = 80\r\n$checkBox_ssl.height             = 25\r\n$checkBox_ssl.checked            = $settings.ssl\r\n\r\n$label2_debug                    = New-Object system.Windows.Forms.Label\r\n$label2_debug.text               = \"Debug Logging:\"\r\n$label2_debug.AutoSize           = $true\r\n$label2_debug.width              = 70\r\n$label2_debug.height             = 20\r\n$label2_debug.location           = New-Object System.Drawing.Point(15,325)\r\n$label2_debug.Font               = 'Microsoft Sans Serif,8'\r\n$label2_debug.ForeColor          = \"#ffffff\"\r\n\r\n$checkBox_debug                  = New-Object System.Windows.Forms.Checkbox \r\n$checkBox_debug.location         = New-Object System.Drawing.Point(110,320)\r\n$checkBox_debug.Size             = New-Object System.Drawing.Size(80,25)\r\n$checkBox_debug.width            = 80\r\n$checkBox_debug.height           = 25\r\n$checkBox_debug.checked          = $settings.logging\r\n\r\n$label2_ssl_info                 = New-Object system.Windows.Forms.Label\r\n$label2_ssl_info.text            = \"[Restart Saverr after changing SSL or Debug options]\"\r\n$label2_ssl_info.AutoSize        = $true\r\n$label2_ssl_info.width           = 70\r\n$label2_ssl_info.height          = 20\r\n$label2_ssl_info.location        = New-Object System.Drawing.Point(15,360)\r\n$label2_ssl_info.Font            = 'Microsoft Sans Serif,8'\r\n$label2_ssl_info.ForeColor       = \"#ffffff\"\r\n\r\n$button2_servers                 = New-Object system.Windows.Forms.Button\r\n$button2_servers.BackColor       = \"#f5a623\"\r\n$button2_servers.text            = \"List Servers\"\r\n$button2_servers.width           = 95\r\n$button2_servers.height          = 25\r\n$button2_servers.location        = New-Object System.Drawing.Point(350,199)\r\n$button2_servers.Font            = 'Microsoft Sans Serif,9,style=Bold'\r\n$button2_servers.FlatStyle       = \"Flat\"\r\n\r\n$label2_serverStatus             = New-Object system.Windows.Forms.Label\r\n$label2_serverStatus.text        = \"\"\r\n$label2_serverStatus.AutoSize    = $true\r\n$label2_serverStatus.width       = 70\r\n$label2_serverStatus.height      = 20\r\n$label2_serverStatus.location    = New-Object System.Drawing.Point(350,225)\r\n$label2_serverStatus.Font        = 'Microsoft Sans Serif,8'\r\n$label2_serverStatus.ForeColor   = \"#ffff00\"\r\n\r\n$label2_notice2                  = New-Object system.Windows.Forms.Label\r\n$label2_notice2.text             = \"\"\r\n$label2_notice2.AutoSize         = $true\r\n$label2_notice2.width            = 70\r\n$label2_notice2.height           = 20\r\n$label2_notice2.location         = New-Object System.Drawing.Point(15,395)\r\n$label2_notice2.Font             = 'Microsoft Sans Serif,8'\r\n$label2_notice2.ForeColor        = \"#ffffff\"\r\n\r\n$label2_saveStatus               = New-Object system.Windows.Forms.Label\r\n$label2_saveStatus.text          = \"\"\r\n$label2_saveStatus.AutoSize      = $true\r\n$label2_saveStatus.width         = 70\r\n$label2_saveStatus.height        = 20\r\n$label2_saveStatus.location      = New-Object System.Drawing.Point(110,275)\r\n$label2_saveStatus.Font          = 'Microsoft Sans Serif,8'\r\n$label2_saveStatus.ForeColor     = \"#00ff00\"\r\n\r\n$label2_help                     = New-Object system.Windows.Forms.LinkLabel\r\n$label2_help.text                = \"Help\"\r\n$label2_help.AutoSize            = $true\r\n$label2_help.width               = 70\r\n$label2_help.height              = 20\r\n$label2_help.location            = New-Object System.Drawing.Point(15,480)\r\n$label2_help.Font                = 'Microsoft Sans Serif,9'\r\n$label2_help.ForeColor           = \"#00ff00\"\r\n$label2_help.LinkColor           = \"#f5a623\"\r\n$label2_help.ActiveLinkColor     = \"#f5a623\"\r\n$label2_help.add_Click({[system.Diagnostics.Process]::start(\"https://github.com/ninthwalker/saverr\")})\r\n\r\n$label2_version                  = New-Object system.Windows.Forms.Label\r\n$label2_version.text             = \"Ver. 1.1.2\"\r\n$label2_version.AutoSize         = $true\r\n$label2_version.width            = 70\r\n$label2_version.height           = 20\r\n$label2_version.location         = New-Object System.Drawing.Point(480,480)\r\n$label2_version.Font             = 'Microsoft Sans Serif,9'\r\n$label2_version.ForeColor        = \"#f5a623\"\r\n\r\n$form2.controls.AddRange(@($label2_title,$label2_username,$label2_password,$label2_dlPath,$label2_server,$label2_pathStatus,$label2_serverStatus,$label2_notice,$label2_notice2,$label2_saveStatus,$label2_tokenStatus,$label2_help,$label2_version,$textBox2_username,$textBox2_password,$textBox2_dlPath,$label2_debug,$checkBox_debug,$label2_ssl,$checkBox_ssl,$label2_ssl_info,$comboBox2_servers,$button2_servers,$pictureBox2_logo,$button2_getToken,$button2_dlPath))\r\n\r\n\r\n############################## CODE ################################\r\n\r\n\r\n# search server for media. Movies/tv are by firstletter. Music is by artist.\r\nfunction search {\r\n\r\n    Try {\r\n\r\n        # clear old searches\r\n        clearMediaInfo\r\n        clearDLStatus\r\n        $comboBox_results.Text = \"Searching ...\"\r\n\r\n        # get sections\r\n        $sections = $scheme + $settings.server + \"/library/sections/\" + \"?X-Plex-Token=\" + $settings.serverToken\r\n        $xmlsearch = plx $sections\r\n\r\n        #$sectionType = $groupBox_type.Controls | ? { $_.Checked } | Select-Object Text\r\n\r\n            # GUI Selection of 'type' to search for. Remove spaces and leading 'the' and 'a' since plex removes those from search words\r\n            $searchName = ($textBox_search.Text).TrimStart().TrimEnd()\r\n            $searchName = $searchName -replace '^the |^a ', ''\r\n            $sectionType = $groupBox_type.Controls | ? { $_.Checked -eq $true} | Select-Object Text\r\n\r\n            Switch ($sectionType.Text)\r\n            {\r\n                'Movies'   {$script:type = \"movie\"\r\n                            $subSection = \"Video\"; Break\r\n                }\r\n                'TV Shows' {$script:type = \"show\"\r\n                            $subSection = \"Directory\"; Break\r\n                }\r\n                'Artists'  {$script:type = \"artist\"\r\n                            $subSection = \"Directory\"; Break\r\n                }\r\n            }\r\n            \r\n            # get 'type' of key\r\n            $sections2search = $xmlsearch.MediaContainer.Directory | ? {$_.type -eq $type} | select key\r\n            $firstChar = $searchName.ToUpper()[0]\r\n\r\n            # Search movies/tv\r\n            if ($type -ne \"artist\") {\r\n                $sectionsList = new-object collections.generic.list[object]\r\n\r\n                foreach ($section in $sections2search) {\r\n    \r\n                    $sectionsUrl = $scheme + $settings.server + \"/library/sections/$($section.key)/firstCharacter/$firstChar/\" + \"?X-Plex-Token=\" + $settings.serverToken\r\n                    $sectionsList.Add((plx $sectionsUrl))\r\n                }\r\n\r\n            # search through list for match\r\n            $script:searchResults = $sectionsList.MediaContainer.$subSection | ? {$_.title -like \"*$searchName*\" -and $_.type -eq $type} | select title,type,key,tagline,summary,year,contentrating,thumb,rating\r\n\r\n            }\r\n\r\n            #search artists\r\n            else {\r\n                $artistList = new-object collections.generic.list[object]\r\n\r\n                foreach ($section in $sections2search) {\r\n    \r\n                    $sectionsUrl = $scheme + $settings.server + \"/library/sections/$($section.key)/all\" + \"?X-Plex-Token=\" + $settings.serverToken\r\n                    $artistList.Add((plx $sectionsUrl))\r\n                     \r\n                }\r\n\r\n            $script:searchResults = $artistList.MediaContainer.$subSection | ? {$_.title -like \"*$searchName*\" -and $_.type -eq $type} | select title,type,key,thumb\r\n\r\n            # search through list for match\r\n            $trackList = new-object collections.generic.list[object]\r\n            $artistPath = $artistsList.MediaContainer.$subSection | select key\r\n                foreach ($artist in $artistPath) {\r\n                    $artistURL = $scheme + $settings.server + \"$($artist.key)\" + \"?X-Plex-Token=\" + $settings.serverToken\r\n                    $trackList.Add((plx $artistURl))\r\n            }\r\n\r\n\r\n            }\r\n\r\n            #show results\r\n            if ($searchresults) {\r\n                $comboBox_results.Text = \"$(@($searchResults).count) $($sectionType.Text) found!\"\r\n                $comboBox_results.Text = \"$(@($searchResults).count) $($sectionType.Text) found!\"\r\n                foreach ($item in $searchresults) {\r\n                    if ($type -ne \"artist\") {\r\n                        if ($item.year) {\r\n                            $comboBox_results.Items.Add($item.title + ' (' + $item.year + ')') \r\n                        }\r\n                        else {\r\n                            $comboBox_results.Items.Add($item.title)\r\n                        }\r\n                    }\r\n                    else {\r\n                        $comboBox_results.Items.Add($item.title)\r\n                    }\r\n                }\r\n            }\r\n            else {\r\n                $ComboBox_results.Text = \"No results found!\"\r\n            }\r\n    }\r\n\r\n    Catch {\r\n        logit\r\n        $comboBox_results.Items.Clear()\r\n        $ComboBox_results.Text = \"Error! Check settings/token/server status?\"\r\n    }\r\n}\r\n\r\nfunction mediaInfo {\r\n\r\n    clearDLStatus\r\n    $comboBox_index = $comboBox_results.SelectedIndex\r\n    $script:info = $searchResults[$comboBox_index] | Select title,type,key,tagline,summary,year,contentrating,thumb,rating,size\r\n    $thumb = $scheme + $settings.server + $info.thumb + \"?X-Plex-Token=\" + $settings.serverToken\r\n\r\n    # enable download button if no other downloads in progress\r\n    if (!(Get-BitsTransfer)) {\r\n        $button_download.Enabled = $true\r\n    }\r\n\r\n    if ($info.thumb) {\r\n        $pictureBox_thumb.ImageLocation = \"$thumb\"\r\n        $pictureBox_thumb.Visible = $true\r\n    }\r\n    else {\r\n        $pictureBox_thumb.ImageLocation = \"\"\r\n        $pictureBox_thumb.Image = $loading\r\n        $pictureBox_thumb.Visible = $true\r\n    }\r\n    if ($info.year) {\r\n        $label_mediaTitle.Text = \"$($info.title) ($($info.year))\"\r\n    }\r\n    else {\r\n        $label_mediaTitle.Text = \"$($info.title)\"\r\n    }\r\n    if ($info.contentrating) {\r\n        $label_mediaRating.Text = \"$($info.contentrating)\"\r\n    }\r\n    elseif ($type -ne \"artist\") {\r\n        $label_mediaRating.Text = \"No Rating\"\r\n    }\r\n    if ($info.rating) {\r\n        $label_mediaScore.Text = \"$($info.rating)\"\r\n    }\r\n    if ($info.summary) {\r\n        $label_mediaSummary.Text = \"$($info.summary)\"\r\n    }\r\n\r\n    # show season/ep boxes\r\n    if ($type -eq \"show\") {\r\n\r\n        #get seasons\r\n        $comboBox_seasons.Items.Clear()\r\n        $seasonPath = $scheme + $settings.server + \"$($info.key)\" + \"?X-Plex-Token=\" + $settings.serverToken\r\n        $xmlSeason = plx $seasonPath\r\n            $script:seasons = $xmlSeason.MediaContainer.directory | select title,key,index\r\n        foreach ($season in $seasons) {\r\n            $comboBox_seasons.Items.Add($season.title)\r\n        }\r\n        if (($comboBox_seasons.Items).count -ne \"1\" ) {\r\n            $comboBox_seasons.Text = $comboBox_seasons.items[1]\r\n        }\r\n        else {\r\n            $comboBox_seasons.Text = $comboBox_seasons.items[0]\r\n        }\r\n    }\r\n\r\n    if ($type -eq \"artist\") {\r\n\r\n        #get albums\r\n        $comboBox_seasons.Items.Clear()\r\n        $seasonPath = $scheme + $settings.server + \"$($info.key)\" + \"?X-Plex-Token=\" + $settings.serverToken\r\n        $xmlSeason = plx $seasonPath\r\n            $script:seasons = $xmlSeason.MediaContainer.directory | select title,key,index,year\r\n\r\n        foreach ($season in $seasons) {\r\n            $comboBox_seasons.Items.Add($season.title)\r\n        }\r\n\r\n        if (($comboBox_seasons.Items).count -ge 2) {\r\n            $comboBox_seasons.Items.Add(\"All Albums\")\r\n        }\r\n\r\n        $comboBox_seasons.Text = $comboBox_seasons.items[0]\r\n    }\r\n\r\n}\r\n\r\n#get episodes/tracks\r\nfunction episodeSelection {\r\n    \r\n    clearDLStatus\r\n    # Movies and tv shows\r\n    if ($type -ne \"artist\") {\r\n        $comboBox_episodes.Items.Clear()\r\n        $script:comboBox_seasons_index = $comboBox_seasons.SelectedIndex\r\n\r\n        if ($comboBox_seasons.Text -ne \"All Episodes\") {\r\n            $episodePath = $scheme + $settings.server + \"$($seasons[$comboBox_seasons_index].key)\" + \"?X-Plex-Token=\" + $settings.serverToken\r\n            $script:xmlEpisode = plx $episodePath\r\n                $script:episodes = $xmlEpisode.MediaContainer.video | select title,key,contentrating,summary,rating,year,thumb,originallyAvailableAt,index,duration\r\n        \r\n            foreach ($episode in $episodes) {\r\n                $comboBox_episodes.Items.Add($episode.index)\r\n            }\r\n            \r\n            if ($comboBox_episodes.Items -ge 2) {\r\n                $comboBox_episodes.Items.Add(\"All\")\r\n            }\r\n\r\n            $comboBox_episodes.Text = $comboBox_episodes.items[0]\r\n        }\r\n        else {\r\n            $comboBox_episodes.Text = \"All\"\r\n            $label_mediaTitle.Text = \"Download All Episodes from All Seasons\"\r\n            $label_mediaRating.Text = \"\"\r\n            $label_mediaScore.Text = \"\"\r\n            $label_mediaSummary.Text = \"Notice: This may take a very long time depending on number of seasons/episodes.\"\r\n        }\r\n    }\r\n\r\n    # music\r\n    else {\r\n        $comboBox_episodes.Items.Clear()\r\n        $comboBox_seasons_index = $comboBox_seasons.SelectedIndex\r\n        $episodePath = $scheme + $settings.server + \"$($seasons[$comboBox_seasons_index].key)\" + \"?X-Plex-Token=\" + $settings.serverToken\r\n        $script:xmlEpisode = plx $episodePath\r\n        $script:episodes = $xmlEpisode.MediaContainer.track | select title,key,index,duration,summary,parentYear,thumb,grandparentthumb,addedAt\r\n\r\n        foreach ($episode in $episodes) {\r\n            $comboBox_episodes.Items.Add($episode.title)\r\n        }\r\n        if (($comboBox_episodes.Items).count -ge 2) {\r\n            $comboBox_episodes.Items.Add(\"All Tracks\")\r\n        }\r\n\r\n        if ($comboBox_seasons.text -ne \"All Albums\") {\r\n            $comboBox_episodes.Text = $comboBox_episodes.items[0]\r\n        }\r\n        else {\r\n            $comboBox_episodes.Text = \"All Tracks\"\r\n            $label_mediaTitle.Text = \"Download All Albums\"\r\n            $label_mediaRating.Text = \"\"\r\n            $label_mediaScore.Text = \"\"\r\n            $label_mediaSummary.Text = \"Notice: This may take a very long time depending on number of albums/tracks.\"\r\n\r\n        }\r\n\r\n    }\r\n}\r\n\r\n\r\n\r\nfunction mediaEpInfo {\r\n\r\n    clearDLStatus\r\n    $comboBox_episode_index = $comboBox_episodes.SelectedIndex\r\n    if ($comboBox_episode_index -ne $null -and $episodes -ne $null) {\r\n        $script:infoEp = $episodes[$comboBox_episode_index] | Select title,type,key,tagline,summary,year,contentrating,thumb,rating\r\n    }\r\n    \r\n    if ($comboBox_episodes.Text -eq \"All\" -and $comboBox_seasons.Text -ne \"All episodes\") {\r\n        $label_mediaTitle.Text = \"Download All Episodes from $($comboBox_seasons.Text)\"\r\n        $label_mediaRating.Text = \"\"\r\n        $label_mediaScore.Text = \"\"\r\n        $label_mediaSummary.Text = \"Notice: This may take a very long time depending on number of episodes.\"\r\n    }\r\n    elseif ($comboBox_episodes.Text -eq \"All Tracks\" -and $comboBox_seasons.Text -ne \"All Albums\") {\r\n        $label_mediaTitle.Text = \"Download All Tracks from $($comboBox_seasons.Text)\"\r\n        $label_mediaRating.Text = \"\"\r\n        $label_mediaScore.Text = \"\"\r\n        $label_mediaSummary.Text = \"Notice: This may take a very long time depending on number of tracks.\"\r\n    }\r\n    else {\r\n        if ($infoEp.year) {\r\n            $label_mediaTitle.Text = \"$($infoEp.title) ($($infoEp.year))\"\r\n        }\r\n        else {\r\n            $label_mediaTitle.Text = \"$($infoEp.title)\"\r\n        }\r\n        if ($infoEp.contentrating) {\r\n            $label_mediaRating.Text = \"$($infoEp.contentrating)\"\r\n        }\r\n        elseif ($type -ne \"artist\") {\r\n            $label_mediaRating.Text = \"No Rating\"\r\n        }\r\n        if ($infoEp.rating) {\r\n            $label_mediaScore.Text = \"$($infoEp.rating)\"\r\n        }\r\n        if ($infoEp.summary) {\r\n            $label_mediaSummary.Text = \"$($infoEp.summary)\"\r\n        }\r\n        else {\r\n            $label_mediaSummary.Text = \"\"\r\n        }\r\n    }\r\n}\r\n\r\n# retrieve token. Does not store username/password, only the token\r\nfunction getToken {\r\n    try { \r\n        $label2_tokenStatus.ForeColor = \"#ffff00\"\r\n        $label2_tokenStatus.Text = \"Retrieving ...\"\r\n        $username = $textBox2_username.Text\r\n        $password = $textBox2_password.Text\r\n\r\n        # Use this method for now for more powershell version backwards compatability instead of -credential\r\n        $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes((\"{0}:{1}\" -f $username,$password)))\r\n\r\n        $headers = @{\r\n            \"X-Plex-Version\" = \"1.1.2\"\r\n            \"X-Plex-Product\" = \"Saverr\"\r\n            \"X-Plex-Client-Identifier\" = \"271938\"\r\n            \"Content-Type\" = \"application/xml\"\r\n            \"Authorization\" = (\"Basic {0}\" -f $base64AuthInfo)\r\n        }\r\n\r\n        $data = Invoke-RestMethod -Method POST -Uri $plexSignInUrl -Headers $headers\r\n        $script:userToken = $data.user.authToken\r\n\r\n        # update settings file\r\n        if (Test-Path .\\saverrSettings.xml) {\r\n            $script:settings = Import-Clixml .\\saverrSettings.xml\r\n            Add-Member -InputObject $settings -MemberType NoteProperty -Name 'userToken' -Value $userToken -force\r\n            $settings | Export-Clixml .\\saverrSettings.xml\r\n        }\r\n        else {\r\n            $script:settings = [pscustomobject] @{\r\n                userToken = $userToken\r\n            }\r\n            $settings | Export-Clixml .\\saverrSettings.xml\r\n        }\r\n        $settings = Import-Clixml .\\saverrSettings.xml\r\n        $label2_tokenStatus.ForeColor = \"#00ff00\"\r\n        $label2_tokenStatus.Text = \"Token Saved!\"\r\n    }\r\n    catch {\r\n        logit\r\n        $label2_tokenStatus.ForeColor = \"#ff0000\"\r\n        $label2_tokenStatus.Text = \"Error! User/Pass?\"\r\n    }\r\n}\r\n\r\nfunction getServers {\r\n    Try {\r\n        $label2_serverStatus.text = \"Searching ...\"\r\n        $label2_notice2.text = \"\"\r\n        # full server url\r\n        $serversUrl = $plexServersUrl + \"?X-Plex-Token=\" + $settings.userToken\r\n\r\n        # get servers\r\n        $serversXml = plx $serversUrl\r\n        $script:serverList =  $serversxml.MediaContainer.Server | select name,host,port,accessToken,localAddresses,owned\r\n\r\n        #output servers\r\n        if ($serverList) {\r\n            $comboBox2_servers.Items.Clear();\r\n            $comboBox2_servers.Text = \"$(@($serverList).count) Plex Servers found!\"\r\n            foreach ($server in $serverList) {\r\n                $comboBox2_servers.Items.Add($server.Name)\r\n            }\r\n        }\r\n        else {\r\n            $comboBox2_servers.Items.Clear()\r\n            $ComboBox2_servers.Text = \"No Plex servers found! Got Token?\"\r\n        }\r\n        $label2_serverStatus.text = \"\"\r\n    }\r\n    Catch {\r\n        logit\r\n        $label2_serverStatus.text = \"\"\r\n        $comboBox2_servers.Items.Clear()\r\n        $ComboBox2_servers.Text = \"Error! Check token?\"\r\n    }\r\n}\r\n\r\n\r\n# save all setttings to file\r\nfunction saveServer {\r\n\r\n    Try {\r\n        $comboBox2_index = $comboBox2_servers.SelectedIndex\r\n        $selectedServer = $serverList[$comboBox2_index]\r\n                \r\n        if ($selectedServer.owned -ne \"1\") {\r\n            $serverUrl = $selectedServer.Host + \":\" + $selectedServer.Port\r\n        }\r\n        else {\r\n            $ipCheck = Invoke-RestMethod http://ipinfo.io/json | Select -exp ip\r\n            if ($ipcheck -eq $selectedServer.Host) {\r\n\r\n                if ( (($selectedServer.localaddresses).GetType().name) -eq \"String\" ) {\r\n                    $serverUrl = $selectedServer.localAddresses + \":\" + \"32400\"\r\n                }\r\n                elseif ( (($selectedServer.localaddresses).GetType().name) -eq \"Array\" ) {\r\n                    $serverUrl = $selectedServer.localAddresses[0] + \":\" + \"32400\"\r\n                }\r\n            }\r\n            else {\r\n                $serverUrl = $selectedServer.Host + \":\" + $selectedServer.Port\r\n            }\r\n        }\r\n\r\n        $serverToken = $($selectedServer.accessToken)\r\n        $serverName = $($selectedServer.name)\r\n\r\n        [PsCustomObject] @{\r\n        name = \"$serverName\"\r\n        server = \"$serverUrl\"\r\n        dlPath = \"$($textBox2_dlPath.Text)\"\r\n        userToken = \"$($settings.userToken)\"\r\n        serverToken = \"$serverToken\"\r\n\t\tssl = \"$ssl\"\r\n        logging = \"$debug\"\r\n        } | Export-Clixml .\\saverrSettings.xml\r\n\r\n        $label2_serverStatus.ForeColor = \"#00ff00\"\r\n        $label2_serverStatus.text = \"Server Saved!\"\r\n    }\r\n    Catch {\r\n        logit\r\n        $label2_notice2.ForeColor = \"#ff0000\"\r\n        $label2_notice2.text = \"Error saving! Got token? selected a server?\"\r\n    }\r\n}\r\n\r\nfunction clearStatusSave {\r\n\r\n    # save path\r\n    # $dlPath = \"$($textBox2_dlPath.Text)\" # old way before dialog box\r\n\r\n    if (Test-Path .\\saverrSettings.xml) {\r\n        $script:settings = Import-Clixml .\\saverrSettings.xml\r\n        if ($dlPath) {\r\n            Add-Member -InputObject $settings -MemberType NoteProperty -Name 'dlPath' -Value $dlPath -force\r\n            $settings | Export-Clixml .\\saverrSettings.xml\r\n        }\r\n    }\r\n    else {\r\n        if ($dlPath) {\r\n            $script:settings = [pscustomobject] @{\r\n                dlPath = $dlPath\r\n            }\r\n        }\r\n    }\r\n    \r\n    # clear status\r\n    clearMediaInfo\r\n    clearDLStatus\r\n    $errorMsg = \"\"\r\n    $label2_saveStatus.text   = \"\"\r\n    $label2_serverStatus.text = \"\"\r\n    $label2_tokenStatus.Text  = \"\"\r\n    $label2_pathStatus.Text = \"\"\r\n    $label2_notice2.Text = \"\"\r\n    $textBox_search.Text = \"\"\r\n    $textBox2_dlPath.Text = $settings.dlPath\r\n    $textBox2_username.Text = \"\"\r\n    $textBox2_password.Text = \"\"\r\n    $comboBox2_servers.Items.Clear()\r\n    $comboBox2_servers.Text = $settings.name\r\n\r\n    Try {\r\n        if ($dlPath) {\r\n            New-Item -ItemType Directory -Force -Path $dlPath\r\n        }\r\n        $label_mediaTitle.ForeColor = \"#ffffff\"\r\n        $label_mediaTitle.Text = \"\"\r\n        $label_mediaSummary.Text = \"\"\r\n    }\r\n    Catch {\r\n        logit\r\n        $label_mediaTitle.ForeColor = \"#ff0000\"\r\n        $label_mediaTitle.Text = \"Error creating download Path\"\r\n        $label_mediaSummary.Text = \"Could Not validate download directory:`n$dlPath.`n`nCheck path name or system permissions maybe?\"\r\n    }\r\n    \r\n    Try {\r\n        if ($settings) {\r\n            $settings | Export-Clixml .\\saverrSettings.xml\r\n        }\r\n        $label_mediaTitle.ForeColor = \"#ffffff\"\r\n        $label_mediaTitle.Text = \"\"\r\n        $label_mediaSummary.Text = \"\"\r\n    }\r\n    Catch {\r\n        logit\r\n        $label_mediaTitle.ForeColor = \"#ff0000\"\r\n        $label_mediaTitle.Text = \"Error saving settings\"\r\n        $label_mediaSummary.Text = \"Could Not Create settings file at:`n$PSScriptRoot.`n`nCheck path or system permissions maybe?\"\r\n    }\r\n\r\n    if ((!($settings.name)) -or (!($settings.server)) -or (!($settings.userToken)) -or (!($settings.serverToken)) -or (!($settings.dlPath))) {\r\n        $label_mediaSummary.text = \"Settings are not fully configured.`nPlease click the gear icon before searching.\"\r\n    }\r\n    else {\r\n        $label_mediaSummary.text = \"\"\r\n    }\r\n\r\n}\r\n\r\nfunction clearMediaInfo {\r\n\r\n    $comboBox_results.Items.Clear()\r\n    $comboBox_results.Text = \"\"\r\n    $pictureBox_thumb.Visible = $false\r\n    $pictureBox_thumb.image = $loading\r\n    $pictureBox_thumb.ImageLocation = \"\"\r\n    $label_mediaTitle.Text = \"\"\r\n    $label_mediaRating.Text = \"\"\r\n    $label_mediaScore.Text = \"\"\r\n    $label_mediaSummary.Text = \"\"\r\n    $comboBox_seasons.Text = \"\"\r\n    $comboBox_episodes.Text = \"\"\r\n    $comboBox_seasons.Items.Clear()\r\n    $comboBox_episodes.Items.Clear()\r\n    $button_download.Enabled = $false\r\n\r\n}\r\n\r\nfunction clearDLStatus {\r\n\r\n    if ($label_DLTitle.Text -match \"^Download Completed|^Download Failed|^Download Cancelled|^There was an error|^Error\") {\r\n            $label_DLTitle.Text = \"\"\r\n    }\r\n    if ($label_DLProgress.Text -ne \"Download Paused!\") {\r\n        $label_DLProgress.Text = \"\"\r\n        $label_DLProgress.ForeColor = \"#f5a623\"\r\n    }\r\n\r\n}\r\n\r\nfunction cancelJob {\r\n    $progressBar.Value = 0\r\n    $label_DLTitle.ForeColor = \"#ff0000\"\r\n    $label_DLTitle.Text = \"Download Cancelled!\"\r\n    $label_DLProgress.Text = \"\"\r\n    $progressBar.Visible = $false\r\n    if ($comboBox_results.Items) {\r\n        $button_download.Enabled = $true\r\n    }\r\n    $button_cancel.Visible = $false\r\n    $button_cancel.Enabled = $false\r\n    $CheckBoxButton_pause.Visible = $false\r\n    $CheckboxButton_pause.Enabled = $false\r\n    $script:pauseLoop = $false\r\n    $checkBoxButton_pause.Text = \"Pause\"\r\n    Get-BitsTransfer | Complete-BitsTransfer\r\n\r\n    # clean up any empty folders created.\r\n    # This can throw an error in the console sometimes if the path is deleted too fast and then it doesn't exist. Not worth it to remove error, doesn't stop the app.\r\n    if ($dlType -eq \"allEp\" -or $dlType -eq \"allSeasons\") {\r\n        if (Test-Path $allSeasonPath) {\r\n            Get-ChildItem $allSeasonPath -Directory -recurse | where {-NOT $_.GetFiles(\"*\",\"AllDirectories\")} | del -recurse -ErrorAction SilentlyContinue\r\n            if (Test-Path $allSeasonPath) {\r\n                if ((Get-ChildItem $allSeasonPath | Measure-Object).Count -eq 0) {\r\n                    del $allSeasonPath -ErrorAction SilentlyContinue\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    # enable minimize again\r\n    $form.MinimizeBox = $true\r\n\r\n}\r\n\r\n########### OPERATIONS ###############\r\n\r\n# Buttons\r\n$button_download.Add_Click({\r\n\r\n    Try {\r\n        if ((Get-BitsTransfer).JobState -ne \"Suspended\") {\r\n            # tell them what's going on, reset status\r\n            $button_download.Enabled = $false\r\n            $label_DLTitle.ForeColor = \"#f5a623\"\r\n            $label_DLProgress.ForeColor = \"#f5a623\"\r\n            $label_DLProgress.Text = \"\"\r\n            $label_DLTitle.Text = \"Processing download request\"\r\n            $label_DLTitle.Refresh()\r\n            $button_download.Text = \"Download\"\r\n            $checkBoxButton_pause.Checked = $false\r\n            $status = \"success\"\r\n\r\n            # movie dl links\r\n            if ($type -eq \"movie\") {\r\n                $mediaURL = $scheme + $settings.server + $info.key + \"?X-Plex-Token=\" + $settings.serverToken\r\n                $mediaPath = plx $mediaURL\r\n                $mediaInfo = $mediaPath.MediaContainer.Video.Media.Part | select key,file -First 1\r\n                $dlURL = $scheme + $settings.server + $mediaInfo.key + \"?download=1\" + \"&X-Plex-Token=\" + $settings.serverToken\r\n                $script:dlName = Split-Path $mediaInfo.file -Leaf\r\n                $script:dlType = \"one\"\r\n            }\r\n\r\n            # tv show dl links\r\n            if ($type -eq \"show\") {\r\n\r\n                # if all episodes from one season is selected\r\n                if ($comboBox_episodes.Text -eq \"All\" -and $comboBox_seasons.Text -ne \"All episodes\") {\r\n                    $script:allSeasonPath = \"$($settings.dlPath)\\$(Remove-InvalidChars $info.title)\"\r\n                    $allEpPath = \"$allSeasonPath\\$(Remove-InvalidChars $comboBox_seasons.Text)\"\r\n                    New-Item -ItemType Directory -Force -Path $allEpPath\r\n                    $allEp = $xmlepisode.MediaContainer.Video.Media.Part | select @{n=\"Source\";e={$scheme + $settings.server + $_.key + \"?X-Plex-Token=\" + $settings.serverToken}},@{n=\"Destination\";e={$allEpPath + \"\\\" + (Split-Path $_.file -Leaf)}}\r\n                    $script:dlType = \"allEp\"\r\n\r\n                    # remove links that have already been downloaded\r\n                    $allEpData = @()\r\n                    For ($I=0; $I -lt $allep.count; $I++) {\r\n\r\n                        if (!(Test-Path $allEp.destination[$I])) {\r\n                            $allEpData += [pscustomobject] @{\r\n                                Source  = $allep.source[$I]\r\n                                Destination = $allEp.destination[$I]\r\n                            }\r\n                        }\r\n\r\n                    }\r\n\r\n                }\r\n                # if all seasons and all episodes is selected\r\n                elseif ($comboBox_episodes.Text -eq \"All\" -and $comboBox_seasons.Text -eq \"All episodes\") {\r\n                    $script:allSeasonPath = \"$($settings.dlPath)\\$(Remove-InvalidChars $info.title)\"\r\n                    $mediaURL = $scheme + $settings.server + $seasons.key[0] + \"?X-Plex-Token=\" + $settings.serverToken\r\n                    $mediaPath = plx $mediaURL\r\n                    $seasonNumber = $mediaPath.MediaContainer.Video | select parenttitle\r\n                    $seasonClean = $seasonNumber.parenttitle | % {Remove-InvalidChars $_}\r\n                    $allEp = $mediaPath.MediaContainer.Video.Media.Part | select @{n=\"Source\";e={$scheme + $settings.server + $_.key + \"?X-Plex-Token=\" + $settings.serverToken}},@{n=\"Destination\";e={(Split-Path $_.file -Leaf)}}\r\n                    $allEpClean = $allEp.destination | % {Remove-InvalidChars $_}\r\n                    $script:dlType = \"allSeasons\"\r\n\r\n                    # combine source/destination/season data for Bitstransfer import\r\n                    # remove links that have already been downloaded\r\n                    $allEpData = @()\r\n                    For ($I=0; $I -lt $allep.count; $I++) {\r\n\r\n                        $finalDestination = $allSeasonPath + \"\\\" + $seasonClean[$I] + \"\\\" + $allEpClean[$I]\r\n\r\n                        if (!(Test-Path $finalDestination)) {\r\n                            $allEpData += [pscustomobject] @{\r\n                                Source  = $allep.source[$I]\r\n                                Destination = $finalDestination\r\n                            }\r\n                        }\r\n                    }\r\n\r\n\r\n                    # Bitstransfer defaults to 200 max files per job. Truncate download to 200 unless registry value is set to something else.\r\n                    if ($allEpData.length -ge $limit) {\r\n                        $setLimit = $limit - 1\r\n                        $allEpData = $allEpData[0..$setLimit]\r\n                        $noLimitStatus = \"(Max limit set to $limit)\"\r\n                    }    \r\n\r\n                    # pre-create directories for seasons\r\n                    $seasonClean | select -Unique | % {New-Item -ItemType Directory -Force -Path \"$allSeasonPath\\$_\"}\r\n\r\n                }\r\n\r\n                # if just one episode or a movie is selected\r\n                else {\r\n                    $mediaURL = $scheme + $settings.server + $infoEp.key + \"?X-Plex-Token=\" + $settings.serverToken\r\n                    $mediaPath = plx $mediaURL\r\n                    $mediaInfo = $mediaPath.MediaContainer.Video.Media.Part | select key,file -First 1\r\n                    $dlURL = $scheme + $settings.server + $mediaInfo.key + \"?download=1\" + \"&X-Plex-Token=\" + $settings.serverToken\r\n                    $script:dlName = Split-Path $mediaInfo.file -Leaf | % {Remove-InvalidChars $_}\r\n                    $script:dlType = \"one\"\r\n                }\r\n             \r\n            }\r\n  \r\n            # music dl links\r\n            if ($type -eq \"artist\") {\r\n\r\n                # if all tracks from one album is selected\r\n                if ($comboBox_episodes.Text -eq \"All Tracks\" -and $comboBox_seasons.Text -ne \"All Albums\") {\r\n                    $script:allSeasonPath = \"$($settings.dlPath)\\$(Remove-InvalidChars $info.title)\"\r\n                    $allEpPath = \"$allSeasonPath\\$(Remove-InvalidChars $comboBox_seasons.Text)\"\r\n                    New-Item -ItemType Directory -Force -Path $allEpPath\r\n                    $allEp = $xmlepisode.MediaContainer.Track.Media.Part | select @{n=\"Source\";e={$scheme + $settings.server + $_.key + \"?X-Plex-Token=\" + $settings.serverToken}},@{n=\"Destination\";e={$allEpPath + \"\\\" + (Split-Path $_.file -Leaf)}}\r\n                    $script:dlType = \"allTracks\"\r\n\r\n                    # remove links that have already been downloaded\r\n                    $allEpData = @()\r\n                    For ($I=0; $I -lt $allep.count; $I++) {\r\n\r\n                        if (!(Test-Path $allEp.destination[$I])) {\r\n                            $allEpData += [pscustomobject] @{\r\n                                Source  = $allep.source[$I]\r\n                                Destination = $allEp.destination[$I]\r\n                            }\r\n                        }\r\n\r\n                    }\r\n\r\n                }\r\n\r\n                # if all tracks and all albums is selected\r\n                elseif ($comboBox_episodes.Text -eq \"All Tracks\" -and $comboBox_seasons.Text -eq \"All Albums\") {\r\n                    $script:allSeasonPath = \"$($settings.dlPath)\\$(Remove-InvalidChars $info.title)\"\r\n\r\n                    # collect all album metadata paths\r\n                    $mediaURL = @()\r\n                    $seasons | % { $mediaURL += $scheme + $settings.server + $_.key + \"?X-Plex-Token=\" + $settings.serverToken }\r\n\r\n                    # get all tracks\r\n                    $all = $mediaURL | % {(plx $_).MediaContainer.Track}\r\n                    $allEp = $all.media.part | select @{n=\"Source\";e={$scheme + $settings.server + $_.key + \"?X-Plex-Token=\" + $settings.serverToken}},@{n=\"Destination\";e={(Split-Path $_.file -Leaf)}}  \r\n                    $allClean = $all.parenttitle | % {Remove-InvalidChars $_}\r\n                    $allSeasonClean = $all.parenttitle | % {Remove-InvalidChars $_}\r\n                    $allEpClean = $allEp.destination | % {Remove-InvalidChars $_}\r\n                    $script:dlType = \"allAlbums\"\r\n\r\n                    # combine source/destination/season data for Bitstransfer import\r\n                    $allEpData = @()\r\n                    For ($I=0; $I -lt $allEp.count; $I++) {\r\n\r\n                        $finalDestination = $allSeasonPath + \"\\\" + $allSeasonClean[$I] + \"\\\" + $allEpClean[$I]\r\n\r\n                        if (!(Test-Path $finalDestination)) {\r\n                            $allEpData += [pscustomobject] @{\r\n                                Source  = $allEp.source[$I]\r\n                                Destination = $finalDestination\r\n                            }\r\n                        }\r\n\r\n                    }\r\n\r\n                    # Bitstransfer defaults to 200 max files per job. Truncate download to 200 unless registry value is set to something else.\r\n                    if ($allEpData.length -ge $limit) {\r\n                        $setLimit = $limit - 1\r\n                        $allEpData = $allEpData[0..$setLimit]\r\n                        $noLimitStatus = \"(Max limit set to $limit)\"\r\n                    }\r\n\r\n                    # pre-create directories for seasons\r\n                    $allClean | select -Unique | % {New-Item -ItemType Directory -Force -Path \"$allSeasonPath\\$_\"}\r\n\r\n                }\r\n\r\n                # if just one music track is selected\r\n                else {\r\n                    $mediaURL = $scheme + $settings.server + $infoEp.key + \"?X-Plex-Token=\" + $settings.serverToken\r\n                    $mediaPath = plx $mediaURL\r\n                    $mediaInfo = $mediaPath.MediaContainer.track.media.part | select key,file -First 1\r\n                    $mediaInfo2 = $mediaPath.MediaContainer.track | select grandparentTitle,parentTitle,title -First 1\r\n                    $dlURL = $scheme + $settings.server + $mediaInfo.key + \"?download=1\" + \"&X-Plex-Token=\" + $settings.serverToken\r\n                    $script:dlName = Split-Path $mediaInfo.file -Leaf | % {Remove-InvalidChars $_}\r\n                    $script:dlType = \"one\"\r\n                }\r\n\r\n            }        \r\n        \r\n            # Cancelling all old Bits jobs\r\n            Get-BitsTransfer | Remove-BitsTransfer\r\n\r\n            # get starting time\r\n            $startTime = Get-Date\r\n\r\n            # disable minimize since it causes issues during downloads\r\n            $form.MinimizeBox = $false\r\n\r\n            # download all episodes from a season or album\r\n            if ($dlType -eq \"allEp\" -or $dlType -eq \"allTracks\") {\r\n                $script:myjob = Start-BitsTransfer -source \"$($allEpData.Source[0])\" -Destination \"$($allEpData.Destination[0])\" -DisplayName \"Downloading ...\" -Description \"All Episodes\" -Asynchronous -Suspended\r\n                $allEpData[1..($allEpData.Length -1)] | Add-BitsFile $myjob\r\n                if ($ssl -eq $True) {bitsadmin /SetSecurityFlags $myjob.displayname 30}\r\n                Resume-BitsTransfer $myjob -Asynchronous\r\n            }\r\n\r\n            # download all seasons or all albums\r\n            elseif ($dltype -eq \"allSeasons\" -or $dlType -eq \"allAlbums\") {\r\n                $script:myjob = Start-BitsTransfer -source \"$($allEpData.Source[0])\" -Destination \"$($allEpData.Destination[0])\" -DisplayName \"Downloading ...\" -Description \"All Episodes\" -Asynchronous -Suspended\r\n                $allEpData[1..($allEpData.Length -1)] | Add-BitsFile $myjob\r\n                if ($ssl -eq $True) {bitsadmin /SetSecurityFlags $myjob.displayname 30}\r\n                Resume-BitsTransfer $myjob -Asynchronous\r\n            }\r\n\r\n            # download a movie or one episode or one song\r\n            else {\r\n                $script:myjob = Start-BitsTransfer -Source $dlURL -Destination \"$($settings.dlPath)\\$dlName\" -DisplayName \"Downloading ...\" -Description $dlName -Asynchronous -Suspended\r\n                if ($ssl -eq $True) {bitsadmin /SetSecurityFlags $myjob.displayname 30}\r\n\t\t\t\tResume-BitsTransfer $myjob -Asynchronous\r\n            }\r\n\r\n        }\r\n        elseif ((Get-BitsTransfer).JobState -eq \"Suspended\") {\r\n            # resume if they paused the download\r\n            $button_download.Enabled = $false\r\n            $button_download.Text = \"Download\"\r\n            $label_DLTitle.ForeColor = \"#f5a623\"\r\n            $label_DLProgress.ForeColor = \"#f5a623\"\r\n            $label_DLTitle.Text = \"Paused download detected. Resuming progress ...\"\r\n            $checkBoxButton_pause.Text = \"Pause\"\r\n            $label_DLProgress.Text = \"\"\r\n            $label_DLProgress.ForeColor = \"#f5a623\"\r\n            Resume-BitsTransfer $myjob -Asynchronous\r\n            $label_DLTitle.Refresh()\r\n            $status = \"success\"\r\n        }\r\n        # disable minimize since it causes issues during downloads\r\n        $form.MinimizeBox = $false\r\n\r\n        # Pause to let it start before checking progress. Timeout after 30sec\r\n        $count    = 0\r\n        $noDot    = (0,4,8,12,16,20,24,28)\r\n        $oneDot   = (1,5,9,13,17,21,25,29)\r\n        $twoDot   = (2,6,10,14,18,22,26,30)\r\n        $threeDot = (3,7,11,15,19,23,27)\r\n\r\n        # timeout\r\n        :check while ($count -lt $timeout) {\r\n\r\n            if (((Get-BitsTransfer | ? { $_.JobState -eq \"Transferring\" }).Count -gt 0) -or (Get-BitsTransfer | ? { $_.JobState -eq \"Transferred\" }) -or (Get-BitsTransfer | ? { $_.JobState -eq \"Error\" })) {   \r\n                # exit check\r\n                break check\r\n            }\r\n\r\n            if ($noDot -contains $count) {\r\n                $label_DLTitle.Text = \"Processing download request\"\r\n                $label_DLTitle.Refresh()\r\n            }\r\n            elseif ($oneDot -contains $count) {\r\n                $label_DLTitle.Text = \"Processing download request .\"\r\n                $label_DLTitle.Refresh()\r\n            }\r\n            elseif ($twoDot -contains $count) {\r\n                $label_DLTitle.Text = \"Processing download request . .\"\r\n                $label_DLTitle.Refresh()\r\n            }\r\n            elseif ($threeDot -contains $count) {\r\n                $label_DLTitle.Text = \"Processing download request . . .\"\r\n                $label_DLTitle.Refresh()\r\n            }\r\n\r\n            # increase counter\r\n            Start-Sleep -Seconds 1\r\n            $count++\r\n\r\n        }\r\n\r\n        if ($count -ge $timeout) {\r\n            $status = \"failed\"\r\n\r\n            if (Get-BitsTransfer | ? { $_.JobState -like \"*Error*\" }) {\r\n                $bitsError = (Get-BitsTransfer | select ErrorDescription).ErrorDescription\r\n                if ($debug) {\r\n                    $eMSG = \"$(Get-Date): Connection Timed out after $timeout seconds. $bitsError\"\r\n                    $eMSG | Out-File \".\\saverrLog.txt\" -Append\r\n                }\r\n            }\r\n\r\n            # remove bitstransfer jobs and clean up empty directories created\r\n            Get-BitsTransfer | Remove-BitsTransfer\r\n            if ($dlType -like \"all*\") {\r\n                if (Test-Path $allSeasonPath) {\r\n                    Get-ChildItem $allSeasonPath -Directory -recurse | where {-NOT $_.GetFiles(\"*\",\"AllDirectories\")} | del -recurse -ErrorAction SilentlyContinue\r\n                    if (Test-Path $allSeasonPath) {\r\n                        if ((Get-ChildItem $allSeasonPath | Measure-Object).Count -eq 0) {\r\n                            del $allSeasonPath -ErrorAction SilentlyContinue\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n\r\n            $label_DLTitle.ForeColor = \"#ff0000\"\r\n            $label_DLTitle.Text = \"Download Failed! Timed out.`n Error: $bitsError\"\r\n            $button_download.Enabled = $true\r\n            $label_DLProgress.Text = \"\"\r\n        }\r\n\r\n        if ((Get-BitsTransfer | select ErrorDescription).ErrorDescription -like \"*404*\") {\r\n            $status = \"failed\"\r\n\r\n            # remove bitstransfer jobs and clean up empty directories created\r\n            Get-BitsTransfer | Remove-BitsTransfer\r\n            if ($dlType -like \"all*\") {\r\n                if (Test-Path $allSeasonPath) {\r\n                    Get-ChildItem $allSeasonPath -Directory -recurse | where {-NOT $_.GetFiles(\"*\",\"AllDirectories\")} | del -recurse -ErrorAction SilentlyContinue\r\n                    if (Test-Path $allSeasonPath) {\r\n                        if ((Get-ChildItem $allSeasonPath | Measure-Object).Count -eq 0) {\r\n                            del $allSeasonPath -ErrorAction SilentlyContinue\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n\r\n            $label_DLTitle.ForeColor = \"#ff0000\"\r\n            $label_DLTitle.Text = \"Download Failed! File not found. Check server\"\r\n            $button_download.Enabled = $true\r\n            $label_DLProgress.Text = \"\"\r\n\r\n        }\r\n\r\n        if ($status -eq \"success\") {\r\n            # Show progress\r\n            $progressBar.Visible = $true\r\n            $progressBar.Value = 0\r\n            $label_DLProgress.Text = \"\"\r\n            $label_DLProgress.ForeColor = \"#f5a623\"\r\n\r\n            # Init CancelLoop\r\n            $script:cancelLoop = $false\r\n            $button_cancel.Enabled = $true\r\n            $button_cancel.Visible = $true\r\n            $checkBoxButton_pause.Enabled = $true\r\n            $checkBoxButton_pause.Visible = $true\r\n\r\n            if (Get-BitsTransfer | ? { $_.JobState -ne \"Transferred\" }) {\r\n\r\n                :xfer while ((Get-BitsTransfer | ? { $_.JobState -eq \"Transferring\" }).Count -gt 0) { \r\n                    $totalbytes=0;    \r\n                    $bytestransferred=0; \r\n                    $timeTaken = 0;\r\n                    foreach ($job in (Get-BitsTransfer | ? { $_.JobState -eq \"Transferring\" } | Sort-Object CreationTime)) {\r\n                             \r\n                        $totalbytes += [math]::round($job.BytesTotal /1MB);\r\n                        $totalSize = byteSize $($job.BytesTotal)         \r\n                        $bytestransferred += [math]::round($job.bytestransferred /1MB)\r\n                        $transferSize = byteSize $($job.bytestransferred)   \r\n                        if ($timeTaken -eq 0) { \r\n                            #Get the time of the oldest transfer aka the one that started first\r\n                            $timeTaken = ((Get-Date) - $job.CreationTime).TotalMinutes \r\n                        }\r\n                    }    \r\n                    #TimeRemaining = (TotalFileSize - BytesDownloaded) * TimeElapsed/BytesDownloaded\r\n                    [System.Windows.Forms.Application]::DoEvents()\r\n\r\n                    # cancel download if asked\r\n                    if ($script:cancelLoop -eq $true) {\r\n                        cancelJob\r\n                        # exit loop\r\n                        break xfer\r\n                    }\r\n\r\n                    # pause download if asked\r\n                    if ($script:pauseLoop -eq $true) {\r\n                        $label_DLProgress.Text = \"Download Paused!\"\r\n                        $label_DLProgress.ForeColor = \"#ffff00\" # yellow\r\n                        Get-BitsTransfer | Suspend-BitsTransfer\r\n\r\n                        # allow minimize while paused\r\n                        $form.MinimizeBox = $true\r\n\r\n                        # exit loop\r\n                        break xfer\r\n                    }\r\n\r\n                    if ($totalbytes -gt 0 -and $bytestransferred -gt 0 -and $timetaken -gt 0) {        \r\n                        [int]$timeLeft = ($totalBytes - $bytestransferred) * ($timeTaken / $bytestransferred)\r\n                        [int]$pctComplete = $(($bytestransferred*100)/$totalbytes);     \r\n                        $label_DLProgress.Text = \"$transferSize of $totalSize ($pctComplete%) - Approx. $timeLeft minutes remaining\"\r\n                        $progressBar.Value = $pctComplete\r\n                        #$label_DLProgress.Refresh()\r\n\r\n                        Switch ($dlType)\r\n                            {\r\n                                'one'           { $label_DLTitle.Text = \"Downloading: $dlName\"; Break }\r\n                                'allEp'         { $label_DLTitle.Text = \"Completed: $([int]$myjob.FilesTransferred) of $([int]$myjob.FilesTotal) Episodes $noLimitStatus\"; Break }\r\n                                'allTracks'     { $label_DLTitle.Text = \"Completed: $([int]$myjob.FilesTransferred) of $([int]$myjob.FilesTotal) Tracks $noLimitStatus\"; Break }\r\n                                'allSeasons'    { $label_DLTitle.Text = \"Completed: $([int]$myjob.FilesTransferred) of $([int]$myjob.FilesTotal) Episodes $noLimitStatus\"; Break }\r\n                                'allAlbums'     { $label_DLTitle.Text = \"Completed: $([int]$myjob.FilesTransferred) of $([int]$myjob.FilesTotal) Tracks $noLimitStatus\"; Break }\r\n                            }\r\n\r\n                        $progressBar.PerformStep()\r\n                        Start-Sleep -Seconds 1\r\n                    }\r\n                }\r\n            }\r\n\r\n            # download went too fast. Pause to show title downloaded\r\n            else {\r\n                Switch ($dlType)\r\n                    {\r\n                        'one'           { $label_DLTitle.Text = \"Downloading: $dlName\"; Break }\r\n                        'allEp'         { $label_DLTitle.Text = \"Completed: $([int]$myjob.FilesTransferred) of $([int]$myjob.FilesTotal) Episodes\"; Break }\r\n                        'allTracks'     { $label_DLTitle.Text = \"Completed: $([int]$myjob.FilesTransferred) of $([int]$myjob.FilesTotal) Tracks\"; Break }\r\n                        'allSeasons'    { $label_DLTitle.Text = \"Completed: $([int]$myjob.FilesTransferred) of $([int]$myjob.FilesTotal) Episodes\"; Break }\r\n                        'allAlbums'     { $label_DLTitle.Text = \"Completed: $([int]$myjob.FilesTransferred) of $([int]$myjob.FilesTotal) Tracks\"; Break }\r\n                    }\r\n\r\n                Start-Sleep -Seconds 2\r\n\r\n            }\r\n\r\n            # Finish and close Bitstransfer\r\n            if ($script:cancelLoop -eq $false -and $script:pauseLoop -eq $false) {\r\n\r\n                if (Get-BitsTransfer | ? { $_.JobState -like \"*Error*\" }) {\r\n                    $bitsError = (Get-BitsTransfer | select ErrorDescription).ErrorDescription\r\n                    if ($debug) {\r\n                        $eMSG = \"$(Get-Date): Download Error. $bitsError\"\r\n                        $eMSG | Out-File \".\\saverrLog.txt\" -Append\r\n                    }\r\n                    $label_DLTitle.ForeColor = \"#ff0000\"\r\n                    $label_DLProgress.Text = \"\"\r\n                    $label_DLTitle.Text = \"Error: $bitsError\"\r\n                    $progressBar.Visible = $false\r\n                    $progressBar.Value = 0\r\n                    $button_download.Enabled = $true\r\n                    $button_cancel.Visible = $false\r\n                    $button_cancel.Enabled = $false\r\n                    $checkBoxButton_pause.Visible = $false\r\n                    $CheckBoxButton_pause.Enabled = $false\r\n                    \r\n                }\r\n                else {\r\n                    if ($startTime -ne $null) {\r\n                        $howLong = (get-date).Subtract($startTime)\r\n                        if ($howLong.Minutes -eq \"0\") {\r\n                            $dlTime = \"$($howLong.Seconds) seconds\"\r\n                        }\r\n                        else {\r\n                            $dlTime = \"$($howLong.Minutes) minutes\"\r\n                        }\r\n                    }\r\n                    else {\r\n                        $dlTime = \"Unknown time\"\r\n                    }\r\n\r\n                    $label_DLProgress.Text = \"\"\r\n                    $label_DLTitle.ForeColor = \"#00ff00\"\r\n                    $label_DLTitle.Text = \"Download Completed in: $dlTime\"\r\n                    $button_download.Enabled = $true\r\n                    $button_cancel.Visible = $false\r\n                    $button_cancel.Enabled = $false\r\n                    $checkBoxButton_pause.Visible = $false\r\n                    $CheckBoxButton_pause.Enabled = $false\r\n                    $progressBar.Visible = $false\r\n                    $progressBar.Value = 0\r\n                }\r\n\r\n                Get-BitsTransfer | Complete-BitsTransfer\r\n\r\n                # remove any empty folder created\r\n                if ($dlType -like \"all*\") {\r\n                    if (Test-Path $allSeasonPath) {\r\n                        Get-ChildItem $allSeasonPath -Directory -recurse | where {-NOT $_.GetFiles(\"*\",\"AllDirectories\")} | del -recurse -ErrorAction SilentlyContinue\r\n                        if (Test-Path $allSeasonPath) {\r\n                            if ((Get-ChildItem $allSeasonPath | Measure-Object).Count -eq 0) {\r\n                                del $allSeasonPath -ErrorAction SilentlyContinue\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n\r\n                # allow minimize again\r\n                $form.MinimizeBox = $true\r\n\r\n            }\r\n        }\r\n\r\n    }\r\n\r\n    Catch {\r\n        logit\r\n        Get-BitsTransfer | Remove-BitsTransfer\r\n\r\n        # clean up any empty folders\r\n        if ($dlType -like \"all*\") {\r\n            if (Test-Path $allSeasonPath) {\r\n                Get-ChildItem $allSeasonPath -Directory -recurse | where {-NOT $_.GetFiles(\"*\",\"AllDirectories\")} | del -recurse -ErrorAction SilentlyContinue\r\n                if (Test-Path $allSeasonPath) {\r\n                    if ((Get-ChildItem $allSeasonPath | Measure-Object).Count -eq 0) {\r\n                        del $allSeasonPath -ErrorAction SilentlyContinue\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        $label_DLTitle.ForeColor = \"#ff0000\"\r\n        $label_DLProgress.Text = \"\"\r\n        $label_DLTitle.Text = \"There was an error with the download.\"\r\n        $progressBar.Visible = $false\r\n        $progressBar.Value = 0\r\n        $button_download.Enabled = $true\r\n        $button_cancel.Visible = $false\r\n        $button_cancel.Enabled = $false\r\n\r\n        # enable minimize again\r\n        $form.MinimizeBox = $true\r\n    }\r\n\r\n})\r\n\r\n\r\n$button_search.Add_Click({search})\r\n\r\n$button_settings.Add_Click({[void]$form2.ShowDialog()})\r\n\r\n$button_cancel.Add_Click({\r\n    $cancelMsg = [System.Windows.Forms.MessageBox]::Show(\"Are you sure you want to cancel the download?`nAll non-completed files will be deleted!\",'Cancel Download','YesNo','Question')\r\n\r\n    if ($cancelMsg -eq \"Yes\" -and $script:pauseLoop -ne $true) {\r\n        $script:cancelLoop = $true\r\n    }\r\n    elseif ($cancelMsg -eq \"Yes\" -and $script:pauseLoop -eq $true) {\r\n        $script:cancelLoop = $true\r\n        cancelJob\r\n    }\r\n})\r\n\r\n$button2_getToken.Add_Click({getToken})\r\n\r\n$button2_servers.Add_Click({getServers})\r\n\r\n$button2_dlPath.Add_Click({\r\n    try {\r\n        $script:dlPath = Get-SavePath\r\n        if ($dlPath) {\r\n            $textBox2_dlPath.Text = $dlPath\r\n            $label2_pathStatus.ForeColor = \"#00ff00\"\r\n            $label2_pathStatus.Text = \"Path Saved!\"\r\n        }\r\n    }\r\n    catch {\r\n        logit\r\n        $label2_pathStatus.ForeColor = \"#ff0000\"\r\n        $label2_pathStatus.Text = \"Error! Check log\"\r\n    }\r\n\r\n})\r\n\r\n# save token on enter key\r\n$textBox2_password.Add_KeyUp({\r\n    if ($_.KeyCode -eq \"Enter\") {\r\n        getToken\r\n    }\r\n})\r\n\r\n# search on enter key\r\n$textBox_search.Add_KeyUp({\r\n    if ($_.KeyCode -eq \"Enter\") {search}\r\n})\r\n\r\n $checked_type ={\r\n             if ($RadioButton_movie.Checked){\r\n                   clearMediaInfo\r\n                   clearDLStatus\r\n                   $textBox_search.Text = \"\"\r\n                   $label_seasons.Text = \"\"\r\n                   $label_episodes.Text = \"\"\r\n                   $label_search.text = \"Search Movie:\"\r\n                   $combobox_seasons.Visible = $false\r\n                   $combobox_episodes.Visible = $false\r\n                   $label_mediaTitle.location = $label_mediaTitle_default_xy\r\n                   $label_mediaRating.location = $label_mediaRating_default_xy\r\n                   $label_mediaScore.location = $label_mediaScore_default_xy\r\n                   $label_mediaSummary.location = $label_mediaSummary_default_xy\r\n                   $label_mediaSummary.height = $label_mediaSummary_default_height\r\n                   $toolTip.SetToolTip($label_search, \"Searches by First Letter. Excluding 'The' and 'A'\")\r\n                   }\r\n            if ($RadioButton_tv.Checked){\r\n                   clearMediaInfo\r\n                   clearDLStatus\r\n                   $textBox_search.Text = \"\"\r\n                   $label_search.text = \"Search TV Show:\"\r\n                   $label_seasons.Text = \"Season:\"\r\n                   $label_episodes.text = \"Episode:\"\r\n                   $combobox_seasons.Visible = $true\r\n                   $combobox_episodes.Visible = $true\r\n                   $label_episodes.location = New-Object System.Drawing.Point(215,225)\r\n                   $comboBox_episodes.location = New-Object System.Drawing.Point(270,215)\r\n                   $label_mediaTitle.location = $label_mediaTitle_default_xy\r\n                   $label_mediaRating.location = $label_mediaRating_default_xy\r\n                   $label_mediaScore.location = $label_mediaScore_default_xy\r\n                   $label_mediaSummary.location = $label_mediaSummary_default_xy\r\n                   $label_mediaSummary.height = $label_mediaSummary_default_height\r\n                   $combobox_seasons.width = 130\r\n                   $combobox_episodes.width = 45\r\n                   $toolTip.SetToolTip($label_search, \"Searches by first Letter. Excluding 'The' and 'A'\")\r\n                   }\r\n            elseif ($radiobutton_music.Checked) {\r\n                   clearMediaInfo\r\n                   clearDLStatus\r\n                   $textBox_search.Text = \"\"\r\n                   $label_search.text = \"Search Artist:\"\r\n                   $label_seasons.Text = \"Album:\"\r\n                   $label_episodes.Text = \"Track:\"\r\n                   $label_episodes.location = New-Object System.Drawing.Point(280,225)\r\n                   $comboBox_episodes.location = New-Object System.Drawing.Point(325,215)\r\n                   $combobox_seasons.Visible = $true\r\n                   $combobox_episodes.Visible = $true\r\n                   $combobox_seasons.width = 195\r\n                   $combobox_episodes.width = 210\r\n                   $label_mediaTitle.location = New-Object System.Drawing.Point(140,280)\r\n                   $label_mediaRating.location = New-Object System.Drawing.Point(140,300)\r\n                   $label_mediaScore.location = New-Object System.Drawing.Point(140,300)\r\n                   $label_mediaSummary.location = New-Object System.Drawing.Point(140,320)\r\n                   $label_mediaSummary.height = 85\r\n                   $toolTip.SetToolTip($label_search, \"Searches by Artist Name\")\r\n                }\r\n}\r\n\r\n$checkBoxButton_pause.Add_CheckedChanged({\r\n    if ($checkBoxButton_pause.Checked -eq $true){\r\n        $script:pauseLoop = $true\r\n        $checkBoxButton_pause.Text = \"Resume\"\r\n    }\r\n    else {\r\n        if ((Get-BitsTransfer).JobState -eq \"Suspended\") {\r\n            $script:pauseLoop = $false\r\n            $checkBoxButton_pause.Text = \"Pause\"\r\n            $button_download.Enabled = $true\r\n            $button_download.PerformClick()\r\n        }\r\n    }\r\n})\r\n\r\n$checkBox_debug.Add_CheckedChanged({\r\n    if ($checkBox_debug.Checked -eq $true){\r\n        $setDebug = $true\r\n    }\r\n    else {\r\n        $setDebug = $false\r\n    }\r\n    # update settings file\r\n    if (Test-Path .\\saverrSettings.xml) {\r\n        $script:settings = Import-Clixml .\\saverrSettings.xml\r\n        Add-Member -InputObject $settings -MemberType NoteProperty -Name 'logging' -Value $setDebug -force\r\n        $settings | Export-Clixml .\\saverrSettings.xml\r\n    }\r\n    else {\r\n        $script:settings = [pscustomobject] @{\r\n            logging = $setDebug\r\n        }\r\n        $settings | Export-Clixml .\\saverrSettings.xml\r\n    }\r\n    $settings = Import-Clixml .\\saverrSettings.xml\r\n    $debug = $settings.logging\r\n})\r\n\r\n$checkBox_ssl.Add_CheckedChanged({\r\n    if ($checkBox_ssl.Checked -eq $true){\r\n        $setSSL = $true\r\n    }\r\n    else {\r\n        $setSSL = $false\r\n    }\r\n    # update settings file\r\n    if (Test-Path .\\saverrSettings.xml) {\r\n        $script:settings = Import-Clixml .\\saverrSettings.xml\r\n        Add-Member -InputObject $settings -MemberType NoteProperty -Name 'ssl' -Value $setSSL -force\r\n        $settings | Export-Clixml .\\saverrSettings.xml\r\n    }\r\n    else {\r\n        $script:settings = [pscustomobject] @{\r\n            ssl = $setSSL\r\n        }\r\n        $settings | Export-Clixml .\\saverrSettings.xml\r\n    }\r\n    $settings = Import-Clixml .\\saverrSettings.xml\r\n    $ssl = $settings.ssl\r\n})\r\n\r\n\r\n# show extra season/artist fields\r\n$RadioButton_movie.Add_CheckedChanged($checked_type)\r\n$RadioButton_tv.Add_CheckedChanged($checked_type)\r\n$RadioButton_music.Add_CheckedChanged($checked_type)\r\n\r\n# Show season media info on selection\r\n$comboBox_results.Add_SelectedIndexChanged({mediaInfo})\r\n\r\n# show episodes after season selection\r\n$comboBox_seasons.Add_SelectedIndexChanged({episodeSelection})\r\n\r\n# show ep media info after season selection\r\n$comboBox_episodes.Add_SelectedIndexChanged({mediaEpInfo})\r\n\r\n# save server on selection\r\n$comboBox2_servers.Add_SelectedValueChanged({saveServer})\r\n\r\n$form2.add_FormClosing({clearStatusSave})\r\n\r\n# confirm closing. clear any downloads on close.\r\n$form.add_FormClosing({\r\n    if (Get-BitsTransfer) {\r\n        $question = [System.Windows.Forms.MessageBox]::Show(\"Are you sure you want to Exit?`nAll non-completed files will be deleted!\", 'Exit Saverr', 'YesNo', 'Question')\r\n\r\n        if ($question -eq 'Yes') {\r\n            $script:cancelLoop = $true\r\n            Get-BitsTransfer | Complete-BitsTransfer\r\n\r\n            # remove empty folders created\r\n            if (($dlType -like \"all*\") -and ($script:pauseLoop -eq $true)) {\r\n                if (Test-Path $allSeasonPath) {\r\n                    Get-ChildItem $allSeasonPath -Directory -recurse | where {-NOT $_.GetFiles(\"*\",\"AllDirectories\")} | del -recurse -ErrorAction SilentlyContinue\r\n                    if (Test-Path $allSeasonPath) {\r\n                        if ((Get-ChildItem $allSeasonPath | Measure-Object).Count -eq 0) {\r\n                            del $allSeasonPath -ErrorAction SilentlyContinue\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n\r\n        }\r\n        else {\r\n            $_.Cancel = $true\r\n        }\r\n    }\r\n})\r\n\r\n# show the form\r\n[void]$form.ShowDialog()\r\n\r\n# close the forms\r\n$form.Dispose()\r\n$form2.Dispose()\r\n# end\r\n"
  },
  {
    "path": "screenshots/README.MD",
    "content": "## Screenshots\n"
  }
]