6 Mar 2011

Twitter OAuth Perl Module

Since Twitter changed their authentication method for using their API to OpenAuth, sending an automated tweet has become a whole lot more difficult.
In response to this I decided to code my own PERL module for OAuth.

Limitations of the module


Just before I post the code below I will mention that all this module currently does is allow you to post tweets, it does not handle retrieving access tokens or any other OAuth jazz. This module is really for single user twitter apps, like RSS feeds and twitter bots, or other situations where you already have all the required access tokens. If you register an app on twitter as a single access app, twitter will give you all the OAuth tokens you need. Point your browser at http://twitter.com/apps/new and sign in as your twitter bot or RSS feed posting account.

The Code


package Jimtweet;
#####JimTweet 0.1 By James Januszka 2010
#####Email:jimjanuszka@gmail.com
#####Twitter:@jamesjanuszka
use strict;
use warnings;
use LWP;
use HTTP::Headers;
use URI::Encode qw(uri_encode);
use URI::Escape qw(uri_escape);
use Digest::HMAC_SHA1;

####Constructor####
sub new {
 my $self={};
 $self->{OAUTH_VERSION}=uri_escape("1.0");
 $self->{OAUTH_SIGNATURE_METHOD}=uri_escape("HMAC-SHA1");
 $self->{OAUTH_TIMESTAMP}=undef;
 $self->{OAUTH_NONCE}=undef;
 $self->{AGENT}="jimtweet/0.1";
 $self->{URL}="http://api.twitter.com/1/statuses/update.xml";
 $self->{BROWSER}=LWP::UserAgent->new(agent =>$self->{AGENT});
 $self->{CONSUMER_KEY}=undef;
 $self->{CONSUMER_SECRET}=undef;
 $self->{OAUTH_TOKEN}=undef;
 $self->{OAUTH_TOKEN_SECRET}=undef;
 $self->{STATUS}=undef;
 bless($self);
 return $self;
} 

sub consumer_key{
 my $self=shift;
        if (@_) { $self->{CONSUMER_KEY}=uri_escape(shift) }
        return $self->{CONSUMER_KEY};
}
sub consumer_secret{
 my $self = shift;
        if (@_) { $self->{CONSUMER_SECRET}=uri_escape(shift) }
        return $self->{CONSUMER_SECRET};
}
sub oauth_token{
 my $self = shift;
        if (@_) { $self->{OAUTH_TOKEN}=uri_escape(shift) }
        return $self->{OAUTH_TOKEN};
}
sub oauth_token_secret{
 my $self = shift;
        if (@_) { $self->{OAUTH_TOKEN_SECRET}=uri_escape(shift) }
        return $self->{OAUTH_TOKEN_SECRET};
}

sub update_status(@){
 sleep(2);
 my $self = shift;
        if (@_) { $self->{STATUS}=uri_escape(shift) }
        my $seconds = time(); 
        $self->{OAUTH_TIMESTAMP}=uri_escape($seconds);
        $self->{OAUTH_NONCE}=$self->{OAUTH_TIMESTAMP};
       
       my $query=qq(oauth_consumer_key=$self->{CONSUMER_KEY}&oauth_nonce=$self->{OAUTH_NONCE}&oauth_signature_method=$self->{OAUTH_SIGNATURE_METHOD}&oauth_timestamp=$self->{OAUTH_TIMESTAMP}&oauth_token=$self->{OAUTH_TOKEN}&oauth_version=$self->{OAUTH_VERSION}&status=$self->{STATUS});
       
       my $sig="POST&";
$sig .=uri_encode($self->{URL},1);
$sig .="&";
$sig .=uri_encode($query,1);


my $sig_key=$self->{CONSUMER_SECRET};
$sig_key .="&";
$sig_key .=$self->{OAUTH_TOKEN_SECRET};

my $hmac = Digest::HMAC_SHA1->new($sig_key);
$hmac->add($sig);
my $oauth_signature_base64=$hmac->b64digest;
$oauth_signature_base64 .="=";
my $utf8_oauth_signature_base64=uri_escape($oauth_signature_base64);

my $debug="-v";
my $curlpost=qq(status=$self->{STATUS});

my $header=qq(OAuth oauth_nonce="$self->{OAUTH_NONCE}", oauth_signature_method="$self->{OAUTH_SIGNATURE_METHOD}", oauth_timestamp="$self->{OAUTH_TIMESTAMP}", oauth_consumer_key="$self->{CONSUMER_KEY}", oauth_token="$self->{OAUTH_TOKEN}", oauth_signature="$utf8_oauth_signature_base64", oauth_version="$self->{OAUTH_VERSION}");
my $req=HTTP::Request->new(POST => $self->{URL});
$req->content_type('application/x-www-form-urlencoded');
$req->content($curlpost);

$req->header('Authorization' => $header);  # set

my $res = $self->{BROWSER}->request($req);
return 1
}

####Footer####
1;  #so the require or use succeeds 


Usage


The first thing you need to do is include the module in your perl script, then you have to set up a new tweet object.

my $tweet=Jimtweet->new();

Next you have to specify your OAuth tokens

$tweet->consumer_key($consumer_key);
$tweet->consumer_secret($consumer_secret); 
$tweet->oauth_token($oauth_token);
$tweet->oauth_token_secret($oauth_token_secret);

Finally to send a tweet

$tweet->update_status($status);

The module sets up the nonce and timestamp for you as well as setting up the OAuth signature that many people have trouble with.

Well thats it I hope you all like it.

3 comments:

  1. Thank you James.

    I had a Python set up that did this, but your PERL approach is much simpler and easier to use.

    Best Regards,
    Bob Smither

    ReplyDelete
    Replies
    1. Thanks Bob,
      Hope it comes in useful.

      Delete
  2. Thanks a lot james.
    I was trying more scripts but not getting actual response.
    But your Perl code is very straight forward. Because I have used same concept in Ferite programming language and its working perfectly.

    Best Reagards,
    Mujibur Rahman

    ReplyDelete