Thursday 20 October 2011

Using Powershell V3 to control utorrent via Webui and JSON

Script purpose
Create a powershell script that could change utorrent settings via the webUI interface.

Points
The Utorrent webUI communicates across HTML using JSON.
Powershell V3 preview has been released and it contains new functions to allow you to work with JSON objects.
Remember to check that the webUI is enabled in the utorrent application.

To be able to communicate with uTorrent you first need to understand the token authentication process. This involves authenticating with the application and then attaching a token to all future communications. All data returned from utorrent is in JSON format and can be parsed using the new powershell V3 function ConvertFrom-Json.

The resulting script can be use the adjust any of the utorrent setting. The uTorrent webUI API link below detials all the differnt commands.

Example execution
To ensure that the scheduler is enabled (I often disable it and forget to re enable it) I run the example below every day at 1 am. It sets the scheduler to be on.

#Enable utorrent scheduler
Utorrent-SetSettings "sched_enable" 1

Script
$Script:Version      = '0.1.0.1'
#########################################################
#Load config from file
#########################################################
[String]$Script:Server = 'servername'
[String]$Script:Port = 'port'
[String]$Script:User = 'utorrent user name'
[String]$Script:Pass = 'pass'

[String]$Script:UtorrentUrl = "http://$server`:$port/gui/"
[String]$Script:token = ""
$Script:webClient = $null

function Utorrent-HttpGet([string]$Comand)
{
    if ([string]::IsNullOrEmpty($Script:token) -eq $true -or $Script:webClient -eq $null) 
    {
        $Script:webClient = new-object System.Net.WebClient
        $Script:webClient.Headers.Add("user-agent", "PowerShell Script")
    
        if ([string]::IsNullOrEmpty($Script:User) -eq $false) 
        {
            $Script:webClient.Credentials = new-object System.Net.NetworkCredential($Script:User, $Script:Pass)
        }

        $responce = $Script:webClient.DownloadString($Script:UtorrentUrl + "token.html")
        [string]$cookies =  $Script:webClient.ResponseHeaders["Set-Cookie"]

        if ($responce -match ".*<div[^>]*id=[`"`']token[`"`'][^>]*>([^<]*)</div>.*")
        {
            $Script:token = $matches[1]
            $Script:webClient.Headers.Add("Cookie", $cookies)
     }
    }
    $url = "$($UtorrentUrl)?$($Comand)&token=$($Script:token)"
    Write-Host ("Calling url`t$url")
    $response = $Script:webClient.DownloadString($url)
    $json = ConvertFrom-JSON $response
    if($json.build -ne $null)
    {
        Write-Host ("Success $($json.build)")
    }
    return $json
}

function Utorrent-GetList() 
{
    Write-verbose ("$($MyInvocation.MyCommand.Name) v$Version")
 $dict = @{};
    $json = Utorrent-HttpGet "list=1"
    $json.torrents | Foreach-Object {
        $dict.add($_[2],$_)
    } 
    return $dict 
}

function Utorrent-GetSettings() 
{
 Write-verbose ("$($MyInvocation.MyCommand.Name) v$Version")
 $dict = @{};
    $json = Utorrent-HttpGet "action=getsettings"
    $json.settings | Foreach-Object {
        $dict.add($_[0],$_)
    } 
    $dict
}

function Utorrent-SetSettings([string]$setting, [string]$value) 
{
 Write-verbose ("$($MyInvocation.MyCommand.Name) v$Version")
    $json = Utorrent-HttpGet "action=setsetting&s=$setting&v=$value"
}

function Utorrent-GetTorrentFiles([string]$torrentHash) 
{
 Write-verbose ("$($MyInvocation.MyCommand.Name) v$Version")
 $dict = @{};
    $json = Utorrent-HttpGet "action=getfiles&hash=$torrentHash"
    $json.files | Foreach-Object {
        $dict.add($_[0],$_)
    } 
    $dict
}

function Utorrent-GetTorrentProps([string]$torrentHash) 
{
 Write-verbose ("$($MyInvocation.MyCommand.Name) v$Version")
 $dict = @{};
    $json = Utorrent-HttpGet "action=getprops&hash=$torrentHash"
    $json.props | Foreach-Object {
        $dict.add($_[0],$_)
    } 
    $dict
}

function Utorrent-SetTorrentProps([string]$torrentHash, [string]$property, [string]$value) 
{
 Write-verbose ("$($MyInvocation.MyCommand.Name) v$Version")
 $json = Utorrent-HttpGet "action=setprops&hash=$torrentHash&s=$property&v=$value"
}

function Utorrent-ParseSettings([string]$json) 
{
 if ([string]::IsNullOrEmpty($json) -eq $false -and $jayson[0] -eq "{")
    {
        return ConvertFrom-Json $json
    }
}