File Coverage

blib/lib/Net/Disqus.pm
Criterion Covered Total %
statement 32 84 38.1
branch 5 34 14.7
condition 1 13 7.6
subroutine 9 14 64.2
pod 4 4 100.0
total 51 149 34.2


line stmt bran cond sub pod time code
1 4     4   30995 use warnings;
  4         10  
  4         160  
2 4     4   22 use strict;
  4         9  
  4         219  
3             package Net::Disqus;
4             BEGIN {
5 4     4   66 $Net::Disqus::VERSION = '1.19';
6             }
7 4     4   3842 use Try::Tiny;
  4         6696  
  4         253  
8 4     4   2236 use Net::Disqus::UserAgent;
  4         13  
  4         123  
9 4     4   2430 use Net::Disqus::Interfaces;
  4         11  
  4         112  
10 4     4   26 use Net::Disqus::Exception;
  4         7  
  4         27  
11 4     4   126 use base 'Class::Accessor';
  4         8  
  4         4415  
12              
13             __PACKAGE__->mk_ro_accessors(qw(api_key api_secret api_url ua pass_api_errors));
14             __PACKAGE__->mk_accessors(qw(interfaces rate_limit rate_limit_remaining rate_limit_reset fragment path));
15              
16             our $AUTOLOAD;
17              
18             sub new {
19 3     3 1 3585 my $class = shift;
20              
21 3 50       16 die Net::Disqus::Exception->new({ code => 500, text => '"new" is not an instance method'}) if(ref($class));
22              
23 0         0 my %args = (
24             secure => 0,
25             pass_api_errors => 0,
26             ua_args => {},
27 3 50 33     29 (@_ == 1 && ref $_[0] eq 'HASH') ? %{$_[0]} : @_,
28             interfaces => {},
29             api_url => 'http://disqus.com/api/3.0',
30             );
31              
32 3 100       30 die Net::Disqus::Exception->new({ code => 500, text => "missing required argument 'api_secret'"}) unless $args{'api_secret'};
33              
34 1         2 $args{'ua'} = Net::Disqus::UserAgent->new(%{$args{'ua_args'}});
  1         8  
35 1 50       6 $args{'api_url'} = 'https://secure.disqus.com/api/3.0' if($args{'secure'});
36 1         19 my $self = $class->SUPER::new({%args});
37              
38 1         24 $self->interfaces(Net::Disqus::Interfaces->INTERFACES());
39 1         30 return $self;
40             }
41              
42             sub fetch {
43 0     0 1   my $self = shift;
44 0           my $url = shift;
45 0           my $t = $self;
46              
47 0           $url =~ s/^\///;
48 0           my @url = split(/\//, $url);
49 0           my $last = pop(@url);
50              
51 0           $t = $t->$_() for(@url);
52 0           return $t->$last(@_);
53             }
54              
55             sub rate_limit_resets_in {
56 0     0 1   my $self = shift;
57 0           my $now = time();
58              
59 0 0         return ($now > $self->rate_limit_reset)
60             ? undef
61             : $self->rate_limit_reset - $now;
62             }
63              
64             sub rate_limit_wait {
65 0     0 1   my $self = shift;
66 0           my $now = time();
67 0   0       my $reset = $self->rate_limit_reset || 0;
68              
69 0 0         return undef unless($reset > 0);
70 0 0         return undef if($now > $reset);
71              
72 0           my $diff = $reset - $now;
73 0           my $remaining = $self->rate_limit_remaining;
74              
75 0 0 0       return undef if($diff == 0 || $remaining == 0);
76            
77             # we can do X requests every Y seconds to fill it up right
78             # to the reset time
79 0           my $wait = int($diff/$remaining);
80 0 0         $wait-- if($wait * $remaining > $diff);
81 0           return $wait;
82             }
83              
84             sub _mk_request {
85 0     0     my $self = shift;
86 0           my $fragment = $self->fragment;
87 0           my %args = (@_);
88              
89 0           $self->fragment(undef);
90              
91 0           my $url = sprintf('%s%s.json', $self->api_url, $self->path);
92 0           my $method = lc($fragment->{method});
93 0   0       my $required = $fragment->{required} || [];
94              
95 0           for(@$required) {
96 0 0         die Net::Disqus::Exception->new({ code => 500, text => "missing required argument '$_'"}) unless($args{$_});
97             }
98 0           $args{'api_secret'} = $self->api_secret;
99              
100             # and there we are.
101 0           my ($json, $rate) = $self->ua->request($method, $url, %args);
102 0 0 0       die Net::Disqus::Exception->new({ code => $json->{code}, text => $json->{response}}) if(!$self->pass_api_errors && $json->{code} != 0);
103              
104 0           $self->rate_limit($rate->{'X-Ratelimit-Limit'});
105 0           $self->rate_limit_remaining($rate->{'X-Ratelimit-Remaining'});
106 0           $self->rate_limit_reset($rate->{'X-Ratelimit-Reset'});
107 0           return $json;
108             }
109              
110             sub AUTOLOAD {
111 0     0     my $self = shift;
112 0 0         my $fragment = ((($_ = $AUTOLOAD) =~ s/.*://) ? $_ : "");
113 0 0         return if($fragment eq uc($fragment));
114              
115 0 0         unless($self->fragment) {
116 0           $self->fragment($self->interfaces);
117 0           $self->path('');
118             }
119 0           $self->path($self->path . '/' . $fragment);
120 0 0         if($self->fragment->{$fragment}) {
121 0           $self->fragment($self->fragment->{$fragment});
122 0 0         return ($self->fragment->{method})
123             ? $self->_mk_request(@_)
124             : $self;
125             } else {
126 0           $self->fragment(undef);
127 0 0         my $path = $self->path and $self->path(undef);
128 0           die Net::Disqus::Exception->new({ code => 500, text => "No such API endpoint"});
129             }
130             }
131            
132             1;
133             __END__