Net::Laconica - Perl extension for fetching from, and sending notices/messages to Laconica instances


Net-Laconica documentation Contained in the Net-Laconica distribution.

Index


Code Index:

NAME

Top

Net::Laconica - Perl extension for fetching from, and sending notices/messages to Laconica instances

VERSION

Top

Version 0.08

SYNOPSIS

Top

    use Net::Laconica;

    my $identi = Net::Laconica->new(
        uri      => 'http://identi.ca/',
        username => 'alanhaggai',
        password => 'topsecret'
    );

    print map { $_, "\n" } $identi->fetch;

DESCRIPTION

Top

This module is designed to support fetching and sending messages to Laconica instances.

METHODS

Top

The implemented methods are:

new

Returns a blessed hash reference object. This method accepts a hash reference with uri, username and password as keys. uri and username are required, whereas password is optional.

uri

Holds the URI to the particular Laconica instance to which the object is to be bound.

Example:

    uri => 'http://identi.ca'  # Presence or absence of a trailing slash in the URI does not matter

username

Username for the Laconica instance.

Example:

    username => 'alanhaggai'

password

Password for the Laconica instance.

Password is required only if you wish to send messages.

Example:

    my $identi = Net::Laconica->new(
        uri      => 'http://identi.ca/',
        username => 'alanhaggai',
        password => 'topsecret'
    );

Or:

    my $identi = Net::Laconica->new(
        uri      => 'http://identi.ca/',
        username => 'alanhaggai',
        password => 'topsecret'
    );

fetch

Returns an array of recent messages.

Default number of recent messages returned is 10. The value can be changed by passing the value as an argument to the method. Maximum limit for the value is 20.

Example:

    my @messages = $laconica->fetch;  # Fetches the top 10 messages
                                      # (If there exists less than 10 messages,
                                      # they are all returned)

Or:

    my @messages = $laconica->fetch(3);  # Fetches the top 3 messages

send

Sends a message.

Returns 0 if an error occurs.

Example:

    if( $laconica->send('Hello world') ) {
        print 'Message sent successfully.';
    }

TODO

Top

These are some features which will be implemented soon:

* Migrate to the API once it is made a standard
* Delete notices
* Subscriptions
* Profile
* Favourites
* Replies
* Inbox
* Outbox
* Avatars

AUTHOR

Top

Alan Haggai Alavi, <alanhaggai at alanhaggai.org>

BUGS

Top

Please report any bugs or feature requests to bug-net-laconica at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-Laconica. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

Top

You can find documentation for this module with the perldoc command.

    perldoc Net::Laconica

You can also look for information at:

* RT: CPAN's request tracker

http://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-Laconica

* AnnoCPAN: Annotated CPAN documentation

http://annocpan.org/dist/Net-Laconica

* CPAN Ratings

http://cpanratings.perl.org/d/Net-Laconica

* Search CPAN

http://search.cpan.org/dist/Net-Laconica

COPYRIGHT & LICENSE

Top


Net-Laconica documentation Contained in the Net-Laconica distribution.
package Net::Laconica;

use warnings;
use strict;
use HTML::Parser;
use LWP::UserAgent;
use Data::Validate qw(is_alphanumeric);
use Data::Validate::URI qw(is_http_uri);
use Carp;

our $VERSION = '0.08';

my $ua = LWP::UserAgent->new;
$ua->agent('Mozilla');
$ua->cookie_jar({ file => 'cookies.txt' });


sub new {
    my $class = shift;
    my $self  = { login => 1, @_ };

    unless( exists $self->{uri} && exists $self->{username} && exists $self->{password}
        or exists $self->{uri} && exists $self->{username} ) {
        croak 'Invalid arguments';
    }

    # Sanitise arguments and check for validity
    is_http_uri($self->{uri}) || croak 'Invalid URI';
    is_alphanumeric($self->{username}) || croak 'Invalid username';

    # Append a slash at the end of uri if it does not end with one
    if( substr($self->{uri}, (length $self->{uri}) - 1, 1) ne '/' ) {
        $self->{uri} .= '/';
    }

    # Convert the username to lowercase and return the blessed reference
    $self->{username} = lc $self->{username};
    bless $self, $class;
}


sub fetch {
    my $self = shift;
    undef $self->{contents};
    my $number;

    # Get/set the number of messages to be fetched
    if( @_ == 1 ) {
        $number = shift;
        if($number > 20) {
            $number = 20;
        }
    } elsif( @_ == 0 ) {
        $number = 10;
    } else {
        croak 'Invalid arguments';
    }

    # Start fetching messages
    my $p = HTML::Parser->new(api_version => 3);
    $p->handler(start => sub { $self->_start_handler(@_) }, 'self,tagname,attr');
    $p->handler(end   => sub {
        return unless defined $self->{value};
        return if $self->{value} eq 'content' && shift eq 'a';
        $self->{value} = undef;
    }, 'tagname');
    $p->utf8_mode(1);

    my $response = $ua->get($self->{uri} . $self->{username} . '/all');
    $p->parse($response->content);

    unless( $self->{login} ) {
        croak 'Incorrect username';
    }

    # Ignore the first array element which is undef, and return the rest of the elements
    splice @{$self->{contents}}, 1, $number;
}


sub send {
    my $self = shift;
    my $message;

    unless( exists $self->{password} ) {
        return $self->{login} = 0;
    }

    if( @_ == 1 ) {
        # Strip the message to 140 characters if the message is longer
        $message = shift;
        if(length $message > 140) {
            $message = substr $message, 0, 140;
        }
    } else {
        croak 'Invalid arguments';
    }

    # Start sending messages
    my $p = HTML::Parser->new(api_version => 3);
    $p->handler(start => sub { $self->_start_handler(@_) }, 'self,tagname,attr');
    $p->handler(end   => sub {
        return unless defined $self->{value};
        return if $self->{value} eq 'content' && shift eq 'a';
        $self->{value} = undef;
    }, 'tagname');
    $p->utf8_mode(1);

    my $response = $ua->post($self->{uri} . 'main/login', [nickname => $self->{username}, password => $self->{password}]);
    $p->parse($response->content);

    # Return 0 if not logged in
    return 0 unless $self->{login};
    $response = $ua->post($self->{uri} . 'notice/new', [status_textarea => $message, returnto => 'all']);
}


sub _start_handler {
    my $class = shift;
    my $self  = shift;

    return unless exists $_[1]->{class};

    if( $_[1]->{class} eq 'nickname' ) {
        $class->{value} = 'nickname';
        $class->{counter}++;
    } elsif( $_[1]->{class} eq 'content' ) {
        $class->{value} = 'content';
    } elsif( $_[1]->{class} eq 'error' ) {
        $class->{value} = 'error';
    }

    $self->handler(text => sub {
        return unless defined $class->{value};
        if( $class->{value} eq 'content' ) {
            $class->{contents}[$class->{counter}] .= shift;
        } elsif( $class->{value} eq 'nickname' ) {
            $class->{contents}[$class->{counter}] .= shift(@_) . ': ';
        } elsif( $class->{value} eq 'error' ) {
            my $error = shift;
            if( $error eq 'Incorrect username or password.' || $error eq 'No such user.' ) {
                $class->{login} = 0;
            }
        }
    }, 'dtext');
}

1;

__END__

1; # End of Net::Laconica