summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2015-03-26 02:03:30 -0400
committerJesse Luehrs <doy@tozt.net>2015-03-26 02:03:30 -0400
commit37df3760ab4de8090fd56ed421bad9231e346186 (patch)
tree0e1bb5ad8f6d7779d6639f0bcdce209f975f810a
parentd60f4d4660de6c4c4a19b5334db7d33231bb8bfc (diff)
downloadwww-pocket-37df3760ab4de8090fd56ed421bad9231e346186.tar.gz
www-pocket-37df3760ab4de8090fd56ed421bad9231e346186.zip
initial implementation
-rw-r--r--bin/pocket6
-rw-r--r--lib/WWW/Pocket.pm119
-rw-r--r--lib/WWW/Pocket/Script.pm130
3 files changed, 255 insertions, 0 deletions
diff --git a/bin/pocket b/bin/pocket
new file mode 100644
index 0000000..c38d497
--- /dev/null
+++ b/bin/pocket
@@ -0,0 +1,6 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use WWW::Pocket::Script;
+WWW::Pocket::Script->new_with_options->run;
diff --git a/lib/WWW/Pocket.pm b/lib/WWW/Pocket.pm
index e69de29..20da851 100644
--- a/lib/WWW/Pocket.pm
+++ b/lib/WWW/Pocket.pm
@@ -0,0 +1,119 @@
+package WWW::Pocket;
+use Moose;
+
+use HTTP::Tiny;
+use JSON::PP;
+
+has consumer_key => (
+ is => 'rw',
+ isa => 'Str',
+);
+
+has access_token => (
+ is => 'rw',
+ isa => 'Str',
+);
+
+has username => (
+ is => 'rw',
+ isa => 'Str',
+);
+
+has base_uri => (
+ is => 'ro',
+ isa => 'Str',
+ default => 'https://getpocket.com/v3/',
+);
+
+has ua => (
+ is => 'ro',
+ isa => 'HTTP::Tiny',
+ lazy => 1,
+ default => sub { HTTP::Tiny->new },
+);
+
+sub start_authentication {
+ my $self = shift;
+ my ($consumer_key, $redirect_uri) = @_;
+
+ return if $self->consumer_key && $self->access_token;
+
+ $redirect_uri ||= 'https://getpocket.com/';
+
+ my $response = $self->_request(
+ $self->base_uri . 'oauth/request',
+ {
+ consumer_key => $consumer_key,
+ redirect_uri => $redirect_uri,
+ },
+ );
+ return $response->{code};
+}
+
+sub finish_authentication {
+ my $self = shift;
+ my ($consumer_key, $code) = @_;
+
+ my $response = $self->_request(
+ $self->base_uri . 'oauth/authorize',
+ {
+ consumer_key => $consumer_key,
+ code => $code,
+ },
+ );
+
+ $self->consumer_key($consumer_key);
+ $self->access_token($response->{access_token});
+ $self->username($response->{username});
+}
+
+sub add {
+ my $self = shift;
+ my (%params) = @_;
+ return $self->_endpoint_request('add', \%params);
+}
+
+sub modify {
+ my $self = shift;
+ my (%params) = @_;
+ return $self->_endpoint_request('send', \%params);
+}
+
+sub retrieve {
+ my $self = shift;
+ my (%params) = @_;
+ return $self->_endpoint_request('get', \%params);
+}
+
+sub _endpoint_request {
+ my $self = shift;
+ my ($endpoint, $params) = @_;
+ $params->{consumer_key} = $self->consumer_key;
+ $params->{access_token} = $self->access_token;
+ return $self->_request($self->base_uri . $endpoint, $params);
+}
+
+sub _request {
+ my $self = shift;
+ my ($uri, $params) = @_;
+
+ my $response = $self->ua->post(
+ $uri,
+ {
+ content => encode_json($params),
+ headers => {
+ 'Content-Type' => 'application/json; charset=UTF-8',
+ 'X-Accept' => 'application/json',
+ },
+ },
+ );
+ die "Request for $uri failed ($response->{status}): $response->{reason}"
+ unless $response->{success};
+
+ return decode_json($response->{content});
+}
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
diff --git a/lib/WWW/Pocket/Script.pm b/lib/WWW/Pocket/Script.pm
new file mode 100644
index 0000000..119894a
--- /dev/null
+++ b/lib/WWW/Pocket/Script.pm
@@ -0,0 +1,130 @@
+package WWW::Pocket::Script;
+use Moose;
+
+with 'MooseX::Getopt';
+
+use JSON::PP;
+use Path::Class;
+
+use WWW::Pocket;
+
+has consumer_key => (
+ is => 'ro',
+ isa => 'Str',
+ lazy => 1,
+ default => sub { die "consumer_key is required to authenticate" },
+);
+
+has redirect_uri => (
+ is => 'ro',
+ isa => 'Str',
+ default => 'https://getpocket.com/',
+);
+
+has credentials_file => (
+ is => 'ro',
+ isa => 'Str',
+ default => "$ENV{HOME}/.pocket",
+);
+
+has pocket => (
+ traits => ['NoGetopt'],
+ is => 'ro',
+ isa => 'WWW::Pocket',
+ lazy => 1,
+ default => sub {
+ my $self = shift;
+
+ my $pocket = WWW::Pocket->new;
+ my $credentials_file = file($self->credentials_file);
+ if (-e $credentials_file) {
+ $self->_apply_credentials($pocket, $credentials_file);
+ }
+ else {
+ $self->_authenticate($pocket);
+ }
+
+ $pocket
+ },
+);
+
+sub run {
+ my $self = shift;
+ my @args = @{ $self->extra_argv };
+
+ my $method = shift @args;
+ if ($self->can($method)) {
+ return $self->$method(@args);
+ }
+ else {
+ $self->print_usage_text($self->usage);
+ }
+}
+
+sub authenticate {
+ my $self = shift;
+ $self->pocket;
+}
+
+sub add {
+ my $self = shift;
+ my @args = @_;
+
+ $self->_pretty_print($self->pocket->add(@args));
+}
+
+sub modify {
+ my $self = shift;
+ my @args = @_;
+
+ $self->_pretty_print($self->pocket->modify(@args));
+}
+
+sub retrieve {
+ my $self = shift;
+ my @args = @_;
+
+ $self->_pretty_print($self->pocket->retrieve(@args));
+}
+
+sub _apply_credentials {
+ my $self = shift;
+ my ($pocket, $file) = @_;
+
+ my ($consumer_key, $access_token, $username) = $file->slurp(chomp => 1);
+ $pocket->consumer_key($consumer_key);
+ $pocket->access_token($access_token);
+ $pocket->username($username);
+}
+
+sub _authenticate {
+ my $self = shift;
+ my ($pocket) = @_;
+
+ my $consumer_key = $self->consumer_key;
+ my $redirect_uri = $self->redirect_uri;
+ my $code = $pocket->start_authentication($consumer_key, $redirect_uri);
+
+ print "Visit https://getpocket.com/auth/authorize?request_token=${code}&redirect_uri=${redirect_uri} and log in. When you're done, press enter to continue.\n";
+ <STDIN>;
+
+ $pocket->finish_authentication($consumer_key, $code);
+
+ my $fh = file($self->credentials_file)->openw;
+ $fh->write($pocket->consumer_key . "\n");
+ $fh->write($pocket->access_token . "\n");
+ $fh->write($pocket->username . "\n");
+ $fh->close;
+}
+
+sub _pretty_print {
+ my $self = shift;
+ my ($data) = @_;
+
+ print JSON::PP->new->utf8->pretty->canonical->encode($data), "\n";
+}
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;