File Coverage

blib/lib/Github/Score.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1             package Github::Score;
2             #ABSTRACT: Pull author contribution counts for github repos
3              
4 1     1   42920 use strict;
  1         1  
  1         37  
5 1     1   5 use warnings;
  1         2  
  1         30  
6 1     1   872 use LWP;
  1         50962  
  1         31  
7 1     1   1087 use JSON;
  1         38817  
  1         6  
8 1     1   167 use HTTP::Request;
  1         2  
  1         30  
9 1     1   47 use URI;
  1         2  
  1         31  
10              
11 1     1   6 use Data::Dumper;
  1         11  
  1         65  
12              
13 1     1   1192 use Moose; # automatically turns on strict and warnings
  0            
  0            
14              
15             has 'user' => (is => 'rw', );
16             has 'repo' => (is => 'rw', );
17             has 'timeout' => (is => 'rw', );
18             has 'api_version' => (is => 'rw', );
19              
20             sub clear {
21             my $self = shift;
22             $self->$_(undef) for qw(ua user json uri timeout);
23             }
24              
25              
26             our $VERSION = '0.001';
27             $VERSION = eval $VERSION;
28            
29             sub new {
30             my $self = shift;
31             my @args = @_;
32            
33             unshift @args, 'url' if @args % 2 && !ref( $args[0] );
34            
35             my %args = ref( $args[0] ) ? %{ $args[0] } : @args;
36             if ( exists $args{url} ) {
37             ( $args{user}, $args{repo} ) = ( split /\//, delete $args{url} );
38             }
39            
40             my $timeout = $args{timeout} || 10;
41            
42             bless {
43             user => $args{user},
44             repo => $args{repo},
45             timeout => $timeout,
46             api_version => ($args{api_version} || 'v2'),
47             }, $self;
48             }
49            
50             sub ua {
51             LWP::UserAgent->new(
52             timeout => $_[0]->timeout,
53             agent => join ' ', ( __PACKAGE__, $VERSION )
54             );
55             }
56              
57              
58             sub uri {
59             URI->new( sprintf( 'http://github.com/api/%s/json/repos/show/%s/%s/contributors',
60             $_[0]->api_version,$_[0]->user, $_[0]->repo )
61             );
62             }
63             sub json { JSON->new->allow_nonref }
64            
65             sub scores {
66             my $self = shift;
67            
68             my $response = $self->ua->request( HTTP::Request->new( GET => $self->uri->canonical ) );
69             return {} unless $response->is_success;
70            
71             my %scores;
72             my $contributors = $self->json->decode( $response->content )->{contributors};
73            
74             map { $scores{ $_->{login} } = $_->{contributions} } @$contributors;
75             return \%scores;
76             }
77            
78             1;
79              
80              
81             =pod
82              
83             =head1 NAME
84              
85             Github::Score - Pull author contribution counts for github repos
86              
87             =head1 VERSION
88              
89             version 0.2.0
90              
91             =head1 AUTHOR
92              
93             justin.d.hunter@gmail.com
94              
95             =head1 COPYRIGHT AND LICENSE
96              
97             This software is copyright (c) 2011 by AHB.
98              
99             This is free software; you can redistribute it and/or modify it under
100             the same terms as the Perl 5 programming language system itself.
101              
102             =cut
103              
104              
105             __DATA__
106              
107              
108             =head1 NAME
109              
110             Github::Score - Collect contributions data from the Github api.
111              
112             =head1 SYNOPSIS
113              
114             use Github::Score;
115            
116             my $gs1 = Github::Score->new(); ##Bare constructor. Not much use without:
117             $gs1->user('Getty'); ## Still need a:
118             $gs1->repo('p5-www-duckduckgo');
119            
120             my $contributors_scores = $gs1->scores();
121             ## Do stuff with an array of this sort of thing:
122             #$VAR1 = [
123             # {
124             # 'login' => 'doy',
125             # 'contributions' => 119
126             # },
127             # {
128             # 'login' => 'stevan',
129             # 'contributions' => 36
130             # },
131             # {
132             # 'login' => 'jasonmay',
133             # 'contributions' => 5
134             # },
135             # {
136             # 'login' => 'arcanez',
137             # 'contributions' => 3
138             # }
139             # ];
140            
141             ## Save yourself a few key-strokes
142             my $gs2 = Github::Score->new(user=>'Getty', repo=>'p5-www-duckduckgo');
143             $contributors_scores = $gs2->scores();
144            
145             ## Save yourself a few more key-strokes
146             my $gs3 = Github::Score->new('Getty/p5-www-duckduckgo');
147             $contributors_scores = $gs3->scores();
148            
149             ## Can't afford to wait for up to 10 seconds?
150             $gs3->timeout(9.99);
151             $contributors_scores = $gs3->scores();
152              
153             =head1 DESCRIPTION
154              
155             http://github-high-scores.heroku.com/ is a site with a retro-80s look and
156             feel where you can look up the author contribution counts for projecs on Github.
157             Github::Score is an OO perl API to the same data from the site aimed at the
158             DuckDuckGo community platform.
159              
160             =head1 METHODS
161              
162             =head2 Constructors
163              
164             =head3 new
165              
166             Github::Score objects can be constructed in different ways:
167              
168             =over 4
169              
170             =item Empty constructor call
171              
172             C< new()>
173              
174             =item Single url-style string
175              
176             C< new('contributor/github-repo')>
177              
178             =item Key-value pairs
179              
180             C<< new(user=>someone, repo=>'some-repo', timeout=> $_10_if_you_leave_it_out) >>
181              
182             =item Hash reference
183              
184             C<< new( {user=>someone, repo=>'some-repo', timeout=> $_10_if_you_leave_it_out)} >>
185              
186             =back
187              
188             =head2 Accessors
189              
190             =head3 B<user>
191              
192             Will set $self->{user} to $_[0], if an argument is given.
193             Returns: $self->{user}
194              
195             =head3 B<repo>
196              
197             Will set $self-{repo} to $_[0], if an argument is given.
198             Returns: $self-{repo}
199              
200             =head3 B<timeout>
201              
202             Will set $self->{timeout} to $_[0], if an argument is given.
203             Returns: $self->{timeout}
204              
205             Note: Defaults to 10 when the object is constructed.
206              
207             =head3 B<ua>
208              
209             Returns: A LWP::UserAgent instance
210              
211             Note: Do not use this method directly. It is automatically invoked by the
212             scores method.
213              
214             =head3 B<uri>
215              
216             Returns: A URI instance
217            
218             Note: Do not use this method directly. It is automatically invoked by the
219             scores method.
220              
221             =head3 B<json>
222              
223             Returns: A JSON instance
224            
225             Note: Do not use this method directly. It is automatically invoked by the
226             scores method.
227              
228             =head2 Behaviour
229              
230             =head3 B<scores>
231              
232             Returns: A reference to a hash of login/contribution pairs.
233            
234             Note: The hash could be empty if there is some error with the request,
235             or example a timeout, or if the query is invalid, for example user
236             does not contribute to the repository.
237              
238             =head1 BUGS
239              
240             None known, but they will be there somewhere.
241              
242             =head1 TODO
243              
244             =over 6
245              
246             =item Github api v3 support
247              
248             =item Support regex user/repo queries
249              
250             =item Retry on timeout?
251              
252             =item Better documentation.
253              
254             =back
255              
256             =head1 SEE ALSO
257              
258             =over 4
259              
260             =item L<http://github-high-scores.heroku.com/>
261              
262             =item L<Net::GitHub>
263              
264             =item L<http://github.com>
265              
266             =item L<App::DuckDuckGo>
267              
268             =item L<WWW::DuckDuckGo>
269              
270             =item L<http://duck.co/>
271              
272             =back
273              
274              
275             =for
276             Kind of thing you get from the api:
277             $VAR1 = [
278             {
279             'gravatar_id' => 'dd9aceaf17982bc33972b3bb8701cd19',
280             'location' => 'O\'Fallon, IL',
281             'name' => 'Jesse Luehrs',
282             'blog' => 'http://tozt.net/',
283             'login' => 'doy',
284             'email' => 'doy at tozt dot net',
285             'type' => 'User',
286             'company' => 'Infinity Interactive',
287             'contributions' => 119
288             },
289             {
290             'gravatar_id' => '0bffad37a60feece78c306af4456f53a',
291             'name' => 'Stevan Little',
292             'blog' => 'http://moose.perl.org',
293             'login' => 'stevan',
294             'email' => 'stevan.little@iinteractive.com',
295             'type' => 'User',
296             'company' => 'Infinity Interactive',
297             'contributions' => 36
298             },
299             {
300             'gravatar_id' => 'c68ae3a25b34be3310bd975c2036940d',
301             'location' => 'Annville, PA',
302             'name' => 'Jason May',
303             'blog' => 'http://jarsonmar.org/',
304             'login' => 'jasonmay',
305             'email' => 'jason.a.may@gmail.com',
306             'type' => 'User',
307             'company' => 'Best Practical Solutions',
308             'contributions' => 5
309             },
310             {
311             'gravatar_id' => 'be68b0e46958d0dcb621f696f9b1bc1c',
312             'location' => 'Revere, MA',
313             'name' => 'Justin Hunter',
314             'blog' => 'http://warpedreality.org',
315             'login' => 'arcanez',
316             'email' => 'justin.d.hunter@gmail.com',
317             'type' => 'User',
318             'company' => 'Cantella',
319             'contributions' => 3
320             }
321             ];
322             =cut