Showing posts with label Perl. Show all posts
Showing posts with label Perl. Show all posts

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.

6 Sept 2008

Getmail for twitter

Getmail a nice little Perl script that when setup with a cron job automatically scans your inbox on behalf of you or one of your twitter apps for emails from twitter and responds accordingly.

There are two types of email messages it responds to the first, is the email you get from twitter when someone sends you a direct message, the second is the one that twitter sends you when someone follows you.


How it works

The Getmail script works as an imap client and accesses the inbox of whichever twitter bot it is monitoring. It uses the Mail::IMAPClient perl module. Once it has successfully connected to the mail sever it selects a mail box, ie your inbox, or a specific mailbox of your choosing.

Once inside it looks for any recent mail. To put it another way it checks for any mail that has the imap RECENT flag attached to it. There is a slight problem with this method in that a message is only flagged as RECENT if no other imap clients have seen it, bare that in mind if you want to use this on your personal mail box, it will stop the script from seeing any mail.

When the script finds a message that is RECENT it checks the headers for the twitter custom headers (for example "X-Twitteremailtype"), and checks their value.

If the X-Twitteremailtype value is "is_following" then it calls a subroutine called follow. This subroutine doesn't do anything yet, it's up to you to fill it with commands. The most obvious would be to auto-follow.

If the  X-Twitteremailtype is "direct_message" then it calls an empty subroutine called directMsg, once again it's up to you the user of the script to define what that subroutine does.

Any other emails it finds in the inbox it just ignores, which is probably a good thing ;)


Possible Applications of this groovy script


You are free to do with this script what ever you wish, of course. This script will obviously be useful if you want to auto-follow people who follow you, or your twitter app. Some people may find use for the directMsg subroutine.

My reason for writting this script was so I co redesign echobot to auto-follow new users and to check direct messages without having to query twitter.


The Source Code

#!/usr/bin/perl

# Getmail.pl (For Twitter)
# By James Januszka, @jamesjanuszka, http://blog.jamesjanuszka.com
# Do as you will with this script but don't blame me if it f**k's up

use strict; # Spank me!
use warnings; # Stop or I'll shoot!
use Mail::IMAPClient;
my $host = "imap.smurfmail.net"; # Contact your email admin for this address
my $username = "pappa\@smurf.com"; # Don't forget to escape characters. Example \@
my $pass = "I <3 Smurfette"; # If you don't know this then, er ... Good Luck!
my $folder ="INBOX";# Which folder you want to look in. Example INBOX 
my $imap;

sub login{
 # login
  $imap = Mail::IMAPClient->new(
            Server => $host,
            User    => $username,
            Password=> $pass,
            )or die "Cannot connect to $host as $username: $@";
}

sub checkMail{
 # Check your mail
 $imap->select($folder) or die "Could not select: $@\n";
 my @recent = $imap->recent;# This checks for recent mail, if you check this mailbox with another client then run this script, it won't have any recent mail. Sorry thats the IMAP specification for you.
 foreach (@recent){
  my $messageType = $imap->get_header($_, "X-Twitteremailtype");
  my $messageFrom = $imap->get_header($_, "X-Twittersenderscreenname");
  my $messageString = $imap->body_string($_);
  if ($messageType eq "direct_message"){
   directMsg("$messageString");
  }
  if ($messageType eq "is_following"){
   follow($messageFrom);
  } 
 }
 
}

sub directMsg{
 # Do what you do with your direct messages here. 
 my @string = split(/\r/, "@_");# Split message email by returns, I used /r because /n was giving me problems
 print "$string[0] \n";
}

sub follow{
 # Do what you do when someone follows you. Ooh could this be a way of Auto-following someone ? ;)
 print "##########################FOLLOW @_#########################\n";
}


sub logout {
 #logout
 $imap->logout or die "Could not logout: $@\n";
}

# It's all very well writing pretty subroutines, but you need to remember to call them 
login;
checkMail;
logout;


picture credit gaetanlee
 

10 Jun 2008

TinyUrl Perl Script

It's been a while since my last post so I thought I'd write up a quick post about what I did today.

I've been using the TinyUrl service for some time now and I came across their API, so I though I'd knock up a quick 'n' dirty script to make my TinyUrling easier.

#!/usr/bin/perl -w
use strict;
use LWP;
my $input = $ARGV[0];
$input =~ s/^ht{2}p:\/{2}//;
my $url = 'http://tinyurl.com/api-create.php?url=http://'.$input;
my $browser = LWP::UserAgent->new;
my $response = $browser->get($url);
die "Can't get $url --", $response->status_line unless $response->is_success;
print $response->content."\n"


This script takes your input and prints out the TinyUrl of it, usage is as follows;
$ perl -w tinyurl.pl www.google.com

which gives an output of;
http://tinyurl.com/1c2

Not bad for about 5 minutes work, I hope you will agree.