Controlling transmission using json-rpc in perl

For some time I have wanted to play with the json-rpc interface of Transmission. Today I jumped into it.

I decided to make a program that would run on my local computer and should be called via cron every X minutes, and scan a directory for .torrent files. Any .torrent files found should be added to the download queue in transmission - running on my OpenWrt router.

First of, I installed some perl modules using cpan

sudo cpan -i JSON::RPC MIME::Base64::Perl

and then I started programming. Using JSON::RPC and json-rpc documentation for transmission it is pretty simple once you get a hold of it. One thing I had problems with was the fact that transmissions rpc interface is password protected. How one should deal with this was not documented in JSON::RPC's documentation, so I downloaded the souce code for JSON::RPC::Client and started to read. It uses LWP::Simple, so there is support for basic authentication. This is a small example on how to configure it:

#!/usr/bin/perl

use JSON::RPC::Client;

my $client = new JSON::RPC::Client;  
$client->ua->credentials("host:9091",'Transmission RPC Server','user','pass');
my $uri = 'http://www.example.com/jsonrpc/Test';  
my $obj = {  
  method => 'sum',  
  params => [10, 20],  
};  
my $res = $client->call( $uri, $obj )  
# do handling here...

This was the first time I used rpc over json, and some time since I last programmed in perl, so it was a bit of a challenge, but as with most challenges it was also very fun - and I will definitely play around with transmission/json-rpc in the future.

Now, an example! A program that watches a directory for .torrent files, and adds them to transmission for downloading. Note that this functionality has since been added to transmission.

#!/usr/bin/perl

# ------------------------------------------------------------------------------
# "THE BEER-WARE LICENSE" (Revision 42):
# Jannich Brendle  wrote this file. As long as you retain
# this notice you can do whatever you want with this stuff. If we meet some day,
# and you think this stuff is worth it, you can buy me a beer in return
# Jannich Brendle
# ------------------------------------------------------------------------------

use JSON::RPC::Client;
use MIME::Base64::Perl qw(encode_base64);
use strict;

my $path='/tmp';    # the directory that needs watching
my $host='127.0.0.1';
my $port=9091;
my $username='test';
my $password='test';
my $uri = "http://$host:$port/transmission/rpc";
my $metadata ='';
my $client = new JSON::RPC::Client;

opendir(DIR, $path);
my @files= readdir(DIR); 
closedir(DIR);

$client->ua->credentials("$host:$port",'Transmission',$username,$password);

my @content;
$content[0] = $client->ua->get("http://$host:$port/transmission/rpc")->content;
@content = split('X-Transmission-Session-Id: ',$content[0]);
@content = split('',$content[1]);
$client->ua->default_header('X-Transmission-Session-Id'=>"$content[0]");

foreach my $file (@files) {
    next if ($file eq "." or $file eq "..");
    next if ($file  !~ m/torrent$/i);
    $metadata='';
    open(FILE, $path."/".$file) or die "$!";
    while (read(FILE, my $buf, 60*57)) {
        $metadata.= encode_base64($buf);
    }
    close(FILE);

    my $obj = {
       method  => 'torrent-add',
       arguments  => {metainfo=>$metadata}
    };

    my $res = $client->call( $uri, $obj ) || die $! . " $uri\n";

    if($res){
        if ($res->is_success) {
            unlink ($path . "/". $file);
        }
    }
}

To make the program run every 5 minutes, add this line to /etc/crontab:

*/5 * * * * username perl /path/to/addtorrents.pl

Of course you have to adjust the path to the program and the username.


Written by Jannich Brendle tor 09 juli 2009 In Programming

tags: howtoOpenWrtperltransmission

Related posts

social