.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Net::Twitter::Manual::MigratingToV1_1 3pm" .TH Net::Twitter::Manual::MigratingToV1_1 3pm "2022-06-16" "perl v5.34.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Net::Twitter::Manual::MigratingToV1_1 \- Migrating from Twitter API v1 to v1.1 .SH "VERSION" .IX Header "VERSION" version 4.01043 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Net::Twitter \& \& my $nt = Net::Twitter\->new( \& traits => [qw/API::RESTv1_1/], \& consumer_key => $consumer_key, \& consumer_secret => $consumer_secret, \& access_token => $access_token, \& access_token_secret => $access_token_secret, \& ); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Net::Twitter prior to version 4.0 used Twitter \s-1API\s0 version 1. Twitter \s-1API\s0 v1.1 introduced changes that are not entirely backwards compatible, requiring some changes to calling code. .PP Net::Twitter attempts to provided backwards compatibility where possible. This document describes the changes required to your existing application code, using Net::Twitter, for use with Twitter's \s-1API\s0 v1.1. .SH "FIRST" .IX Header "FIRST" .SS "Include the API::RESTv1_1 trait" .IX Subsection "Include the API::RESTv1_1 trait" Wherever you create a Net::Twitter object by calling \f(CW\*(C`new\*(C'\fR, replace trait \&\f(CW\*(C`API::REST\*(C'\fR with \f(CW\*(C`API::RESTv1_1\*(C'\fR. For most applications, that's all that is required. .SH "EXCEPTIONS" .IX Header "EXCEPTIONS" .IP "Trait RateLimit incompatible with API::RESTv1_1" 4 .IX Item "Trait RateLimit incompatible with API::RESTv1_1" The \f(CW\*(C`RateLimit\*(C'\fR trait is incompatible with Twitter \s-1API\s0 v1.1. Rate limiting is one of the most extensive changes in v1.1. In v1 there were two hourly rate limits, one per \s-1IP\s0 address for unauthenticated calls, and one per\-user/application for authenticated calls. In v1.1, all calls must be authenticated, and each \s-1API\s0 endpoint (i.e., each method) has it's own rate limit. Rather than hourly, the new rate limits operate on a 15 minute window. .Sp If your code currently uses the \f(CW\*(C`RateLimit\*(C'\fR role, you'll need to write some custom code provide equivalent functionality. .IP "rate_limit_status" 4 .IX Item "rate_limit_status" The return value for \f(CW\*(C`rate_limit_status\*(C'\fR is entirely different. See Twitter's \&\s-1API\s0 rate_limit_status documentation for details. .IP "blocking" 4 .IX Item "blocking" .PD 0 .IP "blocking_ids" 4 .IX Item "blocking_ids" .IP "friends" 4 .IX Item "friends" .IP "followers" 4 .IX Item "followers" .PD With \s-1API\s0 v1.1, these methods use cursor based paging. If you do not pass a \&\f(CW\*(C`cursor\*(C'\fR parameter, Twitter assumes \f(CW\*(C`cursor => \-1\*(C'\fR>. Existing code that expects an arrayref return value must be modified to expect a hashref and dereference the \f(CW\*(C`users\*(C'\fR slot: .Sp .Vb 3 \& # With API v1 \& my $r = $nt\->friends; \& my @friends = @$r; \& \& # With API v1.1 \& my $r = $nt\->friends; \& my @friends = @{$r\->{users}}; .Ve .IP "search" 4 .IX Item "search" The \f(CW\*(C`search\*(C'\fR method semantics and return value are substantially different between Twitter \s-1API\s0 v1 and v1.1. In v1, \f(CW\*(C`search\*(C'\fR was provided by the \&\f(CW\*(C`API::Search\*(C'\fR trait. In v1.1, \f(CW\*(C`search\*(C'\fR is included in the \f(CW\*(C`API::RESTv1_1\*(C'\fR trait. .Sp So, first, drop \f(CW\*(C`API::Search\*(C'\fR from your calls to \f(CW\*(C`new\*(C'\fR. The \f(CW\*(C`API::Search\*(C'\fR trait is incompatible with \f(CW\*(C`API::RESTv1_1\*(C'\fR. .Sp In v1, Twitter returned a hashref with several keys containing meta data. The actual array of results were contained in the \f(CW\*(C`results\*(C'\fR slot: .Sp .Vb 2 \& # With Twitter API v1 \& my $nt = Net::Twitter\->new(traits => [qw/API::REST API::Search/]); \& \& my $r = $nt\->search(\*(Aqperl hacker\*(Aq); \& for my $status ( @{$r\->{results} ) { \& # process each status... \& } .Ve .Sp In v1.1, Twitter returns a hash with 2 slots: \f(CW\*(C`search_metadata\*(C'\fR and \f(CW\*(C`statuses\*(C'\fR. .Sp .Vb 2 \& # With Twitter API v1.1 \& my $nt = Net::Twitter\->new(traits => [qw/API::RESTv1_1/], %oauth_credentials); \& \& my $r = $nt\->search(\*(Aqperl hacker\*(Aq); \& for my $status ( @{$r\->{statuses} ) { \& # process each status... \& } .Ve .Sp Paging through search results works differently in v1.1. In v1, Twitter offered a \f(CW\*(C`page\*(C'\fR parameter: .Sp .Vb 4 \& # With Twitter API v1 \& for ( my $page = 1; $page <= 10; ++$page ) { \& my $r = $nt\->search({ q => $query, page => $page, rpp => 100 }); \& last unless @{$r\->{results}}; \& \& # process a page of results... \& } .Ve .Sp In v1.1, use \f(CW\*(C`max_id\*(C'\fR and \f(CW\*(C`count\*(C'\fR to get paged results: .Sp .Vb 4 \& # With Twitter API v1.1 \& for ( my %args = ( q => $query, count => 100 ), my $n = 0; $n < 1000; ) { \& my $r = $nt\->search({ %args }); \& last unless @{$r\->{statuses}}; \& \& $args{max_id} = $r\->{statuses}[\-1]{id} \- 1; \& $n += @{$r\->{statuses}}; \& \& # process a page of results... \& } .Ve .SS "\s-1DEPRECATED METHODS\s0" .IX Subsection "DEPRECATED METHODS" Some Twitter \s-1API\s0 v1 methods are not available in v1.1: .IP "friends_timeline" 4 .IX Item "friends_timeline" Use \f(CW\*(C`home_timeline\*(C'\fR instead. .IP "friendship_exists" 4 .IX Item "friendship_exists" .PD 0 .IP "relationship_exists" 4 .IX Item "relationship_exists" .IP "follows" 4 .IX Item "follows" .PD \&\f(CW\*(C`friendship_exists\*(C'\fR and it's aliases are not supported in \s-1API\s0 v1.1. Use \f(CW\*(C`show_friendship\*(C'\fR instead: .Sp .Vb 7 \& my $r = $nt\->show_relationship({ \& source_screen_name => $user_a, \& target_screen_name => $user_b, \& }); \& if ( $r\->{relationship}{source}{following} ) { \& # $user_a follows $user_b \& } .Ve