From 92e646ff78152142bc63c4789c4051121c142950 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Tue, 13 Sep 2011 23:20:38 -0500 Subject: initial implementation --- lib/Linkulator/Twitter.pm | 163 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) (limited to 'lib/Linkulator/Twitter.pm') diff --git a/lib/Linkulator/Twitter.pm b/lib/Linkulator/Twitter.pm index e69de29..84134ce 100644 --- a/lib/Linkulator/Twitter.pm +++ b/lib/Linkulator/Twitter.pm @@ -0,0 +1,163 @@ +package Linkulator::Twitter; +use Moose; +use namespace::autoclean; +# ABSTRACT: scrape linkulator urls and turn them into tweets + +use LWP::UserAgent; +use Net::Twitter; +use String::Truncate 'elide'; +use WWW::Shorten 'VGd'; +use XML::RAI; + +use Linkulator::Twitter::Link; + +has feed_url => ( + is => 'ro', + isa => 'Str', + default => 'http://offtopic.akrasiac.org/?feed=sfw', +); + +has twitter_user => ( + is => 'ro', + isa => 'Str', + default => 'crawl_offtopic', +); + +has twitter_access_token => ( + is => 'ro', + isa => 'Str', + predicate => 'has_twitter_access_token', +); + +has twitter_access_token_secret => ( + is => 'ro', + isa => 'Str', + predicate => 'has_twitter_access_token_secret', +); + +has links => ( + traits => ['Array'], + isa => 'ArrayRef[Linkulator::Twitter::Link]', + default => sub { [] }, + handles => { + links => 'elements', + add_link => 'push', + }, +); + +has twitter_consumer_key => ( + is => 'ro', + isa => 'Str', + default => '6mW3vek1Edty1NGJe7yPFg', +); + +has twitter_consumer_secret => ( + is => 'ro', + isa => 'Str', + default => 'OzQuhNQ4HlO2eQw9tdo8R4QDLYqORwSEIzkF6ZBCAY', +); + +has ua => ( + is => 'ro', + isa => 'LWP::UserAgent', + default => sub { LWP::UserAgent->new }, +); + +has twitter => ( + is => 'ro', + isa => 'Net::Twitter', + lazy => 1, + default => sub { + my $self = shift; + Net::Twitter->new( + traits => ['API::REST', 'OAuth'], + consumer_key => $self->twitter_consumer_key, + consumer_secret => $self->twitter_consumer_secret, + ($self->has_twitter_access_token + ? (access_token => $self->twitter_access_token) + : ()), + ($self->has_twitter_access_token_secret + ? (access_token_secret => $self->twitter_access_token_secret) + : ()), + ); + }, +); + +sub authenticate_twitter { + my $self = shift; + my ($pin) = @_; + + return if $self->twitter->authorized; + + return $self->twitter->get_authorization_url + if !defined $pin; + + my ($token, $secret, $id, $user) = $self->twitter->request_access_token( + verifier => $pin, + ); + die "Authenticated the wrong user: $user (should be " . $self->twitter_user . ')' + unless $self->twitter_user eq $user; + + return ($token, $secret); +} + +sub update { + my $self = shift; + + my $res = $self->ua->get($self->feed_url); + die "couldn't get " . $self->feed_url . " : " . $res->status_line + unless $res->is_success; + + my $rss = $self->_munge_xml($res->content); + + my $feed = XML::RAI->parse_string($rss); + die "got no items!" unless $feed->item_count; + + for my $item (@{ $feed->items }) { + my ($link_num) = ($item->identifier =~ /(\d+)$/); + my $uri = $item->link; + $uri =~ s/^\s+|\s+$//g; + my $desc = $item->title; + $desc =~ s/^\s+|\s+$//g; + $self->add_link( + Linkulator::Twitter::Link->new( + id => $link_num, + uri => $uri, + desc => $desc, + ) + ); + } +} + +sub tweet { + my $self = shift; + my ($link) = @_; + + die "not a link" + unless blessed($link) && $link->isa('Linkulator::Twitter::Link'); + + my $uri = makeashorterlink($link->uri); + my $desc = elide($link->desc, 140 - length($uri) - 1, { at_space => 1 }); + + $self->twitter->update("$desc $uri"); +} + +# the feed produces invalid xml - the and tags don't escape +# ampersands in urls, and the xml parser chokes on this. need to fix it up +# here. +sub _munge_xml { + my $self = shift; + my ($xml) = @_; + + $xml =~ s#<(link|guid)(.*)>([^<]*)# + my ($tag, $attrs, $text) = ($1, $2, $3); + $text =~ s+&+&+g; + "<${tag}${attrs}>$text" + #eg; + + return $xml; +} + +__PACKAGE__->meta->make_immutable; + +1; -- cgit v1.2.3-54-g00ecf