diff --git a/CouchPotato/CouchPotato-logo.png b/CouchPotato/CouchPotato-logo.png
new file mode 100644
index 0000000..d3e6d9f
Binary files /dev/null and b/CouchPotato/CouchPotato-logo.png differ
diff --git a/CouchPotato/CouchPotato.nuspec b/CouchPotato/CouchPotato.nuspec
new file mode 100644
index 0000000..e85fbe5
--- /dev/null
+++ b/CouchPotato/CouchPotato.nuspec
@@ -0,0 +1,45 @@
+
+
+
+ CouchPotato
+ CouchPotato automatic NZB downloader
+ 2012.11.04
+ RuudBurger
+ Ethan Brown
+ CouchPotato (CP) is an automatic NZB and torrent downloader. You can keep a "movies I want"-list and it will search for NZBs/torrents of these movies every X hours. Once a movie is found, it will send it to SABnzbd or download the torrent to a specified directory.
+ CouchPotato is an automatic NZB and torrent downloader.
+You can keep a "want to watch"-list and it will search for NZBs/torrents of these items every X hours. Once a correct release is found, matching the correct quality, it will send it to SABnzbd or download the .nzb or .torrent to a specified directory.
+
+ This package performs a number of normally quite painful / tedious tasks
+ - Installs SABnzbd+ (compiled version)
+ - Installs Python
+ - Installs PyWin32
+ - Git clones the CouchPotato source to site-packages
+ - Configures Git within CouchPotato to auto-update
+ - Configures for XBMC metadata
+ - Configures XMBC notifications - to port 9090 as SABnzbd+ uses 8080
+ - Configures CouchPotato to send NZBs to SABnzbd+ using API key
+ - Configures CouchPotato to run as a Windows service
+ - Configured alternate sabToCouchPotato.py SABnzbd+ post-processing scripts
+
+ https://couchpota.to/
+ CouchPotato Python Usenet NZB torrent
+ https://github.com/RuudBurger/CouchPotatoServer/blob/master/license.txt
+ false
+ https://github.com/Iristyle/ChocolateyPackages/raw/master/CouchPotato/CouchPotato-logo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CouchPotato/tools/chocolateyInstall.ps1 b/CouchPotato/tools/chocolateyInstall.ps1
new file mode 100644
index 0000000..e794cb9
--- /dev/null
+++ b/CouchPotato/tools/chocolateyInstall.ps1
@@ -0,0 +1,347 @@
+$package = 'CouchPotato'
+
+try {
+
+ function Get-CurrentDirectory
+ {
+ $thisName = $MyInvocation.MyCommand.Name
+ [IO.Path]::GetDirectoryName((Get-Content function:$thisName).File)
+ }
+
+ . (Join-Path (Get-CurrentDirectory) 'Get-IniContent.ps1')
+ . (Join-Path (Get-CurrentDirectory) 'Out-IniFile.ps1')
+ . (Join-Path (Get-CurrentDirectory) 'WaitForSuccess.ps1')
+
+ #simulate the unix command for finding things in path
+ #http://stackoverflow.com/questions/63805/equivalent-of-nix-which-command-in-powershell
+ function Which([string]$cmd)
+ {
+ Get-Command -ErrorAction "SilentlyContinue" $cmd |
+ Select -ExpandProperty Definition
+ }
+
+ $couchPotatoRunning = {
+ $service = Get-Service 'CouchPotato' -ErrorAction SilentlyContinue
+ return ($service -and ($service.Status -eq 'Running'))
+ }
+ $couchPotatoServing = {
+ $pingUrl = 'http://localhost:5050/docs/'
+ try
+ {
+ (New-Object Net.WebClient).DownloadString($pingUrl)
+ return $true
+ }
+ catch {}
+
+ return $false
+ }
+
+ # Use PYTHONHOME if it exists, or fallback to 'Where' to search PATH
+ if ($Env:PYTHONHOME) { $localPython = Join-Path $Env:PYTHONHOME 'python.exe' }
+
+ if (!$Env:PYTHONHOME -or !(Test-Path $localPython))
+ { $localPython = Which python.exe }
+
+ if (!(Test-Path $localPython))
+ {
+ Write-ChocolateyFailure 'CouchPotato requires a Python runtime to install'
+ return
+ }
+
+ $pythonRoot = Split-Path $localPython
+
+ # as we're running a service as SYSTEM, Machine needs python in PATH
+ # TODO: Bug in Install-ChocolateyPath won't add to MACHINE if already in USER
+ $setMachinePathScript = @"
+ `$vars = [Environment]::GetEnvironmentVariable('PATH', 'Machine') -split ';';
+ if (!(`$vars -contains '$pythonRoot')) { `$vars += '$pythonRoot' };
+ [Environment]::SetEnvironmentVariable('PATH', (`$vars -join ';'), 'Machine');
+ [Environment]::SetEnvironmentVariable('PYTHONHOME', '$pythonRoot', 'Machine');
+"@
+
+ Start-ChocolateyProcessAsAdmin $setMachinePathScript
+
+ $sitePackages = (Join-Path (Join-Path $pythonRoot 'Lib') 'site-packages')
+ if (!(Test-Path $sitePackages))
+ {
+ Write-ChocolateyFailure 'Could not find Python site-packages directory'
+ return
+ }
+
+ # grab the latest sources if not present
+ Push-Location $sitePackages
+ $git = Which git
+ $couchPotatoPath = (Join-Path $sitePackages 'CouchPotatoServer')
+ $couchPotatoEmpty = $true
+ if (Test-Path $couchPotatoPath)
+ {
+ $files = Get-ChildItem $couchPotatoPath -Recurse -ErrorAction SilentlyContinue
+ $couchPotatoEmpty = ($files.Count -eq 0)
+ }
+ if (!$couchPotatoEmpty)
+ {
+ Write-ChocolateySuccess 'CouchPotato already installed!'
+ return
+ }
+ else
+ {
+ Write-Host 'Cloning CouchPotato source from GitHub'
+ &git clone https://github.com/RuudBurger/CouchPotatoServer.git
+ }
+
+ # Read SABNzbd+ config file to find scripts directory
+ $sabDataPath = Join-Path $Env:LOCALAPPDATA 'sabnzbd'
+ $sabIniPath = Join-Path $sabDataPath 'sabnzbd.ini'
+ if (Test-Path $sabIniPath)
+ {
+ Write-Host "Reading SABnzbd+ config file at $sabIniPath"
+ $sabConfig = Get-IniContent -Path $sabIniPath
+
+ # 3 options - missing script_dir, script_dir set to "", or configured script_dir
+ if (!$sabConfig.misc.script_dir -or `
+ ($sabConfig.misc.script_dir -eq "`"`""))
+ {
+ $scriptDir = (Join-Path $sabDataPath 'scripts')
+ Write-Host "Configured SABnzbd+ script_dir to $scriptDir"
+ $sabConfig.misc.script_dir = $scriptDir
+ $sabConfig | Out-IniFile -FilePath $sabIniPath -Force -Encoding UTF8
+ }
+
+ if (!(Test-Path $sabConfig.misc.script_dir))
+ {
+ New-Item -Path $sabConfig.misc.script_dir -Type Directory | Out-Null
+ }
+
+ # To use alternate CouchPotato script, requires modified SickBeard bits
+ # copy and configure autoprocessing scripts in SABNzbd+ scripts directory
+ Write-Host "Copying CouchPotato post-processing scripts to SABnzbd+"
+ Get-ChildItem (Get-CurrentDirectory) -Filter '*.py' |
+ # overwrite SickBeard scripts if they exist
+ Copy-Item -Destination $sabConfig.misc.script_dir -Force
+
+ if (!$sabconfig.categories.movies)
+ {
+ Write-Host "Configuring movies category inside SABnzbd+"
+ $movies = New-Object Collections.Specialized.OrderedDictionary
+ $movies.priority = 0;
+ $movies.pp = 3; # Download + Unpack +Repair +Delete
+ $movies.name = 'movies';
+ $movies.script = 'sabToCouchPotato.py';
+ $movies.newzbin = '';
+ $movies.dir = 'movies';
+ $sabconfig.categories.movies = $movies
+ }
+
+ if (([string]::IsNullOrEmpty($sabconfig.categories.movies.script)) -or `
+ ($sabconfig.categories.movies.script -ieq 'None') -or
+ ($sabconfig.categories.movies.script -ieq "`"`""))
+ {
+ $sabconfig.categories.movies.script = 'sabToCouchPotato.py'
+ }
+
+ # allows failed post processing of empty files (out of retention, etc)
+ $sabConfig.misc.empty_postproc = 1
+
+ Write-Host 'Configured movies category in SABnzbd+'
+ $sabConfig | Out-IniFile -FilePath $sabIniPath -Force -Encoding UTF8
+ }
+
+ # regardless of sabnzbd+ install status, .PY should be executable
+ if (($ENV:PATHEXT -split ';') -inotcontains '.PY')
+ {
+ Write-Host 'Adding .PY to PATHEXT'
+ $ENV:PATHEXT += ';.PY'
+ [Environment]::SetEnvironmentVariable('PATHEXT', $ENV:PATHEXT, 'Machine')
+ }
+
+ # find resource kit tools and configure CouchPotato as a service
+ # http://htpcbuild.com/htpc-software/sickbeard/sickbeard-service/
+ # http://stackoverflow.com/questions/32404/can-i-run-a-python-script-as-a-service-in-windows-how
+ $resourceKit = ${Env:ProgramFiles(x86)}, $Env:ProgramFiles |
+ % { Join-Path (Join-Path $_ 'Windows Resource Kits') 'Tools' } |
+ ? { Test-Path $_ } |
+ Select -First 1
+
+ if ($resourceKit)
+ {
+ Write-Host "Found resource kit - registering CouchPotato as a service"
+ Push-Location $resourceKit
+ $srvAny = Join-Path $resourceKit 'srvany.exe'
+ .\instsrv CouchPotato $srvany | Out-Null
+
+ # Set-Service cmdlet doesn't have depend OR delayed start :(
+ Write-Host "Configuring service delayed auto with Tcpip dependency"
+ sc.exe config CouchPotato depend= Tcpip
+ sc.exe config CouchPotato start= delayed-auto
+ Pop-Location
+
+ New-Item HKLM:\SYSTEM\CurrentControlSet\Services -Name CouchPotato `
+ -ErrorAction SilentlyContinue | Out-Null
+ New-Item HKLM:\SYSTEM\CurrentControlSet\Services\CouchPotato `
+ -Name Parameters -ErrorAction SilentlyContinue | Out-Null
+ $couchPotatoParams = Get-Item HKLM:\SYSTEM\CurrentControlSet\Services\CouchPotato\Parameters
+ New-ItemProperty -Path $couchPotatoParams.PSPath -PropertyType String `
+ -Name 'AppDirectory' -Value $pythonRoot -Force | Out-Null
+ $pythonW = (Join-Path $pythonRoot 'pythonw.exe')
+ New-ItemProperty -Path $couchPotatoParams.PSPath -PropertyType String `
+ -Name 'Application' -Value $pythonW -Force | Out-Null
+ $startCouchPotato = (Join-Path $couchPotatoPath 'CouchPotato.py')
+ New-ItemProperty -Path $couchPotatoParams.PSPath -PropertyType String `
+ -Name 'AppParameters' -Value $startCouchPotato -Force | Out-Null
+
+ Start-Service CouchPotato
+
+ $sysProfile = Join-Path 'config' 'systemprofile'
+ $roamingData = Join-Path $sysProfile 'AppData\Roaming'
+
+ # config files are created on first start-up
+ $configPath = (Join-Path ([Environment]::GetFolderPath('System')) $roamingData),
+ # must handle SYSWOW64 on x64 (works inside both 32-bit and 64-bit host procs)
+ (Join-Path ([Environment]::GetFolderPath('SystemX86')) $roamingData) |
+ Select -Unique |
+ ? { Test-Path $_ } |
+ % { Join-Path $_ 'CouchPotato\settings.conf' } |
+ Select -First 1
+ Write-Host "Expecting configuration file at $configPath"
+
+ # to start hacking settings.conf the service needs to be up, settings.conf needs
+ # to exist, and CouchPotato must respond to requests (settings.conf is complete)
+ $waitOnConfig = {
+ if (!(&$couchPotatoRunning)) { return $false }
+ if (!(Test-Path $configPath)) { return $false }
+ return &$couchPotatoServing
+ }
+
+ if (WaitForSuccess $waitOnConfig 20 'CouchPotato to start and create config')
+ {
+ Write-Host 'CouchPotato started and configuration files created'
+ # an alternative to modifying conf directly is to use the API
+ # /api/KEY/settings
+ $couchPotatoConfig = Get-IniContent -Path $configPath
+ $couchPotatoApiKey = $couchPotatoConfig.core.api_key
+
+ Write-Host 'Configuring Windows Firewall for the CouchPotato port'
+ # configure windows firewall
+ netsh advfirewall firewall delete rule name="CouchPotato"
+ # program="$pythonW"
+ $port = $couchPotatoConfig.core.port
+ netsh advfirewall firewall add rule name="CouchPotato" dir=in protocol=tcp localport=$port action=allow
+
+ $couchPotatoConfig.core.launch_browser = 'False'
+
+ # make sure autoupdate is turned on with a correct path to Git
+ $couchPotatoConfig.updater.notification = 'True'
+ $couchPotatoConfig.updater.enabled = 'True'
+ $couchPotatoConfig.updater.git_command = "`"$($git -replace '\\', '\\')`""
+ $couchPotatoConfig.updater.automatic = 'True'
+
+ $movieDownloads = Join-Path (Join-Path $sabDataPath 'Downloads') `
+ $sabConfig.categories.movies.dir
+
+ $couchPotatoConfig.manage.cleanup = 'True'
+ # TODO: once we can sniff out the XBMC directory, we can auto-config this
+ # $couchPotatoConfig.manage.enabled = 'False'
+ # $couchPotatoConfig.manage.library = ''
+
+ # Write-Host "Using SABNzbd+ movies download directory, but the to must be configured"
+ $couchPotatoConfig.renamer.from = "`"$($movieDownloads -replace '\\', '\\')`""
+ $couchPotatoConfig.renamer.enabled = 'True'
+ $couchPotatoConfig.renamer.cleanup = 'True'
+ $couchPotatoConfig.renamer.folder_name = ' []'
+ $couchPotatoConfig.renamer.move_leftover = 1
+ # because we're using alternate post-processing script, don't auto-run this
+ # on a schedule
+ $couchPotatoConfig.renamer.run_every = 0
+
+ # configure for XBMC with default user / pass of xbmc / xbmc
+ $couchPotatoConfig.xbmc.enabled = 1
+ $couchPotatoConfig.xbmc.meta_enabled = 'True'
+ $couchPotatoConfig.xbmc.meta_thumbnail = 'True'
+ $couchPotatoConfig.xbmc.meta_fanart = 'True'
+ $couchPotatoConfig.xbmc.meta_nfo = 'True'
+ $couchPotatoConfig.xbmc.host = 'localhost:9090'
+ $couchPotatoConfig.xbmc.username = 'xbmc'
+ $couchPotatoConfig.xbmc.password = 'xbmc'
+
+ # configure CouchPotato to use SABNzbd
+ $couchPotatoConfig.sabnzbd.enabled = 1
+ $couchPotatoConfig.sabnzbd.api_key = $sabConfig.misc.api_key
+ $couchPotatoConfig.sabnzbd.category = 'movies'
+ $couchPotatoConfig.sabnzbd.host = "localhost:$($sabConfig.misc.port)"
+
+ $couchPotatoConfig |
+ Out-IniFile -File $configPath -Force -Encoding ASCII |
+ Out-Null
+
+ $restartUrl = "http://localhost:$port/api/$couchPotatoApiKey/app.restart/"
+ try
+ {
+ Write-Host "Restarting CouchPotato using API to accept config"
+ (New-Object Net.WebClient).DownloadString($restartUrl)
+ }
+ catch
+ {
+ Write-Host "Error using API - restarting service manually"
+ Restart-Service CouchPotato
+ }
+ }
+
+ # Using alternative CouchPotato renamer script like SickBeard
+ # https://couchpota.to/forum/showthread.php?tid=343
+ # files at http://www.freefilehosting.net/autoprocessmediabuilds-win
+ # The main benefits to this script are:
+ # 1 less CPU usage (due to SABnzbd polling an regular disk scanning etc)
+ # 2 less hard disk scanning
+ # 3 ability to get hard disk to spin down when not downloading
+ # 4 the renamer is fired (on demand)
+ # 5 if you are using SABnzbd renaming this script will add to the manage list without using the renamer.
+
+ $autoConfig = Join-Path $sabConfig.misc.script_dir 'autoProcessMovie.cfg'
+ if (!(Test-Path $autoConfig))
+ {
+ # order shouldn't matter, but don't trust Python ;0
+ $sbAuto = New-Object Collections.Specialized.OrderedDictionary
+ $sbAuto.host = $couchPotatoConfig.core.host -replace '0\.0\.0\.0',
+ 'localhost';
+ $sbAuto.port = $couchPotatoConfig.core.port;
+ $sbAuto.username = $couchPotatoConfig.core.username;
+ $sbAuto.password = $couchPotatoConfig.core.password;
+ $sbAuto.ssl = 0;
+ $sbAuto.web_root = $couchPotatoConfig.core.url_base;
+ $sbAuto.apikey = $couchPotatoConfig.core.api_key
+ $sbAuto.delay = 60 # must be minimum of 60 seconds
+ $sbAuto.method = 'renamer' #or 'manage'
+
+ @{ 'CouchPotato' = $sbAuto } |
+ Out-IniFile -FilePath $autoConfig -Encoding ASCII -Force
+
+ Write-Host @"
+CouchPotato SABNzbd+ post-processing scripts configured
+ If CouchPotato is reconfigured with a username or password or another
+ host or different API key then those same changes must be made to $configPath
+"@
+ }
+
+ $url = ("http://localhost:$($sabConfig.misc.port)/api?mode=restart" +
+ "&apikey=$($sabConfig.misc.api_key)")
+ Write-Host "Restarting SABnzbd+ to accept configuration changes at $url"
+ (New-Object Net.WebClient).DownloadString($url)
+
+ #wait up to 5 seconds for service to fire up
+ if (WaitForSuccess $couchPotatoServing 5 'CouchPotato to start')
+ {
+ #launch local default browser for additional config
+ $configUrl = "http://localhost:$($couchPotatoConfig.core.port)"
+ [Diagnostics.Process]::Start($configUrl) | Out-Null
+ }
+
+ Write-Host "For use in other apps, CouchPotato API key: $couchPotatoApiKey"
+
+ Pop-Location
+ }
+
+ Write-ChocolateySuccess $package
+} catch {
+ Write-ChocolateyFailure $package "$($_.Exception.Message)"
+ throw
+}
diff --git a/CouchPotato/tools/chocolateyUninstall.ps1 b/CouchPotato/tools/chocolateyUninstall.ps1
new file mode 100644
index 0000000..d03c273
--- /dev/null
+++ b/CouchPotato/tools/chocolateyUninstall.ps1
@@ -0,0 +1,134 @@
+$package = 'CouchPotato'
+
+try
+{
+ function Get-CurrentDirectory
+ {
+ $thisName = $MyInvocation.MyCommand.Name
+ [IO.Path]::GetDirectoryName((Get-Content function:$thisName).File)
+ }
+
+ # load INI parser
+ . (Join-Path (Get-CurrentDirectory) 'Get-IniContent.ps1')
+ . (Join-Path (Get-CurrentDirectory) 'Out-IniFile.ps1')
+
+ #simulate the unix command for finding things in path
+ #http://stackoverflow.com/questions/63805/equivalent-of-nix-which-command-in-powershell
+ function Which([string]$cmd)
+ {
+ Get-Command -ErrorAction "SilentlyContinue" $cmd |
+ Select -ExpandProperty Definition
+ }
+
+ Write-Host 'Deleting CouchPotato Windows Firewall config'
+ netsh advfirewall firewall delete rule name="CouchPotato"
+
+ # check registry for path to CouchPotato
+ $servicePath = 'HKLM:\SYSTEM\CurrentControlSet\Services\CouchPotato\Parameters'
+ $installDir = Get-ItemProperty $servicePath -ErrorAction SilentlyContinue |
+ Select -ExpandProperty AppParameters
+
+ if ($installDir)
+ {
+ $couchPotatoDir = Split-Path $installDir
+ $sitePackages = Split-Path $couchPotatoDir
+ Write-Host "Found CouchPotato service configuration directory of $couchPotatoDir"
+ }
+ # not found - do some guesswork
+ else
+ {
+ # Use PYTHONHOME if it exists, or fallback to 'Where' to search PATH
+ if ($Env:PYTHONHOME) { $localPython = Join-Path $Env:PYTHONHOME 'python.exe' }
+
+ if (!$Env:PYTHONHOME -or !(Test-Path $localPython))
+ { $localPython = Which python.exe }
+
+ if (!(Test-Path $localPython))
+ {
+ Write-Warning 'Could not find CouchPotato or Python!'
+ }
+ else
+ {
+ $pythonRoot = Split-Path $localPython
+ $sitePackages = (Join-Path (Join-Path $pythonRoot 'Lib') 'site-packages')
+ $couchPotatoDir = Join-Path $sitePackages 'CouchPotatoServer'
+ Write-Host "CouchPotato service configuration not found - assuming $couchPotatoDir"
+ }
+ }
+
+ # delete the service and reg keys
+ if (Get-Service CouchPotato -ErrorAction SilentlyContinue)
+ {
+ Write-Host 'Deleting CouchPotato service'
+ Stop-Service CouchPotato
+ sc.exe delete CouchPotato
+ }
+
+ # we found CouchPotato on disk, so delete all the files
+ if (Test-Path $couchPotatoDir)
+ {
+ Write-Host "Removing all files in $couchPotatoDir"
+ Remove-Item $couchPotatoDir -Recurse -Force -ErrorAction SilentlyContinue
+ if (Test-Path $couchPotatoDir)
+ {
+ Write-Warning "$couchPotatoDir must be deleted manually"
+ }
+ }
+
+ $sysProfile = Join-Path 'config' 'systemprofile'
+ $couchPotatoData = Join-Path (Join-Path 'AppData' 'Roaming') 'CouchPotato'
+ $couchPotatoData = Join-Path $sysProfile $couchPotatoData
+
+ # config files are created on first start-up
+ $configPath = (Join-Path ([Environment]::GetFolderPath('System')) $couchPotatoData),
+ # must handle SYSWOW64 on x64 (works inside both 32-bit and 64-bit host procs)
+ (Join-Path ([Environment]::GetFolderPath('SystemX86')) $couchPotatoData) |
+ Select -Unique |
+ % {
+ if (Test-Path $_)
+ {
+ Write-Warning "$_ data directory must be deleted manually"
+ }
+ }
+
+ # Read SABNzbd+ config file to delete CouchPotato scripts if configured
+ $sabDataPath = Join-Path $Env:LOCALAPPDATA 'sabnzbd'
+ $sabIniPath = Join-Path $sabDataPath 'sabnzbd.ini'
+ if (Test-Path $sabIniPath)
+ {
+ Write-Host "Reading SABnzbd+ config file at $sabIniPath"
+ $sabConfig = Get-IniContent $sabIniPath
+
+ $scriptsDir = $sabConfig.misc.script_dir
+ # found a legit scripts dir, so delete CouchPotato files
+ if ($scriptsDir -and ($scriptsDir -ne "`"`"") -and (Test-Path $scriptsDir))
+ {
+ Write-Warning "SABnzbd+ post-processing scripts at $scriptsDir must be deleted manually"
+ }
+
+ $movies = $sabconfig.categories.movies
+ if ($movies -and ($movies.script -eq 'sabToCouchPotato.py'))
+ {
+ Write-Host 'Removed sabToCouchPotato.py script from movies category inside SABnzbd+'
+ $movies.script = 'None'
+ $sabConfig | Out-IniFile -FilePath $sabIniPath -Force -Encoding UTF8
+ }
+
+ Write-Host 'Restarting SABnzbd+ to accept configuration changes'
+ $url = ("http://localhost:$($sabConfig.misc.port)/api?mode=restart" +
+ "&apikey=$($sabConfig.misc.api_key)")
+ try
+ {
+ (New-Object Net.WebClient).DownloadString($url)
+ }
+ catch
+ {
+ Write-Host "SABNzbd+ not responding to restart request"
+ }
+ }
+
+ Write-ChocolateySuccess $package
+} catch {
+ Write-ChocolateyFailure $package "$($_.Exception.Message)"
+ throw
+}