Added Lists API support (ported from Net::Twitter 3.13002_02)
Marc Mims
14 years ago
0 | 0.9002_02 2010-05-12 | |
1 | - ported from Net::Twitter 3.13002_02 | |
2 | - Added Lists API support | |
3 | ||
0 | 4 | 0.09001 2010-05-10 |
1 | 5 | - removed Try::Tiny from unicode test to avoid an additional dependency |
2 | 6 | - Fixed unicode test, aburch (Ansgar Burchardt) |
0 | 0 | use inc::Module::Install; |
1 | 1 | |
2 | version '0.09001'; | |
2 | version '0.09002_02'; | |
3 | 3 | |
4 | 4 | if ( $Module::Install::AUTHOR ) { |
5 | 5 | eval "use Net::Twitter::Core"; |
1 | 1 | Net::Twitter::Lite - A perl interface to the Twitter API |
2 | 2 | |
3 | 3 | VERSION |
4 | This document describes Net::Twitter::Lite version 0.09001 | |
4 | This document describes Net::Twitter::Lite version 0.09002_02 | |
5 | 5 | |
6 | 6 | SYNOPSIS |
7 | 7 | use Net::Twitter::Lite; |
253 | 253 | |
254 | 254 | useragent |
255 | 255 | The value for "User-Agent" HTTP header. It defaults to |
256 | "Net::Twitter::Lite/0.09001 (Perl)". | |
256 | "Net::Twitter::Lite/0.09002_02 (Perl)". | |
257 | 257 | |
258 | 258 | source |
259 | 259 | The value used in the "source" parameter of API method calls. It |
819 | 819 | |
820 | 820 | Returns: ArrayRef[Status] |
821 | 821 | |
822 | lookup_users | |
823 | ||
824 | Parameters: user_id, screen_name | |
825 | Required: *none* | |
826 | ||
827 | Return up to 20 users worth of extended information, specified by | |
828 | either ID, screen name, or combination of the two. The author's most | |
829 | recent status (if the authenticating user has permission) will be | |
830 | returned inline. This method is rate limited to 1000 calls per hour. | |
831 | ||
832 | This method will accept user IDs or screen names as either a comma | |
833 | delimited string, or as an ARRAY ref. It will also accept arguments | |
834 | in the normal HASHREF form or as a simple list of named arguments. | |
835 | I.e., any of the following forms are acceptable: | |
836 | ||
837 | $nt->lookup_users({ user_id => '1234,6543,3333' }); | |
838 | $nt->lookup_users(user_id => '1234,6543,3333'); | |
839 | $nt->lookup_users({ user_id => [ 1234, 6543, 3333 ] }); | |
840 | $nt->lookup_users({ screen_name => 'fred,barney,wilma' }); | |
841 | $nt->lookup_users(screen_name => ['fred', 'barney', 'wilma']); | |
842 | ||
843 | $nt->lookup_users( | |
844 | screen_name => ['fred', 'barney' ], | |
845 | user_id => '4321,6789', | |
846 | ); | |
847 | ||
848 | Returns: ArrayRef[User] | |
849 | ||
822 | 850 | mentions |
823 | 851 | alias: replies |
824 | 852 | |
1353 | 1381 | Required: *none* |
1354 | 1382 | |
1355 | 1383 | Returns the top 30 trending topics for each day in a given week. |
1384 | ||
1385 | Returns: HashRef | |
1386 | ||
1387 | Lists API Methods | |
1388 | add_list_member | |
1389 | add_list_member(user, list_id, id) | |
1390 | ||
1391 | Parameters: user, list_id, id | |
1392 | Required: user, list_id, id | |
1393 | ||
1394 | Adds the user identified by "id" to the list. | |
1395 | ||
1396 | Returns a reference the added user as a hash reference. | |
1397 | ||
1398 | Returns: User | |
1399 | ||
1400 | create_list | |
1401 | create_list(user, name) | |
1402 | ||
1403 | Parameters: user, name, mode, description | |
1404 | Required: user, name | |
1405 | ||
1406 | Creates a new list for the authenticated user. The "mode" parameter | |
1407 | may be either "public" or "private". If not specified, it defaults | |
1408 | to "public". | |
1409 | ||
1410 | Returns: HashRef | |
1411 | ||
1412 | delete_list | |
1413 | delete_list(user, list_id) | |
1414 | ||
1415 | Parameters: user, list_id | |
1416 | Required: user, list_id | |
1417 | ||
1418 | Deletes a list owned by the authenticating user. Returns the list as | |
1419 | a hash reference. | |
1420 | ||
1421 | Returns: | |
1422 | ||
1423 | delete_list_member | |
1424 | delete_list_member(user, list_id, id) | |
1425 | alias: remove_list_member | |
1426 | ||
1427 | Parameters: user, list_id, id | |
1428 | Required: user, list_id, id | |
1429 | ||
1430 | Deletes the user identified by "id" from the specified list. | |
1431 | ||
1432 | Returns the deleted user as a hash reference. | |
1433 | ||
1434 | Returns: | |
1435 | ||
1436 | get_list | |
1437 | get_list(user, list_id) | |
1438 | ||
1439 | Parameters: user, list_id | |
1440 | Required: user, list_id | |
1441 | ||
1442 | Returns the specified list as a hash reference. | |
1443 | ||
1444 | Returns: HashRef | |
1445 | ||
1446 | get_lists | |
1447 | get_lists(user) | |
1448 | alias: list_lists | |
1449 | ||
1450 | Parameters: user, cursor | |
1451 | Required: user | |
1452 | ||
1453 | Returns a reference to an array of lists owned by the specified | |
1454 | user. If the user is the authenticated user, it returns both public | |
1455 | and private lists. Otherwise, it only returns public lists. | |
1456 | ||
1457 | When the "cursor" parameter is used, a hash reference is returned; | |
1458 | the lists are returned in the "lists" element of the hash. | |
1459 | ||
1460 | Returns: ArrayRef[List] | |
1461 | ||
1462 | is_list_member | |
1463 | is_list_member(user, list_id, id) | |
1464 | ||
1465 | Parameters: user, list_id, id | |
1466 | Required: user, list_id, id | |
1467 | ||
1468 | Returns the list member as a HASH reference if "id" is a member of | |
1469 | the list. Otherwise, returns undef. | |
1470 | ||
1471 | Returns: ArrayRef[User] | |
1472 | ||
1473 | is_list_subscriber | |
1474 | is_list_subscriber(user, list_id, id) | |
1475 | alias: is_subscribed_list | |
1476 | ||
1477 | Parameters: user, list_id, id | |
1478 | Required: user, list_id, id | |
1479 | ||
1480 | Returns the subscriber as a HASH reference if "id" is a subscriber | |
1481 | to the list. Otherwise, returns undef. | |
1482 | ||
1483 | Returns: ArrayRef[User] | |
1484 | ||
1485 | list_members | |
1486 | list_members(user, list_id) | |
1487 | ||
1488 | Parameters: user, list_id, id, cursor | |
1489 | Required: user, list_id | |
1490 | ||
1491 | Returns the list members as an array reference. | |
1492 | ||
1493 | The optional "id" parameter can be used to determine if the user | |
1494 | specified by "id" is a member of the list. If so, the user is | |
1495 | returned as a hash reference; if not, "undef" is returned. | |
1496 | ||
1497 | When the "cursor" parameter is used, a hash reference is returned; | |
1498 | the members are returned in the "users" element of the hash. | |
1499 | ||
1500 | Returns: ArrayRef[User] | |
1501 | ||
1502 | list_memberships | |
1503 | list_memberships(user) | |
1504 | ||
1505 | Parameters: user, cursor | |
1506 | Required: user | |
1507 | ||
1508 | Returns the lists the specified user is a member of as an array | |
1509 | reference. | |
1510 | ||
1511 | When the "cursor" parameter is used, a hash reference is returned; | |
1512 | the lists are returned in the "lists" element of the hash. | |
1513 | ||
1514 | Returns: | |
1515 | ||
1516 | list_statuses | |
1517 | list_statuses(user, list_id) | |
1518 | ||
1519 | Parameters: user, list_id, since_id, max_id, per_page, page | |
1520 | Required: user, list_id | |
1521 | ||
1522 | Returns a timeline of list member statuses as an array reference. | |
1523 | ||
1524 | Returns: ArrayRef[Status] | |
1525 | ||
1526 | list_subscribers | |
1527 | list_subscribers(user, list_id) | |
1528 | ||
1529 | Parameters: user, list_id, id, cursor | |
1530 | Required: user, list_id | |
1531 | ||
1532 | Returns the subscribers to a list as an array reference. | |
1533 | ||
1534 | When the "cursor" parameter is used, a hash reference is returned; | |
1535 | the subscribers are returned in the "users" element of the hash. | |
1536 | ||
1537 | Returns: ArrayRef[User] | |
1538 | ||
1539 | list_subscriptions | |
1540 | list_subscriptions(user) | |
1541 | ||
1542 | Parameters: user, cursor | |
1543 | Required: user | |
1544 | ||
1545 | Returns a lists to which the specified user is subscribed as an | |
1546 | array reference. | |
1547 | ||
1548 | When the "cursor" parameter is used, a hash reference is returned; | |
1549 | the lists are returned in the "lists" element of the hash. | |
1550 | ||
1551 | Returns: | |
1552 | ||
1553 | subscribe_list | |
1554 | subscribe_list(user, list_id) | |
1555 | ||
1556 | Parameters: user, list_id | |
1557 | Required: user, list_id | |
1558 | ||
1559 | Subscribes the authenticated user to the specified list. | |
1560 | ||
1561 | Returns: List | |
1562 | ||
1563 | unsubscribe_list | |
1564 | unsubscribe_list(user, list_id) | |
1565 | ||
1566 | Parameters: user, list_id | |
1567 | Required: user, list_id | |
1568 | ||
1569 | Unsubscribes the authenticated user from the specified list. | |
1570 | ||
1571 | Returns: List | |
1572 | ||
1573 | update_list | |
1574 | update_list(user, list_id) | |
1575 | ||
1576 | Parameters: user, list_id, name, mode, description | |
1577 | Required: user, list_id | |
1578 | ||
1579 | Updates a list to change the name, mode, description, or any | |
1580 | combination thereof. | |
1356 | 1581 | |
1357 | 1582 | Returns: HashRef |
1358 | 1583 |
22 | 22 | |
23 | 23 | return |
24 | 24 | sort { $a->{name} cmp $b->{name} } |
25 | grep { blessed $_ && $_->isa('Net::Twitter::Meta::Method') } | |
26 | $nt->meta->get_all_methods; | |
25 | grep { | |
26 | $_->isa('Net::Twitter::Meta::Method') | |
27 | } | |
28 | map { | |
29 | $_->isa('Class::MOP::Method::Wrapped') ? $_->get_original_method : $_ | |
30 | } $nt->meta->get_all_methods; | |
27 | 31 | } |
28 | 32 | |
29 | 33 | sub get_base_url_for { |
17 | 17 | sub new { |
18 | 18 | my ($class, %args) = @_; |
19 | 19 | |
20 | my $ssl = delete $args{ssl}; | |
21 | if ( $ssl ) { | |
22 | eval { require Crypt::SSLeay } && $Crypt::SSLeay::VERSION >= 0.5 | |
23 | || croak "Crypt::SSLeay version 0.50 is required for SSL support"; | |
24 | } | |
25 | ||
26 | 20 | my $netrc = delete $args{netrc}; |
27 | 21 | my $new = bless { |
28 | apiurl => 'http://api.twitter.com/1', | |
22 | apiurl => 'http://api.twitter.com/1', | |
23 | searchapiurl => 'http://search.twitter.com', | |
24 | search_trends_api_url => 'http://api.twitter.com/1', | |
25 | lists_api_url => 'http://api.twitter.com/1', | |
29 | 26 | apirealm => 'Twitter API', |
30 | 27 | $args{identica} ? ( apiurl => 'http://identi.ca/api' ) : (), |
31 | searchurl => 'http://search.twitter.com', | |
32 | 28 | useragent => __PACKAGE__ . "/$VERSION (Perl)", |
33 | 29 | clientname => __PACKAGE__, |
34 | 30 | clientver => $VERSION, |
47 | 43 | %args |
48 | 44 | }, $class; |
49 | 45 | |
50 | $new->{apiurl} =~ s/http/https/ if $ssl; | |
46 | ||
47 | if ( delete $args{ssl} ) { | |
48 | eval { require Crypt::SSLeay } && $Crypt::SSLeay::VERSION >= 0.5 | |
49 | || croak "Crypt::SSLeay version 0.50 is required for SSL support"; | |
50 | ||
51 | $new->{$_} =~ s/http/https/ | |
52 | for qw/apiurl searchurl search_trends_api_url lists_api_url/; | |
53 | } | |
51 | 54 | |
52 | 55 | # get username and password from .netrc |
53 | 56 | if ( $netrc ) { |
113 | 116 | |
114 | 117 | eval '$Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A'; |
115 | 118 | die $@ if $@; |
116 | ||
119 | ||
117 | 120 | 'Net::OAuth'; |
118 | 121 | }; |
119 | 122 | } |
135 | 138 | no strict 'refs'; |
136 | 139 | *{__PACKAGE__ . "::$method"} = sub { |
137 | 140 | my $self = shift; |
138 | ||
141 | ||
139 | 142 | $self->{$method} = shift if @_; |
140 | 143 | return $self->{$method}; |
141 | 144 | }; |
301 | 304 | |
302 | 305 | sub _oauth_authenticated_request { |
303 | 306 | my ($self, $http_method, $uri, $args, $authenticate) = @_; |
304 | ||
307 | ||
305 | 308 | delete $args->{source}; # not necessary with OAuth requests |
306 | 309 | |
307 | 310 | my $is_multipart = grep { ref } %$args; |
383 | 386 | : POST($uri, $args); |
384 | 387 | } |
385 | 388 | |
389 | { ### scope $api_def | |
390 | ||
386 | 391 | my $api_def = [ |
387 | [% FOREACH api IN [ 'REST', 'Search' ] -%] | |
392 | [% FOREACH api IN [ 'REST', 'Search', 'Lists' ] -%] | |
388 | 393 | [ [% api %] => [ |
389 | 394 | [% FOREACH method IN get_methods_for(api) -%] |
390 | 395 | [ '[% method.name %]', { |
397 | 402 | deprecated => [% method.deprecated %], |
398 | 403 | authenticate => [% method.authenticate %], |
399 | 404 | booleans => [ qw/[% method.booleans.join(' ') %]/ ], |
405 | base_url_method => '[% method.base_url_method %]', | |
400 | 406 | } ], |
401 | 407 | [% END -%] |
402 | 408 | ] ], |
420 | 426 | my $api_name = shift @$api; |
421 | 427 | my $methods = shift @$api; |
422 | 428 | |
423 | my $url_attr = $api_name eq 'REST' ? 'apiurl' : 'searchurl'; | |
424 | ||
425 | my $base_url = sub { shift->{$url_attr} }; | |
426 | ||
427 | 429 | for my $method ( @$methods ) { |
428 | 430 | my $name = shift @$method; |
429 | 431 | my %options = %{ shift @$method }; |
439 | 441 | # copy callers args since we may add ->{source} |
440 | 442 | my $args = ref $_[-1] eq 'HASH' ? { %{pop @_} } : {}; |
441 | 443 | |
442 | if ( @_ ) { | |
443 | @_ == @$arg_names || croak "$name expected @{[ scalar @$arg_names ]} args"; | |
444 | @{$args}{@$arg_names} = @_; | |
444 | croak sprintf "$name expected %d args", scalar @$arg_names if @_ > @$arg_names; | |
445 | ||
446 | # promote positional args to named args | |
447 | for ( my $i = 0; @_; ++$i ) { | |
448 | my $param = $arg_names->[$i]; | |
449 | croak "duplicate param $param: both positional and named" | |
450 | if exists $args->{$param}; | |
451 | ||
452 | $args->{$param} = shift; | |
445 | 453 | } |
454 | ||
446 | 455 | $args->{source} ||= $self->{source} if $options{add_source}; |
447 | 456 | |
448 | 457 | my $authenticate = exists $args->{authenticate} ? delete $args->{authenticate} |
465 | 474 | $local_path =~ s,/:id$,, unless exists $args->{id}; # remove optional trailing id |
466 | 475 | $local_path =~ s/:(\w+)/delete $args->{$1} or croak "required arg '$1' missing"/eg; |
467 | 476 | |
468 | my $uri = URI->new($base_url->($self) . "/$local_path.json"); | |
477 | my $uri = URI->new($self->{$options{base_url_method}} . "/$local_path.json"); | |
469 | 478 | |
470 | 479 | return $self->_parse_result( |
471 | 480 | $self->_authenticated_request($options{method}, $uri, $args, $authenticate) |
476 | 485 | *{__PACKAGE__ . "::$_"} = $code for $name, @{$options{aliases}}; |
477 | 486 | } |
478 | 487 | } |
488 | $DB::single = 1; | |
489 | ||
490 | # catch expected error and promote it to an undef | |
491 | for ( qw/list_members is_list_member list_subscribers is_list_subscriber/ ) { | |
492 | my $orig = __PACKAGE__->can($_) or die; | |
493 | ||
494 | my $code = sub { | |
495 | my $r = eval { $orig->(@_) }; | |
496 | if ( $@ ) { | |
497 | return if $@ =~ /The specified user is not a (?:memb|subscrib)er of this list/; | |
498 | ||
499 | die $@; | |
500 | } | |
501 | ||
502 | return $r; | |
503 | }; | |
504 | ||
505 | no strict 'refs'; | |
506 | no warnings 'redefine'; | |
507 | *{__PACKAGE__ . "::$_"} = $code; | |
508 | } | |
509 | ||
510 | # special case parameter handling for lookup_users | |
511 | for ( qw/lookup_users/ ) { | |
512 | my $orig = __PACKAGE__->can($_) or die; | |
513 | ||
514 | my $code = sub { | |
515 | my $self = shift; | |
516 | ||
517 | my $args = ref $_[-1] eq 'HASH' ? pop @_ : {}; | |
518 | $args = { %$args, @_ }; | |
519 | ||
520 | for ( qw/screen_name user_id/ ) { | |
521 | $args->{$_} = join(',' => @{ $args->{$_} }) if ref $args->{$_} eq 'ARRAY'; | |
522 | } | |
523 | ||
524 | return $orig->($self, $args); | |
525 | }; | |
526 | ||
527 | no strict 'refs'; | |
528 | no warnings 'redefine'; | |
529 | *{__PACKAGE__ . "::$_"} = $code; | |
530 | } | |
531 | ||
532 | ||
533 | ||
534 | } ### end scope for $api_def | |
479 | 535 | |
480 | 536 | sub _from_json { |
481 | 537 | my ($self, $json) = @_; |
1033 | 1089 | |
1034 | 1090 | [% INCLUDE APIDOC class='Search' %] |
1035 | 1091 | |
1092 | =head1 Lists API Methods | |
1093 | ||
1094 | [% INCLUDE APIDOC class='Lists' %] | |
1095 | ||
1036 | 1096 | =head1 ERROR HANDLING |
1037 | 1097 | |
1038 | 1098 | When C<Net::Twitter::Lite> encounters a Twitter API error or a network error, it |
0 | #!perl | |
1 | use warnings; | |
2 | use strict; | |
3 | use Test::More; | |
4 | use Net::Twitter; | |
5 | ||
6 | eval 'use LWP::UserAgent 5.819'; | |
7 | plan skip_all => 'LWP::UserAgent 5.819 required' if $@; | |
8 | ||
9 | my $nt = Net::Twitter->new(traits => [qw/API::Lists/], username => 'fred', password => 'secret'); | |
10 | ||
11 | my $req; | |
12 | my $res = HTTP::Response->new(200); | |
13 | $res->content('{"response":"done"}'); | |
14 | $nt->ua->add_handler(request_send => sub { $req = shift; return $res }); | |
15 | ||
16 | my @tests = ( | |
17 | create_list => { | |
18 | args => [ 'owner', { name => 'Test list', description => 'Just a test', mode => 'private' } ], | |
19 | path => '/owner/lists', | |
20 | params => { name => 'Test list', description => 'Just a test', mode => 'private' }, | |
21 | method => 'POST', | |
22 | }, | |
23 | update_list => { | |
24 | args => [ 'owner', 'test-list', { mode => 'public' } ], | |
25 | path => '/owner/lists/test-list', | |
26 | params => { mode => 'public' }, | |
27 | method => 'POST', | |
28 | }, | |
29 | list_lists => { | |
30 | args =>[ 'owner' ], | |
31 | path => '/owner/lists', | |
32 | params => {}, | |
33 | method => 'GET', | |
34 | }, | |
35 | list_memberships => { | |
36 | args => [ 'owner' ], | |
37 | path => '/owner/lists/memberships', | |
38 | params => {}, | |
39 | method => 'GET', | |
40 | }, | |
41 | delete_list => { | |
42 | args => [ 'owner', 'test-list' ], | |
43 | path => '/owner/lists/test-list', | |
44 | params => {}, | |
45 | method => 'DELETE', | |
46 | }, | |
47 | list_statuses => { | |
48 | args => [ 'owner', 'test-list' ], | |
49 | path => '/owner/lists/test-list/statuses', | |
50 | params => {}, | |
51 | method => 'GET', | |
52 | }, | |
53 | get_list => { | |
54 | args => [ 'owner', 'test-list' ], | |
55 | path => '/owner/lists/test-list', | |
56 | params => {}, | |
57 | method => 'GET', | |
58 | }, | |
59 | add_list_member => { | |
60 | args => [ 'owner', 'test-list', 1234 ], | |
61 | path => '/owner/test-list/members', | |
62 | params => { id => 1234 }, | |
63 | method => 'POST', | |
64 | }, | |
65 | delete_list_member => { | |
66 | args => [ 'owner', 'test-list', 1234 ], | |
67 | path => '/owner/test-list/members', | |
68 | params => { id => 1234 }, | |
69 | method => 'DELETE', | |
70 | }, | |
71 | remove_list_member => { | |
72 | args => [ 'owner', 'test-list', 1234 ], | |
73 | path => '/owner/test-list/members', | |
74 | params => { id => 1234 }, | |
75 | method => 'DELETE', | |
76 | }, | |
77 | list_members => { | |
78 | args => [ 'owner', 'test-list' ], | |
79 | path => '/owner/test-list/members', | |
80 | params => {}, | |
81 | method => 'GET', | |
82 | }, | |
83 | is_list_member => { | |
84 | args => [ 'owner', 'test-list', 1234 ], | |
85 | path => '/owner/test-list/members/1234', | |
86 | params => {}, | |
87 | method => 'GET', | |
88 | }, | |
89 | subscribe_list => { | |
90 | args => [ 'owner', 'some-list' ], | |
91 | path => '/owner/some-list/subscribers', | |
92 | params => {}, | |
93 | method => 'POST', | |
94 | }, | |
95 | list_subscribers => { | |
96 | args => [ 'owner', 'some-list' ], | |
97 | path => '/owner/some-list/subscribers', | |
98 | params => {}, | |
99 | method => 'GET', | |
100 | }, | |
101 | list_subscriptions => { | |
102 | args => [ 'owner' ], | |
103 | path => '/owner/lists/subscriptions', | |
104 | params => {}, | |
105 | method => 'GET', | |
106 | }, | |
107 | unsubscribe_list => { | |
108 | args => [ 'owner', 'test-list' ], | |
109 | path => '/owner/test-list/subscribers', | |
110 | params => {}, | |
111 | method => 'DELETE', | |
112 | }, | |
113 | is_list_subscriber => { | |
114 | args => [ 'owner', 'test-list', 1234 ], | |
115 | path => '/owner/test-list/subscribers/1234', | |
116 | params => {}, | |
117 | method => 'GET', | |
118 | }, | |
119 | is_subscribed_list => { | |
120 | args => [ 'owner', 'test-list', 1234 ], | |
121 | path => '/owner/test-list/subscribers/1234', | |
122 | params => {}, | |
123 | method => 'GET', | |
124 | }, | |
125 | ); | |
126 | ||
127 | plan tests => scalar @tests / 2 * 3 + 2; | |
128 | ||
129 | while ( @tests ) { | |
130 | my $api_method = shift @tests; | |
131 | my $t = shift @tests; | |
132 | ||
133 | my $r = $nt->$api_method(@{ $t->{args} }); | |
134 | is $req->uri->path, "/1$t->{path}.json", "$api_method: path"; | |
135 | is $req->method, $t->{method}, "$api_method: HTTP method"; | |
136 | is_deeply extract_args($req), $t->{params}, | |
137 | "$api_method: parameters"; | |
138 | } | |
139 | ||
140 | { | |
141 | # unauthenticated call | |
142 | my $r = $nt->list_statuses(twitter => 'team', { authenticate => 0 }); | |
143 | ok !$req->header('authorization'), 'unauthenticated call'; | |
144 | ||
145 | # authenticated call (default) | |
146 | $r = $nt->list_statuses(twitter => 'team'); | |
147 | like $req->header('authorization'), qr/^Basic/, 'authenticated request (default)'; | |
148 | } | |
149 | ||
150 | sub extract_args { | |
151 | my $req = shift; | |
152 | ||
153 | my $uri; | |
154 | if ( $req->method eq 'POST' ) { | |
155 | $uri = URI->new; | |
156 | $uri->query($req->content); | |
157 | } | |
158 | else { | |
159 | $uri = $req->uri; | |
160 | } | |
161 | ||
162 | return { $uri->query_form }; | |
163 | } |