summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorfranck cuny <franck@lumberjaph.net>2009-12-21 20:53:59 +0100
committerfranck cuny <franck@lumberjaph.net>2009-12-21 20:53:59 +0100
commitd42ef058b85760a2063c2ac209a4afa88978d918 (patch)
tree62578215b1735980b1d9416657e61f5d0fac0a85 /lib
parentfrom a dumb .pl to Tatsumaki (diff)
downloadlifestream-d42ef058b85760a2063c2ac209a4afa88978d918.tar.gz
basic Tatsumaki application
Diffstat (limited to '')
-rw-r--r--lib/Lifestream.pm50
-rw-r--r--lib/Lifestream/Handler.pm17
-rw-r--r--lib/Lifestream/Schema.pm6
-rw-r--r--lib/Lifestream/Schema/Result/Entry.pm34
-rw-r--r--lib/Lifestream/Schema/Result/Feed.pm34
-rw-r--r--lib/Lifestream/Worker.pm90
6 files changed, 231 insertions, 0 deletions
diff --git a/lib/Lifestream.pm b/lib/Lifestream.pm
new file mode 100644
index 0000000..c101ff1
--- /dev/null
+++ b/lib/Lifestream.pm
@@ -0,0 +1,50 @@
+package Lifestream;
+
+use Moose;
+extends "Tatsumaki::Application";
+
+use Lifestream::Handler;
+use Lifestream::Worker;
+
+our $VERSION = '0.01';
+
+has config => (
+ is => "rw",
+ isa => "HashRef"
+);
+
+has schema => (
+ is => 'ro',
+ isa => 'Lifestream::Schema',
+ lazy => 1,
+ default => sub {
+ my $self = shift;
+ return Lifestream::Schema->connect(
+ @{ $self->config->{connect_info} } );
+ }
+);
+
+sub app {
+ my ( $class, %args ) = @_;
+ my $self = $class->new( [ '/' => 'Lifestream::Handler', ] );
+ $self->config( $args{config} );
+ $self->add_service( Lifestream::Worker->new( config => $self->config ) );
+ $self;
+}
+
+sub memes {
+ my $self = shift;
+ my $page = shift || 1;
+ my $rs = $self->schema->resultset('Entry')
+ ->search( {}, { rows => 25, order_by => { -desc => [qw/date/], } } );
+ my $pager = $rs->page($page)->pager();
+ return { total => int($pager->total_entries / 25), memes => $rs->page($page) };
+}
+
+sub services {
+ my $self = shift;
+ my $services = $self->schema->resultset('Feed')->search();
+ return $services;
+}
+
+1;
diff --git a/lib/Lifestream/Handler.pm b/lib/Lifestream/Handler.pm
new file mode 100644
index 0000000..3dfd72d
--- /dev/null
+++ b/lib/Lifestream/Handler.pm
@@ -0,0 +1,17 @@
+package Lifestream::Handler;
+use Moose;
+extends 'Tatsumaki::Handler';
+
+sub get {
+ my $self = shift;
+ my %params = %{$self->request->params};
+ $self->render(
+ 'lifestream.html',
+ {
+ memes => $self->application->memes($params{page}),
+ services => $self->application->services
+ }
+ );
+}
+
+1;
diff --git a/lib/Lifestream/Schema.pm b/lib/Lifestream/Schema.pm
new file mode 100644
index 0000000..0bf0295
--- /dev/null
+++ b/lib/Lifestream/Schema.pm
@@ -0,0 +1,6 @@
+package Lifestream::Schema;
+use base qw/DBIx::Class::Schema/;
+
+__PACKAGE__->load_namespaces();
+
+1;
diff --git a/lib/Lifestream/Schema/Result/Entry.pm b/lib/Lifestream/Schema/Result/Entry.pm
new file mode 100644
index 0000000..43013c5
--- /dev/null
+++ b/lib/Lifestream/Schema/Result/Entry.pm
@@ -0,0 +1,34 @@
+package Lifestream::Schema::Result::Entry;
+use base qw/DBIx::Class/;
+
+__PACKAGE__->load_components(qw/Core/);
+__PACKAGE__->table('entry');
+__PACKAGE__->add_columns(
+ id => {
+ data_type => "varchar",
+ is_nullable => 0,
+ },
+ permalink => {
+ data_type => "varchar",
+ is_nullable => 0,
+ },
+ feedid => {
+ data_type => "integer",
+ is_nullable => 0,
+ },
+ date => {
+ data_type => "date",
+ is_nullable => 0,
+ },
+ title => {
+ data_type => "text",
+ is_nullable => 0,
+ },
+);
+__PACKAGE__->set_primary_key('id');
+__PACKAGE__->belongs_to(
+ feed => 'Lifestream::Schema::Result::Feed',
+ 'feedid'
+);
+
+1;
diff --git a/lib/Lifestream/Schema/Result/Feed.pm b/lib/Lifestream/Schema/Result/Feed.pm
new file mode 100644
index 0000000..8bb7bea
--- /dev/null
+++ b/lib/Lifestream/Schema/Result/Feed.pm
@@ -0,0 +1,34 @@
+package Lifestream::Schema::Result::Feed;
+use base qw/DBIx::Class/;
+
+__PACKAGE__->load_components(qw/Core/);
+__PACKAGE__->table('feed');
+__PACKAGE__->add_columns(
+ feedid => {
+ data_type => "integer",
+ is_nullable => 0,
+ is_auto_increment => 1
+ },
+ name => {
+ data_type => "text",
+ is_nullable => 0,
+ },
+ profile_url => {
+ data_type => "varchar",
+ is_nullable => 0,
+ },
+ feed_url => {
+ data_type => "varchar",
+ is_nullable => 0,
+ },
+ favico_url => {
+ data_type => "varchar",
+ is_nullable => 1,
+ }
+);
+__PACKAGE__->set_primary_key('feedid');
+__PACKAGE__->has_many(
+ entries => 'Lifestream::Schema::Result::Entry',
+ 'feedid'
+);
+1;
diff --git a/lib/Lifestream/Worker.pm b/lib/Lifestream/Worker.pm
new file mode 100644
index 0000000..c22abcb
--- /dev/null
+++ b/lib/Lifestream/Worker.pm
@@ -0,0 +1,90 @@
+package Lifestream::Worker;
+use Moose;
+extends 'Tatsumaki::Service';
+use Digest::SHA qw(sha256_hex);
+
+use Lifestream::Schema;
+
+use Tatsumaki::HTTPClient;
+use Try::Tiny;
+use XML::Feed;
+
+has config => (
+ is => "rw",
+ isa => "HashRef"
+);
+
+has schema => (
+ is => 'ro',
+ isa => 'Lifestream::Schema',
+ lazy => 1,
+ default => sub {
+ my $self = shift;
+ return Lifestream::Schema->connect(
+ @{ $self->config->{connect_info} } );
+ }
+);
+
+sub start {
+ my $self = shift;
+ my $t;
+ $t = AE::timer 0, 15, sub {
+ $self->fetch_feeds;
+ };
+ #$self->fetch_feeds();
+}
+
+sub fetch_feeds {
+ my $self = shift;
+ my $feeds = $self->schema->resultset('Feed')->search();
+ while ( my $feed = $feeds->next ) {
+ if ( !$feed->favico_url ) {
+ my $uri = URI->new( $feed->profile_url );
+ $uri->path('favicon.ico');
+ $self->schema->txn_do(
+ sub {
+ $feed->update( { favico_url => $uri->as_string } );
+ }
+ );
+ }
+ $self->work_feed( $feed->feed_url, $feed->id );
+ }
+}
+
+sub work_feed {
+ my ( $self, $url, $id ) = @_;
+ warn "fetching $url\n";
+ Tatsumaki::HTTPClient->new->get(
+ $url,
+ sub {
+ my $res = shift;
+ if ( !$res->is_success ) {
+ warn "can't fetch $url\n";
+ return;
+ }
+ my $feed = XML::Feed->parse( \$res->content );
+ for my $entry ( $feed->entries ) {
+ my $entry_id = sha256_hex( $entry->link );
+ next if $self->schema->resultset('Entry')->find($id);
+ try {
+ $self->schema->txn_do(
+ sub {
+ $self->schema->resultset('Entry')->find_or_create(
+ {
+ id => $entry_id,
+ permalink => $entry->link,
+ title => $entry->title,
+ date => $entry->issued,
+ feedid => $id,
+ }
+ );
+ }
+ );
+ }
+ catch { warn "can't insert meme : $_\n"; };
+ }
+ }
+ );
+}
+
+1;