Net-Twitter-4.01043/000755 000766 000024 00000000000 13227713560 014147 5ustar00marcstaff000000 000000 Net-Twitter-4.01043/Changes000644 000766 000024 00000040767 13227713560 015460 0ustar00marcstaff000000 000000 4.01043 2018-01-17 - deprecation notice: Twitter::API is the new Net::Twitter - deprecated update_with_media - doc and build updates - remove debugger breakpoint (Oof!) 4.01042 2017-02-06 - deprecated contributors/contributees - Fixed: follow_suggestions and follow_suggestions_for were reversed - fix "overwriting a accessor" warnings under Moose 2.2004 #70 - build changes: keep dist.ini, create Makefile.PL (ether) 4.01041 2016-11-19 - hack dist.ini to get POD and README back into the distribution O_o 4.01040 2016-11-19 - added trait WrapResult (returns both the HTTP response, with rate limit accessors, and the decoded JSON response) - rename placeholder :category to :slug with backwards compatibility to match Twitter's documentation - add attachment_url parameter to update method - add links to Twitter API docs 4.01030 2016-11-18 - cleaned up Net::Twitter::Error and documented stack_trace and stack_frame methods - Add method upload_status (ghathwar on Github) 4.01020 2016-04-03 - Add create_media_metadata endpoint endpoint (AnnMary Mathew) - Use JSON::MaybeXS (Olaf Alders) 4.01010 2015-03-25 - Replace missing POD file 4.01009 2015-03-24 - Added Application-Only Authentication via trait AppAuth 4.01008 2015-01-19 - Added REST API mithods muting, create_mute, destroy_mute (Ashley Willis) 4.01007 2015-01-07 - Added REST API method lookup_statuses (thanks SocialFlow) - Typo fixes (thanks Zaki Mughal) - Bumped IO::Socket::SSL requirement to 2.005; recent versions seem to fix an issue with stalled connections. 4.01006 2014-11-17 - Default `ssl => 1` - Added `mutes` (@pjcj on Github) 4.01005 2014-08-12 - Added upload_media for multi-image support (@ghathwar) 4.01004 2014-04-11 - PUT requires paramters in the message body, now (Samuel Kaufman) 4.01003 2014-03-12 - Net::Twitter::Error's twitter_error_text excludes stack trace line number 4.01002 2014-01-16 - Fix POD bugs 4.01001 2014-01-16 - Warn if ssl option to new is not passed (deprecation cycle) 4.01000 2013-11-19 - Add API method retweeters_ids - Fix update_with_media with utf8 status (RT#72814) - Expand Carp::Clan list (should resolve RT#77306) - Remove reliance on MooseX::Aliases (issue #35) - Use Class::Load to replace deprecated Class::Mop method (issue #35) - Add missing dependency: LWP::Protocol::https (issue #25) - Fix OAuth failure for UTF8 params (issue #21) 4.00007 2013-08-12 - Support for HTTP method PUT (sartak) - example improvements (clmh) 4.00006 2013-05-30 - Spelling error fixed (spazm@github) - Added path_suffix parameter to twitter_api_method (sartak) - tidy + pod fix (sartak) 4.00005 2013-04-25 - Added list_ownerships (eleniS no Github) - Removed Makefile.PL (cruft - using Module::Build, now) 4.00004 - Dependecy Net::HTTP fixed in 6.06 (30 second timeout in OAuth requests) 4.00003 - Fixed URI argument encoding (v1.1 is more stringent) 4.00002 2013-02-23 - Removed Test::NoWarnings to accommodate HTTP::Request::Common 6.03 - Added method twitter_error_code to Net::Twitter::Error 4.00001 2013-02-21 - First general release with Twitter API v1.1 support - Twitter::Manual::MigratingToV1_1 4.00000_03 2013-02-19 - Fixed: needed skip directives for dzil's AutoPrereqs plugin - Stripped version numbers---let dzil put them in 4.00000_02 2013-02-19 - use Dist::Zilla instead of Module::Install 4.00000_01 2013-01-28 - Added Twitter API version 1.1 support 3.18004 2012-10-15 - Allow extra parameters to get_auth*_url methods (this accommodates Twitter's optional force_login and screen_name parameters to those endpoints. 3.18003 2012-06-27 - Use path statuses/mentions, not statuses/replies 3.18002 2012-04-24 - added API method subscriptions; list_subscriptions is now all_subscriptions with alias list_subscriptions - deprecated TwitterVision API support - added API method members_destroy_all with alias remove_list_members - added deprecation warning for 'trends'; calls trends_location(1), instead 3.18001 2011-09-29 - fixed: AutoCursor: - no behavior change when user passes "cursor" arg - work with InflateObjects trait - synthetic ags use (-) prefix: -authenticate, -since, -legacy_lists_api - Replaced JSON::Any with JSON - documented new arguments for friendship_exists 3.18000_01 2011-09-21 - added update_with_media (Allen Haim) - added get_privacy_policy and get_tos API methods - added get_languages and get_settings API methods - added contributors and contributees API methods - added geo_search, geo_search, similar_places, and add_place API methods - friends/followers API methods deprecated - implemented the *new* Lists API in the API::REST trait - replaced MX:MultiInitArg::Trait with MX:Aliases (Justin Hunter) - fixed bad whatis entry (patch from debian, closes RT #67203) - use Digest::SHA instead of Digest::SHA1 (patch from debian, closes RT #67202) 3.17001 2011-03-31 - fixed intermittent bug in AutoCursor (result of Class::MOP anon class caching) 3.17000 2011-03-29 - production release with new AutoCursor trait 3.16000_1 2011-03-27 - Added AutoCursor trait 3.16000 2011-03-26 - Moved trends methods to API::REST; added warning to API::Search::Trends - Added no_retweet_ids method - modify searchapiurl for identica option - added deprecation notice to Net::Identica with Net::Twitter examples - replaced Test::Exception with Test::Fatal in tests 3.15000 2011-02-25 - added Lists API method members_create_all (alias add_list_members) - added tests dependency: Test::Exception (closes RT #65786) 3.14003 2011-02-07 - Fixed: trends_location (closes RT #65506) - Added parameters trim_user, include_entities, include_rts (frank cuny, closes RT #62542) 3.14002 2010-11-02 - Fixed: use File::Spec tests that failed in Win32 (turugina) 3.14001 2010-10-19 - Make Crypt::SSLeay a hard requirement (really no longer practical without it) 3.14000 2010-10-19 - Added #newtwitter API methods (account_totals, account_settings, suggestion_categories, user_suggestions, show_direct_message, retweeted_to_user, retweeted_by_user, lookup_friendships, update_friendship, all_lists, related_results) - fixed: memory leak in RateLimit trait 3.13009 2010-09-17 - use Athorization header for OAuth token requests rather than query params - "identica => 1" sets OAuth URLs (assist from barbie) - updated Synopsis with OAuth (closes RT#61273) 3.13008_02 2010-09-04 - fixed stack frame filter - fixed missing dependency - detect Twitter's errors array as an error object 3.13008_01 2010-08-31 - extract error from the various disparate error formats 3.13008 2010-08-26 - use HTTPS for all OAuth token negotiation steps 3.13007 2010-07-06 - decode_html_entities now decodes all fields (incl source in search results) - Role::OAuth doc patch by Doug Bell - fixed: incompatibility between "since" and InflateObjects 3.13006 2010-06-18 - test fix: bump the skip count for a new test in t/unicode.t for optional module 3.13005 2010-06-18 - fixed: since (synthetic arg) filtering - fixed: don't use args for OAuth signature on multi-part mime posts 3.13004 2010-06-18 - fixed: OAuth signature error with unicode args (RT#58493) 3.13003 2010-05-21 - production release with Lists API refactor and OAuth changes 3.13002_03 2010-05-13 - fixed: generate new OAuth authorization hearder on retry (RetryOnError trait) 3.13002_02 2010-05-12 - fixed: removed redundant alias declarations 3.13002_01 2010-05-12 - Refactored the Lists API to use Net::Twitter::API 3.13001 2010-11 - use POST with Authorization header for XAuth (per Twitter documentation) - replace homegrown XAuth support with Net::OAuth's native support - accommodate 2 base URLs for API::Search (search and trends* methods use different base URLs) - enable SSL support for API::Search 3.13000 2010-05-09 - added support and documentation for optional timeline parameter skip_user - fixed tests: plan was called twice when LWP was too old - added friends_incoming and friendships_outgoing methods 3.12000 2010-03-19 - added new API methods: retweeted_by and retweeted_by_ids - fixed: t/51_since.t was actually connecting to twitter 3.11012 2010-03-13 - fixed: added fallback since Test::More 0.95_01 does not stringify in "is" (tokuhirom) 3.11011 2010-03-11 - fixed documentation to include lookup_users 3.11010 2010-03-11 - Added lookup_users API method 3.11009 2010-03-10 - Added RetryOnError trait (see perldoc Net::Twitter::Role::RetryOnError) - Import Sclar::Util::blessed in the POD Synopsis to make it clear callers need to do so (RT#55283) - Use newly documented "preferred" oauth endpoints: http://api.twitter.com/oauth/* - Added SimulateCursors trait for Identi.ca compatibility 3.11008 2010-03-02 - Added support for new api methods: reverse_geocode, geo_id - Updated method "update" with new parameters: place_id, display_coordinates 3.11007 2010-02-27 - xAuth implemented and tested 3.11006_01 2010-02-26 - xAuth implemented: @oauth = $nt->xauth($username, $password); 3.11006 2010-02-25 - Fixed: unicode.t skip needed number of tests to skip (miyagawa) 3.11005 2010-02-25 - Fixed: image updates accept a single array ref argument (RT#54422) - Fixed: "since" synthetic arg with InflateObjects role (RT#54901) - Fixed: utf8 encoding error for latin1 using Basic Authentication - Allow a pre-created user agent object as argument to new (ua => $ua) - FAQ: How do I get Twitter to display something other than "from Perl Net::Twitter"? 3.11004 2010-02-09 - Removed an extraneous tar ball from the distribution (no code changes) 3.11003 2010-01-29 - Renamed "retweeted_of_me" REST API call to the correct "retweets_of_me" (Dan Moore @mgrdcm) - Back the Moose requirement down to 0.09 (earliest version with native traits) 3.11002 2010-01-28 - Use Moose 0.94 with native traits (resolves CPAN testers failing reports) 3.11001 2010-01-28 - Honor synthetic args (authenticate and since) for Lists API calls 3.11000 2010-01-27 - Lists API overhaul; bug fixes, added parameters, documentation - Create meaninful names for anonymous classes; better error context - Added "Paging and Cursors" documentation section 3.10003 2009-12-15 - Oops! Fixed bug in new test in t/10_net-twitter-regression.t (oh, the irony!) 3.10002 2009-12-15 - Added netrc_machine option to new with default 'api.twitter.com' - Fixed: netrc failed without trait API::REST - Fixed: retweeted_{to,of}_me API URLs (RT#52784) 3.10001 2009-11-26 - Fixed: new t/51_rate_limit.t needs to skip tests unless LWP >= 5.819 3.10000 2009-11-24 - Fixed: ssl not applied when both Lists and REST api used - Added Role::RateLimit - Added trends_available and trends_location methods to the REST API - Documented the lat and long parameters to update 3.09000 2009-11-17 - Bumped Net::OAuth requirement to 0.20 (hopefully resolves CPAN Testers failures) - Added users_search/find_people API method - Updated default apiurl: http://api.twitter.com/1 - Deprecated apihost option to new - Fixed ssl handling for Lists API 3.08000 2009-11-02 - return user_id and screen_name from request_access_token (Roberto Etcheverry) 3.07999_01 2009-10-23 - Added experimental Lists API support 3.07004 2009-10-22 - Fixed: cached request_token results in a stale authentication/authorization urls 3.07003 2009-10-13 - Added new API method: report_spam 3.07002 2009-10-05 - Documented the cursor parameter for friends, followers, friends_ids, and followers_ids. - Fixed: synthetic since parameter (could fail with multiple API traits defined) - Added support for since in YYYY-MM-DD format 3.07001 2009-09-28 - Added specific versions for DateTime and DateTime::Format::Strptime (closes RT#50069) - better deps (Alexandr Ciornii) 3.07000 2009-09-22 - added 'retweets' REST API method - added synthetic 'since' parameter - fixed: object inflation for Search API returns (different timestamp format!) 3.06000 2009-09-16 - support for multipart/from-data posts, used by update_profile_image and update_profile_background_image - bumped version requirement on namespace::autoclean to avoid deprecation notice 3.05003 2009-09-10 - URI 1.35 breaks unicode support; require 1.40 (thanks to Dan Boger, @zigdon) - Removed deprecated is_authorized from examples in pod (thanks to Nigel Metheringham) 3.05002 2009-08-27 - Work around perl bug requiring encoded hash keys when client uses "use utf8" 3.05001 2009-08-21 - Added get_authentication_url for "Sign in with Twitter" authentication flow - Updated "source" option documentation (closes RT 48786) 3.05000 2009-08-14 - Added new API methods: home_timeline, retweet, retweed_{by,of,to}_me - Removed JSON::DWIW from supported handlers (lacks support for JSON::Any's uft8 option) 3.04006 2009-07-29 - Silence Net::OAuth double encoding error (false positives) - Fixed: infrequent OAuth signature failures 3.04005 2009-07-28 - Fix: OAuth / unicode conflict 3.04004 2009-07-28 - Bug fix: OAuth signatures on POST requests (Galen Huntington) 3.04003 2009-07-23 - properly utf-8 encode output to twitter (should provide full unicode support, now) 3.04002 2009-07-21 - Optionally decode HTML entities in status text 3.04001 2009-07-17 - Set JSON::Any option utf8 for consistent unicode support - Added ssl and netrc options (from Net::Twitter::Lite) 3.04000 2009-07-07 - Added inflation of Twitter return HASH refs to Moose objects 3.03003 2009-07-07 - Fixed a typo in Makefile.PL 3.03002 2009-07-04 - Updated documentation to include callback parameter to get_authorization_url - Different OAuth nonce algorithm avoids duplicates in forked processes - Bumped JSON version dependencies for better JSON boolean handling 3.03001 2009-06-29 - Updated to Moose 0.85 - Properly subclassed top level Net::Twitter modules 3.03000 2009-06-25 - Twitter API update: - Added screen_name and user_id parameters to new_direct_message - Added show_friendship method (friendships/show.json) - Made Net::Twitter safe for subclassing - Added "authenticate" parameter handling. By default REST API methods inclued an Authorization header; Search API methods do not. Can be overridden with "authenticate => 0|1". This finally allows getting rate_limit_status by user (the default), or by IP address, with ->rate_limit_status({ authenticate => 0 }). - Added FAQ section to pod 3.02000 2009-06-21 - Added OAuth 1.0a support - Added init_args user/pass for compat with NT 2.12 3.01000_01 2009-06-12 - Updated OAuth support for desktop app PIN numbers (oauth_verifier) 3.01000 2009-06-07 - Added support for the saved_search API methods. 3.00004 2009-06-06 - Fixed: accept extra args as a hashref (search behaved this way in 2.12) 3.00003 2009-06-03 - Added a workaround for JSON backends that don't handle booleans properly 3.00002 2009-06-01 - Updated version requirements in Makefile.PL 3.00001 2009-05-30 - Provided version numbers for modules that already existed on CPAN 3.00000 2009-05-30 - upgrade get/put parms so Latin-1 can be handled as UTF-8 2.99000_05 2009-05-27 - Restructured module hierarchy: all roles/traits moved to Net/Twitter/Role/ - Itegrated Tatsuhiko Miyagawa's OAuth support as a trait - Identica fixes: strings '"true"' and '"false"' to bools; mentions => replies - Fixed useragent_args type. (Christopher Biggs) - Store HTTP::Response even on success in WrapError for legacy support (Christopher Biggs) 2.99000_04 2009-05-25 - Moved Net::Twitter to Net::Twitter::Core; Net::Twitter provides new -> new_with_traits - Added legacy => [0|1] shortcut option 2.99000_03 2009-05-22 - Broke MANIFEST on the prior dist (fixed) 2.99000_02 2009-05-22 - Corrected POD NAME sections and module naming - Temporarily removed lib/Net/Twitter/Search.pm from MANIFEST 2.99000_01 2009-05-22 - Initial dev release of 3.00 candidate - Moose based replacement for Net::Twitter This is a complete rewrite of Net::Twitter. For earlier versions, see: http://cpansearch.perl.org/src/CTHOM/Net-Twitter-2.12/Changes Net-Twitter-4.01043/dist.ini000644 000766 000024 00000002552 13227713560 015617 0ustar00marcstaff000000 000000 name = Net-Twitter version = 4.01043 author = Marc Mims license = Perl_5 copyright_holder = Marc Mims copyright_year = 2018 [GithubMeta] [MetaResources] bugtracker = http://github.com/semifor/Net-Twitter/issues [PkgVersion] [PodVersion] [GatherDir] [PruneCruft] [ManifestSkip] [MetaYAML] [License] [ExtraTests] [MakeMaker] eumm_version = 7.1101 [Manifest] [TestRelease] [ConfirmRelease] [UploadToCPAN] [Run::BeforeBuild] run = NET_TWITTER_NO_TRENDS_WARNING=1 %x -Ilib src/build.pl %v 'src/net-twitter-pod.tt2' 'lib/Net/Twitter.pod' run = pod2text 'lib/Net/Twitter.pod' 'README' [Run::AfterBuild] run = rm lib/Net/Twitter.pod README [MetaNoIndex] directory = src directory = examples [PruneFiles] filename = README.md match = ^nytprof.* match = ^perl5 match = ^cpan.* match = ^src/ [AutoPrereqs] skip = ^API:: skip = ^(Legacy|OAuth|WrapError)$ [Prereqs] Net::HTTP = >=0,!=6.04,!=6.05 LWP::Protocol::https = 0 IO::Socket::SSL = >=2.005 [Prereqs / TestRequires] Test::More = 0.98 Test::Fatal = 0 [PodSyntaxTests] [PodCoverageTests] ; authordep Pod::Coverage::TrustPod ; authordep Test::Pod::Coverage [Test::Compile] ;[@Git] ;changelog = Changes ;allow_dirty = dist.ini ;allow_dirty = Changes ;commit_msg = v%v%n%n%c ;tag_format = %v ;tag_message = %v ;push_to = origin ; ;[Git::NextVersion] ;version_regexp = ^(\d+\.\d{2})$ ; authordep Template Net-Twitter-4.01043/examples/000755 000766 000024 00000000000 13227713560 015765 5ustar00marcstaff000000 000000 Net-Twitter-4.01043/lib/000755 000766 000024 00000000000 13227713560 014715 5ustar00marcstaff000000 000000 Net-Twitter-4.01043/LICENSE000644 000766 000024 00000043644 13227713560 015167 0ustar00marcstaff000000 000000 This software is copyright (c) 2018 by Marc Mims. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2018 by Marc Mims. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2018 by Marc Mims. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End Net-Twitter-4.01043/Makefile.PL000644 000766 000024 00000006301 13227713560 016121 0ustar00marcstaff000000 000000 # This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.010. use strict; use warnings; use 5.008001; use ExtUtils::MakeMaker 7.1101; my %WriteMakefileArgs = ( "ABSTRACT" => "A perl interface to the Twitter API", "AUTHOR" => "Marc Mims ", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => "7.1101" }, "DISTNAME" => "Net-Twitter", "LICENSE" => "perl", "MIN_PERL_VERSION" => "5.008001", "NAME" => "Net::Twitter", "PREREQ_PM" => { "Carp::Clan" => 0, "Class::Load" => 0, "Data::Visitor::Callback" => 0, "DateTime" => 0, "DateTime::Format::Strptime" => 0, "Devel::StackTrace" => 0, "Digest::SHA" => 0, "Encode" => 0, "HTML::Entities" => 0, "HTTP::Request::Common" => 0, "IO::Socket::SSL" => "2.005", "JSON::MaybeXS" => 0, "LWP::Protocol::https" => 0, "List::Util" => 0, "Moose" => 0, "Moose::Exporter" => 0, "Moose::Meta::Method" => 0, "Moose::Role" => 0, "Moose::Util::TypeConstraints" => 0, "MooseX::Role::Parameterized" => 0, "Net::HTTP" => ">= 0, != 6.04, != 6.05", "Net::Netrc" => 0, "Net::OAuth" => 0, "Scalar::Util" => 0, "Time::HiRes" => 0, "Try::Tiny" => 0, "URI" => 0, "URI::Escape" => 0, "namespace::autoclean" => 0, "overload" => 0 }, "TEST_REQUIRES" => { "Carp" => 0, "File::Spec" => 0, "HTTP::Response" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "LWP::UserAgent" => "5.819", "Net::OAuth::Message" => 0, "Test::Fatal" => 0, "Test::More" => "0.98", "Test::Warn" => 0, "base" => 0, "blib" => "1.01", "lib" => 0, "strict" => 0, "utf8" => 0, "warnings" => 0 }, "VERSION" => "4.01043", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Carp" => 0, "Carp::Clan" => 0, "Class::Load" => 0, "Data::Visitor::Callback" => 0, "DateTime" => 0, "DateTime::Format::Strptime" => 0, "Devel::StackTrace" => 0, "Digest::SHA" => 0, "Encode" => 0, "File::Spec" => 0, "HTML::Entities" => 0, "HTTP::Request::Common" => 0, "HTTP::Response" => 0, "IO::Handle" => 0, "IO::Socket::SSL" => "2.005", "IPC::Open3" => 0, "JSON::MaybeXS" => 0, "LWP::Protocol::https" => 0, "LWP::UserAgent" => "5.819", "List::Util" => 0, "Moose" => 0, "Moose::Exporter" => 0, "Moose::Meta::Method" => 0, "Moose::Role" => 0, "Moose::Util::TypeConstraints" => 0, "MooseX::Role::Parameterized" => 0, "Net::HTTP" => ">= 0, != 6.04, != 6.05", "Net::Netrc" => 0, "Net::OAuth" => 0, "Net::OAuth::Message" => 0, "Scalar::Util" => 0, "Test::Fatal" => 0, "Test::More" => "0.98", "Test::Warn" => 0, "Time::HiRes" => 0, "Try::Tiny" => 0, "URI" => 0, "URI::Escape" => 0, "base" => 0, "blib" => "1.01", "lib" => 0, "namespace::autoclean" => 0, "overload" => 0, "strict" => 0, "utf8" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); Net-Twitter-4.01043/MANIFEST000644 000766 000024 00000003370 13227713560 015303 0ustar00marcstaff000000 000000 # This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.010. Changes LICENSE MANIFEST META.yml Makefile.PL README dist.ini examples/oauth_desktop.pl examples/oauth_webapp.pl lib/Net/Identica.pm lib/Net/Twitter.pm lib/Net/Twitter.pod lib/Net/Twitter/API.pm lib/Net/Twitter/Core.pm lib/Net/Twitter/Error.pm lib/Net/Twitter/Manual/MigratingToV1_1.pod lib/Net/Twitter/OAuth.pm lib/Net/Twitter/Role/API/Lists.pm lib/Net/Twitter/Role/API/REST.pm lib/Net/Twitter/Role/API/RESTv1_1.pm lib/Net/Twitter/Role/API/Search.pm lib/Net/Twitter/Role/API/Search/Trends.pm lib/Net/Twitter/Role/API/TwitterVision.pm lib/Net/Twitter/Role/API/Upload.pm lib/Net/Twitter/Role/API/UploadMedia.pm lib/Net/Twitter/Role/AppAuth.pm lib/Net/Twitter/Role/AutoCursor.pm lib/Net/Twitter/Role/InflateObjects.pm lib/Net/Twitter/Role/Legacy.pm lib/Net/Twitter/Role/OAuth.pm lib/Net/Twitter/Role/RateLimit.pm lib/Net/Twitter/Role/RetryOnError.pm lib/Net/Twitter/Role/SimulateCursors.pm lib/Net/Twitter/Role/WrapError.pm lib/Net/Twitter/Role/WrapResult.pm lib/Net/Twitter/Search.pm lib/Net/Twitter/Types.pm lib/Net/Twitter/WrappedResult.pm t/00-compile.t t/00_load.t t/01_basic.t t/01_basic_v1_1.t t/02_fails.t t/10_net-twitter-regression.t t/11_useragent.t t/12_identica.t t/13_search.t t/14_authenticate.t t/15_subclass.t t/20_exceptions.t t/20_generated.t t/21_wraperror.t t/22_twitter_insanity.t t/30_legacy.t t/40_nt_subclasses.t t/50_inflate_objects.t t/51_rate_limit.t t/51_since.t t/60-api_lists.t t/99-pod_spelling.t t/aliases.t t/app-auth.t t/author-pod-coverage.t t/author-pod-syntax.t t/auto-cursor.t t/deprecated_v1_1.t t/geo.t t/leak.t t/lib/TestUA.pm t/lookup_users.t t/retry.t t/role-wrap-result.t t/stack_trace.t t/stringent-encoding.t t/twitter_error.t t/unicode.t t/url-attributes.t Net-Twitter-4.01043/META.yml000644 000766 000024 00000003202 13227713560 015415 0ustar00marcstaff000000 000000 --- abstract: 'A perl interface to the Twitter API' author: - 'Marc Mims ' build_requires: Carp: '0' File::Spec: '0' HTTP::Response: '0' IO::Handle: '0' IPC::Open3: '0' LWP::UserAgent: '5.819' Net::OAuth::Message: '0' Test::Fatal: '0' Test::More: '0.98' Test::Warn: '0' base: '0' blib: '1.01' lib: '0' strict: '0' utf8: '0' warnings: '0' configure_requires: ExtUtils::MakeMaker: '7.1101' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.010, CPAN::Meta::Converter version 2.150001' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Net-Twitter no_index: directory: - examples - src requires: Carp::Clan: '0' Class::Load: '0' Data::Visitor::Callback: '0' DateTime: '0' DateTime::Format::Strptime: '0' Devel::StackTrace: '0' Digest::SHA: '0' Encode: '0' HTML::Entities: '0' HTTP::Request::Common: '0' IO::Socket::SSL: '2.005' JSON::MaybeXS: '0' LWP::Protocol::https: '0' List::Util: '0' Moose: '0' Moose::Exporter: '0' Moose::Meta::Method: '0' Moose::Role: '0' Moose::Util::TypeConstraints: '0' MooseX::Role::Parameterized: '0' Net::HTTP: '>= 0, != 6.04, != 6.05' Net::Netrc: '0' Net::OAuth: '0' Scalar::Util: '0' Time::HiRes: '0' Try::Tiny: '0' URI: '0' URI::Escape: '0' namespace::autoclean: '0' overload: '0' perl: '5.008001' resources: bugtracker: http://github.com/semifor/Net-Twitter/issues homepage: https://github.com/semifor/Net-Twitter repository: https://github.com/semifor/Net-Twitter.git version: '4.01043' x_serialization_backend: 'YAML::Tiny version 1.69' Net-Twitter-4.01043/README000644 000766 000024 00000306746 13227713560 015047 0ustar00marcstaff000000 000000 NAME Net::Twitter - A perl interface to the Twitter API SYNOPSIS use Net::Twitter; use Scalar::Util 'blessed'; # When no authentication is required: my $nt = Net::Twitter->new(legacy => 0); # As of 13-Aug-2010, Twitter requires OAuth for authenticated requests my $nt = Net::Twitter->new( traits => [qw/API::RESTv1_1/], consumer_key => $consumer_key, consumer_secret => $consumer_secret, access_token => $token, access_token_secret => $token_secret, ); my $result = $nt->update('Hello, world!'); eval { my $statuses = $nt->friends_timeline({ since_id => $high_water, count => 100 }); for my $status ( @$statuses ) { print "$status->{created_at} <$status->{user}{screen_name}> $status->{text}\n"; } }; if ( my $err = $@ ) { die $@ unless blessed $err && $err->isa('Net::Twitter::Error'); warn "HTTP Response Code: ", $err->code, "\n", "HTTP Message......: ", $err->message, "\n", "Twitter error.....: ", $err->error, "\n"; } TWITTER API V1.1 SUPPORT This version of Net::Twitter provides Twitter API v1.1 support. Enable it by including the "API::RESTv1_1" trait instead of "API::REST". Using Twitter API v1.1 may require changes to you code! It is not completely backwards compatible with v1. For help migrating your application to Twitter API v1.1, see Net::Twitter::Manual::MigratingToV1_1. DESCRIPTION This module has been superseded by Twitter::API. Please update as soon as you possibly can to use new features and the new API versions. This module will no longer be supported. This module provides a perl interface to the Twitter APIs. See for a full description of the Twitter APIs. TWITTER API VERSION 1.1 Twitter will (perhaps has by the time you read this) deprecated version 1 of the API. Documentation, here, assumes version 1.1 of the API. For version 1 documentation, see Net::Twitter::Role::API::REST. To use Twitter API version 1.1, simply replace "API::REST" in the "traits" argument to "new" with "API::RESTv1_1". The "Net::Twitter" API is backwards compatible to the extent possible. If Twitter does not provide a 1.1 endpoint for a version 1 call, "Net::Twitter" cannot support it, of course. Twitter API version 1.1 requires OAuth authentication for all calls. There is no longer an IP address limit and a per-user limit. Each API call has it's own rate limit. Most are 15 calls reset every 15 minutes. Others are 180 calls, reset every 15 minutes. These limits may change. For current rate limits, see . OMG! THE MOOSE! Net::Twitter is Moose based. Moose provides some advantages, including the ability for the maintainer of this module to respond quickly to Twitter API changes. See Net::Twitter::Lite if you need an alternative without Moose and its dependencies. Net::Twitter::Lite's API method definitions and documentation are generated from Net::Twitter. It is a related module, but does not depend on Net::Twitter or Moose for installation. RETURN VALUES Net::Twitter decodes the data structures returned by the Twitter API into native perl data structures (HASH references and ARRAY references). The full layout of those data structures are not documented, here. They change often, usually with the addition of new elements, and documenting all of those changes would be a significant challenge. Instead, rely on the online Twitter API documentation and inspection of the returned data. The Twitter API online documentation is located at . To inspect the data, use Data::Dumper or similar module of your choice. Here's a simple example using Data::Dumper: use Data::Dumper; my $r = $nt->search($search_term); print Dumper $r; For more information on perl data structures, see perlreftut, perldsc, and perllol. METHODS AND ARGUMENTS new This constructs a "Net::Twitter" object. It takes several named parameters, all of them optional: traits An ARRAY ref of traits used to control which APIs the constructed "Net::Twitter" object will support and how it handles errors. Possible values are: API::RESTv1_1 Provides support for the Twitter REST API version 1.1 methods. API::Search Deprecated. Use "search" in API::RESTv1_1 instead. AppAuth Provides Application-Only Authentication with methods, "request_access_token" and "invalidate_token". See Net::Twitter::Role::AppAuth. Example: my $nt = Net::Twitter->new( traits => [ qw/AppAuth API::RESTv1_1/ ], consumer_key => 'my-consumer-key', consumer_secret => 'my-consumer-secret', ); $nt->request_access_token; say 'token: ', $nt->access_token; my $r = $nt->followers_ids({ screen_name => 'timtoady', cursor => -1, }); # good until invalidated, with ... $nt->invalidate_token AutoCursor "AutoCursor" is a parameterized trait that provides an automatic loop for cursored calls, returning an ARRAY reference to the combined results. By default, it handles "friends_ids" and "followers_ids". See Net::Twitter::Role::AutoCursor for details. InflateObjects When this optional trait is included, Net::Twitter inflates HASH refs returned by Twitter into objects with read accessors for each element. In addition, it inflates dates to DateTime objects and URLs to URI objects. Objects that include a "created_at" attribute also have a "relative_created_at" method. For example, with "InflateObjects" applied, the method returns an array of status objects: $r = $nt->friends_timeline; for my $status ( @$r ) { $r->user->screen_name; # same as $r->{user}{screen_name} # $created_at is a DateTime; $age is a DateTime::Duration my $age = DateTime->now - $r->created_at; # print an age in a similar style to the Twitter web site, e.g.: # less than a minute ago # about a minute ago # 6 minutes ago # 1 day ago # etc. print $r->relative_created_at; Legacy This trait provides backwards compatibility to "Net::Twitter" versions prior to 3.00. It implies the traits "API::REST", "API::Search", "API::TwitterVision", and "API::WrapError". It also provides additional functionality to ensure consistent behavior for applications written for use with legacy versions of "Net::Twitter". In the current version, this trait is automatically included if the "traits" option is not specified. This ensures backwards compatibility for existing applications using "Net::Twitter" versions prior to 3.00. See section "LEGACY COMPATIBILITY" for more details. OAuth The "OAuth" trait provides OAuth authentication rather than the default Basic Authentication for Twitter API method calls. See the "Authentication" section and Net::Twitter::Role::OAuth for full documentation. RateLimit The "RateLimit" trait adds utility methods that return information about the current rate limit status. See Net::Twitter::Role::RateLimit for details. RetryOnError The "RetryOnError" trait automatically retries Twitter API calls with temporary failures. See Net::Twitter::Role::RetryOnError for details. WrapError "Net::Twitter" normally throws exceptions on error. When this trait is included, "Net::Twitter" returns undef when a method fails and makes the error available through method "get_error". This is the way all errors were handled in Net::Twitter versions prior to version 3.00. Some examples of using the "traits" parameter in "new": # provide support for *only* the REST API; throw exceptions on error $nt = Net::Twitter->new(traits => ['API::RESTv1_1']); # provide support for both the REST and Search APIs; wrap errors $nt = Net::Twitter->new(traits => [qw/API::RESTv1_1 API::Search WrapError/]); # Provide legacy support for applications written with Net::Twitter # prior to version 3.0. $nt = Net::Twitter->new(traits => ['Legacy']); legacy A boolean. If set to 0, "new" constructs a "Net::Twitter" object implementing the REST API and throws exceptions on API method errors. Net::Twitter->new(legacy => 0); is a shortcut for: Net::Twitter->new(traits => ['API::RESTv1_1']); If set to 1, "new" constructs a "Net::Twitter" object with the "Legacy" trait. Net::Twitter->new(legacy => 1); is a shortcut for: Net::Twitter->new(traits => ['Legacy']); username This is the username for Basic Authentication. NOTE: as of 31-Aug-2010, Twitter no longer supports Basic Authentication. Use OAuth instead. Other Twitter compatible services may, however, accept Basic Authentication, so support for it remains in "Net::Twitter". password This is the password used for Basic Authentication. clientname The value for the "X-Twitter-Client-Name" HTTP header. It defaults to "Perl Net::Twitter". Note: This option has nothing to do with the "via" application byline. clientver The value for the "X-Twitter-Client-Version" HTTP header. It defaults to current version of the "Net::Twitter" module. clienturl The value for the "X-Twitter-Client-URL" HTTP header. It defaults to the search.cpan.org page for the "Net::Twitter" distribution. useragent_class The "LWP::UserAgent" compatible class used internally by "Net::Twitter". It defaults to "LWP::UserAgent". For POE based applications, consider using "LWP::UserAgent::POE". useragent_args An HASH ref of arguments to pass to constructor of the class specified with "useragent_class", above. It defaults to {} (an empty HASH ref). useragent The value for "User-Agent" HTTP header. It defaults to "Net::Twitter/4.01043 (Perl)". source Twitter on longer uses the "source" parameter. Support for it remains in "Net::Twitter" for any compatible services that may use it. It was originally used by Twitter to provide an "via" application byline. apiurl The URL for the Twitter API. This defaults to "http://api.twitter.com/1". This option is available when the "API::RESTv1_1" trait is included. apihost DEPRECATED - Setting the "apiurl" is sufficient. apirealm A string containing the Twitter API realm used for Basic Authentication. It defaults to "Twitter API". This option is available when the "API::RESTv1_1" trait is included. identica If set to 1, "Net::Twitter" overrides the defaults for "apiurl", "apihost", and "apirealm" to "http://identi.ca/api", "identi.ca:80", and "Laconica API" respectively. It defaults to 0. This option is available when the "API::RESTv1_1" trait is included. consumer_key A string containing the OAuth consumer key provided by Twitter when an application is registered. This option is available when the "OAuth" trait is included. consumer_secret A string containing the OAuth consumer secret. This option is available when the "OAuth" trait is included. ssl If set to 1, an SSL connection will be used for all API calls. Defaults to 1. netrc (Optional) Sets the *machine* key to look up in ".netrc" to obtain credentials. If set to 1, Net::Twitter will use the value of the "netrc_machine" option (below). # in .netrc machine api.twitter.com login YOUR_TWITTER_USER_NAME password YOUR_TWITTER_PASSWORD machine semifor.twitter.com login semifor password SUPERSECRET # in your perl program $nt = Net::Twitter->new(netrc => 1); $nt = Net::Twitter->new(netrc => 'semifor.twitter.com'); netrc_machine (Optional) Sets the "machine" entry to look up in ".netrc" when "> is used. Defaults to "api.twitter.com". decode_html_entities Twitter encodes HTML entities in the "text" field of statuses. Set this option to 1 to have them automatically decoded. Default 0. credentials($username, $password) Set the credentials for Basic Authentication. This is helpful for managing multiple accounts. ua Provides access to the constructed user agent object used internally by "Net::Twitter". Use it with caution. AUTHENTICATION With REST API version 1.1, all API calls require OAuth. Since 31-Aug-2010, version 1 required OAuth requests requiring authentication. Other Twitter compatible services, like Identi.ca, accept Basic Authentication. So, "Net::Twitter" provides support for both. To set up OAuth, include the "consumer_key" and "consumer_secret" options to "new". When they are provided, the "OAuth" trait will be automatically included. See Net::Twitter::Role::OAuth for more information on using OAuth, including examples. To set up Basic Authentication in "Net::Twitter", provide the "username" and "password" options to "new" or call the "credentials" method. In addition to the arguments specified for each API method described below, an additional "-authenticate" parameter can be passed. To request an "Authorization" header, pass "-authenticate => 1"; to suppress an authentication header, pass "-authenticate => 0". Even if requested, an Authorization header will not be added if there are no user credentials (username and password for Basic Authentication; access tokens for OAuth). This is probably only useful for non-Twitter sites that use the Twitter API and support unauthenticated calls. API METHODS AND ARGUMENTS Most Twitter API methods take parameters. All Net::Twitter API methods will accept a HASH ref of named parameters as specified in the Twitter API documentation. For convenience, many Net::Twitter methods accept simple positional arguments. The positional parameter passing style is optional; you can always use the named parameters in a HASH reference if you prefer. You may pass any number of required parameters as positional parameters. You must pass them in the order specified in the documentation for each method. Optional parameters must be passed as named parameters in a HASH reference. The HASH reference containing the named parameters must be the final parameter to the method call. Any required parameters not passed as positional parameters, must be included in the named parameter HASH reference. For example, the REST API method "update" has one required parameter, "status". You can call "update" with a HASH ref argument: $nt->update({ status => 'Hello world!' }); Or, you can use the convenient, positional parameter form: $nt->update('Hello world!'); The "update" method also has an optional parameter, "in_reply_to_status_id". To use it, you must use the HASH ref form: $nt->update({ status => 'Hello world!', in_reply_to_status_id => $reply_to }); You may use the convenient positional form for the required "status" parameter with the optional parameters specified in the named parameter HASH reference: $nt->update('Hello world!', { in_reply_to_status_id => $reply_to }); Convenience form is provided for the required parameters of all API methods. So, these two calls are equivalent: $nt->friendship_exists({ user_a => $fred, user_b => $barney }); $nt->friendship_exists($fred, $barney); Many API methods have aliases. You can use the API method name, or any of its aliases, as you prefer. For example, these calls are all equivalent: $nt->friendship_exists($fred, $barney); $nt->relationship_exists($fred, $barney); $nt->follows($fred, $barney); Aliases support both the HASH ref and convenient forms: $nt->follows({ user_a => $fred, user_b => $barney }); Cursors and Paging Some methods return partial results a page at a time. Originally, methods that returned partial results used a "page" parameter. A more recent addition to the Twitter API for retrieving multiple pages uses the "cursor" parameter. Usually, a method uses either the "page" parameter or the "cursor" parameter, but not both. There have been exceptions to this rule when Twitter deprecates the use of "page" for a method in favor of "cursor". In that case, both methods may work during a transition period. So, if a method supports both, you should always use the "cursor" parameter. Paging For methods that support paging, the first page is returned by passing "page => 1", the second page by passing "page => 2", etc. If no "page" parameter is passed, the first page is returned. Here's an example that demonstrates how to obtain all favorites in a loop: my @favs; for ( my $page = 1; ; ++$page ) { my $r = $nt->favorites({ page => $page }); last unless @$r; push @favs, @$r; } Cursors Cursoring employs a different strategy. To obtain the first page of results, pass "cursor => -1". Twitter returns a reference to a hash that includes entries "next_cursor", "previous_cursor", and an entry with a reference to an array containing a page of the requested items. The key for the array reference will be named "users", "ids", or something similar depending upon the type of returned items. For example, when "cursor" parameter is used with the "followers_ids" method, the returned in hash entry "ids". The "next_cursor" value can be used in a subsequent call to obtain the next page of results. When you have obtained the last page of results, "next_cursor" will be 0. Likewise, you can use the value for "previous_cursor" to obtain the previous page of results. When you have obtained the first page, "previous_cursor" will be 0. Here's an example that demonstrates how to obtain all follower IDs in a loop using the "cursor" parameter: my @ids; for ( my $cursor = -1, my $r; $cursor; $cursor = $r->{next_cursor} ) { $r = $nt->followers_ids({ cursor => $cursor }); push @ids, @{ $r->{ids} }; } Synthetic Arguments In addition to the arguments described in the Twitter API Documentation for each API method, Net::Twitter supports additional *synthetic* arguments. -authenticate When set to 1, Net::Twitter will provide an Authorization header for the API call; when set to 0, it will suppress the Authentication header. This argument overrides the defined authentication behavior for the API method. It is probably only useful for the "rate_limit_status" method which returns different values for authenticated and unauthenticated calls. See "AUTHENTICATION" for more details. -since API methods that accept the "since_id" argument will also accept the synthetic "-since" argument, instead. "-since" may be a "Date::Time" object, an epoch time (the number of seconds since the system epoch), or a string in the same format returned by Twitter for the "created_at" attribute. Only statuses with a "created_at" time greater than "-since" will be returned by the API call. -legacy_lists_api This option is only effective when the legacy "API::Lists" trait is applied. Passing "-legacy_lists_api" set to 0 for lists methods will use the new lists endpoints and semantics. This will facilitate upgrading an application to use the new lists api methods. When the "API::Lists" trait is not applied, this option is ignored. REST API Methods These methods are provided when trait "API::RESTv1_1" is included in the "traits" option to "new". Common Parameters id Several of these methods accept a user ID as the "id" parameter. The user ID can be either a screen name, or the users numeric ID. To disambiguate, use the "screen_name" or "user_id" parameters, instead. For example, These calls are equivalent: $nt->create_friend('perl_api'); # screen name $nt->create_friend(1564061); # numeric ID $nt->create_friend({ id => 'perl_api' }); $nt->create_friend({ screen_name => 'perl_api' }); $nt->create_friend({ user_id => 1564061 }); However user_id 911 and screen_name 911 are separate Twitter accounts. These calls are NOT equivalent: $nt->create_friend(911); # interpreted as screen name $nt->create_friend({ user_id => 911 }); # screen name: richellis Whenever the "id" parameter is required and "user_id" and "screen_name" are also parameters, using any one of them satisfies the requirement. skip_user The timeline methods all accept an optional "skip_user" parameter. When set to a true value, the statuses returned in a timeline will not contain an entire embedded user HASH. Instead, the user node will contain only an "id" element to indicate the numerical ID of the Twitter user that sent the status. Methods account_settings Parameters: *none* Required: *none* Returns the current trend, geo and sleep time information for the authenticating user. Returns: HashRef Twitter API documentation: GET account/settings account_totals DEPRECATED Parameters: *none* Required: *none* Returns the current count of friends, followers, updates (statuses) and favorites of the authenticating user. Returns: HashRef add_list_member Parameters: list_id, slug, user_id, screen_name, owner_screen_name, owner_id Required: *none* Add a member to a list. The authenticated user must own the list to be able to add members to it. Note that lists can't have more than 500 members. Returns: User Twitter API documentation: POST lists/members/create add_place add_place(name, contained_within, token, lat, long) Parameters: name, contained_within, token, lat, long, attribute:street_address, callback Required: name, contained_within, token, lat, long Creates a new place object at the given latitude and longitude. Before creating a place you need to query "similar_places" with the latitude, longitude and name of the place you wish to create. The query will return an array of places which are similar to the one you wish to create, and a token. If the place you wish to create isn't in the returned array you can use the token with this method to create a new one. Returns: Place Twitter API documentation: POST geo/place block_exists DEPRECATED block_exists(id) Parameters: id, user_id, screen_name, include_entities Required: id Returns if the authenticating user is blocking a target user. Will return the blocked user's object if a block exists, and error with HTTP 404 response code otherwise. Returns: BasicUser blocking alias: blocks_list Parameters: cursor, include_entities, skip_status Required: *none* Returns an array of user objects that the authenticating user is blocking. Returns: ArrayRef[BasicUser] Twitter API documentation: GET blocks/list blocking_ids alias: blocks_ids Parameters: cursor, stringify_ids Required: *none* Returns an array of numeric user ids the authenticating user is blocking. Returns: ArrayRef[Int] Twitter API documentation: GET blocks/ids contributees DEPRECATED Parameters: user_id, screen_name, include_entities, skip_satus Required: *none* Returns an array of users that the specified user can contribute to. Returns: ArrayRef[User] contributors DEPRECATED Parameters: user_id, screen_name, include_entities, skip_satus Required: *none* Returns an array of users who can contribute to the specified account. Returns: ArrayRef[User] create_block create_block(id) Parameters: user_id, screen_name, include_entities, skip_status Required: id Blocks the user specified in the "user_id" or "screen_name" parameter as the authenticating user. Returns the blocked user when successful. You can find out more about blocking in the Twitter Support Knowledge Base. Returns: BasicUser Twitter API documentation: POST blocks/create create_favorite create_favorite(id) Parameters: id, include_entities Required: id Favorites the status specified in the ID parameter as the authenticating user. Returns the favorite status when successful. Returns: Status Twitter API documentation: POST favorites/create create_friend alias: follow alias: follow_new alias: create_friendship Parameters: user_id, screen_name, follow Required: *none* Follows the user specified in the "user_id" or "screen_name" parameter as the authenticating user. Returns the befriended user when successful. Returns a string describing the failure condition when unsuccessful. Returns: BasicUser Twitter API documentation: POST friendships/create create_list create_list(name) Parameters: list_id, slug, name, mode, description, owner_screen_name, owner_id Required: name Creates a new list for the authenticated user. Note that you can't create more than 20 lists per account. Returns: List Twitter API documentation: POST lists/create create_media_metadata create_media_metadata(media_id) Parameters: media_id, alt_text Required: media_id Adds metadata -- alt text, in particular -- to a previously uploaded media object, specified by its ID. (One knows this ID via the return value of the preceding "upload" call.) The "alt_text" parameter must have as its value a hashref containing a single key-value pair. The key must be "text", and the value is the alt text to assign to the media object. The text must be 400 characters or fewer in length. Returns: HashRef Twitter API documentation: POST media/metadata/create create_mute create_mute(id) Parameters: user_id, screen_name Required: id Mutes the user specified in the "user_id" or "screen_name" parameter as the authenticating user. Returns the muted user when successful. You can find out more about muting in the Twitter Support Knowledge Base. Returns: BasicUser Twitter API documentation: POST mutes/users/create create_saved_search create_saved_search(query) Parameters: query Required: query Creates a saved search for the authenticated user. Returns: SavedSearch Twitter API documentation: POST saved_searches/create delete_list Parameters: owner_screen_name, owner_id, list_id, slug Required: *none* Deletes the specified list. The authenticated user must own the list to be able to destroy it. Returns: List Twitter API documentation: POST lists/destroy delete_list_member alias: remove_list_member Parameters: list_id, slug, user_id, screen_name, owner_screen_name, owner_id Required: *none* Removes the specified member from the list. The authenticated user must be the list's owner to remove members from the list. Returns: User Twitter API documentation: POST lists/members/destroy destroy_block destroy_block(id) Parameters: user_id, screen_name, include_entities, skip_status Required: id Un-blocks the user specified in the "user_id" or "screen_name" parameter as the authenticating user. Returns the un-blocked user when successful. Returns: BasicUser Twitter API documentation: POST blocks/destroy destroy_direct_message destroy_direct_message(id) Parameters: id, include_entities Required: id Destroys the direct message specified in the required ID parameter. The authenticating user must be the recipient of the specified direct message. Important: this method requires an access token with RWD (read, write, and direct message) permissions. Returns: DirectMessage Twitter API documentation: POST direct_messages/destroy destroy_favorite destroy_favorite(id) Parameters: id, include_entities Required: id Un-favorites the status specified in the ID parameter as the authenticating user. Returns the un-favorited status. Returns: Status Twitter API documentation: POST favorites/destroy destroy_friend destroy_friend(id) alias: unfollow alias: destroy_friendship Parameters: user_id, screen_name Required: id Discontinues friendship with the user specified in the "user_id" or "screen_name" parameter as the authenticating user. Returns the un-friended user when successful. Returns a string describing the failure condition when unsuccessful. Returns: BasicUser Twitter API documentation: POST friendships/destroy destroy_mute destroy_mute(id) Parameters: user_id, screen_name Required: id Un-mutes the user specified in the "user_id" or "screen_name" parameter as the authenticating user. Returns the un-muted user when successful. Returns: BasicUser Twitter API documentation: POST mutes/users/destroy destroy_saved_search destroy_saved_search(id) alias: delete_saved_search Parameters: id Required: id Destroys a saved search. The search, specified by "id", must be owned by the authenticating user. Returns: SavedSearch Twitter API documentation: POST saved_searches/destroy/:id destroy_status destroy_status(id) Parameters: id, trim_user Required: id Destroys the status specified by the required ID parameter. The authenticating user must be the author of the specified status. Returns: Status Twitter API documentation: POST statuses/destroy/:id direct_messages Parameters: since_id, max_id, count, page, include_entities, skip_status Required: *none* Returns a list of the 20 most recent direct messages sent to the authenticating user including detailed information about the sending and recipient users. Important: this method requires an access token with RWD (read, write, and direct message) permissions. Returns: ArrayRef[DirectMessage] Twitter API documentation: GET direct_messages disable_notifications DEPRECATED disable_notifications(id) Parameters: id, screen_name, include_entities Required: id Disables notifications for updates from the specified user to the authenticating user. Returns the specified user when successful. Returns: BasicUser enable_notifications DEPRECATED enable_notifications(id) Parameters: id, screen_name, include_entities Required: id Enables notifications for updates from the specified user to the authenticating user. Returns the specified user when successful. Returns: BasicUser end_session DEPRECATED Parameters: *none* Required: *none* Ends the session of the authenticating user, returning a null cookie. Use this method to sign users out of client-facing applications like widgets. Returns: Error favorites Parameters: user_id, screen_name, count, since_id, max_id, include_entities Required: *none* Returns the 20 most recent favorite statuses for the authenticating user or user specified by the ID parameter. Returns: ArrayRef[Status] Twitter API documentation: GET favorites/list followers alias: followers_list Parameters: user_id, screen_name, cursor Required: *none* Returns a cursored collection of user objects for users following the specified user. Returns: HashRef Twitter API documentation: GET followers/list followers_ids Parameters: user_id, screen_name, cursor, stringify_ids Required: *none* Returns a reference to an array of numeric IDs for every user following the specified user. The order of the IDs may change from call to call. To obtain the screen names, pass the arrayref to "lookup_users". Use the optional "cursor" parameter to retrieve IDs in pages of 5000. When the "cursor" parameter is used, the return value is a reference to a hash with keys "previous_cursor", "next_cursor", and "ids". The value of "ids" is a reference to an array of IDS of the user's followers. Set the optional "cursor" parameter to -1 to get the first page of IDs. Set it to the prior return's value of "previous_cursor" or "next_cursor" to page forward or backwards. When there are no prior pages, the value of "previous_cursor" will be 0. When there are no subsequent pages, the value of "next_cursor" will be 0. Returns: HashRef|ArrayRef[Int] Twitter API documentation: GET followers/ids friends alias: friends_list Parameters: user_id, screen_name, cursor Required: *none* Returns a cursored collection of user objects for users followed by the specified user. Returns: HashRef Twitter API documentation: GET friends/list friends_ids alias: following_ids Parameters: user_id, screen_name, cursor, stringify_ids Required: *none* Returns a reference to an array of numeric IDs for every user followed by the specified user. The order of the IDs is reverse chronological. Use the optional "cursor" parameter to retrieve IDs in pages of 5000. When the "cursor" parameter is used, the return value is a reference to a hash with keys "previous_cursor", "next_cursor", and "ids". The value of "ids" is a reference to an array of IDS of the user's friends. Set the optional "cursor" parameter to -1 to get the first page of IDs. Set it to the prior return's value of "previous_cursor" or "next_cursor" to page forward or backwards. When there are no prior pages, the value of "previous_cursor" will be 0. When there are no subsequent pages, the value of "next_cursor" will be 0. Returns: HashRef|ArrayRef[Int] Twitter API documentation: GET friends/ids friends_timeline DEPRECATED alias: following_timeline Parameters: since_id, max_id, count, exclude_replies, contributor_details, include_entities, trim_user Required: *none* Returns the 20 most recent statuses, including retweets, posted by the authenticating user and that user's friends. Returns: ArrayRef[Status] friendship_exists DEPRECATED friendship_exists(user_a, user_b) alias: relationship_exists alias: follows Parameters: user_id_a, user_id_b, screen_name_a, screen_name_b, user_a, user_b Required: user_a, user_b This method is provided for backwards compatibility with Twitter API V1.0. Twitter API V1.1 does not provide an endpoint for this call. Instead, "show_friendship" is called, the result is inspected, and an appropriate value is returned which can be evaluated in a boolean context. Tests for the existence of friendship between two users. Will return true if user_a follows user_b, otherwise will return false. Use of "user_a" and "user_b" is deprecated. It has been preserved for backwards compatibility, and is used for the two-argument positional form: $nt->friendship_exists($user_a, $user_b); Instead, you should use one of the named argument forms: $nt->friendship_exists({ user_id_a => $id1, user_id_b => $id2 }); $nt->friendship_exists({ screen_name_a => $name1, screen_name_b => $name2 }); Consider using "show_friendship" instead. Returns: Bool friendships_incoming alias: incoming_friendships Parameters: cursor, stringify_ids Required: *none* Returns an HASH ref with an array of numeric IDs in the "ids" element for every user who has a pending request to follow the authenticating user. Returns: HashRef Twitter API documentation: GET friendships/incoming friendships_outgoing alias: outgoing_friendships Parameters: cursor, stringify_ids Required: *none* Returns an HASH ref with an array of numeric IDs in the "ids" element for every protected user for whom the authenticating user has a pending follow request. Returns: HashRef Twitter API documentation: GET friendships/outgoing geo_id geo_id(place_id) Parameters: place_id Required: place_id Returns details of a place returned from the "reverse_geocode" method. Returns: HashRef Twitter API documentation: GET geo/id/:place_id geo_search Parameters: lat, long, query, ip, granularity, accuracy, max_results, contained_within, attribute:street_address, callback Required: *none* Search for places that can be attached to a statuses/update. Given a latitude and a longitude pair, an IP address, or a name, this request will return a list of all the valid places that can be used as the place_id when updating a status. Conceptually, a query can be made from the user's location, retrieve a list of places, have the user validate the location he or she is at, and then send the ID of this location with a call to statuses/update. This is the recommended method to use find places that can be attached to statuses/update. Unlike geo/reverse_geocode which provides raw data access, this endpoint can potentially re-order places with regards to the user who is authenticated. This approach is also preferred for interactive place matching with the user. Returns: HashRef Twitter API documentation: GET geo/search get_configuration Parameters: *none* Required: *none* Returns the current configuration used by Twitter including twitter.com slugs which are not usernames, maximum photo resolutions, and t.co URL lengths. It is recommended applications request this endpoint when they are loaded, but no more than once a day. Returns: HashRef Twitter API documentation: GET help/configuration get_languages Parameters: *none* Required: *none* Returns the list of languages supported by Twitter along with their ISO 639-1 code. The ISO 639-1 code is the two letter value to use if you include lang with any of your requests. Returns: ArrayRef[Lanugage] Twitter API documentation: GET help/languages get_list alias: show_list Parameters: list_id, slug, owner_screen_name, owner_id Required: *none* Returns the specified list. Private lists will only be shown if the authenticated user owns the specified list. Returns: List Twitter API documentation: GET lists/show get_lists alias: list_lists alias: all_subscriptions Parameters: user_id, screen_name, reverse Required: *none* Returns all lists the authenticating or specified user subscribes to, including their own. The user is specified using the user_id or screen_name parameters. If no user is given, the authenticating user is used. A maximum of 100 results will be returned by this call. Subscribed lists are returned first, followed by owned lists. This means that if a user subscribes to 90 lists and owns 20 lists, this method returns 90 subscriptions and 10 owned lists. The reverse method returns owned lists first, so with "reverse =" 1>, 20 owned lists and 80 subscriptions would be returned. If your goal is to obtain every list a user owns or subscribes to, use and/or "list_subscriptions" instead. Returns: Hashref Twitter API documentation: GET lists/list get_privacy_policy Parameters: *none* Required: *none* Returns Twitter's privacy policy. Returns: HashRef Twitter API documentation: GET help/privacy get_tos Parameters: *none* Required: *none* Returns the Twitter Terms of Service. These are not the same as the Developer Rules of the Road. Returns: HashRef Twitter API documentation: GET help/tos home_timeline Parameters: since_id, max_id, count, exclude_replies, contributor_details, include_entities, trim_user Required: *none* Returns the 20 most recent statuses, including retweets, posted by the authenticating user and that user's friends. Returns: ArrayRef[Status] Twitter API documentation: GET statuses/home_timeline list_members Parameters: list_id, slug, owner_screen_name, owner_id, cursor, include_entities, skip_status Required: *none* Returns the members of the specified list. Private list members will only be shown if the authenticated user owns the specified list. Returns: Hashref Twitter API documentation: GET lists/members list_memberships Parameters: user_id, screen_name, cursor, filter_to_owned_lists Required: *none* Returns the lists the specified user has been added to. If user_id or screen_name are not provided the memberships for the authenticating user are returned. Returns: Hashref Twitter API documentation: GET lists/memberships list_ownerships Parameters: user_id, screen_name, count, cursor Required: *none* Obtain a collection of the lists owned by the specified Twitter user. Private lists will only be shown if the authenticated user is also the owner of the lists. Returns: ArrayRef[List] Twitter API documentation: GET lists/ownerships list_statuses Parameters: list_id, slug, owner_screen_name, owner_id, since_id, max_id, count, include_entities, include_rts Required: *none* Returns tweet timeline for members of the specified list. Historically, retweets were not available in list timeline responses but you can now use the include_rts=true parameter to additionally receive retweet objects. Returns: ArrayRef[Status] Twitter API documentation: GET lists/statuses list_subscribers Parameters: list_id, slug, owner_screen_name, owner_id, cursor, include_entities, skip_status Required: *none* Returns the subscribers of the specified list. Private list subscribers will only be shown if the authenticated user owns the specified list. Returns: Hashref Twitter API documentation: GET lists/subscribers list_subscriptions alias: subscriptions Parameters: user_id, screen_name, count, cursor Required: *none* Obtain a collection of the lists the specified user is subscribed to, 20 lists per page by default. Does not include the user's own lists. Returns: ArrayRef[List] Twitter API documentation: GET lists/subscriptions lookup_friendships Parameters: user_id, screen_name Required: *none* Returns the relationship of the authenticating user to the comma separated list or ARRAY ref of up to 100 screen_names or user_ids provided. Values for connections can be: following, following_requested, followed_by, none. Requires authentication. Returns: ArrayRef Twitter API documentation: GET friendships/lookup lookup_statuses lookup_statuses(id) Parameters: id, include_entities, trim_user, map Required: id Returns a hash reference of tweets from an arbitrary set of ids. Returns: HashRef Twitter API documentation: GET statuses/lookup lookup_users Parameters: user_id, screen_name, include_entities Required: *none* Return up to 100 users worth of extended information, specified by either ID, screen name, or combination of the two. The author's most recent status (if the authenticating user has permission) will be returned inline. This method is rate limited to 1000 calls per hour. This method will accept user IDs or screen names as either a comma delimited string, or as an ARRAY ref. It will also accept arguments in the normal HASHREF form or as a simple list of named arguments. I.e., any of the following forms are acceptable: $nt->lookup_users({ user_id => '1234,6543,3333' }); $nt->lookup_users(user_id => '1234,6543,3333'); $nt->lookup_users({ user_id => [ 1234, 6543, 3333 ] }); $nt->lookup_users({ screen_name => 'fred,barney,wilma' }); $nt->lookup_users(screen_name => ['fred', 'barney', 'wilma']); $nt->lookup_users( screen_name => ['fred', 'barney' ], user_id => '4321,6789', ); Returns: ArrayRef[User] Twitter API documentation: GET users/lookup members_create_all alias: add_list_members Parameters: list_id, slug, owner_screen_name, owner_id Required: *none* Adds multiple members to a list, by specifying a reference to an array or a comma-separated list of member ids or screen names. The authenticated user must own the list to be able to add members to it. Note that lists can't have more than 500 members, and you are limited to adding up to 100 members to a list at a time with this method. Returns: List Twitter API documentation: POST lists/members/create_all members_destroy_all alias: remove_list_members Parameters: list_id, slug, user_id, screen_name, owner_screen_name, owner_id Required: *none* Removes multiple members from a list, by specifying a reference to an array of member ids or screen names, or a string of comma separated user ids or screen names. The authenticated user must own the list to be able to remove members from it. Note that lists can't have more than 500 members, and you are limited to removing up to 100 members to a list at a time with this method. Please note that there can be issues with lists that rapidly remove and add memberships. Take care when using these methods such that you are not too rapidly switching between removals and adds on the same list. Returns: List Twitter API documentation: POST lists/members/destroy_all mentions alias: replies alias: mentions_timeline Parameters: since_id, max_id, count, trim_user, include_entities, contributor_details Required: *none* Returns the 20 most recent mentions (statuses containing @username) for the authenticating user. Returns: ArrayRef[Status] Twitter API documentation: GET statuses/mentions_timeline mutes mutes(cursor) alias: muting_ids alias: muted_ids Parameters: cursor Required: *none* Returns an array of numeric user ids the authenticating user has muted. Returns: ArrayRef[Int] Twitter API documentation: GET mutes/users/ids muting alias: mutes_list Parameters: cursor, include_entities, skip_status Required: *none* Returns an array of user objects that the authenticating user is muting. Returns: ArrayRef[BasicUser] Twitter API documentation: GET mutes/users/list new_direct_message new_direct_message(text) Parameters: user_id, screen_name, text Required: text Sends a new direct message to the specified user from the authenticating user. Requires both the user and text parameters. Returns the sent message when successful. In order to support numeric screen names, the "screen_name" or "user_id" parameters may be used instead of "user". Important: this method requires an access token with RWD (read, write, and direct message) permissions. Returns: DirectMessage Twitter API documentation: POST direct_messages/new no_retweet_ids alias: no_retweets_ids Parameters: *none* Required: *none* Returns an ARRAY ref of user IDs for which the authenticating user does not want to receive retweets. Returns: ArrayRef[UserIDs] Twitter API documentation: GET friendships/no_retweets/ids oembed Parameters: id, url, maxwidth, hide_media, hide_thread, omit_script, align, related, lang Required: *none* Returns information allowing the creation of an embedded representation of a Tweet on third party sites. See the oEmbed specification for information about the response format. While this endpoint allows a bit of customization for the final appearance of the embedded Tweet, be aware that the appearance of the rendered Tweet may change over time to be consistent with Twitter's Display Requirements . Do not rely on any class or id parameters to stay constant in the returned markup. Returns: Status Twitter API documentation: GET statuses/oembed profile_banner Parameters: user_id, screen_name Required: *none* Returns a hash reference mapping available size variations to URLs that can be used to retrieve each variation of the banner. Returns: HashRef Twitter API documentation: GET users/profile_banner rate_limit_status rate_limit_status(resources) Parameters: resources Required: *none* Returns the remaining number of API requests available to the authenticated user before the API limit is reached for the current hour. Use "->rate_limit_status({ authenticate => 0 })" to force an unauthenticated call, which will return the status for the IP address rather than the authenticated user. (Note: for a web application, this is the server's IP address.) Returns: RateLimitStatus Twitter API documentation: GET application/rate_limit_status related_results DEPRECATED related_results(id) Parameters: id Required: id If available, returns an array of replies and mentions related to the specified status. There is no guarantee there will be any replies or mentions in the response. This method is only available to users who have access to #newtwitter. Requires authentication. Returns: ArrayRef[Status] remove_profile_banner Parameters: *none* Required: *none* Removes the uploaded profile banner for the authenticating user. Returns: Nothing Twitter API documentation: POST account/remove_profile_banner report_spam report_spam(id) Parameters: user_id, screen_name Required: id The user specified in the id is blocked by the authenticated user and reported as a spammer. Returns: User Twitter API documentation: POST users/report_spam retweet retweet(id) Parameters: idtrim_user Required: id Retweets a tweet. Returns: Status Twitter API documentation: POST statuses/retweet/:id retweeted_by DEPRECATED retweeted_by(id) Parameters: id, count, page, trim_user, include_entities Required: id Returns up to 100 users who retweeted the status identified by "id". Returns: ArrayRef[User] retweeted_by_ids DEPRECATED retweeted_by_ids(id) Parameters: id, count, page, trim_user, include_entities Required: id Returns the IDs of up to 100 users who retweeted the status identified by "id". Returns: ArrayRef[User] retweeted_by_me DEPRECATED Parameters: since_id, max_id, count, page, trim_user, include_entities Required: *none* Returns the 20 most recent retweets posted by the authenticating user. Returns: ArrayRef[Status] retweeted_by_user DEPRECATED retweeted_by_user(id) Parameters: id, user_id, screen_name Required: id Returns the 20 most recent retweets posted by the specified user. The user is specified using the user_id or screen_name parameters. This method is identical to "retweeted_by_me" except you can choose the user to view. Does not require authentication, unless the user is protected. Returns: ArrayRef retweeted_to_me DEPRECATED Parameters: since_id, max_id, count, page Required: *none* Returns the 20 most recent retweets posted by the authenticating user's friends. Returns: ArrayRef[Status] retweeted_to_user DEPRECATED retweeted_to_user(id) Parameters: id, user_id, screen_name Required: id Returns the 20 most recent retweets posted by users the specified user follows. The user is specified using the user_id or screen_name parameters. This method is identical to "retweeted_to_me" except you can choose the user to view. Does not require authentication, unless the user is protected. Returns: ArrayRef retweeters_ids retweeters_ids(id) Parameters: id, cursor, stringify_ids Required: id Returns a collection of up to 100 user IDs belonging to users who have retweeted the tweet specified by the id parameter. This method offers similar data to "retweets" and replaces API v1's "retweeted_by_ids" method. Returns: HashRef Twitter API documentation: GET statuses/retweeters/ids retweets retweets(id) Parameters: id, count, trim_user Required: id Returns up to 100 of the first retweets of a given tweet. Returns: Arrayref[Status] Twitter API documentation: GET statuses/retweets/:id retweets_of_me alias: retweeted_of_me Parameters: since_id, max_id, count, trim_user, include_entities, include_user_entities Required: *none* Returns the 20 most recent tweets of the authenticated user that have been retweeted by others. Returns: ArrayRef[Status] Twitter API documentation: GET statuses/retweets_of_me reverse_geocode reverse_geocode(lat, long) Parameters: lat, long, accuracy, granularity, max_results, callback Required: lat, long Search for places (cities and neighborhoods) that can be attached to a statuses/update. Given a latitude and a longitude, return a list of all the valid places that can be used as a place_id when updating a status. Conceptually, a query can be made from the user's location, retrieve a list of places, have the user validate the location he or she is at, and then send the ID of this location up with a call to statuses/update. There are multiple granularities of places that can be returned -- "neighborhoods", "cities", etc. At this time, only United States data is available through this method. lat Required. The latitude to query about. Valid ranges are -90.0 to +90.0 (North is positive) inclusive. long Required. The longitude to query about. Valid ranges are -180.0 to +180.0 (East is positive) inclusive. accuracy Optional. A hint on the "region" in which to search. If a number, then this is a radius in meters, but it can also take a string that is suffixed with ft to specify feet. If this is not passed in, then it is assumed to be 0m. If coming from a device, in practice, this value is whatever accuracy the device has measuring its location (whether it be coming from a GPS, WiFi triangulation, etc.). granularity Optional. The minimal granularity of data to return. If this is not passed in, then "neighborhood" is assumed. "city" can also be passed. max_results Optional. A hint as to the number of results to return. This does not guarantee that the number of results returned will equal max_results, but instead informs how many "nearby" results to return. Ideally, only pass in the number of places you intend to display to the user here. Returns: HashRef Twitter API documentation: GET geo/reverse_geocode saved_searches Parameters: *none* Required: *none* Returns the authenticated user's saved search queries. Returns: ArrayRef[SavedSearch] Twitter API documentation: GET saved_searches/list search search(q) Parameters: q, count, callback, lang, locale, rpp, since_id, max_id, until, geocode, result_type, include_entities Required: q Returns a HASH reference with some meta-data about the query including the "next_page", "refresh_url", and "max_id". The statuses are returned in "results". To iterate over the results, use something similar to: my $r = $nt->search($search_term); for my $status ( @{$r->{statuses}} ) { print "$status->{text}\n"; } Returns: HashRef Twitter API documentation: GET search/tweets sent_direct_messages alias: direct_messages_sent Parameters: since_id, max_id, page, count, include_entities Required: *none* Returns a list of the 20 most recent direct messages sent by the authenticating user including detailed information about the sending and recipient users. Important: this method requires an access token with RWD (read, write, and direct message) permissions. Returns: ArrayRef[DirectMessage] Twitter API documentation: GET direct_messages/sent show_direct_message show_direct_message(id) Parameters: id Required: id Returns a single direct message, specified by an id parameter. Like the "direct_messages" request, this method will include the user objects of the sender and recipient. Requires authentication. Important: this method requires an access token with RWD (read, write, and direct message) permissions. Returns: HashRef Twitter API documentation: GET direct_messages/show show_friendship alias: show_relationship Parameters: source_id, source_screen_name, target_id, target_screen_name Required: *none* Returns detailed information about the relationship between two users. Returns: Relationship Twitter API documentation: GET friendships/show show_list_member alias: is_list_member Parameters: owner_screen_name, owner_id, list_id, slug, user_id, screen_name, include_entities, skip_status Required: *none* Check if the specified user is a member of the specified list. Returns the user or undef. Returns: Maybe[User] Twitter API documentation: GET lists/members/show show_list_subscriber alias: is_list_subscriber alias: is_subscriber_lists Parameters: owner_screen_name, owner_id, list_id, slug, user_id, screen_name, include_entities, skip_status Required: *none* Returns the user if they are a subscriber. Returns: User Twitter API documentation: GET lists/subscribers/show show_saved_search show_saved_search(id) Parameters: id Required: id Retrieve the data for a saved search, by "id", owned by the authenticating user. Returns: SavedSearch Twitter API documentation: GET saved_searches/show/:id show_status show_status(id) Parameters: id, trim_user, include_entities, include_my_retweet Required: id Returns a single status, specified by the id parameter. The status's author will be returned inline. Returns: Status Twitter API documentation: GET statuses/show/:id show_user Parameters: user_id, screen_name, include_entities Required: *none* Returns extended information of a given user, specified by ID or screen name as per the required id parameter. This information includes design settings, so third party developers can theme their widgets according to a given user's preferences. You must be properly authenticated to request the page of a protected user. Returns: ExtendedUser Twitter API documentation: GET users/show similar_places similar_places(lat, long, name) Parameters: lat, long, name, contained_within, attribute:street_address, callback Required: lat, long, name Locates places near the given coordinates which are similar in name. Conceptually you would use this method to get a list of known places to choose from first. Then, if the desired place doesn't exist, make a request to "add_place" to create a new one. The token contained in the response is the token needed to be able to create a new place. Returns: HashRef Twitter API documentation: GET geo/similar_places subscribe_list Parameters: owner_screen_name, owner_id, list_id, slug Required: *none* Subscribes the authenticated user to the specified list. Returns: List Twitter API documentation: POST lists/subscribers/create suggestion_categories Parameters: *none* Required: *none* Returns the list of suggested user categories. The category slug can be used in the "user_suggestions" API method get the users in that category . Does not require authentication. Returns: ArrayRef Twitter API documentation: GET users/suggestions test DEPRECATED Parameters: *none* Required: *none* Returns the string "ok" status code. Returns: Hash trends_available Parameters: *none* Required: *none* Returns the locations with trending topic information. The response is an array of "locations" that encode the location's WOEID (a Yahoo! Where On Earth ID ) and some other human-readable information such as a the location's canonical name and country. For backwards compatibility, this method accepts optional "lat" and "long" parameters. You should call "trends_closest" directly, instead. Use the WOEID returned in the location object to query trends for a specific location. Returns: ArrayRef[Location] Twitter API documentation: GET trends/available trends_closest Parameters: lat, long Required: *none* Returns the locations with trending topic information. The response is an array of "locations" that encode the location's WOEID (a Yahoo! Where On Earth ID ) and some other human-readable information such as a the location's canonical name and country. The results are sorted by distance from that location, nearest to farthest. Use the WOEID returned in the location object to query trends for a specific location. Returns: ArrayRef[Location] Twitter API documentation: GET trends/closest trends_current DEPRECATED trends_current(exclude) Parameters: exclude Required: *none* Returns the current top ten trending topics on Twitter. The response includes the time of the request, the name of each trending topic, and query used on Twitter Search results page for that topic. Returns: HashRef trends_daily DEPRECATED Parameters: date, exclude Required: *none* Returns the top 20 trending topics for each hour in a given day. Returns: HashRef trends_place trends_place(id) alias: trends_location Parameters: id, exclude Required: id Returns the top 10 trending topics for a specific WOEID. The response is an array of "trend" objects that encode the name of the trending topic, the query parameter that can be used to search for the topic on Search, and the direct URL that can be issued against Search. This information is cached for five minutes, and therefore users are discouraged from querying these endpoints faster than once every five minutes. Global trends information is also available from this API by using a WOEID of 1. Returns: ArrayRef[Trend] Twitter API documentation: GET trends/place trends_weekly DEPRECATED Parameters: date, exclude Required: *none* Returns the top 30 trending topics for each day in a given week. Returns: HashRef unsubscribe_list Parameters: list_id, slug, owner_screen_name, owner_id Required: *none* Unsubscribes the authenticated user from the specified list. Returns: List Twitter API documentation: POST lists/subscribers/destroy update update(status) Parameters: attachment_url, display_coordinates, in_reply_to_status_id, lat, long, media_ids, place_id, status, trim_user Required: status Updates the authenticating user's status. Requires the status parameter specified. A status update with text identical to the authenticating user's current status will be ignored. status Required. The text of your status update. URL encode as necessary. Statuses over 140 characters will cause a 403 error to be returned from the API. in_reply_to_status_id Optional. The ID of an existing status that the update is in reply to. o Note: This parameter will be ignored unless the author of the tweet this parameter references is mentioned within the status text. Therefore, you must include @username, where username is the author of the referenced tweet, within the update. lat Optional. The location's latitude that this tweet refers to. The valid ranges for latitude is -90.0 to +90.0 (North is positive) inclusive. This parameter will be ignored if outside that range, if it is not a number, if geo_enabled is disabled, or if there not a corresponding long parameter with this tweet. long Optional. The location's longitude that this tweet refers to. The valid ranges for longitude is -180.0 to +180.0 (East is positive) inclusive. This parameter will be ignored if outside that range, if it is not a number, if geo_enabled is disabled, or if there not a corresponding lat parameter with this tweet. place_id Optional. The place to attach to this status update. Valid place_ids can be found by querying "reverse_geocode". display_coordinates Optional. By default, geo-tweets will have their coordinates exposed in the status object (to remain backwards compatible with existing API applications). To turn off the display of the precise latitude and longitude (but keep the contextual location information), pass "display_coordinates =" 0> on the status update. Returns: Status Twitter API documentation: POST statuses/update update_account_settings Parameters: trend_location_woid, sleep_time_enabled, start_sleep_time, end_sleep_time, time_zone, lang Required: *none* Updates the authenticating user's settings. Returns: HashRef Twitter API documentation: POST account/settings update_delivery_device update_delivery_device(device) Parameters: device, include_entities Required: device Sets which device Twitter delivers updates to for the authenticating user. Sending none as the device parameter will disable SMS updates. Returns: BasicUser Twitter API documentation: POST account/update_delivery_device update_friendship Parameters: user_id, screen_name, device, retweets Required: *none* Allows you enable or disable retweets and device notifications from the specified user. All other values are assumed to be false. Requires authentication. Returns: HashRef Twitter API documentation: POST friendships/update update_list Parameters: list_id, slug, name, mode, description, owner_screen_name, owner_id Required: *none* Updates the specified list. The authenticated user must own the list to be able to update it. Returns: List Twitter API documentation: POST lists/update update_location DEPRECATED update_location(location) Parameters: location Required: location This method has been deprecated in favor of the update_profile method. Its URL will continue to work, but please consider migrating to the newer and more comprehensive method of updating profile attributes. Returns: BasicUser update_profile Parameters: name, url, location, description, include_entities, skip_status Required: *none* Sets values that users are able to set under the "Account" tab of their settings page. Only the parameters specified will be updated; to only update the "name" attribute, for example, only include that parameter in your request. Returns: ExtendedUser Twitter API documentation: POST account/update_profile update_profile_background_image Parameters: image, tile, include_entities, skip_status, use Required: *none* Updates the authenticating user's profile background image. The "image" parameter must be an arrayref with the same interpretation as the "image" parameter in the "update_profile_image" method. See that method's documentation for details. The "use" parameter allows you to specify whether to use the uploaded profile background or not. Returns: ExtendedUser Twitter API documentation: POST account/update_profile_background_image update_profile_banner update_profile_banner(banner) Parameters: banner, width, height, offset_left, offset_top Required: banner Uploads a profile banner on behalf of the authenticating user. The "image" parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array ($file) is the name of a file to open. The second value ($filename) is the name given to Twitter for the file. If $filename is not provided, the basename portion of $file is used. If $mime_type is not provided, it will be provided automatically using LWP::MediaTypes::guess_media_type(). $raw_image_data can be provided, rather than opening a file, by passing "undef" as the first array value. Returns: Nothing Twitter API documentation: POST account/update_profile_banner update_profile_colors Parameters: profile_background_color, profile_text_color, profile_link_color, profile_sidebar_fill_color, profile_sidebar_border_color, include_entities, skip_status Required: *none* Sets one or more hex values that control the color scheme of the authenticating user's profile page on twitter.com. These values are also returned in the /users/show API method. Returns: ExtendedUser Twitter API documentation: POST account/update_profile_colors update_profile_image update_profile_image(image) Parameters: image, include_entities, skip_status Required: image Updates the authenticating user's profile image. The "image" parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array ($file) is the name of a file to open. The second value ($filename) is the name given to Twitter for the file. If $filename is not provided, the basename portion of $file is used. If $mime_type is not provided, it will be provided automatically using LWP::MediaTypes::guess_media_type(). $raw_image_data can be provided, rather than opening a file, by passing "undef" as the first array value. Returns: ExtendedUser Twitter API documentation: POST account/update_profile_image update_with_media DEPRECATED update_with_media(status, media[]) Parameters: status, media[], possibly_sensitive, in_reply_to_status_id, lat, long, place_id, display_coordinates Required: status, media[] Updates the authenticating user's status and attaches media for upload. Note that Twitter has marked this endpoint as deprecated, and recommends instead calling "upload", then (optionally) "create_media_metadata", then "update". The "media[]" parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array ($file) is the name of a file to open. The second value ($filename) is the name given to Twitter for the file. If $filename is not provided, the basename portion of $file is used. If $mime_type is not provided, it will be provided automatically using LWP::MediaTypes::guess_media_type(). $raw_image_data can be provided, rather than opening a file, by passing "undef" as the first array value. The Tweet text will be rewritten to include the media URL(s), which will reduce the number of characters allowed in the Tweet text. If the URL(s) cannot be appended without text truncation, the tweet will be rejected and this method will return an HTTP 403 error. Returns: Status upload upload(media) Parameters: media Required: media Uploads an image to twitter without immediately posting it to the authenticating user's timeline. Its return-value hashref notably contains a "media_id" value that's useful as a parameter value in various other endpoint calls, such as "update" and "create_media_metadata". Returns: HashRef Twitter API documentation: POST media/upload upload_status upload_status(media_id, command) Parameters: media_id, command Required: media_id, command Check the status for async video uploads. Returns: status Twitter API documentation: GET media/upload user_suggestions user_suggestions(slug) alias: follow_suggestions Parameters: slug, lang Required: slug Access the users in a given slug (category) of the Twitter suggested user list and return their most recent status if they are not a protected user. Currently supported values for optional parameter "lang" are "en", "fr", "de", "es", "it". Does not require authentication. Returns: ArrayRef Twitter API documentation: GET users/suggestions/:slug/members user_suggestions_for user_suggestions_for(slug) alias: follow_suggestions_for Parameters: slug, lang Required: slug Access the users in a given slug (category) of the Twitter suggested user list. Returns: ArrayRef Twitter API documentation: GET users/suggestions/:slug user_timeline Parameters: user_id, screen_name, since_id, max_id, count, trim_user, exclude_replies, include_rts, contributor_details Required: *none* Returns the 20 most recent statuses posted by the authenticating user, or the user specified by "screen_name" or "user_id". Returns: ArrayRef[Status] Twitter API documentation: GET statuses/user_timeline users_search users_search(q) alias: find_people alias: search_users Parameters: q, per_page, page, count, include_entities Required: q Run a search for users similar to Find People button on Twitter.com; the same results returned by people search on Twitter.com will be returned by using this API (about being listed in the People Search). It is only possible to retrieve the first 1000 matches from this API. Returns: ArrayRef[Users] Twitter API documentation: GET users/search verify_credentials Parameters: include_entities, skip_status, include_email Required: *none* Returns an HTTP 200 OK response code and a representation of the requesting user if authentication was successful; returns a 401 status code and an error message if not. Use this method to test if supplied user credentials are valid. Returns: ExtendedUser Twitter API documentation: GET account/verify_credentials update_with_media update_with_media(status, media) Parameters: status, media[], possibly_sensitive, in_reply_to_status_id, lat, long, place_id, display_coordinates Required: status, media Updates the authenticating user's status and attaches media for upload. The "media[]" parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array ($file) is the name of a file to open. The second value ($filename) is the name given to Twitter for the file. If $filename is not provided, the basename portion of $file is used. If $mime_type is not provided, it will be provided automatically using LWP::MediaTypes::guess_media_type(). $raw_image_data can be provided, rather than opening a file, by passing "undef" as the first array value. The Tweet text will be rewritten to include the media URL(s), which will reduce the number of characters allowed in the Tweet text. If the URL(s) cannot be appended without text truncation, the tweet will be rejected and this method will return an HTTP 403 error. Returns: Status Twitter API documentation: POST statuses/update_with_media Search API Methods These methods are provided when trait "API::Search" is included in the "traits" option to "new". search search(q) Parameters: q, geocode, lang, locale, result_type, count, until, since_id, max_id, include_entities, callback Required: q Returns a HASH reference with some meta-data about the query including the "next_page", "refresh_url", and "max_id". The statuses are returned in "results". To iterate over the results, use something similar to: my $r = $nt->search($search_term); my $r = $nt->search({ q => $search_term, count => 10 }) for my $status ( @{$r->{results}} ) { print "$status->{text}\n"; } Returns: HashRef Lists API Methods The original Lists API methods have been deprecated. Net::Twitter::Role::API::Lists provides backwards compatibility for code written using those deprecated methods. If you're not already using the "API::Lists" trait, don't! Use the lists methods described above. If you are using the "API::Lists" trait, you should remove it from your code and change the arguments in your list API method calls to match those described above. Also, if using the "API::Lists" trait, you can pass synthetic argument "-legacy_lists_api" set to 0 for individual calls to use the new endpoints semantics. TwitterVision API Methods These methods are provided when trait "API::TwitterVision" is included in the "traits" option to "new". current_status current_status(id) Parameters: id, callback Required: id Get the current location and status of a user. Returns: HashRef update_twittervision update_twittervision(location) Parameters: location Required: location Updates the location for the authenticated user. Returns: HashRef LEGACY COMPATIBILITY This version of "Net::Twitter" automatically includes the "Legacy" trait if no "traits" option is provided to "new". Therefore, these 2 calls are currently equivalent: $nt = Net::Twitter->new(username => $user, password => $passwd); $nt = Net::Twitter->new( username => $user, password => $passwd, traits => ['Legacy'], ); Thus, existing applications written for a prior version of "Net::Twitter" should continue to run, without modification, with this version. In a future release, the default traits may change. Prior to that change, however, a nearer future version will add a warning if no "traits" option is provided to "new". To avoid this warning, add an appropriate "traits" option to your existing application code. ERROR HANDLING There are currently two strategies for handling errors: throwing exceptions and wrapping errors. Exception handling is the newer, recommended strategy. Wrapping Errors When trait "WrapError" is specified (or "Legacy", which includes trait "WrapError"), "Net::Twitter" returns undef on error. To retrieve information about the error, use methods "http_code", "http_message", and "get_error". These methods are described in the Net::Twitter::Role::WrapError. if ( my $followers = $nt->followers ) { for my $follower ( @$followers ) { #... } } else { warn "HTTP message: ", $nt->http_message, "\n"; } Since an error is stored in the object instance, this error handling strategy is problematic when using a user agent like "LWP::UserAgent::POE" that provides concurrent requests. The error for one request can be overwritten by a concurrent request before you have an opportunity to access it. Exception Handling When "Net::Twitter" encounters a Twitter API error or a network error, it throws a "Net::Twitter::Error" object. You can catch and process these exceptions by using "eval" blocks and testing $@: eval { my $statuses = $nt->friends_timeline(); # this might die! for my $status ( @$statuses ) { #... } }; if ( $@ ) { # friends_timeline encountered an error if ( blessed $@ && $@->isa('Net::Twitter::Error') ) { #... use the thrown error obj warn $@->error; } else { # something bad happened! die $@; } } "Net::Twitter::Error" stringifies to something reasonable, so if you don't need detailed error information, you can simply treat $@ as a string: eval { $nt->update($status) }; if ( $@ ) { warn "update failed because: $@\n"; } FAQ Why does "->followers({ screen_name => $friend })" return *my* followers instead of $friends's? First, check carefully to make sure you've spelled "screen_name" correctly. Twitter sometimes discards parameters it doesn't recognize. In this case, the result is a list of your own followers---the same thing that would happen if you called "followers" without the "screen_name" parameter. How do I use the "geocode" parameter in the Search API? The "geocode" parameter value includes a latitude, longitude, and radius separated with commas. $r = $nt->search({ geocode => "45.511795,-122.675629,25mi" }); How do I get Twitter to display something other than "from Perl Net::Twitter"? If you set the source parameter to "api", twitter will display "from API", and if you set it to the empty string, twitter will display, "from web". $nt = Net::Twitter->new(netrc => 1,legacy => 0,ssl => 1,source => 'api'); $nt->update('A post with the source parameter overridden.'); # result: http://twitter.com/semifor_test/status/6541105458 $nt = Net::Twitter->new(netrc => 1,legacy => 0,ssl => 1,source => ''); $nt->update('A post with the source parameter overridden.'); # result: http://twitter.com/semifor_test/status/6541257224 If you want something other than "Net::Twitter", "API", or "web", you need to register an application and use OAuth authentication. If you do that, you can have any name you choose for the application printed as the source. Since rolling out OAuth, Twitter has stopped issuing new registered source parameters, only existing register source parameters are valid. SEE ALSO Net::Twitter::Error The "Net::Twitter" exception object. This is the official Twitter API documentation. It describes the methods and their parameters in more detail and may be more current than the documentation provided with this module. LWP::UserAgent::POE This LWP::UserAgent compatible class can be used in POE based application along with Net::Twitter to provide concurrent, non-blocking requests. Catalyst::Authentication::Credential::Twitter This module, by Jesse Stay, provides Twitter OAuth authentication support for the popular Catalyst web application framework. SUPPORT Please report bugs to "bug-net-twitter@rt.cpan.org", or through the web interface at . Join the Net::Twitter IRC channel at . Follow perl_api: . Track Net::Twitter development at . ACKNOWLEDGEMENTS Many thanks to Chris Thompson , the original author of "Net::Twitter" and all versions prior to 3.00. Also, thanks to Chris Prather (perigrin) for answering many design and implementation questions, especially with regards to Moose. AUTHOR Marc Mims (@semifor on Twitter) CONTRIBUTORS Roberto Etcheverry (@retcheverry on Twitter) KATOU Akira Francisco Pecorella Doug Bell Justin Hunter Allen Haim Joe Papperello (@antipasta on Github and Twitter) Samuel Kaufman (ediblenergy on Github) AnnMary Mathew (ammathew on Github) Olaf Alders (oalders on Github) LICENSE Copyright (c) 2009-2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2016 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/t/000755 000766 000024 00000000000 13227713560 014412 5ustar00marcstaff000000 000000 Net-Twitter-4.01043/t/00-compile.t000644 000766 000024 00000004165 13227713560 016452 0ustar00marcstaff000000 000000 use 5.006; use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::Compile 2.054 use Test::More; plan tests => 27 + ($ENV{AUTHOR_TESTING} ? 1 : 0); my @module_files = ( 'Net/Identica.pm', 'Net/Twitter.pm', 'Net/Twitter/API.pm', 'Net/Twitter/Core.pm', 'Net/Twitter/Error.pm', 'Net/Twitter/OAuth.pm', 'Net/Twitter/Role/API/Lists.pm', 'Net/Twitter/Role/API/REST.pm', 'Net/Twitter/Role/API/RESTv1_1.pm', 'Net/Twitter/Role/API/Search.pm', 'Net/Twitter/Role/API/Search/Trends.pm', 'Net/Twitter/Role/API/TwitterVision.pm', 'Net/Twitter/Role/API/Upload.pm', 'Net/Twitter/Role/API/UploadMedia.pm', 'Net/Twitter/Role/AppAuth.pm', 'Net/Twitter/Role/AutoCursor.pm', 'Net/Twitter/Role/InflateObjects.pm', 'Net/Twitter/Role/Legacy.pm', 'Net/Twitter/Role/OAuth.pm', 'Net/Twitter/Role/RateLimit.pm', 'Net/Twitter/Role/RetryOnError.pm', 'Net/Twitter/Role/SimulateCursors.pm', 'Net/Twitter/Role/WrapError.pm', 'Net/Twitter/Role/WrapResult.pm', 'Net/Twitter/Search.pm', 'Net/Twitter/Types.pm', 'Net/Twitter/WrappedResult.pm' ); # no fake home requested my $inc_switch = -d 'blib' ? '-Mblib' : '-Ilib'; use File::Spec; use IPC::Open3; use IO::Handle; open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; my @warnings; for my $lib (@module_files) { # see L my $stderr = IO::Handle->new; my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, '-e', "require q[$lib]"); binmode $stderr, ':crlf' if $^O eq 'MSWin32'; my @_warnings = <$stderr>; waitpid($pid, 0); is($?, 0, "$lib loaded ok"); shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/ and not eval { require blib; blib->VERSION('1.01') }; if (@_warnings) { warn @_warnings; push @warnings, @_warnings; } } is(scalar(@warnings), 0, 'no warnings found') or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ) if $ENV{AUTHOR_TESTING}; Net-Twitter-4.01043/t/00_load.t000755 000766 000024 00000000217 13227713560 016020 0ustar00marcstaff000000 000000 #!perl use Test::More tests => 1; BEGIN { use_ok( 'Net::Twitter' ); } diag( "Testing Net::Twitter $Net::Twitter::VERSION, Perl $], $^X" ); Net-Twitter-4.01043/t/01_basic.t000644 000766 000024 00000015124 13227713560 016163 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use lib qw(t/lib); eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required' if $@; my $screen_name = 'net_twitter'; my $message_id = 1234; my $status = 'Hello, world!'; my @tests = ( [ create_block => [ $screen_name ], POST => "/blocks/create/$screen_name.json", __LINE__ ], [ create_favorite => [ $message_id ], POST => "/favorites/create/$message_id.json", __LINE__ ], [ create_favorite => [ { id => $message_id } ], POST => "/favorites/create/$message_id.json", __LINE__ ], [ create_friend => [ $screen_name ], POST => "/friendships/create/$screen_name.json", __LINE__ ], [ destroy_block => [ $screen_name ], POST => "/blocks/destroy/$screen_name.json", __LINE__ ], [ destroy_direct_message => [ $message_id ], POST => "/direct_messages/destroy/$message_id.json", __LINE__ ], [ destroy_favorite => [ $message_id ], POST => "/favorites/destroy/$message_id.json", __LINE__ ], [ destroy_favorite => [ { id => $message_id } ], POST => "/favorites/destroy/$message_id.json", __LINE__ ], [ destroy_friend => [ $screen_name ], POST => "/friendships/destroy/$screen_name.json", __LINE__ ], [ destroy_status => [ $message_id ], POST => "/statuses/destroy/$message_id.json", __LINE__ ], [ destroy_status => [ { id => $message_id } ], POST => "/statuses/destroy/$message_id.json", __LINE__ ], [ direct_messages => [], GET => "/direct_messages.json", __LINE__ ], [ disable_notifications => [ $screen_name ], POST => "/notifications/leave/$screen_name.json", __LINE__ ], [ disable_notifications => [ { id => $screen_name }], POST => "/notifications/leave/$screen_name.json", __LINE__ ], [ downtime_schedule => [], GET => "/help/downtime_schedule.json", __LINE__ ], [ enable_notifications => [ $screen_name ], POST => "/notifications/follow/$screen_name.json", __LINE__ ], [ enable_notifications => [ { id => $screen_name }], POST => "/notifications/follow/$screen_name.json", __LINE__ ], [ end_session => [], POST => "/account/end_session.json", __LINE__ ], [ favorites => [], GET => "/favorites.json", __LINE__ ], [ followers => [], GET => "/statuses/followers.json", __LINE__ ], [ friends => [], GET => "/statuses/friends.json", __LINE__ ], [ friends_timeline => [], GET => "/statuses/friends_timeline.json", __LINE__ ], [ new_direct_message => [ { user => $screen_name, text => $status } ], POST => "/direct_messages/new.json", __LINE__ ], [ new_direct_message => [ $screen_name, $status ], POST => "/direct_messages/new.json", __LINE__ ], [ new_direct_message => [ { user_id => 1234, text => $status } ], POST => "/direct_messages/new.json", __LINE__ ], [ new_direct_message => [ { screen_name => $screen_name, text => $status } ], POST => "/direct_messages/new.json", __LINE__ ], [ public_timeline => [], GET => "/statuses/public_timeline.json", __LINE__ ], [ rate_limit_status => [], GET => "/account/rate_limit_status.json", __LINE__ ], [ friendship_exists => [ 'a', 'b' ], GET => "/friendships/exists.json", __LINE__ ], [ mentions => [], GET => "/statuses/mentions.json", __LINE__ ], [ sent_direct_messages => [], GET => "/direct_messages/sent.json", __LINE__ ], [ show_status => [ $screen_name ], GET => "/statuses/show/$screen_name.json", __LINE__ ], [ show_user => [ $screen_name ], GET => "/users/show/$screen_name.json", __LINE__ ], [ test => [], GET => "/help/test.json", __LINE__ ], [ update => [ $status ], POST => "/statuses/update.json", __LINE__ ], [ update_delivery_device => [ 'sms' ], POST => "/account/update_delivery_device.json", __LINE__ ], [ update_profile => [ { name => $screen_name } ], POST => "/account/update_profile.json", __LINE__ ], [ update_profile_background_image => [ { image => 'binary' } ], POST => "/account/update_profile_background_image.json", __LINE__ ], [ update_profile_colors => [ { profile_background_color => '#0000' } ], POST => "/account/update_profile_colors.json", __LINE__ ], [ update_profile_image => [ { image => 'binary data here' } ], POST => "/account/update_profile_image.json", __LINE__ ], [ user_timeline => [], GET => "/statuses/user_timeline.json", __LINE__ ], [ verify_credentials => [], GET => "/account/verify_credentials.json", __LINE__ ], ); plan tests => @tests * 2 * 4 + 2; use_ok 'Net::Twitter'; my $nt = Net::Twitter->new(legacy => 1, ssl => 0); isa_ok $nt, 'Net::Twitter'; $nt = Net::Twitter->new( ssl => 0, legacy => 0, username => 'homer', password => 'doh!', ); my $t = TestUA->new(1, $nt->ua); # run 2 passes to ensure the first pass isn't changing internal state for my $pass ( 1, 2 ) { for my $test ( @tests ) { my ($api_call, $args, $method, $path, $line) = @$test; my %args; if ( $api_call eq 'update' ) { %args = ( source => 'twitterpm', status => @$args ); } elsif ( @$args ) { if ( ref $args->[0] ) { %args = %{$args->[0]}; } else { @{args}{@{$nt->meta->get_method($api_call)->original_method->required}} = @$args; } } ok $nt->$api_call(@$args), "[$pass] $api_call call"; # kludge: add the screen_name or message_id to the $t's arguments if either # exists in the path $t->add_id_arg($screen_name); $t->add_id_arg($message_id); is_deeply $t->args, \%args, "[$pass][line $line] $api_call args"; is $t->path, $path, "[$pass][line $line] $api_call path"; is $t->method, $method, "[$pass][line $line] $api_call method"; } } exit 0; Net-Twitter-4.01043/t/01_basic_v1_1.t000644 000766 000024 00000035067 13227713560 017021 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use lib qw(t/lib); eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required' if $@; my $screen_name = 'net_twitter'; my $message_id = 1234; my $status = 'Hello, world!'; my @tests = ( [ account_settings => sub { [] }, {}, GET => '/account/settings.json', __LINE__ ], [ add_list_member => sub { [ { list_id => 1234, user_id => 5678 } ] }, { list_id => 1234, user_id => 5678 }, POST => '/lists/members/create.json', __LINE__ ], [ add_place => sub { [ 'hacker nest', 'baadf00d', '1234', 49, -122 ] }, { name => 'hacker nest', contained_within => 'baadf00d', token => 1234, lat => 49, long => -122 }, POST => '/geo/place.json', __LINE__ ], [ blocking => sub { [] }, {}, GET => '/blocks/list.json', __LINE__ ], [ blocking_ids => sub { [ { cursor => -1 } ] }, { cursor => -1 }, GET => '/blocks/ids.json', __LINE__ ], [ contributees => sub { [ { screen_name => $screen_name } ] }, { screen_name => $screen_name }, GET => '/users/contributees.json', __LINE__ ], [ contributors => sub { [ { screen_name => $screen_name } ] }, { screen_name => $screen_name }, GET => '/users/contributors.json', __LINE__ ], [ create_block => sub { [ $screen_name ] }, { screen_name => $screen_name }, POST => "/blocks/create.json", __LINE__ ], [ create_favorite => sub { [ $message_id ] }, { id => $message_id }, POST => "/favorites/create.json", __LINE__ ], [ create_favorite => sub { [ { id => $message_id } ] }, { id => $message_id }, POST => "/favorites/create.json", __LINE__ ], [ create_friend => sub { [ $screen_name ] }, { screen_name => $screen_name }, POST => "/friendships/create.json", __LINE__ ], [ create_list => sub { [ { name => 'my-list' } ] }, { name => 'my-list' }, POST => '/lists/create.json', __LINE__ ], [ create_saved_search => sub { [ 'perl hacker' ] }, { query => 'perl hacker' }, POST => '/saved_searches/create.json', __LINE__ ], [ delete_list => sub { [ { list_id => 1234 } ] }, { list_id => 1234 }, POST => '/lists/destroy.json', __LINE__ ], [ delete_list_member => sub { [ { list_id => 1234, user_id => 678 } ] }, { list_id => 1234, user_id => 678 }, POST => '/lists/members/destroy.json', __LINE__ ], [ delete_saved_search => sub { [ 1234 ] }, {}, POST => '/saved_searches/destroy/1234.json', __LINE__ ], [ destroy_block => sub { [ $screen_name ] }, { screen_name => $screen_name }, POST => "/blocks/destroy.json", __LINE__ ], [ destroy_direct_message => sub { [ $message_id ] }, { id => $message_id }, POST => "/direct_messages/destroy.json", __LINE__ ], [ destroy_favorite => sub { [ $message_id ] }, { id => $message_id }, POST => "/favorites/destroy.json", __LINE__ ], [ destroy_favorite => sub { [ { id => $message_id } ] }, { id => $message_id }, POST => "/favorites/destroy.json", __LINE__ ], [ destroy_friend => sub { [ $screen_name ] }, { screen_name => $screen_name }, POST => "/friendships/destroy.json", __LINE__ ], [ destroy_status => sub { [ $message_id ] }, {}, POST => "/statuses/destroy/$message_id.json", __LINE__ ], [ destroy_status => sub { [ { id => $message_id } ] }, {}, POST => "/statuses/destroy/$message_id.json", __LINE__ ], [ direct_messages => sub { [] }, {}, GET => "/direct_messages.json", __LINE__ ], [ direct_messages_sent => sub { [] }, {}, GET => '/direct_messages/sent.json', __LINE__ ], [ favorites => sub { [] }, {}, GET => "/favorites/list.json", __LINE__ ], [ followers => sub { [] }, {}, GET => "/followers/list.json", __LINE__ ], [ followers_ids => sub { [ { screen_name => $screen_name, cursor => -1 } ] }, { screen_name => $screen_name, cursor => -1 }, GET => '/followers/ids.json', __LINE__ ], [ friends => sub { [] }, {}, GET => "/friends/list.json", __LINE__ ], [ friends_ids => sub { [ { screen_name => $screen_name, cursor => -1 } ] }, { screen_name => $screen_name, cursor => -1 }, GET => '/friends/ids.json', __LINE__ ], [ friendships_incoming => sub { [] }, {}, GET => '/friendships/incoming.json', __LINE__ ], [ friendships_outgoing => sub { [] }, {}, GET => '/friendships/outgoing.json', __LINE__ ], [ geo_id => sub { [ 'df51dec6f4ee2b2c' ] }, {}, GET => '/geo/id/df51dec6f4ee2b2c.json', __LINE__ ], [ geo_search => sub { [ { query => 'spokane' } ] }, { query => 'spokane' }, GET => '/geo/search.json', __LINE__ ], [ get_configuration => sub { [] }, {}, GET => '/help/configuration.json', __LINE__ ], [ get_languages => sub { [] }, {}, GET => '/help/languages.json', __LINE__ ], [ get_lists => sub { [ { screen_name => $screen_name } ] }, { screen_name => $screen_name }, GET => '/lists/list.json', __LINE__ ], [ get_lists => sub { [] }, {}, GET => '/lists/list.json', __LINE__ ], [ get_privacy_policy => sub { [] }, {}, GET => '/help/privacy.json', __LINE__ ], [ get_tos => sub { [] }, {}, GET => '/help/tos.json', __LINE__ ], [ home_timeline => sub { [] }, {}, GET => '/statuses/home_timeline.json', __LINE__ ], [ list_members => sub { [ { list_id => 12334 } ] }, { list_id => 12334 }, GET => '/lists/members.json', __LINE__ ], [ list_memberships => sub { [ { user_id => 1234 } ] }, { user_id => 1234 }, GET => '/lists/memberships.json', __LINE__ ], [ list_ownerships => sub { [ { screen_name => $screen_name } ] }, { screen_name => $screen_name }, GET => '/lists/ownerships.json', __LINE__ ], [ list_statuses => sub { [ { list_id => 1234 } ] }, { list_id => 1234 }, GET => '/lists/statuses.json', __LINE__ ], [ list_subscribers => sub { [ { list_id => 1234 } ] }, { list_id => 1234 }, GET => '/lists/subscribers.json', __LINE__ ], [ lookup_friendships => sub { [ { user_id => [ 1234, 5678 ] } ] }, { user_id => '1234,5678' }, GET => '/friendships/lookup.json', __LINE__ ], [ lookup_users => sub { [ { screen_name => [qw/foo bar baz/] } ] }, { screen_name => 'foo,bar,baz' }, GET => '/users/lookup.json', __LINE__ ], [ members_create_all => sub { [ { list_id => 1234, screen_name => [qw/a b c/] } ] }, { list_id => 1234, screen_name => 'a,b,c' }, POST => '/lists/members/create_all.json', __LINE__ ], [ members_destroy_all => sub { [ { list_id => 1234 } ] }, { list_id => 1234 }, POST => '/lists/members/destroy_all.json', __LINE__ ], [ mentions => sub { [] }, {}, GET => "/statuses/mentions_timeline.json", __LINE__ ], [ new_direct_message => sub { [ { user_id => 1234, text => $status } ] }, { user_id => 1234, text => $status }, POST => "/direct_messages/new.json", __LINE__ ], [ new_direct_message => sub { [ { screen_name => $screen_name, text => $status } ] }, { screen_name => $screen_name, text => $status }, POST => "/direct_messages/new.json", __LINE__ ], [ no_retweet_ids => sub { [] }, {}, GET => '/friendships/no_retweets/ids.json', __LINE__ ], [ oembed => sub { [ { id => 99530515043983360 } ] }, { id => 99530515043983360 }, GET => '/statuses/oembed.json', __LINE__ ], [ profile_banner => sub { [ { screen_name => $screen_name } ] }, { screen_name => $screen_name }, GET => '/users/profile_banner.json', __LINE__ ], [ rate_limit_status => sub { [ { resources => [qw/help statuses/] } ] }, { resources => 'help,statuses' }, GET => "/application/rate_limit_status.json", __LINE__ ], [ rate_limit_status => sub { [] }, {}, GET => "/application/rate_limit_status.json", __LINE__ ], [ remove_profile_banner => sub { [] }, {}, POST => '/account/remove_profile_banner.json', __LINE__ ], [ report_spam => sub { [ { screen_name => 'spammer' } ] }, { screen_name => 'spammer' }, POST => '/users/report_spam.json', __LINE__ ], [ retweet => sub { [ 44556 ] }, {}, POST => '/statuses/retweet/44556.json', __LINE__ ], [ retweets => sub { [ 44444 ] }, {}, GET => '/statuses/retweets/44444.json', __LINE__ ], [ retweets_of_me => sub { [] }, {}, GET => '/statuses/retweets_of_me.json', __LINE__ ], [ reverse_geocode => sub { [ 37, -122 ] }, { lat => 37, long => -122 }, GET => '/geo/reverse_geocode.json', __LINE__ ], [ saved_searches => sub { [] }, {}, GET => '/saved_searches/list.json', __LINE__ ], [ search => sub { [ 'perl hacker' ] }, { q => 'perl hacker' }, GET => '/search/tweets.json', __LINE__ ], [ search_users => sub { [ 'perl hacker' ] }, { q => 'perl hacker' }, GET => '/users/search.json', __LINE__], [ sent_direct_messages => sub { [] }, {}, GET => "/direct_messages/sent.json", __LINE__ ], [ show_direct_message => sub { [ 1234 ] }, { id => 1234 }, GET => '/direct_messages/show.json', __LINE__ ], [ show_list => sub { [ { list_id => 1234 } ] }, { list_id => 1234 }, GET => '/lists/show.json', __LINE__ ], [ show_list_member => sub { [ { list_id => 1234, screen_name => $screen_name } ] }, { list_id => 1234, screen_name => $screen_name }, GET => '/lists/members/show.json', __LINE__ ], [ show_list_subscriber => sub { [ { list_id => 1234, user_id => 666 } ] }, { list_id => 1234, user_id => 666 }, GET => '/lists/subscribers/show.json', __LINE__ ], [ show_saved_search => sub { [ 1234 ] }, {}, GET => '/saved_searches/show/1234.json', __LINE__ ], [ show_status => sub { [ 12345678 ] }, {}, GET => "/statuses/show/12345678.json", __LINE__ ], [ show_user => sub { [ $screen_name ] }, { screen_name => $screen_name }, GET => "/users/show.json", __LINE__ ], [ similar_places => sub { [ { name => 'spokane' } ] }, { name => 'spokane' }, GET => '/geo/similar_places.json', __LINE__ ], [ subscribe_list => sub { [ { owner_screen_name => $screen_name, slug => 'some-list' }, ] }, { owner_screen_name => $screen_name, slug => 'some-list' }, POST => '/lists/subscribers/create.json', __LINE__ ], [ subscriptions => sub { [ { screen_name => $screen_name } ] }, { screen_name => $screen_name }, GET => '/lists/subscriptions.json', __LINE__ ], [ suggestion_categories => sub { [ { lang => 'en' } ] }, { lang => 'en' }, GET => '/users/suggestions.json', __LINE__ ], [ trends_available => sub { [] }, {}, GET => '/trends/available.json', __LINE__ ], [ trends_closest => sub { [ { lat => 37, long => -122 } ] }, { lat => 37, long => -122 }, GET => '/trends/closest.json', __LINE__ ], [ trends_place => sub { [ 1234 ] }, { id => 1234 }, GET => '/trends/place.json', __LINE__ ], [ unsubscribe_list => sub { [ { list_id => 1234 } ] }, { list_id => 1234 }, POST => '/lists/subscribers/destroy.json', __LINE__ ], [ update => sub { [ $status ] }, { status => $status, source => 'twitterpm' }, POST => "/statuses/update.json", __LINE__ ], [ update_account_settings => sub { [ { lang => 'en' } ] }, { lang => 'en' }, POST => '/account/settings.json', __LINE__ ], [ update_delivery_device => sub { [ 'sms' ] }, { device => 'sms' }, POST => "/account/update_delivery_device.json", __LINE__ ], [ update_friendship => sub { [ { screen_name => $screen_name, retweets => 0 } ] }, { screen_name => $screen_name, retweets => 'false' }, POST => '/friendships/update.json', __LINE__ ], [ update_list => sub { [ { list_id => 1234, mode => 'private' } ] }, { list_id => 1234, mode => 'private' }, POST => '/lists/update.json', __LINE__ ], [ update_profile => sub { [ { name => 'Barney' } ] }, { name => 'Barney' }, POST => "/account/update_profile.json", __LINE__ ], [ update_profile_background_image => sub { [ { image => 'binary' } ] }, { image => 'binary' }, POST => "/account/update_profile_background_image.json", __LINE__ ], [ update_profile_banner => sub { [ { banner => 'binary data here' } ] }, { banner => 'binary data here' }, POST => "/account/update_profile_banner.json", __LINE__ ], [ update_profile_colors => sub { [ { profile_background_color => '#0000' } ] }, { profile_background_color => '#0000' }, POST => "/account/update_profile_colors.json", __LINE__ ], [ update_profile_image => sub { [ { image => 'binary data here' } ] }, { image => 'binary data here' }, POST => "/account/update_profile_image.json", __LINE__ ], [ update_with_media => sub { [ $status, 'binary data' ] }, { status => $status, 'media[]' => 'binary data' }, POST => '/statuses/update_with_media.json', __LINE__ ], [ user_suggestions => sub { [ 'slug', { lang => 'en' } ] }, { lang => 'en' }, GET => '/users/suggestions/slug/members.json', __LINE__ ], [ user_suggestions_for => sub { [ 'slug', { lang => 'en' } ] }, { lang => 'en' }, GET => '/users/suggestions/slug.json', __LINE__ ], [ user_timeline => sub { [] }, {}, GET => "/statuses/user_timeline.json", __LINE__ ], [ verify_credentials => sub { [] }, {}, GET => "/account/verify_credentials.json", __LINE__ ], ); plan tests => @tests * 2 * 4 + 1; use_ok 'Net::Twitter'; my $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::RESTv1_1/], username => 'homer', password => 'doh!', ); my $t = TestUA->new(1.1, $nt->ua); # run 2 passes to ensure the first pass isn't changing internal state for my $pass ( 1, 2 ) { for my $test ( @tests ) { my ($api_call, $input_args, $request_args, $method, $path, $line, $json_response) = @$test; # Fresh copy of args from a coderef because Net::Twitter is allowed to mutated any args hash # passed in. $input_args = $input_args->(); if ( $json_response ) { my $res = HTTP::Response->new(200, 'OK'); $res->content($json_response); $t->response($res); } ok $nt->$api_call(@$input_args), "[$pass][line $line] $api_call call"; is_deeply $t->args, $request_args, "[$pass] $api_call args"; is $t->path, $path, "[$pass] $api_call path"; is $t->method, $method, "[$pass] $api_call method"; $t->reset_response; } } exit 0; Net-Twitter-4.01043/t/02_fails.t000644 000766 000024 00000001260 13227713560 016175 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use Test::Fatal; use lib qw(t/lib); use Net::Twitter; eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required for tests' if $@; plan tests => 2; my $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::REST/], username => 'just_me', password => 'secret', ); my $t = TestUA->new(1, $nt->ua); # things that should fail like exception { $nt->relationship_exists(qw/one two three/) }, qr/expected 2 args/, 'too many args'; like exception { Net::Twitter->new(ssl => 0, useragent_class => 'NoSuchModule::Test7701')->verify_credentials }, qr/Can't locate NoSuchModule/, 'bad useragent_class'; exit 0; Net-Twitter-4.01043/t/10_net-twitter-regression.t000644 000766 000024 00000012557 13227713560 021555 0ustar00marcstaff000000 000000 #!perl use Carp; use strict; use Test::More; use Test::Fatal; use lib qw(t/lib); { # simple mock object for Net::Netrc package # hide from PAUSE Net::Netrc; use Moose; sub lookup { shift->new } sub lpa { qw/fred bedrock/ } $INC{'Net/Netrc.pm'} = __FILE__; } eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required for tests' if $@; use Net::Twitter; my $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::REST/], username => 'homer', password => 'doh!', ); my $t = TestUA->new(1, $nt->ua); ok $nt->friends_timeline, 'friends_timeline no args'; ok $nt->create_friend('flanders'), 'create_friend scalar arg'; ok $nt->create_friend({ id => 'flanders' }), 'create_friend hashref'; ok $nt->destroy_friend('flanders'), 'destroy_friend scalar arg'; $t->response->content('true'); my $r; # back compat: 1.23 accepts scalar args is exception { $r = $nt->relationship_exists('homer', 'marge') }, undef, 'relationship_exists scalar args'; ok $r = $nt->relationship_exists({ user_a => 'homer', user_b => 'marge' }), 'relationship_exists hashref'; # back compat: 1.23 returns bool ok $r, 'relationship_exists returns true'; $t->reset_response; # Net::Twitter calls used by POE::Component::Server::Twirc ok $nt->new_direct_message({ user => 'marge', text => 'hello, world' }), 'new_direct_message'; ok $nt->friends({page => 2}), 'friends'; cmp_ok $t->arg('page'), '==', 2, 'page argument passed'; ok $nt->followers({page => 2}), 'followers'; ok $nt->direct_messages, 'direct_messages'; ok $nt->direct_messages({ since_id => 1 }), 'direct_messages since_id'; ok $nt->friends_timeline({ since_id => 1 }), 'friends_timeline since_id'; ok $nt->replies({ since_id => 1 }), 'replies since_id'; ok $nt->user_timeline, 'user_timeline'; ok $nt->update('hello, world'), 'update'; ok $nt->create_friend('flanders'), 'create_friend'; ok $nt->relationship_exists('homer', 'flanders'), 'relationship exists scalar args'; ok $nt->relationship_exists({ user_a => 'homer', user_b => 'flanders' }), 'relationship exists hashref'; ok $nt->destroy_friend('flanders'), 'destroy_friend'; ok $nt->create_block('flanders'), 'create_block'; ok $nt->destroy_block('flanders'), 'destroy_block'; ok $nt->create_favorite({ id => 12345678 }), 'create_favorite hashref'; ok $nt->rate_limit_status, 'rate_limit_status'; ### Regression: broken in 2.03 ok $nt->show_status('flanders'), 'show_status string arg'; $t->add_id_arg('flanders'); is $t->arg('id'), 'flanders', 'show_status ID set'; ok $nt->show_user('marge'), 'show_user string arg'; $t->add_id_arg('marge'); is $t->arg('id'), 'marge', 'show_user ID set'; ok $nt->show_user({ id => 'homer' }), 'show_user hashref'; $t->add_id_arg('homer'); is $t->arg('id'), 'homer', 'show_user ID set 2'; ok $nt->public_timeline, 'public_timeline blankargs'; ### v3.09000 ### Role BUILD methods not called need after BUILD => sub {...} $nt = Net::Twitter->new(ssl => 1, traits => [qw/API::REST API::Lists/]); $t = TestUA->new(1, $nt->ua); $r = $nt->home_timeline; is $t->request->uri->scheme, 'https', 'ssl used for REST'; $r = $nt->list_lists('perl_api'); is $t->request->uri->scheme, 'https', 'ssl used for Lists'; ### v3.10001 ### netrc used $self->apiurl, which is only available via the API::REST trait is exception { Net::Twitter->new(ssl => 0, netrc => 1, traits => [qw/API::Lists/]) }, undef, 'netrc with API::Lists lives'; ### v3.11004 ### single array ref arg to update_profile_image not proprerly handled $r = $nt->update_profile_image([ undef, 'my_mug.jpg', Content_Type => 'image/jpeg', Content => '' ]); is $t->request->content_type, 'multipart/form-data', 'multipart/form-data'; ### v4.00007 ### unicode args in search result in 401 "Could not authenticate you" { use utf8; require URI::Escape; my $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::RESTv1_1 OAuth/], consumer_key => 'my-consumer-key', consumer_secret => 'my-consumer-secret', access_token => 'my-access-token', access_token_secret => 'my-access-token-secret', ); my $search_term = '作家'; # writer $nt->ua->add_handler(request_send => sub { my $req = shift; my $uri = $req->uri->clone; $uri->query(undef); my $oauth = Net::OAuth->request('protected_resource')->from_authorization_header( $req->header('Authorization'), request_url => $uri, consumer_key => 'my-consumer-key', consumer_secret => 'my-consumer-secret', token => 'my-access-token', token_secret => 'my-access-token-secret', version => '1.0', request_method => 'GET', signature_method => 'HMAC-SHA1', extra_params => { map Encode::decode_utf8($_), $req->uri->query_form }, ); ok $oauth->verify, 'valid oauth signature'; my $res = HTTP::Response->new(200); $res->header('Content-Type' => 'application/json'); $res->content('{}'); return $res; }); $nt->search($search_term); } done_testing Net-Twitter-4.01043/t/11_useragent.t000644 000766 000024 00000000464 13227713560 017101 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More tests => 3; use Test::Fatal; use_ok 'Net::Twitter'; my $nt; is exception { $nt = Net::Twitter->new(ssl => 0, useragent_args => { timeout => 20 }) }, undef, 'object creation with useragent_args'; is $nt->ua->timeout, 20, 'useragent_args applied'; Net-Twitter-4.01043/t/12_identica.t000644 000766 000024 00000001612 13227713560 016661 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use lib qw(t/lib); eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required for tests' if $@; plan tests => 5; use_ok 'Net::Twitter'; { my $nt = Net::Twitter->new(ssl => 0, legacy => 0, identica => 1, username => 'me', password => 'secret'); my $t = TestUA->new(1, $nt->ua); $t->response->content('"true"'); my $r = $nt->follows('night', 'day'); ok $r, 'string "true" is true'; $t->response->content('"false"'); $r = $nt->follows('night', 'day'); ok !$r, 'string "false" is false'; # and when they finally get it right: $t->response->content('"true"'); $r = $nt->follows('night', 'day'); ok $r, 'bool true is true'; } { my $nt = Net::Twitter->new(ssl => 0, traits => [qw/API::REST API::Search/], identica => 1); like $nt->searchapiurl, qr/identi\.ca/, 'use identica url for search'; } Net-Twitter-4.01043/t/13_search.t000644 000766 000024 00000002025 13227713560 016346 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use HTTP::Response; use Test::More; use Test::Warn; use lib qw(t/lib); plan skip_all => 'LWP::UserAgent 5.819 required' if $@; plan tests => 6; use Net::Twitter; my $nt = Net::Twitter->new(ssl => 0, traits => [qw/API::Search API::REST/]); my $request; my %args; my $response = HTTP::Response->new(200, 'OK'); $response->content('{"test":"success"}'); $nt->ua->add_handler(request_send => sub { $request = shift; $response->request($request); %args = $request->uri->query_form; return $response; }); my $search_term = "intelligent life"; my $r = $nt->search($search_term); isa_ok $r, 'HASH', "result is expected type"; is $args{q}, $search_term, "param q has search term"; # additional args in a HASH ref $r = $nt->search($search_term, { page => 2 }); is $args{page}, 2, "page parameter set"; like $request->uri, qr(/search.twitter.com/), 'search endpoint'; warnings_like { $nt->trends } qr/deprecated/i; like $request->uri, qr(/api.twitter.com/1/), 'trends endpoint'; Net-Twitter-4.01043/t/14_authenticate.t000644 000766 000024 00000003427 13227713560 017567 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use Test::Fatal; use lib qw(t/lib); use Net::Twitter; eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required' if $@; plan tests => 13; my $nt = Net::Twitter->new(ssl => 0, legacy => 1); isa_ok $nt, 'Net::Twitter'; $nt = Net::Twitter->new(ssl => 0, legacy => 0); my $t = TestUA->new(1, $nt->ua); is exception { $nt->user_timeline }, undef, "lives without credentials"; ok !$t->request->header('Authorization'), "no auth header without credentials"; $nt->credentials(homer => 'doh!'); is exception { $nt->user_timeline }, undef, "lives with credentials"; like $t->request->header('Authorization'), qr/Basic/, "has Basic Auth header"; $nt->public_timeline; ok $t->request->header('Authorization'), "public timeline auths by default"; $nt->public_timeline({ authenticate => 0 }); ok !$t->request->header('Authorization'), "public timeline can auth"; $nt->public_timeline({ authenticate => 1 }); ok $t->request->header('Authorization'), "can force authentication"; $nt->rate_limit_status({ authenticate => 0 }); ok !$t->request->header('Authorization'), "rate_limit_status allows no-auth"; $nt->rate_limit_status; ok $t->request->header('Authorization'), "rate_limit_status defaults to auth"; $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::REST OAuth/], consumer_key => 'com key', consumer_secret => 'com secret', ); $t = TestUA->new(1, $nt->ua); is exception { $nt->user_timeline }, undef, "lives without oauth tokens"; ok !$t->request->header('Authorization'), "no auth header without access tokens"; $nt->access_token('1234'); $nt->access_token_secret('5678'); is exception { $nt->user_timeline }, undef, "lives with access tokens"; Net-Twitter-4.01043/t/15_subclass.t000644 000766 000024 00000006225 13227713560 016730 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More tests => 27; { package My::Subclass::WithNew; use base qw/Net::Twitter/; sub new { my $class = shift; my $new = $class->SUPER::new(@_); $new->{subclass_attribute} = 'attribute value'; return $new; } sub subclass_method { shift->{subclass_attribute} } } { package My::Subclass::WithoutNew; use base qw/Net::Twitter/; sub subclass_method { my $self = shift; $self->{subclass_attribute} = shift if @_; return $self->{subclass_attribute}; } } { package My::Subclass::WithMoose; use Moose; extends 'Net::Twitter'; has subclass_attribute => ( is => 'rw', default => 'attribute value' ); sub subclass_method { shift->subclass_attribute(@_) } } { package My::Subclass::ValidMoose; use Moose; extends 'Net::Twitter::Core'; with 'Net::Twitter::Role::API::REST'; has subclass_attribute => ( reader => 'subclass_method', default => 'attribute value' ); } #diag 'subclass with new'; my $nt1 = My::Subclass::WithNew->new(ssl => 0, username => 'me', password => 'secret'); isa_ok $nt1, 'Net::Twitter'; isa_ok $nt1, 'Net::Twitter::Core'; isa_ok $nt1, 'My::Subclass::WithNew'; can_ok $nt1, qw/subclass_method user_timeline search credentials/; is $nt1->subclass_method, 'attribute value', 'has subclass attribute value'; is $nt1->password, 'secret', 'has base class attribute value'; #diag 'subclass without new'; my $nt2 = My::Subclass::WithoutNew->new(ssl => 0, username => 'me', password => 'secret'); isa_ok $nt2, 'Net::Twitter'; isa_ok $nt2, 'Net::Twitter::Core'; isa_ok $nt2, 'My::Subclass::WithoutNew'; can_ok $nt2, qw/subclass_method user_timeline search credentials/; is $nt2->subclass_method('test'), 'test', 'has subclass attribute value'; is $nt2->password, 'secret', 'has base class attribute value'; TODO: { local $TODO = 'Moose classes should subclass Core, not Net::Twitter'; #diag 'Moose subclass'; my $nt3 = My::Subclass::WithMoose->new(ssl => 0, username => 'me', password => 'secret'); isa_ok $nt3, 'Net::Twitter'; isa_ok $nt3, 'Net::Twitter::Core'; isa_ok $nt3, 'My::Subclass::WithMoose'; can_ok $nt3, qw/subclass_method user_timeline search credentials/; is $nt3->subclass_method, 'attribute value', 'has subclass attribute value'; is $nt3->password, 'secret', 'has base class attribute value'; } #diag 'valid Moose subclass'; my $nt4 = My::Subclass::ValidMoose->new(ssl => 0, username => 'me', password => 'secret'); ok !$nt4->isa('Net::Twitter'), 'not created by Net::Twitter'; isa_ok $nt4, 'Net::Twitter::Core'; isa_ok $nt4, 'My::Subclass::ValidMoose'; can_ok $nt4, qw/subclass_method user_timeline credentials/; is $nt4->subclass_method, 'attribute value', 'has subclass attribute value'; is $nt4->password, 'secret', 'has base class attribute value'; #diag 'class reuse'; is ref $nt1, ref My::Subclass::WithNew->new(ssl => 0), 'reused anon class'; ok ref $nt1 ne ref $nt2, 'different subclasses have different anon classes'; ok ref $nt1 ne ref My::Subclass::WithNew->new(ssl => 0, legacy => 0), 'different roles have different classes'; Net-Twitter-4.01043/t/20_exceptions.t000644 000766 000024 00000003153 13227713560 017263 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use Test::Fatal; use JSON::MaybeXS qw/encode_json/; use lib qw(t/lib); use Net::Twitter; eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required for tests' if $@; my $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::REST/], username => 'homer', password => 'doh!', ); my $t = TestUA->new(1, $nt->ua); my $response = HTTP::Response->new(404, 'Not Found'); $response->content(encode_json({ request => '/direct_messages/destroy/456.json', error => 'No direct message with that ID found.', })); $t->response($response); eval { $nt->destroy_direct_message(456) }; my $message = '$@ valid after stringification'; if( $@ ) { ok $@, $message; } else { fail $message; } { my $e = exception { $nt->destroy_direct_message(456) }; isa_ok $e, 'Net::Twitter::Error'; like $e, qr/No direct message/, 'error stringifies'; is $e->http_response->code, 404, "respose code"; is $e->code, 404, 'http_response handles code'; like $e->twitter_error->{request}, qr/456.json/, 'twitter_error request'; is $e, $e->error, 'stringifies to $@->error'; } # simulate a 500 response returned by LWP::UserAgent when it can't make a connection $response = HTTP::Response->new(500, "Can't connect to api.twitter.com:80"); $response->content("foo"); $t->response($response); { my $e = exception { $nt->friends_timeline({ since_id => 500_000_000 }) }; isa_ok $e, 'Net::Twitter::Error'; like $e->http_response->content, qr/html/, 'html content'; } done_testing; Net-Twitter-4.01043/t/20_generated.t000644 000766 000024 00000005363 13227713560 017045 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use List::Util qw/sum/; use lib qw(t/lib); eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required for tests' if $@; use Net::Twitter; my $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::REST API::Search API::TwitterVision/], username => 'me', password => 'secret', ); my $t = TestUA->new(1, $nt->ua); my @params = qw/one two three four five/; my @api_methods = grep { blessed $_ && $_->isa('Net::Twitter::Meta::Method') } $nt->meta->get_all_methods; plan tests => 6 * 2 * sum map 1 + @{$_->aliases}, @api_methods; # 2 passes to ensure nothing on the first pass changes internal state affecting the 2nd for my $pass ( 1, 2 ) { for my $entry ( sort { $a->name cmp $b->name } @api_methods ) { my $pos_params = $entry->required; my $path = $entry->path; $pos_params = $entry->params if @$pos_params == 0 && @{$entry->params} == 1; my @named_params = $path =~ /:(\w+)/g; for ( my $i = 0; $i < @named_params; ++$i ) { $path =~ s/:$named_params[$i]/$params[$i]/; } @$pos_params = @named_params; $path = "/$path.json"; for my $call ( $entry->name, @{$entry->aliases} ) { # the parameter names/values expected in GET/POST parameters my %expected; my @local_params = @params[0..$#{$pos_params}]; @expected{@$pos_params} = @local_params; # HACK! Expect "true" or "false" for boolean params for my $bool_param ( @{ $entry->booleans || [] } ) { if ( exists $expected{$bool_param} ) { $expected{$bool_param} = $expected{$bool_param} ? 'true' : 'false'; } } $expected{source} = $nt->source if $entry->add_source; my $r = eval { $nt->$call(@local_params) }; diag "$@\n" if $@; ok $r, "[$pass] $call(@{[ join ', ' => @$pos_params ]})"; my $args = $t->args; { my $expected_count = 0; my $got_count = 0; for ( my $i = 0; $i < @named_params; ++$i ) { delete $expected{$named_params[$i]} && ++$expected_count; $t->path =~ m{/$params[$i] [/.]}x && ++$got_count; } is $got_count, $expected_count, "[$pass] got expected named params"; is $got_count, scalar @named_params, "[$pass] named params count"; } is_deeply $args, \%expected, "[$pass] $call args"; is $t->path, $path, "[$pass] $call path"; is $t->method, $entry->method, "[$pass] $call method"; } } } exit 0; Net-Twitter-4.01043/t/21_wraperror.t000644 000766 000024 00000002644 13227713560 017132 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::Fatal; use Test::More; use lib qw(t/lib); BEGIN { eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required for tests' if $@; plan tests => 12; use_ok 'Net::Twitter', qw/Legacy/; } my $nt = Net::Twitter->new(ssl => 0, username => 'me', password => 'secret'); my $t = TestUA->new(1, $nt->ua); my $msg = 'Test failure'; my $r = $nt->update('Hello, world!'); ok defined $r && !defined $nt->get_error, 'api call success'; $t->response(HTTP::Response->new(500, $msg)); is exception { $r = $nt->public_timeline }, undef, 'exception trapped'; is $nt->http_message, $msg, 'http_message'; isa_ok $nt->get_error, 'HASH', 'get_error returns a HASH ref'; ok !defined $r, 'result is undef'; $t->response(HTTP::Response->new(200, 'fail whale')); $t->response->content('no json'); $r = $nt->user_timeline; ok !defined $r, 'result is undefined on fail whale'; isa_ok $nt->get_error, 'HASH', 'get_error with no JSON'; ok exists $nt->get_error->{error}, 'get_error has {error} member'; $t->response(HTTP::Response->new(200, 'error with OK response')); $t->response->content('{"error":"weirdness"}'); $r = $nt->friends; ok !defined $r, 'error with http response 200'; isa_ok $nt->get_error, 'HASH', 'get_error is a HASH ref on 200 error'; is $nt->get_error->{error}, 'weirdness', '200 error has {error} member'; exit 0; Net-Twitter-4.01043/t/22_twitter_insanity.t000644 000766 000024 00000001401 13227713560 020516 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use lib qw(t/lib); eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required for tests' if $@; plan tests => 1; use Net::Twitter; # For end_session, on success, twitter returns status code 200 and an ERROR # payload!!! my $nt = Net::Twitter->new(ssl => 0, legacy => 0, username => 'me', password => 'secret'); my $t = TestUA->new(1, $nt->ua); $t->response->content('{"error":"Logged out.","request":"/account/end_session.json"}'); # This test will always succeed since we're spoofing the response # from Twitter. It's simply meant to demonstrate Twitter's behavior. # Should we thorw an error, or should we return the HASH? my $r = eval { $nt->end_session }; like $@, qr/Logged out/, 'error on success'; Net-Twitter-4.01043/t/30_legacy.t000644 000766 000024 00000001412 13227713560 016343 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::Fatal; use Test::More; use lib qw(t/lib); BEGIN { eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required for tests' if $@; plan tests => 5; use_ok 'Net::Twitter', qw/Legacy/; } my $nt = Net::Twitter->new(ssl => 0, username => 'me', password => 'secret'); my $t = TestUA->new(1, $nt->ua); my $msg = 'Test failure'; my $r = $nt->update_twittervision(90210); ok !defined $r && !defined $nt->get_error, 'update_twittervision squelched'; $nt->twittervision(1); ok $nt->update_twittervision(90210), 'update_twittervision called'; $t->response(HTTP::Response->new(500, $msg)); is exception { $nt->public_timeline }, undef, 'exception trapped'; is $nt->http_message, $msg, 'http_message'; exit 0; Net-Twitter-4.01043/t/40_nt_subclasses.t000644 000766 000024 00000001512 13227713560 017751 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More tests => 3 + 4 * 3 + 5; use_ok 'Net::Twitter::Search'; use_ok 'Net::Twitter::OAuth'; use_ok 'Net::Identica'; sub does_legacy_roles { my $nt = shift; ok $nt->does($_) for map "Net::Twitter::Role::$_", qw/Legacy API::REST API::Search WrapError/; } my $nt = Net::Twitter::Search->new(ssl => 0); does_legacy_roles($nt); like $nt->apiurl, qr/twitter/, 'twitter url'; is $nt->apihost, 'api.twitter.com:80', 'twitter host'; $nt = Net::Twitter::OAuth->new(ssl => 0, consumer_key => 'key', consumer_secret => 'secret'); does_legacy_roles($nt); ok $nt->does('Net::Twitter::Role::OAuth'); $nt = Net::Identica->new(ssl => 0); does_legacy_roles($nt); like $nt->apiurl, qr/identi[.]ca/, 'identica url'; is $nt->apihost, 'identi.ca:80', 'identica host'; Net-Twitter-4.01043/t/50_inflate_objects.t000644 000766 000024 00000003146 13227713560 020242 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Scalar::Util qw/blessed/; use Test::More; use JSON::MaybeXS qw /encode_json/; use lib qw(t/lib); eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required' if $@; plan tests => 12; use_ok 'Net::Twitter'; my $nt = Net::Twitter->new(ssl => 0, traits => [qw/API::REST InflateObjects/]); my $datetime_parser = do { no warnings 'once'; $Net::Twitter::Role::API::REST::DATETIME_PARSER; }; my $dt = DateTime->now; $dt->subtract(minutes => 6); my $t = TestUA->new(1, $nt->ua); $t->response->content(encode_json([{ text => 'Hello, twittersphere!', user => { screen_name => 'net_twitter', }, created_at => $datetime_parser->format_datetime($dt), }])); my $r = $nt->friends_timeline; ok ref $r eq 'ARRAY', 'got an ArrayRef'; my $object = $r->[0]; ok blessed $object, 'value is an object'; can_ok $object, qw/text user created_at relative_created_at/; isa_ok $object->created_at, 'DateTime', 'DateTime inflation'; is $object->relative_created_at, '6 minutes ago', 'relative_created_at'; is $object->user->screen_name, 'net_twitter', 'nested objects'; # make sure we don't co-mingle our object methods $t->response->content(encode_json({ foo => 'foo', bar => 'bar', baz => 'and of course, baz', })); my $other = $nt->friends_timeline; can_ok $other, qw/foo bar baz/; isnt $other->meta->name, $object->meta->name, 'different anon class'; ok !$other->can('text'), 'different methods'; my $same = $nt->friends_timeline; can_ok $same, qw/foo bar baz/; is $same->meta->name, $other->meta->name, 'same anon class'; Net-Twitter-4.01043/t/51_rate_limit.t000644 000766 000024 00000002360 13227713560 017236 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use JSON::MaybeXS qw/encode_json/; use lib qw(t/lib); use Net::Twitter; eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required' if $@; my $nt = Net::Twitter->new(ssl => 0, traits => [qw/API::REST RateLimit/]); my $reset = time + 1800; my $t = TestUA->new(1, $nt->ua); $t->response->content(encode_json({ remaining_hits => 75, reset_time_in_seconds => $reset, hourly_limit => 150, })); is $nt->rate_limit, 150, 'rate_limit'; is $nt->rate_remaining, 75, 'rate_remaining'; is $nt->rate_reset, $reset, 'rate_reset'; like $t->request->uri, qr/rate_limit_status/, 'rate_limit_status called'; # HACK! Test approxmate values my $ratio = $nt->rate_ratio; ok $ratio > 0.9 && $ratio < 1.1, 'rate_ratio is about 1.0'; my $until = $nt->until_rate(2.0); ok $until > 890 && $until < 910, 'until_rate(2.0) is about 900'; # test clock mismatch $t->response->content(encode_json({ remaining_hits => 10, reset_time_in_seconds => $nt->_rate_limit_status->{rate_reset} = time - 10, hourly_limit => 150, })); ok $nt->rate_reset >= time, 'clock fudged'; is $nt->rate_remaining, 10, 'forced a rate_limit_status call'; done_testing; Net-Twitter-4.01043/t/51_since.t000644 000766 000024 00000003662 13227713560 016214 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Try::Tiny; use Scalar::Util qw/blessed/; use Test::More; use JSON::MaybeXS qw/encode_json/; use lib qw(t/lib); eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required' if $@; plan tests => 8; use_ok 'Net::Twitter'; my $nt = Net::Twitter->new(ssl => 0, traits => [qw/API::REST API::Search RateLimit InflateObjects/]); my $datetime_parser = do { no warnings 'once'; $Net::Twitter::Role::API::REST::DATETIME_PARSER; }; my $dt = DateTime->now; $dt->subtract(minutes => 6); my $t = TestUA->new(1, $nt->ua); $t->response->content(encode_json([ { text => 'Hello, twittersphere!', id => 1234, created_at => $datetime_parser->format_datetime($dt), }, { text => 'Too old', id => 5678, created_at => $datetime_parser->format_datetime($dt - DateTime::Duration->new(days => 2)), }, ])); my $r = $nt->friends_timeline; ok ref $r eq 'ARRAY', 'got an ArrayRef'; cmp_ok @$r, '==', 2, 'got 2 statuses'; $r = $nt->friends_timeline({ since => $dt - DateTime::Duration->new(days => 1) }); cmp_ok @$r, '==', 1, 'filtered with DateTime'; $r = $nt->friends_timeline({ since => time - 3600*25 }); cmp_ok @$r, '==', 1, 'filtered with epoch'; $r = $nt->friends_timeline({ since => $datetime_parser->format_datetime( $dt - DateTime::Duration->new(hours => 25)) }); cmp_ok @$r, '==', 1, 'filtered with string in Twitter timestamp format'; my $test = 'dies on invalid since'; try { $r = $nt->friends_timeline({ since => 'not a date' }); fail $test; } catch { pass $test }; $nt = Net::Twitter->new(ssl => 0, traits => [qw/API::Search API::REST/]); $nt->ua->add_handler(request_send => sub { my $res = HTTP::Response->new(200); $res->content('{"test":"done"}'); return $res; }); $test = 'YYYY-MM-DD'; try { $r = $nt->search({ q => 'perl', since => '2009-10-05' }); pass $test; } catch { fail "$test: $_"; }; Net-Twitter-4.01043/t/60-api_lists.t000644 000766 000024 00000010771 13227713560 017017 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use Net::Twitter; eval 'use LWP::UserAgent 5.819'; plan skip_all => 'LWP::UserAgent 5.819 required' if $@; my $nt = Net::Twitter->new(ssl => 0, traits => [qw/API::Lists/], username => 'fred', password => 'secret'); my $req; my $res = HTTP::Response->new(200); $res->content('{"response":"done"}'); $nt->ua->add_handler(request_send => sub { $req = shift; return $res }); my @tests = ( create_list => { args => [ 'owner', { name => 'Test list', description => 'Just a test', mode => 'private' } ], path => '/owner/lists', params => { name => 'Test list', description => 'Just a test', mode => 'private' }, method => 'POST', }, update_list => { args => [ 'owner', 'test-list', { mode => 'public' } ], path => '/owner/lists/test-list', params => { mode => 'public' }, method => 'POST', }, list_lists => { args =>[ 'owner' ], path => '/owner/lists', params => {}, method => 'GET', }, list_memberships => { args => [ 'owner' ], path => '/owner/lists/memberships', params => {}, method => 'GET', }, delete_list => { args => [ 'owner', 'test-list' ], path => '/owner/lists/test-list', params => {}, method => 'DELETE', }, list_statuses => { args => [ 'owner', 'test-list' ], path => '/owner/lists/test-list/statuses', params => {}, method => 'GET', }, get_list => { args => [ 'owner', 'test-list' ], path => '/owner/lists/test-list', params => {}, method => 'GET', }, add_list_member => { args => [ 'owner', 'test-list', 1234 ], path => '/owner/test-list/members', params => { id => 1234 }, method => 'POST', }, delete_list_member => { args => [ 'owner', 'test-list', 1234 ], path => '/owner/test-list/members', params => { id => 1234 }, method => 'DELETE', }, remove_list_member => { args => [ 'owner', 'test-list', 1234 ], path => '/owner/test-list/members', params => { id => 1234 }, method => 'DELETE', }, list_members => { args => [ 'owner', 'test-list' ], path => '/owner/test-list/members', params => {}, method => 'GET', }, is_list_member => { args => [ 'owner', 'test-list', 1234 ], path => '/owner/test-list/members/1234', params => {}, method => 'GET', }, subscribe_list => { args => [ 'owner', 'some-list' ], path => '/owner/some-list/subscribers', params => {}, method => 'POST', }, list_subscribers => { args => [ 'owner', 'some-list' ], path => '/owner/some-list/subscribers', params => {}, method => 'GET', }, list_subscriptions => { args => [ 'owner' ], path => '/owner/lists/subscriptions', params => {}, method => 'GET', }, unsubscribe_list => { args => [ 'owner', 'test-list' ], path => '/owner/test-list/subscribers', params => {}, method => 'DELETE', }, is_list_subscriber => { args => [ 'owner', 'test-list', 1234 ], path => '/owner/test-list/subscribers/1234', params => {}, method => 'GET', }, is_subscribed_list => { args => [ 'owner', 'test-list', 1234 ], path => '/owner/test-list/subscribers/1234', params => {}, method => 'GET', }, ); plan tests => scalar @tests / 2 * 3 + 2; while ( @tests ) { my $api_method = shift @tests; my $t = shift @tests; my $r = $nt->$api_method(@{ $t->{args} }); is $req->uri->path, "/1$t->{path}.json", "$api_method: path"; is $req->method, $t->{method}, "$api_method: HTTP method"; is_deeply extract_args($req), $t->{params}, "$api_method: parameters"; } { # unauthenticated call my $r = $nt->list_statuses(twitter => 'team', { authenticate => 0 }); ok !$req->header('authorization'), 'unauthenticated call'; # authenticated call (default) $r = $nt->list_statuses(twitter => 'team'); like $req->header('authorization'), qr/^Basic/, 'authenticated request (default)'; } sub extract_args { my $req = shift; my $uri; if ( $req->method eq 'POST' ) { $uri = URI->new; $uri->query($req->content); } else { $uri = $req->uri; } return { $uri->query_form }; } Net-Twitter-4.01043/t/99-pod_spelling.t000644 000766 000024 00000002441 13227713560 017516 0ustar00marcstaff000000 000000 #!perl -w use strict; use warnings; use Test::More; plan skip_all => 'set TEST_POD to enable this test' unless ($ENV{TEST_POD} || -e 'MANIFEST.SKIP'); eval 'use Test::Spelling 0.11'; plan skip_all => 'Test::Spelling 0.11 not installed' if $@; set_spell_cmd('aspell list'); add_stopwords(); all_pod_files_spelling_ok(qw/lib src/); __DATA__ ACKNOWLEDGEMENTS Akira API api APIDOC apihost apirealm APIs apiurl AppAuth AutoCursor BasicUser blogging clientname clienturl clientver contributees CPAN cursored Cursoring cursoring DateTime DirectMessage dzil ediblenergy EOT Etcheverry ExtendedUser favorited friended geo geocode Github GPS granularities Grennan Haim Identi identi identica IM InflateObjects inline IP ip IRC JSON json KATOU Kaugman Laconica lang Marc maxwidth MERCHANTABILITY Mims Miyagawa multipart netrc OAuth oauth oembed oEmbed ok OMG online Papperello parameterized params Pecorella perigrin Prather RateLimit RateLimitStatus refactored reimplemented requester's RetryOnError return's retweet retweeted retweeting Retweets retweets rpp RWD SavedSearch SMS spammer SSL ssl Str stringifies Tatsuhiko timeline tvhost tvrealm tvurl Twitter Twitter's twitterpm TwitterVision twittervision ua Un un unfollow Unsubscribes URI url useragent username usernames WiFi WOEID woeid WrapError xAuth Net-Twitter-4.01043/t/aliases.t000644 000766 000024 00000001155 13227713560 016222 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Net::Twitter; use Test::More; use Test::Warn; my $nt = Net::Twitter->new( ssl => 0, user => 'foo', pass => 'bar', ); is $nt->username, 'foo', 'user alias'; is $nt->password, 'bar', 'pass alias'; { # ensure it warns my @args = ( ssl => 0, username => 'foo', password => 'bar', user => 'other', pass => 'other-pass', ); warnings_like { Net::Twitter->new(@args) } [ qr/Both username and user provided/, qr/Both password and pass provided/, ], 'you have been warned'; } done_testing; Net-Twitter-4.01043/t/app-auth.t000755 000766 000024 00000001263 13227713560 016323 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use Test::Fatal; use Net::Twitter; plan skip_all => 'LWP::UserAgent 5.819 required' if $@; my $nt = Net::Twitter->new( traits => [ qw/AppAuth API::RESTv1_1/ ], consumer_key => 'my-key', consumer_secret => 'my-secret', ssl => 1, ); isa_ok $nt, 'Net::Twitter'; my ( $req, $res ); $nt->ua->add_handler(request_send => sub { $req = shift; $res }); $res = HTTP::Response->new(200, 'OK'); $res->content('{"access_token":"my-token","token_type":"bearer"}'); $nt->request_access_token; ok $nt->authorized, 'has an access token'; is $nt->access_token, 'my-token', 'with the correct value'; done_testing; Net-Twitter-4.01043/t/author-pod-coverage.t000644 000766 000024 00000000536 13227713560 020456 0ustar00marcstaff000000 000000 #!perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } # This file was automatically generated by Dist::Zilla::Plugin::PodCoverageTests. use Test::Pod::Coverage 1.08; use Pod::Coverage::TrustPod; all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' }); Net-Twitter-4.01043/t/author-pod-syntax.t000644 000766 000024 00000000454 13227713560 020210 0ustar00marcstaff000000 000000 #!perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); Net-Twitter-4.01043/t/auto-cursor.t000644 000766 000024 00000003710 13227713560 017063 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use Net::Twitter; use JSON::MaybeXS qw/encode_json/; use HTTP::Response; my $json_result = encode_json({ ids => ['test'], next_cursor => 1 }); sub mock_ua { my $nt = shift; $nt->ua->add_handler(request_send => sub { my $resp = HTTP::Response->new(200); $resp->content($json_result); return $resp; }); } { my $nt_with_max_calls_2 = Net::Twitter->new(ssl => 0, traits => ['API::REST', AutoCursor => { max_calls => 2 }]); my $class_for_max_calls_2 = ref $nt_with_max_calls_2; my $nt_with_max_calls_4 = Net::Twitter->new(ssl => 0, traits => ['API::REST', AutoCursor => { max_calls => 4 }]); my $class_for_max_calls_4 = ref $nt_with_max_calls_4; my $json_result = encode_json({ ids => ['test'], next_cursor => 1 }); mock_ua($_) for $nt_with_max_calls_2, $nt_with_max_calls_4; my $r = $nt_with_max_calls_2->friends_ids({ cursor => -1 }); is scalar @{$r->{ids}}, 1, 'behavior unmodified with "curosor" arg'; $r = $nt_with_max_calls_2->friends_ids({ -force_cursor => 1 }); is scalar @$r, 2, 'max_calls => 2'; $r = $nt_with_max_calls_4->friends_ids({ -force_cursor => 1 }); is scalar @$r, 4, 'max_calls => 4'; $r = $nt_with_max_calls_4->followers_ids({ -force_cursor => 1, max_calls => 10 }); is scalar @$r, 10, 'max_calls per call override'; my $nt = Net::Twitter->new(ssl => 0, traits => ['API::REST', AutoCursor => { max_calls => 2 }]); mock_ua($nt); is ref $nt, $class_for_max_calls_2, 'clone max_calls => 2, class name'; $r = $nt->friends_ids({ -force_cursor => 1 }); is scalar @$r, 2, 'cloned max_calls => 2'; $nt = Net::Twitter->new(ssl => 0, traits => ['API::REST', AutoCursor => { max_calls => 4 }]); mock_ua($nt); is ref $nt, $class_for_max_calls_4, 'clone max_calls => 4, class name'; $r = $nt->friends_ids({ -force_cursor => 1 }); is scalar @$r, 4, 'cloned max_calls => 4'; } done_testing; Net-Twitter-4.01043/t/deprecated_v1_1.t000644 000766 000024 00000005071 13227713560 017530 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use Test::Warn; use lib qw(t/lib); eval 'use TestUA'; plan skip_all => 'LWP::UserAgent 5.819 required' if $@; my $screen_name = 'net_twitter'; my $message_id = 1234; my $status = 'Hello, world!'; my @tests = ( [ disable_notifications => sub { [ $screen_name ] }, { screen_name => $screen_name, device => 'false' }, POST => "/friendships/update.json", __LINE__ ], [ disable_notifications => sub { [ { screen_name => $screen_name } ] }, { screen_name => $screen_name, device => 'false' }, POST => "/friendships/update.json", __LINE__ ], [ enable_notifications => sub { [ $screen_name ] }, { screen_name => $screen_name, device => 'true' }, POST => "/friendships/update.json", __LINE__ ], [ enable_notifications => sub { [ { screen_name => $screen_name } ] }, { screen_name => $screen_name, device => 'true' }, POST => "/friendships/update.json", __LINE__ ], [ friendship_exists => sub { [ 'a', 'b' ] }, { source_screen_name => 'a', target_screen_name => 'b' }, GET => "/friendships/show.json", __LINE__, '{"relationship":{"target":{"followed_by":true}}}' ], [ new_direct_message => sub { [ $screen_name, { text => $status } ] }, { screen_name => $screen_name, text => $status }, POST => "/direct_messages/new.json", __LINE__ ], [ new_direct_message => sub { [ $screen_name, $status ] }, { screen_name => $screen_name, text => $status }, POST => "/direct_messages/new.json", __LINE__ ], [ new_direct_message => sub { [ { user => $screen_name, text => $status } ] }, { screen_name => $screen_name, text => $status }, POST => "/direct_messages/new.json", __LINE__ ], [ new_direct_message => sub { [ 1234, $status ] }, { user_id => 1234, text => $status }, POST => "/direct_messages/new.json", __LINE__ ], ); plan tests => @tests + 1; use_ok 'Net::Twitter'; my $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::RESTv1_1/], username => 'homer', password => 'doh!', ); my $t = TestUA->new(1.1, $nt->ua); for my $test ( @tests ) { my ($api_call, $input_args, $request_args, $method, $path, $line, $json_response) = @$test; # Fresh copy of args from a coderef because Net::Twitter is allowed to mutated any args hash # passed in. $input_args = $input_args->(); if ( $json_response ) { my $res = HTTP::Response->new(200, 'OK'); $res->content($json_response); $t->response($res); } warning_like { $nt->$api_call(@$input_args) } qr/deprecated/i, "[line $line] $api_call"; $t->reset_response; } exit 0; Net-Twitter-4.01043/t/geo.t000644 000766 000024 00000002260 13227713560 015351 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Try::Tiny; use Test::More; use Net::Twitter; eval "use LWP::UserAgent 5.819"; plan skip_all => 'LWP::UserAgent >= 5.819 required' if $@; plan tests => 2; my $req; my $ua = LWP::UserAgent->new; $ua->add_handler(request_send => sub { $req = shift; my $res = HTTP::Response->new(200); $res->content('{"test":"OK"}'); return $res; }); sub params { my $uri = URI->new; $uri->query($req->content); my %params = $uri->query_form; return \%params; } my $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::REST/], username => 'fred', password => 'secret', ua => $ua, ); my $r = $nt->update({ status => 'Hello, world!', lat => 37.78215, long => -122.40060, display_coordinates => 1, }); my $params = params(); is params()->{display_coordinates}, 'true', "1 promoted to true"; $r = $nt->update({ status => 'Hello, world!', lat => 37.78215, long => -122.40060, display_coordinates => 0, }); $params = params(); is params()->{display_coordinates}, 'false', "0 promoted to false"; Net-Twitter-4.01043/t/leak.t000644 000766 000024 00000001032 13227713560 015507 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More tests => 2; use Net::Twitter; # Net::Twitter::Role::RateLimit 3.13009 memory leak { package t::NT; use Moose; extends 'Net::Twitter::Core'; with qw/ Net::Twitter::Role::API::REST Net::Twitter::Role::RateLimit /; our $count = 0; sub BUILD { ++$count } sub DEMOLISH { --$count } } { my $nt = t::NT->new(ssl => 0, consumer_key => 'foo', consumer_secret => 'bar'); is $t::NT::count, 1, "BUILT"; } is $t::NT::count, 0, "DEMOLISHED", Net-Twitter-4.01043/t/lib/000755 000766 000024 00000000000 13227713560 015160 5ustar00marcstaff000000 000000 Net-Twitter-4.01043/t/lookup_users.t000644 000766 000024 00000003564 13227713560 017341 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More; use Net::Twitter; eval "use LWP::UserAgent 5.819"; plan skip_all => 'LWP::UserAgent >= 5.819 required' if $@; eval "use Test::Deep"; plan skip_all => 'Test::Deep required' if $@; my @tests = ( { args => [ { user_id => '1234,6543,3333' } ], expect => { user_id => '1234,6543,3333' }, name => 'hash: comma delimited', }, { args => [ { user_id => '1234,6543,3333' } ], expect => { user_id => '1234,6543,3333' }, name => 'list: comma delimited', }, { args => [ { user_id => [ 1234, 6543, 3333 ] } ], expect => { user_id => '1234,6543,3333' }, name => 'hash: arrayref', }, { args => [ { screen_name => 'fred,barney,wilma' } ], expect => { screen_name => 'fred,barney,wilma' }, name => 'hash: comma delimited', }, { args => [ { screen_name => ['fred', 'barney', 'wilma'] } ], expect => { screen_name => 'fred,barney,wilma' }, name => 'list: arrayref', }, { args => [ { screen_name => ['fred', 'barney' ], user_id => '4321,6789' } ], expect => { screen_name => 'fred,barney', user_id => '4321,6789' }, name => 'list: arrayref screen_name and comma delimited user_id', }, ); my $test_count = 0; $test_count += keys %$_ for map { $_->{expect} } @tests; plan tests => $test_count; my $nt = Net::Twitter->new(ssl => 0, legacy => 0); my $req; $nt->ua->add_handler(request_send => sub { $req = shift; my $res = HTTP::Response->new(200); $res->content('{"test":"ok"}'); return $res; }); for my $test ( @tests ) { my $r = $nt->lookup_users(@{ $test->{args} }); my %query = $req->uri->query_form; for my $arg ( keys %{ $test->{expect} } ) { is $query{$arg}, $test->{expect}{$arg}, "$test->{name} [$arg]"; } } Net-Twitter-4.01043/t/retry.t000644 000766 000024 00000001531 13227713560 015744 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Try::Tiny; use Test::More; use Net::Twitter; eval "use LWP::UserAgent 5.819"; plan skip_all => 'LWP::UserAgent >= 5.819 required' if $@; plan tests => 1; my $req; my $ua = LWP::UserAgent->new; $ua->add_handler(request_send => sub { $req = shift; my $res = HTTP::Response->new(500, 'Uh-oh!'); $res->content('{"test":"OK"}'); return $res; }); sub params { my $uri = URI->new; $uri->query($req->content); my %params = $uri->query_form; return \%params; } my $retry_count = 0; my $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::REST RetryOnError/], username => 'fred', password => 'secret', ua => $ua, max_retries => 5, retry_delay_code => sub { ++$retry_count }, ); try { $nt->verify_credentials }; is $retry_count, 5, 'retried 5 times'; Net-Twitter-4.01043/t/role-wrap-result.t000644 000766 000024 00000001544 13227713560 020027 0ustar00marcstaff000000 000000 #!perl use strict; use warnings; use Test::More; use Net::Twitter; my $nt = Net::Twitter->new( traits => [ qw/API::RESTv1_1 WrapResult/ ], consumer_key => 'my-key', consumer_secret => 'my-secret', access_token => 'token', access_token_secret => 'token-secret', ); $nt->ua->add_handler(request_send => sub { HTTP::Response->new( 200, 'OK', [ 'X-Rate-Limit-Limit' => 222, 'X-Rate-Limit-Remaining' => 111, 'X-Rate-Limit-Reset' => 1234, ], '[1,2,3,4,5]', ); }); my $r = $nt->verify_credentials; is $r->rate_limit, 222, 'rate limit'; is $r->rate_limit_remaining, 111, 'rate limit remaining'; is $r->rate_limit_reset, 1234, 'rate limit reset'; is_deeply $r->result, [ 1..5 ], 'twitter result'; done_testing; Net-Twitter-4.01043/t/stack_trace.t000644 000766 000024 00000002300 13227713560 017055 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More tests => 4; use File::Spec; { package Foo; use Moose; has net_twitter => is => 'rw', required => 1; sub whois { my ( $self, $id ) = @_; # $line follows, should be reported as frame 0 in the stack trace $self->net_twitter->show_user($id); } } my $line = __LINE__ - 4; # is there a better way to do this? use Net::Twitter; use HTTP::Response; use Try::Tiny; my $nt = Net::Twitter->new(ssl => 0, legacy => 0); $nt->ua->add_handler(request_send => sub { my $res = HTTP::Response->new(403); $res->content('{"errors":[{"code":63,"message":"User has been suspended"}]}'); $res; }); my $foo = Foo->new(net_twitter => $nt); try { $foo->whois(1234) } catch { like $_->error, qr/suspended/, 'stringified error contains twitter error message'; my $frame = $_->stack_trace->frame(0); my $file = File::Spec->canonpath(__FILE__); my $file_in_frame = File::Spec->canonpath($frame->{filename}); is $file_in_frame, $file, "first stack frame file"; is $frame->{line}, $line, "first stack frame line"; like $_->error, qr( at \Q$file\E line $line$), 'error contains first stack frame'; }; Net-Twitter-4.01043/t/stringent-encoding.t000644 000766 000024 00000002077 13227713560 020406 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use URI; use Net::Twitter; use Net::OAuth::Message; use Test::More; plan tests => 2; # Ensure post args are encoded per the OAuth spec # # We assume Net::OAuth does the right thing, here. # # Bug reported by Nick Andrew (@elronxenu) 2013-02-27 my $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::RESTv1_1/], consumer_key => 'mykey', consumer_secret => 'mysecret', access_token => 'mytoken', access_token_secret => 'mytokensecret', ); my $req; $nt->ua->add_handler(request_send => sub { $req = shift; my $res = HTTP::Response->new(200, 'OK'); $res->content('{}'); return $res; }); my $text = q[Bob's your !@##$%^&*(){}} uncle!]; $nt->new_direct_message({ screen_name => 'perl_api', text => $text }); my $encoded_text = Net::OAuth::Message::encode($text); like $req->content, qr/\Q$encoded_text/, 'properly encoded'; my $uri = URI->new($req->uri); $uri->query($req->content); my %params = $uri->query_form; is $params{text}, $text, 'decoded text matches'; Net-Twitter-4.01043/t/twitter_error.t000644 000766 000024 00000002773 13227713560 017523 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Test::More tests => 8; use Net::Twitter::Error; use HTTP::Response; { # old school error my $res = HTTP::Response->new(400); my $e = Net::Twitter::Error->new( http_response => $res, twitter_error => { error => "Something wicked" }, ); like $e, qr/Something wicked/, 'old school twitter error'; is $e->twitter_error_text, 'Something wicked', 'twitter_error_text for old school twitter error'; } { # newer variant my $res = HTTP::Response->new(400); my $e = Net::Twitter::Error->new( http_response => $res, twitter_error => { error => { message => "Something wicked" } }, ); like $e, qr/Something wicked/, 'twitter error with message/code'; is $e->twitter_error_text, 'Something wicked', 'twitter_error_text for twitter error with message/code'; } { # array of errors variant my $res = HTTP::Response->new(400); my $e = Net::Twitter::Error->new( http_response => $res, twitter_error => { errors => [{ message => "Something wicked" }] }, ); like $e, qr/Something wicked/, 'twitter array of errors'; is $e->twitter_error_text, 'Something wicked', 'twitter_error_text for twitter array of errors'; } { # unexpected my $res = HTTP::Response->new(400); my $e = Net::Twitter::Error->new( http_response => $res, ); is $e->twitter_error_text, '', 'twitter_error_text is empty string'; like $e, qr/Bad Request/, 'twitter array of errors'; } Net-Twitter-4.01043/t/unicode.t000644 000766 000024 00000005635 13227713560 016236 0ustar00marcstaff000000 000000 #!perl use warnings; use strict; use Try::Tiny; use Test::More; use Encode qw/decode encode_utf8 decode_utf8/; use Net::Twitter; eval "use LWP::UserAgent 5.819"; plan skip_all => 'LWP::UserAgent >= 5.819 required' if $@; plan tests => 13; my $req; my $ua = LWP::UserAgent->new; $ua->add_handler(request_send => sub { $req = shift; my $res = HTTP::Response->new(200); $res->content('{}'); return $res; }); sub raw_sent_status { my $uri = URI->new; $uri->query($req->content); my %params = $uri->query_form; return $params{status}; } sub sent_status { decode_utf8 raw_sent_status() } my $nt = Net::Twitter->new( ssl => 0, traits => [qw/API::REST OAuth/], consumer_key => 'key', consumer_secret => 'secret', ua => $ua, ); $nt->access_token('token'); $nt->access_token_secret('secret'); my $meta = $nt->meta; $meta->make_mutable; $meta->add_around_method_modifier('_make_oauth_request', sub { my ($orig, $self, $type, %args) = @_; ok utf8::is_utf8($args{extra_params}{status}), "status must be decoded"; $self->$orig($type, %args); }); $meta->make_immutable; # "Hello world!" in traditional Chinese if Google translate is correct my $status = "\x{4E16}\x{754C}\x{60A8}\x{597D}\x{FF01}"; ok utf8::is_utf8($status), 'status parameter is decoded'; try { $nt->update($status) }; is sent_status(), $status, 'sent status matches update parameter'; # ISO-8859-1 my $latin1 = "\xabHello, world\xbb"; ok !utf8::is_utf8($latin1), "latin-1 string is not utf8 internally"; try { $nt->update($latin1) }; is sent_status(), $latin1, "latin-1 matches"; ok !utf8::is_utf8($latin1), "latin-1 not promoted to utf8"; ### Net::Twitter expects decoded characters, not encoded bytes ### So, sending encoded utf8 to Net::Twitter will result in double ### encoded data. SKIP: { eval "use Encode::DoubleEncodedUTF8"; skip "requires Encode::DoubleEncodedUTF8", 3 if $@; try { $nt->update(encode_utf8 $status) }; my $bytes = raw_sent_status(); isnt $bytes, encode_utf8($status), "encoded status does not match"; is decode('utf-8-de', $bytes), $status, "double encoded"; }; ############################################################ # Basic Auth ############################################################ $nt = Net::Twitter->new( ssl => 0, legacy => 0, username => 'fred', password => 'pebbles', ua => $ua, ); try { $nt->update($status) }; is sent_status(), $status, 'basic auth'; try { $nt->update($latin1) }; is sent_status(), $latin1, 'latin-1 basic auth'; ############################################################ # update_with_media ############################################################ try { my $r = $nt->update_with_media($status, [ undef, undef, content_type => 'image/png', content => 'image-data', ]); pass 'update_image_with_media'; } catch { fail $_; }; Net-Twitter-4.01043/t/url-attributes.t000644 000766 000024 00000006131 13227713560 017566 0ustar00marcstaff000000 000000 use Test::More; use Net::Twitter; use URI; sub test_uris { my ( $nt, $urls ) = @_; for my $attr ( keys %$urls ) { my $uri = $nt->$attr; ok $uri->isa('URI'), "$attr isa URI"; is "$uri", $urls->{$attr}, "$attr is expected url"; } }; subtest 'default URL attributes' => sub { my %urls = ( authentication_url => 'https://api.twitter.com/oauth/authenticate', authorization_url => 'https://api.twitter.com/oauth/authorize', request_token_url => 'https://api.twitter.com/oauth/request_token', access_token_url => 'https://api.twitter.com/oauth/access_token', xauth_url => 'https://api.twitter.com/oauth/access_token', ); my $nt = Net::Twitter->new( traits => [ qw/API::RESTv1_1 OAuth/ ], consumer_key => 'key', consumer_secret => 'secret', ); test_uris($nt, \%urls); }; subtest 'explicit URL attributes' => sub { my %urls = ( authentication_url => 'https://example.com/authenticate', authorization_url => 'https://example.com/authorize', request_token_url => 'https://example.com/request', access_token_url => 'https://example.com/access', xauth_url => 'https://example.com/xauth', ); my $nt = Net::Twitter->new( traits => [ qw/API::RESTv1_1 OAuth/ ], consumer_key => 'key', consumer_secret => 'secret', %urls, ); test_uris($nt, \%urls); }; subtest 'with URIs' => sub { my %urls = ( authentication_url => URI->new('https://example.com/authenticate'), authorization_url => URI->new('https://example.com/authorize'), request_token_url => URI->new('https://example.com/request'), access_token_url => URI->new('https://example.com/access'), xauth_url => URI->new('https://example.com/xauth'), ); my $nt = Net::Twitter->new( traits => [ qw/API::RESTv1_1 OAuth/ ], consumer_key => 'key', consumer_secret => 'secret', %urls, ); test_uris($nt, \%urls); }; subtest 'oauth_urls pseudo attribute' => sub { my %urls = ( authentication_url => 'https://example.com/authenticate', authorization_url => 'https://example.com/authorize', request_token_url => 'https://example.com/request', access_token_url => 'https://example.com/access', xauth_url => 'https://example.com/xauth', ); my $nt = Net::Twitter->new( traits => [ qw/API::RESTv1_1 OAuth/ ], consumer_key => 'key', consumer_secret => 'secret', oauth_urls => \%urls, ); test_uris($nt, \%urls); }; subtest 'AppAuth URLs' => sub { my %urls = ( request_token_url => "https://api.twitter.com/oauth2/token", invalidate_token_url => "https://api.twitter.com/oauth2/invalidate_token", ); my $nt = Net::Twitter->new( traits => [ qw/API::RESTv1_1 AppAuth/ ], consumer_key => 'key', consumer_secret => 'secret', ); test_uris($nt, \%urls); }; done_testing; Net-Twitter-4.01043/t/lib/TestUA.pm000644 000766 000024 00000003325 13227713560 016666 0ustar00marcstaff000000 000000 package # hide from PAUSE TestUA; use strict; use warnings; use Carp; use Scalar::Util qw/blessed/; use HTTP::Response; use LWP::UserAgent 5.819; sub new { my ($class, $version, $ua, $content) = @_; blessed $ua || croak 'Usage: TestUA->new($api_version, $real_ua [, $content ])'; my $self = bless { version => $version, content => $content }, $class; $self->reset_response; $ua->add_handler(request_send => sub { $self->{request} = shift; $self->{response}->request($self->{request}); # extract arguments from the request uri and content my $uri = $self->{request}->uri->clone; my %args = $uri->query_form; $uri->query($self->{request}->content); $self->{args} = { %args, $uri->query_form }; return $self->{response}; }); return $self; } sub reset_response { my $self = shift; my $res = HTTP::Response->new(200, 'OK'); $res->content($self->{content} || '{"test":"success"}'); $self->{response} = $res; } sub arg { my ($self, $arg) = @_; return $self->{args}{$arg}; } sub args { shift->{args} } # An id can be passed in the URL body for some Twitter API calls; add the ID # arg to the args list if it is in the path in the proper format sub add_id_arg { my ($self, $id) = @_; $self->{args}{id} = $id if $self->path =~ /\/\Q$id\E\.json$/; } sub method { shift->{request}->method } sub path { my $self = shift; my $path = $self->{request}->uri->path; my $re = qr/\/\Q${ \$self->{version} }\E(?=\/)/; $path =~ s{$re}{}; return $path; } sub response { my $self = shift; $self->{response} = shift if @_; return $self->{response}; } sub request { shift->{request} } 1; Net-Twitter-4.01043/lib/Net/000755 000766 000024 00000000000 13227713560 015443 5ustar00marcstaff000000 000000 Net-Twitter-4.01043/lib/Net/Identica.pm000644 000766 000024 00000006727 13227713560 017535 0ustar00marcstaff000000 000000 package Net::Identica; $Net::Identica::VERSION = '4.01043'; use Moose; extends 'Net::Twitter::Core'; with map "Net::Twitter::Role::$_", qw/Legacy/; has '+apiurl' => ( default => 'http://identi.ca/api' ); has '+apirealm' => ( default => 'Laconica API' ); no Moose; __PACKAGE__->meta->make_immutable; 1; __END__ =head1 NAME Net::Identica - A perl interface to the Identi.ca Twitter Compatible API =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Identica; $nt = Net::Identica->new(username => $user, password => $passwd); $nt->update('Hello, Identica friends!'); =head1 DEPRECATED This module is a backwards compatibility wrapper for applications that used L packaged with C versions 2.12 and earlier. Instead, use L with the C option to gain all of the new features and functionality (OAuth, Search, exceptions on error, etc.). use Net::Twitter; # A simple, backwards compatible replacement for Net::Identica my $identica = Net::Twitter->new( legacy => 1, identica => 1, username => $username, password => $password, ); # A more complex object with OAuth and some optional traits my $identica = Net::Twitter->new( traits => [qw/API::REST API::Search InflateObjects/], identica => 1, consumer_key => $consumer_key, consumer_secret => $consumer_secret, access_token => $token, access_token_secret => $token_secret, ); =head1 DESCRIPTION The micro-blogging service L provides a Twitter compatible API. This module simply creates an instance of C with the C option set. See L for full documentation. =head1 METHODS =over 4 =item new Creates a C object by call L with the C option preset. =back =head1 SEE ALSO =over 4 =item L Full documentation. =back =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2009 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/000755 000766 000024 00000000000 13227713560 017105 5ustar00marcstaff000000 000000 Net-Twitter-4.01043/lib/Net/Twitter.pm000644 000766 000024 00000010450 13227713560 017443 0ustar00marcstaff000000 000000 package Net::Twitter; $Net::Twitter::VERSION = '4.01043'; use Moose; use Carp::Clan qw/^(?:Net::Twitter|Moose|Class::MOP)/; use JSON::MaybeXS; use Net::Twitter::Core; use Digest::SHA qw/sha1_hex/; use Class::Load (); use namespace::autoclean; has '_trait_namespace' => ( Moose->VERSION >= '0.85' ? (is => 'bare') : (), default => 'Net::Twitter::Role', ); # See Net/Twitter.pod for documentation, Net/Twitter/Core.pm for implementation. # # For transparent back compat, Net::Twitter->new() creates a Net::Twitter::Core # with the 'Legacy' trait. # transform_trait and resolve_traits stolen from MooseX::Traits sub _transform_trait { my ($class, $name) = @_; my $namespace = $class->meta->find_attribute_by_name('_trait_namespace'); my $base; if($namespace->has_default){ $base = $namespace->default; if(ref $base eq 'CODE'){ $base = $base->(); } } return $name unless $base; return $1 if $name =~ /^[+](.+)$/; return "$base\::$name"; } sub _resolve_traits { my ($class, @traits) = @_; return map { unless ( ref ) { $_ = $class->_transform_trait($_); Class::Load::load_class($_); } $_; } @traits; } sub _isa { my $self = shift; my $isa = shift; return $isa eq __PACKAGE__ || $self->SUPER::isa($isa) }; sub _create_anon_class { my ($superclasses, $traits, $immutable, $package) = @_; # Do we already have a meta class? return $package->meta if $package->can('meta'); my $meta; $meta = Net::Twitter::Core->meta->create_anon_class( superclasses => $superclasses, roles => $traits, methods => { meta => sub { $meta }, isa => \&_isa }, cache => 0, package => $package, ); $meta->make_immutable(inline_constructor => $immutable); return $meta; } { my $serial_number = 0; my %serial_for_params; sub _name_for_anon_class { my @t = @{$_[0]}; my @comps; while ( @t ) { my $t = shift @t; if ( ref $t[0] eq 'HASH' ) { my $params = shift @t; my $sig = sha1_hex(JSON->new->utf8->encode($params)); my $sn = $serial_for_params{$sig} ||= ++$serial_number; $t .= "_$sn"; } $t =~ s/(?:::|\W)/_/g; push @comps, $t; } my $ver = $Net::Twitter::Core::VERSION || 1; $ver =~ s/\W/_/g; return __PACKAGE__ . "_v${ver}_" . join '__', 'with', sort @comps; } } sub new { my $class = shift; croak '"new" is not an instance method' if ref $class; my %args = @_ == 1 && ref $_[0] eq 'HASH' ? %{$_[0]} : @_; my $traits = delete $args{traits}; if ( defined (my $legacy = delete $args{legacy}) ) { croak "Options 'legacy' and 'traits' are mutually exclusive. Use only one." if $traits; $traits = [ $legacy ? 'Legacy' : 'API::REST' ]; } $traits ||= [ qw/Legacy/ ]; # ensure we have the OAuth trait if we have a consumer key (unless we've # specified AppAuth) if ( $args{consumer_key} && !grep $_ eq 'AppAuth', @$traits ) { $traits = [ (grep $_ ne 'OAuth', @$traits), 'OAuth' ]; } # create a unique name for the created class based on trait names and parameters my $anon_class_name = _name_for_anon_class($traits); $traits = [ $class->_resolve_traits(@$traits) ]; my $superclasses = [ 'Net::Twitter::Core' ]; my $meta = _create_anon_class($superclasses, $traits, 1, $anon_class_name); # create a Net::Twitter::Core object with roles applied my $new = $meta->name->new(%args); # rebless it to include a superclass, if we're being subclassed if ( $class ne __PACKAGE__ ) { unshift @$superclasses, $class; my $final_meta = _create_anon_class( $superclasses, $traits, 0, join '::', $class, $anon_class_name ); bless $new, $final_meta->name; } return $new; } __PACKAGE__->meta->make_immutable(inline_constructor => 0); 1; __END__ =head1 NAME Net::Twitter - A perl interface to the Twitter API =head1 VERSION version 4.01043 =head1 DESCRIPTION This module has been superseded by L. Please update your applications and/or downstream dependent modules as soon as possible. Net-Twitter-4.01043/lib/Net/Twitter.pod000644 000766 000024 00000270571 13227713560 017625 0ustar00marcstaff000000 000000 =head1 NAME Net::Twitter - A perl interface to the Twitter API =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; use Scalar::Util 'blessed'; # When no authentication is required: my $nt = Net::Twitter->new(legacy => 0); # As of 13-Aug-2010, Twitter requires OAuth for authenticated requests my $nt = Net::Twitter->new( traits => [qw/API::RESTv1_1/], consumer_key => $consumer_key, consumer_secret => $consumer_secret, access_token => $token, access_token_secret => $token_secret, ); my $result = $nt->update('Hello, world!'); eval { my $statuses = $nt->friends_timeline({ since_id => $high_water, count => 100 }); for my $status ( @$statuses ) { print "$status->{created_at} <$status->{user}{screen_name}> $status->{text}\n"; } }; if ( my $err = $@ ) { die $@ unless blessed $err && $err->isa('Net::Twitter::Error'); warn "HTTP Response Code: ", $err->code, "\n", "HTTP Message......: ", $err->message, "\n", "Twitter error.....: ", $err->error, "\n"; } =head1 TWITTER API V1.1 SUPPORT This version of Net::Twitter provides Twitter API v1.1 support. Enable it by including the C trait instead of C. Using Twitter API v1.1 may require changes to you code! It is not completely backwards compatible with v1. For help migrating your application to Twitter API v1.1, see L. =head1 DESCRIPTION This module has been superseded by L. Please update as soon as you possibly can to use new features and the new API versions. This module will no longer be supported. This module provides a perl interface to the Twitter APIs. See L for a full description of the Twitter APIs. =head1 TWITTER API VERSION 1.1 Twitter will (perhaps has by the time you read this) deprecated version 1 of the API. Documentation, here, assumes version 1.1 of the API. For version 1 documentation, see L. To use Twitter API version 1.1, simply replace C in the C argument to C with C. The C API is backwards compatible to the extent possible. If Twitter does not provide a 1.1 endpoint for a version 1 call, C cannot support it, of course. Twitter API version 1.1 requires OAuth authentication for all calls. There is no longer an IP address limit and a per-user limit. Each API call has it's own rate limit. Most are 15 calls reset every 15 minutes. Others are 180 calls, reset every 15 minutes. These limits may change. For current rate limits, see L. =head1 OMG! THE MOOSE! Net::Twitter is L based. Moose provides some advantages, including the ability for the maintainer of this module to respond quickly to Twitter API changes. See L if you need an alternative without Moose and its dependencies. Net::Twitter::Lite's API method definitions and documentation are generated from Net::Twitter. It is a related module, but does not depend on Net::Twitter or Moose for installation. =head1 RETURN VALUES Net::Twitter decodes the data structures returned by the Twitter API into native perl data structures (HASH references and ARRAY references). The full layout of those data structures are not documented, here. They change often, usually with the addition of new elements, and documenting all of those changes would be a significant challenge. Instead, rely on the online Twitter API documentation and inspection of the returned data. The Twitter API online documentation is located at L. To inspect the data, use L or similar module of your choice. Here's a simple example using Data::Dumper: use Data::Dumper; my $r = $nt->search($search_term); print Dumper $r; For more information on perl data structures, see L, L, and L. =head1 METHODS AND ARGUMENTS =over 4 =item new This constructs a C object. It takes several named parameters, all of them optional: =over 4 =item traits An ARRAY ref of traits used to control which APIs the constructed C object will support and how it handles errors. Possible values are: =over 4 =item API::RESTv1_1 Provides support for the Twitter REST API version 1.1 methods. =item API::Search Deprecated. Use L in API::RESTv1_1 instead. =item AppAuth Provides L with methods, C and C. See L. Example: my $nt = Net::Twitter->new( traits => [ qw/AppAuth API::RESTv1_1/ ], consumer_key => 'my-consumer-key', consumer_secret => 'my-consumer-secret', ); $nt->request_access_token; say 'token: ', $nt->access_token; my $r = $nt->followers_ids({ screen_name => 'timtoady', cursor => -1, }); # good until invalidated, with ... $nt->invalidate_token =item AutoCursor C is a parameterized trait that provides an automatic loop for cursored calls, returning an ARRAY reference to the combined results. By default, it handles C and C. See L for details. =item InflateObjects When this optional trait is included, Net::Twitter inflates HASH refs returned by Twitter into objects with read accessors for each element. In addition, it inflates dates to L objects and URLs to L objects. Objects that include a C attribute also have a C method. For example, with C applied, the method returns an array of status objects: $r = $nt->friends_timeline; for my $status ( @$r ) { $r->user->screen_name; # same as $r->{user}{screen_name} # $created_at is a DateTime; $age is a DateTime::Duration my $age = DateTime->now - $r->created_at; # print an age in a similar style to the Twitter web site, e.g.: # less than a minute ago # about a minute ago # 6 minutes ago # 1 day ago # etc. print $r->relative_created_at; =item Legacy This trait provides backwards compatibility to C versions prior to 3.00. It implies the traits C, C, C, and C. It also provides additional functionality to ensure consistent behavior for applications written for use with legacy versions of C. In the current version, this trait is automatically included if the C option is not specified. This ensures backwards compatibility for existing applications using C versions prior to 3.00. See section L for more details. =item OAuth The C trait provides OAuth authentication rather than the default Basic Authentication for Twitter API method calls. See the L section and L for full documentation. =item RateLimit The C trait adds utility methods that return information about the current rate limit status. See L for details. =item RetryOnError The C trait automatically retries Twitter API calls with temporary failures. See L for details. =item WrapError C normally throws exceptions on error. When this trait is included, C returns undef when a method fails and makes the error available through method C. This is the way all errors were handled in Net::Twitter versions prior to version 3.00. =back Some examples of using the C parameter in C: # provide support for *only* the REST API; throw exceptions on error $nt = Net::Twitter->new(traits => ['API::RESTv1_1']); # provide support for both the REST and Search APIs; wrap errors $nt = Net::Twitter->new(traits => [qw/API::RESTv1_1 API::Search WrapError/]); # Provide legacy support for applications written with Net::Twitter # prior to version 3.0. $nt = Net::Twitter->new(traits => ['Legacy']); =item legacy A boolean. If set to 0, C constructs a C object implementing the REST API and throws exceptions on API method errors. Net::Twitter->new(legacy => 0); is a shortcut for: Net::Twitter->new(traits => ['API::RESTv1_1']); If set to 1, C constructs a C object with the C trait. Net::Twitter->new(legacy => 1); is a shortcut for: Net::Twitter->new(traits => ['Legacy']); =item username This is the username for Basic Authentication. NOTE: as of 31-Aug-2010, Twitter no longer supports Basic Authentication. Use OAuth instead. Other Twitter compatible services may, however, accept Basic Authentication, so support for it remains in C. =item password This is the password used for Basic Authentication. =item clientname The value for the C HTTP header. It defaults to "Perl Net::Twitter". Note: This option has nothing to do with the "via" application byline. =item clientver The value for the C HTTP header. It defaults to current version of the C module. =item clienturl The value for the C HTTP header. It defaults to the search.cpan.org page for the C distribution. =item useragent_class The C compatible class used internally by C. It defaults to "LWP::UserAgent". For L based applications, consider using "LWP::UserAgent::POE". =item useragent_args An HASH ref of arguments to pass to constructor of the class specified with C, above. It defaults to {} (an empty HASH ref). =item useragent The value for C HTTP header. It defaults to "Net::Twitter/4.01043 (Perl)". =item source Twitter on longer uses the C parameter. Support for it remains in C for any compatible services that may use it. It was originally used by Twitter to provide an "via" application byline. =item apiurl The URL for the Twitter API. This defaults to "http://api.twitter.com/1". This option is available when the C trait is included. =item apihost DEPRECATED - Setting the C is sufficient. =item apirealm A string containing the Twitter API realm used for Basic Authentication. It defaults to "Twitter API". This option is available when the C trait is included. =item identica If set to 1, C overrides the defaults for C, C, and C to "http://identi.ca/api", "identi.ca:80", and "Laconica API" respectively. It defaults to 0. This option is available when the C trait is included. =item consumer_key A string containing the OAuth consumer key provided by Twitter when an application is registered. This option is available when the C trait is included. =item consumer_secret A string containing the OAuth consumer secret. This option is available when the C trait is included. =item ssl If set to 1, an SSL connection will be used for all API calls. Defaults to 1. =item netrc (Optional) Sets the I key to look up in C<.netrc> to obtain credentials. If set to 1, Net::Twitter will use the value of the C option (below). # in .netrc machine api.twitter.com login YOUR_TWITTER_USER_NAME password YOUR_TWITTER_PASSWORD machine semifor.twitter.com login semifor password SUPERSECRET # in your perl program $nt = Net::Twitter->new(netrc => 1); $nt = Net::Twitter->new(netrc => 'semifor.twitter.com'); =item netrc_machine (Optional) Sets the C entry to look up in C<.netrc> when C< 1>> is used. Defaults to C. =item decode_html_entities Twitter encodes HTML entities in the C field of statuses. Set this option to 1 to have them automatically decoded. Default 0. =back =item credentials($username, $password) Set the credentials for Basic Authentication. This is helpful for managing multiple accounts. =item ua Provides access to the constructed user agent object used internally by C. Use it with caution. =back =head1 AUTHENTICATION With REST API version 1.1, all API calls require OAuth. Since 31-Aug-2010, version 1 required OAuth requests requiring authentication. Other Twitter compatible services, like Identi.ca, accept Basic Authentication. So, C provides support for both. To set up OAuth, include the C and C options to L. When they are provided, the C trait will be automatically included. See L for more information on using OAuth, including examples. To set up Basic Authentication in C, provide the C and C options to L or call the L method. In addition to the arguments specified for each API method described below, an additional C<-authenticate> parameter can be passed. To request an C header, pass C<< -authenticate => 1 >>; to suppress an authentication header, pass C<< -authenticate => 0 >>. Even if requested, an Authorization header will not be added if there are no user credentials (username and password for Basic Authentication; access tokens for OAuth). This is probably only useful for non-Twitter sites that use the Twitter API and support unauthenticated calls. =head1 API METHODS AND ARGUMENTS Most Twitter API methods take parameters. All Net::Twitter API methods will accept a HASH ref of named parameters as specified in the Twitter API documentation. For convenience, many Net::Twitter methods accept simple positional arguments. The positional parameter passing style is optional; you can always use the named parameters in a HASH reference if you prefer. You may pass any number of required parameters as positional parameters. You must pass them in the order specified in the documentation for each method. Optional parameters must be passed as named parameters in a HASH reference. The HASH reference containing the named parameters must be the final parameter to the method call. Any required parameters not passed as positional parameters, must be included in the named parameter HASH reference. For example, the REST API method C has one required parameter, C. You can call C with a HASH ref argument: $nt->update({ status => 'Hello world!' }); Or, you can use the convenient, positional parameter form: $nt->update('Hello world!'); The C method also has an optional parameter, C. To use it, you B use the HASH ref form: $nt->update({ status => 'Hello world!', in_reply_to_status_id => $reply_to }); You may use the convenient positional form for the required C parameter with the optional parameters specified in the named parameter HASH reference: $nt->update('Hello world!', { in_reply_to_status_id => $reply_to }); Convenience form is provided for the required parameters of all API methods. So, these two calls are equivalent: $nt->friendship_exists({ user_a => $fred, user_b => $barney }); $nt->friendship_exists($fred, $barney); Many API methods have aliases. You can use the API method name, or any of its aliases, as you prefer. For example, these calls are all equivalent: $nt->friendship_exists($fred, $barney); $nt->relationship_exists($fred, $barney); $nt->follows($fred, $barney); Aliases support both the HASH ref and convenient forms: $nt->follows({ user_a => $fred, user_b => $barney }); =head2 Cursors and Paging Some methods return partial results a page at a time. Originally, methods that returned partial results used a C parameter. A more recent addition to the Twitter API for retrieving multiple pages uses the C parameter. Usually, a method uses either the C parameter or the C parameter, but not both. There have been exceptions to this rule when Twitter deprecates the use of C for a method in favor of C. In that case, both methods may work during a transition period. So, if a method supports both, you should always use the C parameter. =head3 Paging For methods that support paging, the first page is returned by passing C<< page => 1 >>, the second page by passing C<< page => 2 >>, etc. If no C parameter is passed, the first page is returned. Here's an example that demonstrates how to obtain all favorites in a loop: my @favs; for ( my $page = 1; ; ++$page ) { my $r = $nt->favorites({ page => $page }); last unless @$r; push @favs, @$r; } =head3 Cursors Cursoring employs a different strategy. To obtain the first page of results, pass C<< cursor => -1 >>. Twitter returns a reference to a hash that includes entries C, C, and an entry with a reference to an array containing a page of the requested items. The key for the array reference will be named C, C, or something similar depending upon the type of returned items. For example, when C parameter is used with the C method, the returned in hash entry C. The C value can be used in a subsequent call to obtain the next page of results. When you have obtained the last page of results, C will be 0. Likewise, you can use the value for C to obtain the previous page of results. When you have obtained the first page, C will be 0. Here's an example that demonstrates how to obtain all follower IDs in a loop using the C parameter: my @ids; for ( my $cursor = -1, my $r; $cursor; $cursor = $r->{next_cursor} ) { $r = $nt->followers_ids({ cursor => $cursor }); push @ids, @{ $r->{ids} }; } =head2 Synthetic Arguments In addition to the arguments described in the Twitter API Documentation for each API method, Net::Twitter supports additional I arguments. =over 4 =item -authenticate When set to 1, Net::Twitter will provide an Authorization header for the API call; when set to 0, it will suppress the Authentication header. This argument overrides the defined authentication behavior for the API method. It is probably only useful for the C method which returns different values for authenticated and unauthenticated calls. See L for more details. =item -since API methods that accept the C argument will also accept the synthetic C<-since> argument, instead. C<-since> may be a C object, an epoch time (the number of seconds since the system epoch), or a string in the same format returned by Twitter for the C attribute. Only statuses with a C time greater than C<-since> will be returned by the API call. =item -legacy_lists_api This option is only effective when the legacy C trait is applied. Passing C<-legacy_lists_api> set to 0 for lists methods will use the new lists endpoints and semantics. This will facilitate upgrading an application to use the new lists api methods. When the C trait is not applied, this option is ignored. =back =head1 REST API Methods These methods are provided when trait C is included in the C option to C. =head2 Common Parameters =over 4 =item id Several of these methods accept a user ID as the C parameter. The user ID can be either a screen name, or the users numeric ID. To disambiguate, use the C or C parameters, instead. For example, These calls are equivalent: $nt->create_friend('perl_api'); # screen name $nt->create_friend(1564061); # numeric ID $nt->create_friend({ id => 'perl_api' }); $nt->create_friend({ screen_name => 'perl_api' }); $nt->create_friend({ user_id => 1564061 }); However user_id 911 and screen_name 911 are separate Twitter accounts. These calls are NOT equivalent: $nt->create_friend(911); # interpreted as screen name $nt->create_friend({ user_id => 911 }); # screen name: richellis Whenever the C parameter is required and C and C are also parameters, using any one of them satisfies the requirement. =item skip_user The timeline methods all accept an optional C parameter. When set to a true value, the statuses returned in a timeline will not contain an entire embedded user HASH. Instead, the user node will contain only an C element to indicate the numerical ID of the Twitter user that sent the status. =back =head2 Methods =over 4 =item B =over 4 =item Parameters: I =item Required: I =back Returns the current trend, geo and sleep time information for the authenticating user. Returns: HashRef Twitter API documentation: L =item B B =over 4 =item Parameters: I =item Required: I =back Returns the current count of friends, followers, updates (statuses) and favorites of the authenticating user. Returns: HashRef =item B =over 4 =item Parameters: list_id, slug, user_id, screen_name, owner_screen_name, owner_id =item Required: I =back Add a member to a list. The authenticated user must own the list to be able to add members to it. Note that lists can't have more than 500 members. Returns: User Twitter API documentation: L =item B =item B =over 4 =item Parameters: name, contained_within, token, lat, long, attribute:street_address, callback =item Required: name, contained_within, token, lat, long =back Creates a new place object at the given latitude and longitude. Before creating a place you need to query C with the latitude, longitude and name of the place you wish to create. The query will return an array of places which are similar to the one you wish to create, and a token. If the place you wish to create isn't in the returned array you can use the token with this method to create a new one. Returns: Place Twitter API documentation: L =item B B =item B =over 4 =item Parameters: id, user_id, screen_name, include_entities =item Required: id =back Returns if the authenticating user is blocking a target user. Will return the blocked user's object if a block exists, and error with HTTP 404 response code otherwise. Returns: BasicUser =item B =item alias: blocks_list =over 4 =item Parameters: cursor, include_entities, skip_status =item Required: I =back Returns an array of user objects that the authenticating user is blocking. Returns: ArrayRef[BasicUser] Twitter API documentation: L =item B =item alias: blocks_ids =over 4 =item Parameters: cursor, stringify_ids =item Required: I =back Returns an array of numeric user ids the authenticating user is blocking. Returns: ArrayRef[Int] Twitter API documentation: L =item B B =over 4 =item Parameters: user_id, screen_name, include_entities, skip_satus =item Required: I =back Returns an array of users that the specified user can contribute to. Returns: ArrayRef[User] =item B B =over 4 =item Parameters: user_id, screen_name, include_entities, skip_satus =item Required: I =back Returns an array of users who can contribute to the specified account. Returns: ArrayRef[User] =item B =item B =over 4 =item Parameters: user_id, screen_name, include_entities, skip_status =item Required: id =back Blocks the user specified in the C or C parameter as the authenticating user. Returns the blocked user when successful. You can find out more about blocking in the Twitter Support Knowledge Base. Returns: BasicUser Twitter API documentation: L =item B =item B =over 4 =item Parameters: id, include_entities =item Required: id =back Favorites the status specified in the ID parameter as the authenticating user. Returns the favorite status when successful. Returns: Status Twitter API documentation: L =item B =item alias: follow =item alias: follow_new =item alias: create_friendship =over 4 =item Parameters: user_id, screen_name, follow =item Required: I =back Follows the user specified in the C or C parameter as the authenticating user. Returns the befriended user when successful. Returns a string describing the failure condition when unsuccessful. Returns: BasicUser Twitter API documentation: L =item B =item B =over 4 =item Parameters: list_id, slug, name, mode, description, owner_screen_name, owner_id =item Required: name =back Creates a new list for the authenticated user. Note that you can't create more than 20 lists per account. Returns: List Twitter API documentation: L =item B =item B =over 4 =item Parameters: media_id, alt_text =item Required: media_id =back Adds metadata -- alt text, in particular -- to a previously uploaded media object, specified by its ID. (One knows this ID via the return value of the preceding C call.) The C parameter must have as its value a hashref containing a single key-value pair. The key must be C, and the value is the alt text to assign to the media object. The text must be 400 characters or fewer in length. Returns: HashRef Twitter API documentation: L =item B =item B =over 4 =item Parameters: user_id, screen_name =item Required: id =back Mutes the user specified in the C or C parameter as the authenticating user. Returns the muted user when successful. You can find out more about muting in the Twitter Support Knowledge Base. Returns: BasicUser Twitter API documentation: L =item B =item B =over 4 =item Parameters: query =item Required: query =back Creates a saved search for the authenticated user. Returns: SavedSearch Twitter API documentation: L =item B =over 4 =item Parameters: owner_screen_name, owner_id, list_id, slug =item Required: I =back Deletes the specified list. The authenticated user must own the list to be able to destroy it. Returns: List Twitter API documentation: L =item B =item alias: remove_list_member =over 4 =item Parameters: list_id, slug, user_id, screen_name, owner_screen_name, owner_id =item Required: I =back Removes the specified member from the list. The authenticated user must be the list's owner to remove members from the list. Returns: User Twitter API documentation: L =item B =item B =over 4 =item Parameters: user_id, screen_name, include_entities, skip_status =item Required: id =back Un-blocks the user specified in the C or C parameter as the authenticating user. Returns the un-blocked user when successful. Returns: BasicUser Twitter API documentation: L =item B =item B =over 4 =item Parameters: id, include_entities =item Required: id =back Destroys the direct message specified in the required ID parameter. The authenticating user must be the recipient of the specified direct message. Important: this method requires an access token with RWD (read, write, and direct message) permissions. Returns: DirectMessage Twitter API documentation: L =item B =item B =over 4 =item Parameters: id, include_entities =item Required: id =back Un-favorites the status specified in the ID parameter as the authenticating user. Returns the un-favorited status. Returns: Status Twitter API documentation: L =item B =item B =item alias: unfollow =item alias: destroy_friendship =over 4 =item Parameters: user_id, screen_name =item Required: id =back Discontinues friendship with the user specified in the C or C parameter as the authenticating user. Returns the un-friended user when successful. Returns a string describing the failure condition when unsuccessful. Returns: BasicUser Twitter API documentation: L =item B =item B =over 4 =item Parameters: user_id, screen_name =item Required: id =back Un-mutes the user specified in the C or C parameter as the authenticating user. Returns the un-muted user when successful. Returns: BasicUser Twitter API documentation: L =item B =item B =item alias: delete_saved_search =over 4 =item Parameters: id =item Required: id =back Destroys a saved search. The search, specified by C, must be owned by the authenticating user. Returns: SavedSearch Twitter API documentation: L =item B =item B =over 4 =item Parameters: id, trim_user =item Required: id =back Destroys the status specified by the required ID parameter. The authenticating user must be the author of the specified status. Returns: Status Twitter API documentation: L =item B =over 4 =item Parameters: since_id, max_id, count, page, include_entities, skip_status =item Required: I =back Returns a list of the 20 most recent direct messages sent to the authenticating user including detailed information about the sending and recipient users. Important: this method requires an access token with RWD (read, write, and direct message) permissions. Returns: ArrayRef[DirectMessage] Twitter API documentation: L =item B B =item B =over 4 =item Parameters: id, screen_name, include_entities =item Required: id =back Disables notifications for updates from the specified user to the authenticating user. Returns the specified user when successful. Returns: BasicUser =item B B =item B =over 4 =item Parameters: id, screen_name, include_entities =item Required: id =back Enables notifications for updates from the specified user to the authenticating user. Returns the specified user when successful. Returns: BasicUser =item B B =over 4 =item Parameters: I =item Required: I =back Ends the session of the authenticating user, returning a null cookie. Use this method to sign users out of client-facing applications like widgets. Returns: Error =item B =over 4 =item Parameters: user_id, screen_name, count, since_id, max_id, include_entities =item Required: I =back Returns the 20 most recent favorite statuses for the authenticating user or user specified by the ID parameter. Returns: ArrayRef[Status] Twitter API documentation: L =item B =item alias: followers_list =over 4 =item Parameters: user_id, screen_name, cursor =item Required: I =back Returns a cursored collection of user objects for users following the specified user. Returns: HashRef Twitter API documentation: L =item B =over 4 =item Parameters: user_id, screen_name, cursor, stringify_ids =item Required: I =back Returns a reference to an array of numeric IDs for every user following the specified user. The order of the IDs may change from call to call. To obtain the screen names, pass the arrayref to L. Use the optional C parameter to retrieve IDs in pages of 5000. When the C parameter is used, the return value is a reference to a hash with keys C, C, and C. The value of C is a reference to an array of IDS of the user's followers. Set the optional C parameter to -1 to get the first page of IDs. Set it to the prior return's value of C or C to page forward or backwards. When there are no prior pages, the value of C will be 0. When there are no subsequent pages, the value of C will be 0. Returns: HashRef|ArrayRef[Int] Twitter API documentation: L =item B =item alias: friends_list =over 4 =item Parameters: user_id, screen_name, cursor =item Required: I =back Returns a cursored collection of user objects for users followed by the specified user. Returns: HashRef Twitter API documentation: L =item B =item alias: following_ids =over 4 =item Parameters: user_id, screen_name, cursor, stringify_ids =item Required: I =back Returns a reference to an array of numeric IDs for every user followed by the specified user. The order of the IDs is reverse chronological. Use the optional C parameter to retrieve IDs in pages of 5000. When the C parameter is used, the return value is a reference to a hash with keys C, C, and C. The value of C is a reference to an array of IDS of the user's friends. Set the optional C parameter to -1 to get the first page of IDs. Set it to the prior return's value of C or C to page forward or backwards. When there are no prior pages, the value of C will be 0. When there are no subsequent pages, the value of C will be 0. Returns: HashRef|ArrayRef[Int] Twitter API documentation: L =item B B =item alias: following_timeline =over 4 =item Parameters: since_id, max_id, count, exclude_replies, contributor_details, include_entities, trim_user =item Required: I =back Returns the 20 most recent statuses, including retweets, posted by the authenticating user and that user's friends. Returns: ArrayRef[Status] =item B B =item B =item alias: relationship_exists =item alias: follows =over 4 =item Parameters: user_id_a, user_id_b, screen_name_a, screen_name_b, user_a, user_b =item Required: user_a, user_b =back This method is provided for backwards compatibility with Twitter API V1.0. Twitter API V1.1 does not provide an endpoint for this call. Instead, C is called, the result is inspected, and an appropriate value is returned which can be evaluated in a boolean context. Tests for the existence of friendship between two users. Will return true if user_a follows user_b, otherwise will return false. Use of C and C is deprecated. It has been preserved for backwards compatibility, and is used for the two-argument positional form: $nt->friendship_exists($user_a, $user_b); Instead, you should use one of the named argument forms: $nt->friendship_exists({ user_id_a => $id1, user_id_b => $id2 }); $nt->friendship_exists({ screen_name_a => $name1, screen_name_b => $name2 }); Consider using C instead. Returns: Bool =item B =item alias: incoming_friendships =over 4 =item Parameters: cursor, stringify_ids =item Required: I =back Returns an HASH ref with an array of numeric IDs in the C element for every user who has a pending request to follow the authenticating user. Returns: HashRef Twitter API documentation: L =item B =item alias: outgoing_friendships =over 4 =item Parameters: cursor, stringify_ids =item Required: I =back Returns an HASH ref with an array of numeric IDs in the C element for every protected user for whom the authenticating user has a pending follow request. Returns: HashRef Twitter API documentation: L =item B =item B =over 4 =item Parameters: place_id =item Required: place_id =back Returns details of a place returned from the C method. Returns: HashRef Twitter API documentation: L =item B =over 4 =item Parameters: lat, long, query, ip, granularity, accuracy, max_results, contained_within, attribute:street_address, callback =item Required: I =back Search for places that can be attached to a statuses/update. Given a latitude and a longitude pair, an IP address, or a name, this request will return a list of all the valid places that can be used as the place_id when updating a status. Conceptually, a query can be made from the user's location, retrieve a list of places, have the user validate the location he or she is at, and then send the ID of this location with a call to statuses/update. This is the recommended method to use find places that can be attached to statuses/update. Unlike geo/reverse_geocode which provides raw data access, this endpoint can potentially re-order places with regards to the user who is authenticated. This approach is also preferred for interactive place matching with the user. Returns: HashRef Twitter API documentation: L =item B =over 4 =item Parameters: I =item Required: I =back Returns the current configuration used by Twitter including twitter.com slugs which are not usernames, maximum photo resolutions, and t.co URL lengths. It is recommended applications request this endpoint when they are loaded, but no more than once a day. Returns: HashRef Twitter API documentation: L =item B =over 4 =item Parameters: I =item Required: I =back Returns the list of languages supported by Twitter along with their ISO 639-1 code. The ISO 639-1 code is the two letter value to use if you include lang with any of your requests. Returns: ArrayRef[Lanugage] Twitter API documentation: L =item B =item alias: show_list =over 4 =item Parameters: list_id, slug, owner_screen_name, owner_id =item Required: I =back Returns the specified list. Private lists will only be shown if the authenticated user owns the specified list. Returns: List Twitter API documentation: L =item B =item alias: list_lists =item alias: all_subscriptions =over 4 =item Parameters: user_id, screen_name, reverse =item Required: I =back Returns all lists the authenticating or specified user subscribes to, including their own. The user is specified using the user_id or screen_name parameters. If no user is given, the authenticating user is used. A maximum of 100 results will be returned by this call. Subscribed lists are returned first, followed by owned lists. This means that if a user subscribes to 90 lists and owns 20 lists, this method returns 90 subscriptions and 10 owned lists. The reverse method returns owned lists first, so with C 1>, 20 owned lists and 80 subscriptions would be returned. If your goal is to obtain every list a user owns or subscribes to, use and/or C instead. Returns: Hashref Twitter API documentation: L =item B =over 4 =item Parameters: I =item Required: I =back Returns Twitter's privacy policy. Returns: HashRef Twitter API documentation: L =item B =over 4 =item Parameters: I =item Required: I =back Returns the Twitter Terms of Service. These are not the same as the Developer Rules of the Road. Returns: HashRef Twitter API documentation: L =item B =over 4 =item Parameters: since_id, max_id, count, exclude_replies, contributor_details, include_entities, trim_user =item Required: I =back Returns the 20 most recent statuses, including retweets, posted by the authenticating user and that user's friends. Returns: ArrayRef[Status] Twitter API documentation: L =item B =over 4 =item Parameters: list_id, slug, owner_screen_name, owner_id, cursor, include_entities, skip_status =item Required: I =back Returns the members of the specified list. Private list members will only be shown if the authenticated user owns the specified list. Returns: Hashref Twitter API documentation: L =item B =over 4 =item Parameters: user_id, screen_name, cursor, filter_to_owned_lists =item Required: I =back Returns the lists the specified user has been added to. If user_id or screen_name are not provided the memberships for the authenticating user are returned. Returns: Hashref Twitter API documentation: L =item B =over 4 =item Parameters: user_id, screen_name, count, cursor =item Required: I =back Obtain a collection of the lists owned by the specified Twitter user. Private lists will only be shown if the authenticated user is also the owner of the lists. Returns: ArrayRef[List] Twitter API documentation: L =item B =over 4 =item Parameters: list_id, slug, owner_screen_name, owner_id, since_id, max_id, count, include_entities, include_rts =item Required: I =back Returns tweet timeline for members of the specified list. Historically, retweets were not available in list timeline responses but you can now use the include_rts=true parameter to additionally receive retweet objects. Returns: ArrayRef[Status] Twitter API documentation: L =item B =over 4 =item Parameters: list_id, slug, owner_screen_name, owner_id, cursor, include_entities, skip_status =item Required: I =back Returns the subscribers of the specified list. Private list subscribers will only be shown if the authenticated user owns the specified list. Returns: Hashref Twitter API documentation: L =item B =item alias: subscriptions =over 4 =item Parameters: user_id, screen_name, count, cursor =item Required: I =back Obtain a collection of the lists the specified user is subscribed to, 20 lists per page by default. Does not include the user's own lists. Returns: ArrayRef[List] Twitter API documentation: L =item B =over 4 =item Parameters: user_id, screen_name =item Required: I =back Returns the relationship of the authenticating user to the comma separated list or ARRAY ref of up to 100 screen_names or user_ids provided. Values for connections can be: following, following_requested, followed_by, none. Requires authentication. Returns: ArrayRef Twitter API documentation: L =item B =item B =over 4 =item Parameters: id, include_entities, trim_user, map =item Required: id =back Returns a hash reference of tweets from an arbitrary set of ids. Returns: HashRef Twitter API documentation: L =item B =over 4 =item Parameters: user_id, screen_name, include_entities =item Required: I =back Return up to 100 users worth of extended information, specified by either ID, screen name, or combination of the two. The author's most recent status (if the authenticating user has permission) will be returned inline. This method is rate limited to 1000 calls per hour. This method will accept user IDs or screen names as either a comma delimited string, or as an ARRAY ref. It will also accept arguments in the normal HASHREF form or as a simple list of named arguments. I.e., any of the following forms are acceptable: $nt->lookup_users({ user_id => '1234,6543,3333' }); $nt->lookup_users(user_id => '1234,6543,3333'); $nt->lookup_users({ user_id => [ 1234, 6543, 3333 ] }); $nt->lookup_users({ screen_name => 'fred,barney,wilma' }); $nt->lookup_users(screen_name => ['fred', 'barney', 'wilma']); $nt->lookup_users( screen_name => ['fred', 'barney' ], user_id => '4321,6789', ); Returns: ArrayRef[User] Twitter API documentation: L =item B =item alias: add_list_members =over 4 =item Parameters: list_id, slug, owner_screen_name, owner_id =item Required: I =back Adds multiple members to a list, by specifying a reference to an array or a comma-separated list of member ids or screen names. The authenticated user must own the list to be able to add members to it. Note that lists can't have more than 500 members, and you are limited to adding up to 100 members to a list at a time with this method. Returns: List Twitter API documentation: L =item B =item alias: remove_list_members =over 4 =item Parameters: list_id, slug, user_id, screen_name, owner_screen_name, owner_id =item Required: I =back Removes multiple members from a list, by specifying a reference to an array of member ids or screen names, or a string of comma separated user ids or screen names. The authenticated user must own the list to be able to remove members from it. Note that lists can't have more than 500 members, and you are limited to removing up to 100 members to a list at a time with this method. Please note that there can be issues with lists that rapidly remove and add memberships. Take care when using these methods such that you are not too rapidly switching between removals and adds on the same list. Returns: List Twitter API documentation: L =item B =item alias: replies =item alias: mentions_timeline =over 4 =item Parameters: since_id, max_id, count, trim_user, include_entities, contributor_details =item Required: I =back Returns the 20 most recent mentions (statuses containing @username) for the authenticating user. Returns: ArrayRef[Status] Twitter API documentation: L =item B =item B =item alias: muting_ids =item alias: muted_ids =over 4 =item Parameters: cursor =item Required: I =back Returns an array of numeric user ids the authenticating user has muted. Returns: ArrayRef[Int] Twitter API documentation: L =item B =item alias: mutes_list =over 4 =item Parameters: cursor, include_entities, skip_status =item Required: I =back Returns an array of user objects that the authenticating user is muting. Returns: ArrayRef[BasicUser] Twitter API documentation: L =item B =item B =over 4 =item Parameters: user_id, screen_name, text =item Required: text =back Sends a new direct message to the specified user from the authenticating user. Requires both the user and text parameters. Returns the sent message when successful. In order to support numeric screen names, the C or C parameters may be used instead of C. Important: this method requires an access token with RWD (read, write, and direct message) permissions. Returns: DirectMessage Twitter API documentation: L =item B =item alias: no_retweets_ids =over 4 =item Parameters: I =item Required: I =back Returns an ARRAY ref of user IDs for which the authenticating user does not want to receive retweets. Returns: ArrayRef[UserIDs] Twitter API documentation: L =item B =over 4 =item Parameters: id, url, maxwidth, hide_media, hide_thread, omit_script, align, related, lang =item Required: I =back Returns information allowing the creation of an embedded representation of a Tweet on third party sites. See the L specification for information about the response format. While this endpoint allows a bit of customization for the final appearance of the embedded Tweet, be aware that the appearance of the rendered Tweet may change over time to be consistent with Twitter's L. Do not rely on any class or id parameters to stay constant in the returned markup. Returns: Status Twitter API documentation: L =item B =over 4 =item Parameters: user_id, screen_name =item Required: I =back Returns a hash reference mapping available size variations to URLs that can be used to retrieve each variation of the banner. Returns: HashRef Twitter API documentation: L =item B =item B =over 4 =item Parameters: resources =item Required: I =back Returns the remaining number of API requests available to the authenticated user before the API limit is reached for the current hour. Use C<< ->rate_limit_status({ authenticate => 0 }) >> to force an unauthenticated call, which will return the status for the IP address rather than the authenticated user. (Note: for a web application, this is the server's IP address.) Returns: RateLimitStatus Twitter API documentation: L =item B B =item B =over 4 =item Parameters: id =item Required: id =back If available, returns an array of replies and mentions related to the specified status. There is no guarantee there will be any replies or mentions in the response. This method is only available to users who have access to #newtwitter. Requires authentication. Returns: ArrayRef[Status] =item B =over 4 =item Parameters: I =item Required: I =back Removes the uploaded profile banner for the authenticating user. Returns: Nothing Twitter API documentation: L =item B =item B =over 4 =item Parameters: user_id, screen_name =item Required: id =back The user specified in the id is blocked by the authenticated user and reported as a spammer. Returns: User Twitter API documentation: L =item B =item B =over 4 =item Parameters: idtrim_user =item Required: id =back Retweets a tweet. Returns: Status Twitter API documentation: L =item B B =item B =over 4 =item Parameters: id, count, page, trim_user, include_entities =item Required: id =back Returns up to 100 users who retweeted the status identified by C. Returns: ArrayRef[User] =item B B =item B =over 4 =item Parameters: id, count, page, trim_user, include_entities =item Required: id =back Returns the IDs of up to 100 users who retweeted the status identified by C. Returns: ArrayRef[User] =item B B =over 4 =item Parameters: since_id, max_id, count, page, trim_user, include_entities =item Required: I =back Returns the 20 most recent retweets posted by the authenticating user. Returns: ArrayRef[Status] =item B B =item B =over 4 =item Parameters: id, user_id, screen_name =item Required: id =back Returns the 20 most recent retweets posted by the specified user. The user is specified using the user_id or screen_name parameters. This method is identical to C except you can choose the user to view. Does not require authentication, unless the user is protected. Returns: ArrayRef =item B B =over 4 =item Parameters: since_id, max_id, count, page =item Required: I =back Returns the 20 most recent retweets posted by the authenticating user's friends. Returns: ArrayRef[Status] =item B B =item B =over 4 =item Parameters: id, user_id, screen_name =item Required: id =back Returns the 20 most recent retweets posted by users the specified user follows. The user is specified using the user_id or screen_name parameters. This method is identical to C except you can choose the user to view. Does not require authentication, unless the user is protected. Returns: ArrayRef =item B =item B =over 4 =item Parameters: id, cursor, stringify_ids =item Required: id =back Returns a collection of up to 100 user IDs belonging to users who have retweeted the tweet specified by the id parameter. This method offers similar data to C and replaces API v1's C method. Returns: HashRef Twitter API documentation: L =item B =item B =over 4 =item Parameters: id, count, trim_user =item Required: id =back Returns up to 100 of the first retweets of a given tweet. Returns: Arrayref[Status] Twitter API documentation: L =item B =item alias: retweeted_of_me =over 4 =item Parameters: since_id, max_id, count, trim_user, include_entities, include_user_entities =item Required: I =back Returns the 20 most recent tweets of the authenticated user that have been retweeted by others. Returns: ArrayRef[Status] Twitter API documentation: L =item B =item B =over 4 =item Parameters: lat, long, accuracy, granularity, max_results, callback =item Required: lat, long =back Search for places (cities and neighborhoods) that can be attached to a statuses/update. Given a latitude and a longitude, return a list of all the valid places that can be used as a place_id when updating a status. Conceptually, a query can be made from the user's location, retrieve a list of places, have the user validate the location he or she is at, and then send the ID of this location up with a call to statuses/update. There are multiple granularities of places that can be returned -- "neighborhoods", "cities", etc. At this time, only United States data is available through this method. =over 4 =item lat Required. The latitude to query about. Valid ranges are -90.0 to +90.0 (North is positive) inclusive. =item long Required. The longitude to query about. Valid ranges are -180.0 to +180.0 (East is positive) inclusive. =item accuracy Optional. A hint on the "region" in which to search. If a number, then this is a radius in meters, but it can also take a string that is suffixed with ft to specify feet. If this is not passed in, then it is assumed to be 0m. If coming from a device, in practice, this value is whatever accuracy the device has measuring its location (whether it be coming from a GPS, WiFi triangulation, etc.). =item granularity Optional. The minimal granularity of data to return. If this is not passed in, then C is assumed. C can also be passed. =item max_results Optional. A hint as to the number of results to return. This does not guarantee that the number of results returned will equal max_results, but instead informs how many "nearby" results to return. Ideally, only pass in the number of places you intend to display to the user here. =back Returns: HashRef Twitter API documentation: L =item B =over 4 =item Parameters: I =item Required: I =back Returns the authenticated user's saved search queries. Returns: ArrayRef[SavedSearch] Twitter API documentation: L =item B =item B =over 4 =item Parameters: q, count, callback, lang, locale, rpp, since_id, max_id, until, geocode, result_type, include_entities =item Required: q =back Returns a HASH reference with some meta-data about the query including the C, C, and C. The statuses are returned in C. To iterate over the results, use something similar to: my $r = $nt->search($search_term); for my $status ( @{$r->{statuses}} ) { print "$status->{text}\n"; } Returns: HashRef Twitter API documentation: L =item B =item alias: direct_messages_sent =over 4 =item Parameters: since_id, max_id, page, count, include_entities =item Required: I =back Returns a list of the 20 most recent direct messages sent by the authenticating user including detailed information about the sending and recipient users. Important: this method requires an access token with RWD (read, write, and direct message) permissions. Returns: ArrayRef[DirectMessage] Twitter API documentation: L =item B =item B =over 4 =item Parameters: id =item Required: id =back Returns a single direct message, specified by an id parameter. Like the C request, this method will include the user objects of the sender and recipient. Requires authentication. Important: this method requires an access token with RWD (read, write, and direct message) permissions. Returns: HashRef Twitter API documentation: L =item B =item alias: show_relationship =over 4 =item Parameters: source_id, source_screen_name, target_id, target_screen_name =item Required: I =back Returns detailed information about the relationship between two users. Returns: Relationship Twitter API documentation: L =item B =item alias: is_list_member =over 4 =item Parameters: owner_screen_name, owner_id, list_id, slug, user_id, screen_name, include_entities, skip_status =item Required: I =back Check if the specified user is a member of the specified list. Returns the user or undef. Returns: Maybe[User] Twitter API documentation: L =item B =item alias: is_list_subscriber =item alias: is_subscriber_lists =over 4 =item Parameters: owner_screen_name, owner_id, list_id, slug, user_id, screen_name, include_entities, skip_status =item Required: I =back Returns the user if they are a subscriber. Returns: User Twitter API documentation: L =item B =item B =over 4 =item Parameters: id =item Required: id =back Retrieve the data for a saved search, by C, owned by the authenticating user. Returns: SavedSearch Twitter API documentation: L =item B =item B =over 4 =item Parameters: id, trim_user, include_entities, include_my_retweet =item Required: id =back Returns a single status, specified by the id parameter. The status's author will be returned inline. Returns: Status Twitter API documentation: L =item B =over 4 =item Parameters: user_id, screen_name, include_entities =item Required: I =back Returns extended information of a given user, specified by ID or screen name as per the required id parameter. This information includes design settings, so third party developers can theme their widgets according to a given user's preferences. You must be properly authenticated to request the page of a protected user. Returns: ExtendedUser Twitter API documentation: L =item B =item B =over 4 =item Parameters: lat, long, name, contained_within, attribute:street_address, callback =item Required: lat, long, name =back Locates places near the given coordinates which are similar in name. Conceptually you would use this method to get a list of known places to choose from first. Then, if the desired place doesn't exist, make a request to C to create a new one. The token contained in the response is the token needed to be able to create a new place. Returns: HashRef Twitter API documentation: L =item B =over 4 =item Parameters: owner_screen_name, owner_id, list_id, slug =item Required: I =back Subscribes the authenticated user to the specified list. Returns: List Twitter API documentation: L =item B =over 4 =item Parameters: I =item Required: I =back Returns the list of suggested user categories. The category slug can be used in the C API method get the users in that category . Does not require authentication. Returns: ArrayRef Twitter API documentation: L =item B B =over 4 =item Parameters: I =item Required: I =back Returns the string "ok" status code. Returns: Hash =item B =over 4 =item Parameters: I =item Required: I =back Returns the locations with trending topic information. The response is an array of "locations" that encode the location's WOEID (a Yahoo! Where On Earth ID L) and some other human-readable information such as a the location's canonical name and country. For backwards compatibility, this method accepts optional C and C parameters. You should call C directly, instead. Use the WOEID returned in the location object to query trends for a specific location. Returns: ArrayRef[Location] Twitter API documentation: L =item B =over 4 =item Parameters: lat, long =item Required: I =back Returns the locations with trending topic information. The response is an array of "locations" that encode the location's WOEID (a Yahoo! Where On Earth ID L) and some other human-readable information such as a the location's canonical name and country. The results are sorted by distance from that location, nearest to farthest. Use the WOEID returned in the location object to query trends for a specific location. Returns: ArrayRef[Location] Twitter API documentation: L =item B B =item B =over 4 =item Parameters: exclude =item Required: I =back Returns the current top ten trending topics on Twitter. The response includes the time of the request, the name of each trending topic, and query used on Twitter Search results page for that topic. Returns: HashRef =item B B =over 4 =item Parameters: date, exclude =item Required: I =back Returns the top 20 trending topics for each hour in a given day. Returns: HashRef =item B =item B =item alias: trends_location =over 4 =item Parameters: id, exclude =item Required: id =back Returns the top 10 trending topics for a specific WOEID. The response is an array of "trend" objects that encode the name of the trending topic, the query parameter that can be used to search for the topic on Search, and the direct URL that can be issued against Search. This information is cached for five minutes, and therefore users are discouraged from querying these endpoints faster than once every five minutes. Global trends information is also available from this API by using a WOEID of 1. Returns: ArrayRef[Trend] Twitter API documentation: L =item B B =over 4 =item Parameters: date, exclude =item Required: I =back Returns the top 30 trending topics for each day in a given week. Returns: HashRef =item B =over 4 =item Parameters: list_id, slug, owner_screen_name, owner_id =item Required: I =back Unsubscribes the authenticated user from the specified list. Returns: List Twitter API documentation: L =item B =item B =over 4 =item Parameters: attachment_url, display_coordinates, in_reply_to_status_id, lat, long, media_ids, place_id, status, trim_user =item Required: status =back Updates the authenticating user's status. Requires the status parameter specified. A status update with text identical to the authenticating user's current status will be ignored. =over 4 =item status Required. The text of your status update. URL encode as necessary. Statuses over 140 characters will cause a 403 error to be returned from the API. =item in_reply_to_status_id Optional. The ID of an existing status that the update is in reply to. o Note: This parameter will be ignored unless the author of the tweet this parameter references is mentioned within the status text. Therefore, you must include @username, where username is the author of the referenced tweet, within the update. =item lat Optional. The location's latitude that this tweet refers to. The valid ranges for latitude is -90.0 to +90.0 (North is positive) inclusive. This parameter will be ignored if outside that range, if it is not a number, if geo_enabled is disabled, or if there not a corresponding long parameter with this tweet. =item long Optional. The location's longitude that this tweet refers to. The valid ranges for longitude is -180.0 to +180.0 (East is positive) inclusive. This parameter will be ignored if outside that range, if it is not a number, if geo_enabled is disabled, or if there not a corresponding lat parameter with this tweet. =item place_id Optional. The place to attach to this status update. Valid place_ids can be found by querying C. =item display_coordinates Optional. By default, geo-tweets will have their coordinates exposed in the status object (to remain backwards compatible with existing API applications). To turn off the display of the precise latitude and longitude (but keep the contextual location information), pass C 0> on the status update. =back Returns: Status Twitter API documentation: L =item B =over 4 =item Parameters: trend_location_woid, sleep_time_enabled, start_sleep_time, end_sleep_time, time_zone, lang =item Required: I =back Updates the authenticating user's settings. Returns: HashRef Twitter API documentation: L =item B =item B =over 4 =item Parameters: device, include_entities =item Required: device =back Sets which device Twitter delivers updates to for the authenticating user. Sending none as the device parameter will disable SMS updates. Returns: BasicUser Twitter API documentation: L =item B =over 4 =item Parameters: user_id, screen_name, device, retweets =item Required: I =back Allows you enable or disable retweets and device notifications from the specified user. All other values are assumed to be false. Requires authentication. Returns: HashRef Twitter API documentation: L =item B =over 4 =item Parameters: list_id, slug, name, mode, description, owner_screen_name, owner_id =item Required: I =back Updates the specified list. The authenticated user must own the list to be able to update it. Returns: List Twitter API documentation: L =item B B =item B =over 4 =item Parameters: location =item Required: location =back This method has been deprecated in favor of the update_profile method. Its URL will continue to work, but please consider migrating to the newer and more comprehensive method of updating profile attributes. Returns: BasicUser =item B =over 4 =item Parameters: name, url, location, description, include_entities, skip_status =item Required: I =back Sets values that users are able to set under the "Account" tab of their settings page. Only the parameters specified will be updated; to only update the "name" attribute, for example, only include that parameter in your request. Returns: ExtendedUser Twitter API documentation: L =item B =over 4 =item Parameters: image, tile, include_entities, skip_status, use =item Required: I =back Updates the authenticating user's profile background image. The C parameter must be an arrayref with the same interpretation as the C parameter in the C method. See that method's documentation for details. The C parameter allows you to specify whether to use the uploaded profile background or not. Returns: ExtendedUser Twitter API documentation: L =item B =item B =over 4 =item Parameters: banner, width, height, offset_left, offset_top =item Required: banner =back Uploads a profile banner on behalf of the authenticating user. The C parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array (C<$file>) is the name of a file to open. The second value (C<$filename>) is the name given to Twitter for the file. If C<$filename> is not provided, the basename portion of C<$file> is used. If C<$mime_type> is not provided, it will be provided automatically using L. C<$raw_image_data> can be provided, rather than opening a file, by passing C as the first array value. Returns: Nothing Twitter API documentation: L =item B =over 4 =item Parameters: profile_background_color, profile_text_color, profile_link_color, profile_sidebar_fill_color, profile_sidebar_border_color, include_entities, skip_status =item Required: I =back Sets one or more hex values that control the color scheme of the authenticating user's profile page on twitter.com. These values are also returned in the /users/show API method. Returns: ExtendedUser Twitter API documentation: L =item B =item B =over 4 =item Parameters: image, include_entities, skip_status =item Required: image =back Updates the authenticating user's profile image. The C parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array (C<$file>) is the name of a file to open. The second value (C<$filename>) is the name given to Twitter for the file. If C<$filename> is not provided, the basename portion of C<$file> is used. If C<$mime_type> is not provided, it will be provided automatically using L. C<$raw_image_data> can be provided, rather than opening a file, by passing C as the first array value. Returns: ExtendedUser Twitter API documentation: L =item B B =item B =over 4 =item Parameters: status, media[], possibly_sensitive, in_reply_to_status_id, lat, long, place_id, display_coordinates =item Required: status, media[] =back Updates the authenticating user's status and attaches media for upload. Note that Twitter has marked this endpoint as B, and recommends instead calling C, then (optionally) C, then C. The C parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array (C<$file>) is the name of a file to open. The second value (C<$filename>) is the name given to Twitter for the file. If C<$filename> is not provided, the basename portion of C<$file> is used. If C<$mime_type> is not provided, it will be provided automatically using L. C<$raw_image_data> can be provided, rather than opening a file, by passing C as the first array value. The Tweet text will be rewritten to include the media URL(s), which will reduce the number of characters allowed in the Tweet text. If the URL(s) cannot be appended without text truncation, the tweet will be rejected and this method will return an HTTP 403 error. Returns: Status =item B =item B =over 4 =item Parameters: media =item Required: media =back Uploads an image to twitter without immediately posting it to the authenticating user's timeline. Its return-value hashref notably contains a C value that's useful as a parameter value in various other endpoint calls, such as C and C. Returns: HashRef Twitter API documentation: L =item B =item B =over 4 =item Parameters: media_id, command =item Required: media_id, command =back Check the status for async video uploads. Returns: status Twitter API documentation: L =item B =item B =item alias: follow_suggestions =over 4 =item Parameters: slug, lang =item Required: slug =back Access the users in a given slug (category) of the Twitter suggested user list and return their most recent status if they are not a protected user. Currently supported values for optional parameter C are C, C, C, C, C. Does not require authentication. Returns: ArrayRef Twitter API documentation: L =item B =item B =item alias: follow_suggestions_for =over 4 =item Parameters: slug, lang =item Required: slug =back Access the users in a given slug (category) of the Twitter suggested user list. Returns: ArrayRef Twitter API documentation: L =item B =over 4 =item Parameters: user_id, screen_name, since_id, max_id, count, trim_user, exclude_replies, include_rts, contributor_details =item Required: I =back Returns the 20 most recent statuses posted by the authenticating user, or the user specified by C or C. Returns: ArrayRef[Status] Twitter API documentation: L =item B =item B =item alias: find_people =item alias: search_users =over 4 =item Parameters: q, per_page, page, count, include_entities =item Required: q =back Run a search for users similar to Find People button on Twitter.com; the same results returned by people search on Twitter.com will be returned by using this API (about being listed in the People Search). It is only possible to retrieve the first 1000 matches from this API. Returns: ArrayRef[Users] Twitter API documentation: L =item B =over 4 =item Parameters: include_entities, skip_status, include_email =item Required: I =back Returns an HTTP 200 OK response code and a representation of the requesting user if authentication was successful; returns a 401 status code and an error message if not. Use this method to test if supplied user credentials are valid. Returns: ExtendedUser Twitter API documentation: L =back =over 4 =item B =item B =over 4 =item Parameters: status, media[], possibly_sensitive, in_reply_to_status_id, lat, long, place_id, display_coordinates =item Required: status, media =back Updates the authenticating user's status and attaches media for upload. The C parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array (C<$file>) is the name of a file to open. The second value (C<$filename>) is the name given to Twitter for the file. If C<$filename> is not provided, the basename portion of C<$file> is used. If C<$mime_type> is not provided, it will be provided automatically using L. C<$raw_image_data> can be provided, rather than opening a file, by passing C as the first array value. The Tweet text will be rewritten to include the media URL(s), which will reduce the number of characters allowed in the Tweet text. If the URL(s) cannot be appended without text truncation, the tweet will be rejected and this method will return an HTTP 403 error. Returns: Status Twitter API documentation: L =back =head1 Search API Methods These methods are provided when trait C is included in the C option to C. =over 4 =item B =item B =over 4 =item Parameters: q, geocode, lang, locale, result_type, count, until, since_id, max_id, include_entities, callback =item Required: q =back Returns a HASH reference with some meta-data about the query including the C, C, and C. The statuses are returned in C. To iterate over the results, use something similar to: my $r = $nt->search($search_term); my $r = $nt->search({ q => $search_term, count => 10 }) for my $status ( @{$r->{results}} ) { print "$status->{text}\n"; } Returns: HashRef =back =head1 Lists API Methods The original Lists API methods have been deprecated. L provides backwards compatibility for code written using those deprecated methods. If you're not already using the C trait, don't! Use the lists methods described above. If you are using the C trait, you should remove it from your code and change the arguments in your list API method calls to match those described above. Also, if using the C trait, you can pass synthetic argument C<-legacy_lists_api> set to 0 for individual calls to use the new endpoints semantics. =head1 TwitterVision API Methods These methods are provided when trait C is included in the C option to C. =over 4 =item B =item B =over 4 =item Parameters: id, callback =item Required: id =back Get the current location and status of a user. Returns: HashRef =item B =item B =over 4 =item Parameters: location =item Required: location =back Updates the location for the authenticated user. Returns: HashRef =back =head1 LEGACY COMPATIBILITY This version of C automatically includes the C trait if no C option is provided to C. Therefore, these 2 calls are currently equivalent: $nt = Net::Twitter->new(username => $user, password => $passwd); $nt = Net::Twitter->new( username => $user, password => $passwd, traits => ['Legacy'], ); Thus, existing applications written for a prior version of C should continue to run, without modification, with this version. In a future release, the default traits may change. Prior to that change, however, a nearer future version will add a warning if no C option is provided to C. To avoid this warning, add an appropriate C option to your existing application code. =head1 ERROR HANDLING There are currently two strategies for handling errors: throwing exceptions and wrapping errors. Exception handling is the newer, recommended strategy. =head2 Wrapping Errors When trait C is specified (or C, which includes trait C), C returns undef on error. To retrieve information about the error, use methods C, C, and C. These methods are described in the L. if ( my $followers = $nt->followers ) { for my $follower ( @$followers ) { #... } } else { warn "HTTP message: ", $nt->http_message, "\n"; } Since an error is stored in the object instance, this error handling strategy is problematic when using a user agent like C that provides concurrent requests. The error for one request can be overwritten by a concurrent request before you have an opportunity to access it. =head2 Exception Handling When C encounters a Twitter API error or a network error, it throws a C object. You can catch and process these exceptions by using C blocks and testing $@: eval { my $statuses = $nt->friends_timeline(); # this might die! for my $status ( @$statuses ) { #... } }; if ( $@ ) { # friends_timeline encountered an error if ( blessed $@ && $@->isa('Net::Twitter::Error') ) { #... use the thrown error obj warn $@->error; } else { # something bad happened! die $@; } } C stringifies to something reasonable, so if you don't need detailed error information, you can simply treat $@ as a string: eval { $nt->update($status) }; if ( $@ ) { warn "update failed because: $@\n"; } =head1 FAQ =over 4 =item Why does C<< ->followers({ screen_name => $friend }) >> return I followers instead of C<$friends>'s? First, check carefully to make sure you've spelled "screen_name" correctly. Twitter sometimes discards parameters it doesn't recognize. In this case, the result is a list of your own followers---the same thing that would happen if you called C without the C parameter. =item How do I use the C parameter in the Search API? The C parameter value includes a latitude, longitude, and radius separated with commas. $r = $nt->search({ geocode => "45.511795,-122.675629,25mi" }); =item How do I get Twitter to display something other than "from Perl Net::Twitter"? If you set the source parameter to C, twitter will display "from API", and if you set it to the empty string, twitter will display, "from web". $nt = Net::Twitter->new(netrc => 1,legacy => 0,ssl => 1,source => 'api'); $nt->update('A post with the source parameter overridden.'); # result: http://twitter.com/semifor_test/status/6541105458 $nt = Net::Twitter->new(netrc => 1,legacy => 0,ssl => 1,source => ''); $nt->update('A post with the source parameter overridden.'); # result: http://twitter.com/semifor_test/status/6541257224 If you want something other than "Net::Twitter", "API", or "web", you need to register an application and use OAuth authentication. If you do that, you can have any name you choose for the application printed as the source. Since rolling out OAuth, Twitter has stopped issuing new registered source parameters, only existing register source parameters are valid. =back =head1 SEE ALSO =over 4 =item L The C exception object. =item L This is the official Twitter API documentation. It describes the methods and their parameters in more detail and may be more current than the documentation provided with this module. =item L This LWP::UserAgent compatible class can be used in L based application along with Net::Twitter to provide concurrent, non-blocking requests. =item L This module, by Jesse Stay, provides Twitter OAuth authentication support for the popular L web application framework. =back =head1 SUPPORT Please report bugs to C, or through the web interface at L. Join the Net::Twitter IRC channel at L. Follow perl_api: L. Track Net::Twitter development at L. =head1 ACKNOWLEDGEMENTS Many thanks to Chris Thompson , the original author of C and all versions prior to 3.00. Also, thanks to Chris Prather (perigrin) for answering many design and implementation questions, especially with regards to Moose. =head1 AUTHOR Marc Mims (@semifor on Twitter) =head1 CONTRIBUTORS Roberto Etcheverry (@retcheverry on Twitter) KATOU Akira Francisco Pecorella Doug Bell Justin Hunter Allen Haim Joe Papperello (@antipasta on Github and Twitter) Samuel Kaufman (ediblenergy on Github) AnnMary Mathew (ammathew on Github) Olaf Alders (oalders on Github) =head1 LICENSE Copyright (c) 2009-2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2016 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/API.pm000644 000766 000024 00000023425 13227713560 020062 0ustar00marcstaff000000 000000 package Net::Twitter::API; $Net::Twitter::API::VERSION = '4.01043'; use Moose (); use Carp::Clan qw/^(?:Net::Twitter|Moose|Class::MOP)/; use Moose::Exporter; use URI::Escape; use DateTime::Format::Strptime; use namespace::autoclean; Moose::Exporter->setup_import_methods( with_caller => [ qw/base_url authenticate datetime_parser twitter_api_method/ ], ); my $_base_url; sub base_url { $_base_url = $_[1] } # kludge: This is very transient! my $do_auth; sub authenticate { $do_auth = $_[1] } # provide a default: we'll use the format of the REST API my $datetime_parser = DateTime::Format::Strptime->new(pattern => '%a %b %d %T %z %Y'); sub datetime_parser { $datetime_parser = $_[1] } sub twitter_api_method { my $caller = shift; my $name = shift; my %options = ( authenticate => $do_auth, datetime_parser => $datetime_parser, base_url_method => $_base_url, path_suffix => '.json', @_, ); my $deprecation_coderef = ref $options{deprecated} eq ref sub {} ? sub { $options{deprecated}->($name) } : sub {}; my $class = Moose::Meta::Class->initialize($caller); my ($arg_names, $path) = @options{qw/required path/}; $arg_names = $options{params} if @$arg_names == 0 && @{$options{params}} == 1; my $code = sub { my $self = shift; # give the deprecation coderef early access in case it intends to die $deprecation_coderef->(); # copy callers args since we may add ->{source} my $args = ref $_[-1] eq 'HASH' ? { %{pop @_} } : {}; # flatten array arguments for ( qw/id user_id screen_name/ ) { $args->{$_} = join ',' => @{ $args->{$_} } if ref $args->{$_} eq 'ARRAY'; } $self->_remap_legacy_synthetic_args($args); croak sprintf "$name expected %d args", scalar @$arg_names if @_ > @$arg_names; # promote positional args to named args for ( my $i = 0; @_; ++$i ) { my $param = $arg_names->[$i]; croak "duplicate param $param: both positional and named" if exists $args->{$param}; $args->{$param} = shift; } $args->{source} ||= $self->source if $options{add_source}; my $authenticate = exists $args->{-authenticate} ? $args->{-authenticate} : $options{authenticate}; # promote boolean parameters for my $boolean_arg ( @{ $options{booleans} } ) { if ( exists $args->{$boolean_arg} ) { next if $args->{$boolean_arg} =~ /^true|false$/; $args->{$boolean_arg} = $args->{$boolean_arg} ? 'true' : 'false'; } } # Workaround Twitter bug: any value passed for skip_user is treated as true. # The only way to get 'false' is to not pass the skip_user at all. delete $args->{skip_user} if exists $args->{skip_user} && $args->{skip_user} eq 'false'; # replace placeholder arguments my $local_path = $path; $local_path =~ s,/:id$,, unless exists $args->{id}; # remove optional trailing id $local_path =~ s/:(\w+)/delete $args->{$1} or croak "required arg '$1' missing"/eg; my $uri = URI->new($self->${ \$options{base_url_method} } . "/$local_path$options{path_suffix}"); return $self->_json_request( $options{method}, $uri, $args, $authenticate, $options{datetime_parser}, $options{content_type} ); }; $class->add_method( $name, Net::Twitter::Meta::Method->new( name => $name, package_name => $caller, body => $code, %options, ), ); $class->add_method($_, $code) for @{$options{aliases} || []}; } package Net::Twitter::Meta::Method; $Net::Twitter::Meta::Method::VERSION = '4.01043'; use Moose; use Carp::Clan qw/^(?:Net::Twitter|Moose|Class::MOP)/; extends 'Moose::Meta::Method'; use namespace::autoclean; has description => ( isa => 'Str', is => 'ro', required => 1 ); has aliases => ( isa => 'ArrayRef[Str]', is => 'ro', default => sub { [] } ); has path => ( isa => 'Str', is => 'ro', required => 1 ); has method => ( isa => 'Str', is => 'ro', default => 'GET' ); has add_source => ( isa => 'Bool', is => 'ro', default => 0 ); has params => ( isa => 'ArrayRef[Str]', is => 'ro', default => sub { [] } ); has required => ( isa => 'ArrayRef[Str]', is => 'ro', default => sub { [] } ); has returns => ( isa => 'Str', is => 'ro', predicate => 'has_returns' ); has deprecated => ( isa => 'Bool|CodeRef', is => 'ro', default => 0 ); has booleans => ( isa => 'ArrayRef[Str]', is => 'ro', default => sub { [] } ); has authenticate => ( isa => 'Bool', is => 'ro', required => 1 ); has datetime_parser => ( is => 'ro', required => 1 ); has base_url_method => ( isa => 'Str', is => 'ro', required => 1 ); has path_suffix => ( isa => 'Str', is => 'ro', required => 1 ); has content_type => ( isa => 'Str', is => 'ro', default => '' ); # TODO: can MooseX::StrictConstructor be made to work here? my %valid_attribute_names = map { $_->init_arg => 1 } __PACKAGE__->meta->get_all_attributes; sub new { my $class = shift; my %args = @_; my @invalid_attributes = grep { !$valid_attribute_names{$_} } keys %args; croak "unexpected argument(s): @invalid_attributes" if @invalid_attributes; $class->SUPER::wrap(@_); } 1; __END__ =head1 NAME Net::Twitter::API - Moose sugar for defining Twitter API methods =head1 VERSION version 4.01043 =head1 SYNOPSIS package My::Twitter::API; use Moose::Role; use Net::Twitter::API; use namespace::autoclean; has apiurl => ( isa => 'Str', is => 'rw', default => 'http://twitter.com' ); base_url 'apiurl'; twitter_api_method friends_timeline => ( description => <<'', Returns the 20 most recent statuses posted by the authenticating user and that user's friends. This is the equivalent of /home on the Web. aliases => [qw/following_timeline/], path => 'statuses/friends_timeline', method => 'GET', params => [qw/since_id max_id count page/], required => [], returns => 'ArrayRef[Status]', ); 1; =head1 DESCRIPTION This module provides some Moose sugar for defining Twitter API methods. It is part of the Net-Twitter distribution on CPAN and is used by C, C, and perhaps others. It's intent is to make maintaining C as easy as possible. =head1 METHODS =over 4 =item base_url Specifies, by name, the attribute which contains the base URL for the defined API. =item twitter_api_method Defines a Twitter API method. Valid arguments are: =over 4 =item authenticate Specifies whether, by default, API methods calls should authenticate. =item datetime_parser Specifies the Date::Time::Format derived parser to use for parsing and formatting date strings for the API being defined. =item description A string describing the method, suitable for documentation. =item aliases An ARRAY ref of strings containing alternate names for the method. =item path A string containing the path part of the API URL =item path_suffix A string containing an additional suffix to append to the path (for legacy reasons). If you want to suffix appended, pass the empty string. Defaults to ".json". =item method A string containing the HTTP method for the call. Defaults to "GET". =item add_source A boolean, indicating whether or not the C parameter should be added to the API call. (The source value is assigned by Twitter for registered applications.) Defaults to 0. =item params An ARRAY ref of strings naming all of the valid parameters. Defaults to an empty ARRAY ref. =item required An ARRAY ref of strings naming all of the required parameters. Defaults to an empty ARRAY ref. =item returns A string describing the return type of the API method call. =item deprecated A boolean indicating whether or not this API is deprecated. If set to 1, code for the method will be created. This option is optional, and is used by the C distribution when generating documentation. It defaults to 0. =back =back =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2009 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/Core.pm000644 000766 000024 00000032312 13227713560 020334 0ustar00marcstaff000000 000000 package Net::Twitter::Core; $Net::Twitter::Core::VERSION = '4.01043'; # ABSTRACT: A perl interface to the Twitter API use 5.008001; use Moose; use Carp::Clan qw/^(?:Net::Twitter|Moose|Class::MOP)/; use JSON::MaybeXS; use URI::Escape; use HTTP::Request::Common; use Net::Twitter::Error; use Scalar::Util qw/blessed reftype/; use List::Util qw/first/; use HTML::Entities (); use Encode qw/encode_utf8/; use DateTime; use Data::Visitor::Callback; use Try::Tiny; use namespace::autoclean; has useragent_class => ( isa => 'Str', is => 'ro', default => 'LWP::UserAgent' ); has useragent_args => ( isa => 'HashRef', is => 'ro', default => sub { {} } ); has username => ( isa => 'Str', is => 'rw', predicate => 'has_username' ); has password => ( isa => 'Str', is => 'rw', predicate => 'has_password' ); has ssl => ( isa => 'Bool', is => 'ro', default => 0 ); has netrc => ( isa => 'Str', is => 'ro', predicate => 'has_netrc' ); has netrc_machine => ( isa => 'Str', is => 'ro', default => 'api.twitter.com' ); has decode_html_entities => ( isa => 'Bool', is => 'rw', default => 0 ); has useragent => ( isa => 'Str', is => 'ro', default => "Net::Twitter/${ \($Net::Twitter::Core::VERSION || 1) } (Perl)", ); has source => ( isa => 'Str', is => 'ro', default => 'twitterpm' ); has ua => ( isa => 'Object', is => 'rw', lazy => 1, builder => '_build_ua' ); has clientname => ( isa => 'Str', is => 'ro', default => 'Perl Net::Twitter' ); has clientver => ( is => 'ro', isa => 'Str', default => $Net::Twitter::Core::VERSION || 1, ); has clienturl => ( isa => 'Str', is => 'ro', default => 'http://search.cpan.org/dist/Net-Twitter/' ); has _base_url => ( is => 'rw' ); ### keeps role composition from bitching ?? has _json_handler => ( is => 'rw', default => sub { JSON->new->allow_nonref->utf8 }, handles => { from_json => 'decode' }, ); sub _legacy_synthetic_args { qw/authenticate since/ } sub _remap_legacy_synthetic_args { my ( $self, $args ) = @_; $args->{"-$_"} = delete $args->{$_} for grep exists $args->{$_}, $self->_legacy_synthetic_args; } sub _natural_args { my ( $self, $args ) = @_; map { $_ => $args->{$_} } grep !/^-/, keys %$args; } around BUILDARGS => sub { my $next = shift; my $class = shift; my %options = @_ == 1 ? %{$_[0]} : @_; # Default to ssl $options{ssl} = 1 unless exists $options{ssl}; # aliases for ( [ user => 'username' ], [ pass => 'password' ] ) { my ( $alias, $base ) = @$_; if ( exists $options{$alias} ) { if ( !defined $options{$base} ) { $options{$base} = delete $options{$alias}; } else { carp "Both $base and $alias provided. Ignoring $alias"; } } } if ( delete $options{identica} ) { %options = ( apiurl => 'http://identi.ca/api', searchapiurl => 'http://identi.ca/api', apirealm => 'Laconica API', oauth_urls => { request_token_url => "https://identi.ca/api/oauth/request_token", authentication_url => "https://identi.ca/api/oauth/authenticate", authorization_url => "https://identi.ca/api/oauth/authorize", access_token_url => "https://identi.ca/api/oauth/access_token", xauth_url => "https://identi.ca/api/oauth/access_token", }, %options, ); } return $next->($class, \%options); }; sub BUILD { my $self = shift; if ( $self->has_netrc ) { require Net::Netrc; # accepts '1' for backwards compatibility my $host = $self->netrc eq '1' ? $self->netrc_machine : $self->netrc; my $nrc = Net::Netrc->lookup($host) || croak "No .netrc entry for $host"; my ($user, $pass) = $nrc->lpa; $self->username($user); $self->password($pass); } $self->credentials($self->username, $self->password) if $self->has_username; } sub _build_ua { my $self = shift; eval "use " . $self->useragent_class; croak $@ if $@; my $ua = $self->useragent_class->new(%{$self->useragent_args}); $ua->agent($self->useragent); $ua->default_header('X-Twitter-Client' => $self->clientname); $ua->default_header('X-Twitter-Client-Version' => $self->clientver); $ua->default_header('X-Twitter-Client-URL' => $self->clienturl); $ua->env_proxy; return $ua; } sub credentials { my ($self, $username, $password) = @_; $self->username($username); $self->password($password); return $self; # make it chainable } sub _encode_args { my ($self, $args) = @_; # Values need to be utf-8 encoded. Because of a perl bug, exposed when # client code does "use utf8", keys must also be encoded. # see: http://www.perlmonks.org/?node_id=668987 # and: http://perl5.git.perl.org/perl.git/commit/eaf7a4d2 return { map { utf8::upgrade($_) unless ref($_); $_ } %$args }; } sub _json_request { my ($self, $http_method, $uri, $args, $authenticate, $dt_parser, $content_type ) = @_; my $msg = $self->_prepare_request($http_method, $uri, $args, $authenticate, $content_type); my $res = $self->_send_request($msg); return $self->_parse_result($res, $args, $dt_parser); } sub _prepare_request { my ($self, $http_method, $uri, $args, $authenticate, $content_type ) = @_; my $msg; my %natural_args = $self->_natural_args($args); $self->_encode_args(\%natural_args); if( $http_method eq 'PUT' ) { $msg = PUT( $uri, 'Content-Type' => 'application/x-www-form-urlencoded', Content => $self->_query_string_for( \%natural_args ) ); } elsif ( $http_method =~ /^(?:GET|DELETE)$/ ) { $uri->query($self->_query_string_for(\%natural_args)); $msg = HTTP::Request->new($http_method, $uri); } elsif ( $http_method eq 'POST' ) { if( $content_type && $content_type eq 'application/json' ) { $msg = POST( $uri, Content_Type => 'application/json', Content => encode_json \%natural_args ); } else { # if any of the arguments are (array) refs, use form-data $msg = (first { ref } values %natural_args) ? POST($uri, Content_Type => 'form-data', Content => [ map { ref $_ ? $_ : encode_utf8 $_ } %natural_args, ], ) : POST($uri, Content => $self->_query_string_for(\%natural_args)) ; } } else { croak "unexpected HTTP method: $http_method"; } $self->_add_authorization_header($msg, \%natural_args) if $authenticate; return $msg; } # Make sure we encode arguments *exactly* the same way Net::OAuth does # ...by letting Net::OAuth encode them. sub _query_string_for { my ( $self, $args ) = @_; my @pairs; while ( my ($k, $v) = each %$args ) { push @pairs, join '=', map URI::Escape::uri_escape_utf8($_,'^\w.~-'), $k, $v; } return join '&', @pairs; } # Basic Auth, overridden by Role::OAuth, if included sub _add_authorization_header { my ( $self, $msg ) = @_; $msg->headers->authorization_basic($self->username, $self->password) if $self->has_username && $self->has_password; } sub _send_request { shift->ua->request(shift) } has _decode_html_entities_visitor => ( is => 'rw', lazy => 1, default => sub { Data::Visitor::Callback->new( plain_value => sub { return unless defined $_; $_ = HTML::Entities::decode_entities($_); } ) }, ); sub _decode_html_entities { shift->_decode_html_entities_visitor->visit(@_) } # By default, Net::Twitter does not inflate objects, so just return the # hashref, untouched. This is really just a hook for Role::InflateObjects. sub _inflate_objects { return $_[2] } sub _parse_result { my ($self, $res, $args, $datetime_parser) = @_; # workaround for Laconica API returning bools as strings # (Fixed in Laconi.ca 0.7.4) my $content = $res->content; $content =~ s/^"(true|false)"$/$1/; my $obj = length $content ? try { $self->from_json($content) } : {}; $self->_decode_html_entities($obj) if $obj && $self->decode_html_entities; # filter before inflating objects if ( (my $since = delete $args->{-since}) && defined $obj ) { $self->_filter_since($datetime_parser, $obj, $since); } # inflate the twitter object(s) if possible $self->_inflate_objects($datetime_parser, $obj); # Twitter sometimes returns an error with status code 200 if ( ref $obj && reftype $obj eq 'HASH' && (exists $obj->{error} || exists $obj->{errors}) ) { die Net::Twitter::Error->new(twitter_error => $obj, http_response => $res); } return $obj if $res->is_success && defined $obj; die Net::Twitter::Error->new( http_response => $res, $obj ? ( twitter_error => $obj ) : (), ); } # Return a DateTime object, given $since as one of: # - DateTime object # - string in format "YYYY-MM-DD" # - string in the same format as created_at values for the particular # Twitter API (Search and REST have different created_at formats!) # - an integer with epoch time (in seconds) # Otherwise, throw an exception sub _since_as_datetime { my ($self, $since, $parser) = @_; return $since if blessed($since) && $since->isa('DateTime'); if ( my ($y, $m, $d) = $since =~ /^(\d{4})-(\d{2})-(\d{2})$/ ) { return DateTime->new(month => $m, day => $d, year => $y); } return eval { DateTime->from_epoch(epoch => $since) } || eval { $parser->parse_datetime($since) } || croak "Invalid 'since' parameter: $since. Must be a DateTime, epoch, string in Twitter timestamp format, or YYYY-MM-DD."; } sub _filter_since { my ($self, $datetime_parser, $obj, $since) = @_; # $since can be a DateTime, an epoch value, or a Twitter formatted timestamp my $since_dt = $self->_since_as_datetime($since, $datetime_parser); my $visitor = Data::Visitor::Callback->new( ignore_return_values => 1, array => sub { my ($visitor, $data) = @_; return unless $self->_contains_statuses($data); # truncate $data when we reach an item as old or older than $since_dt my $i = 0; while ( $i < @$data ) { last if $datetime_parser->parse_datetime($data->[$i]{created_at}) <= $since_dt; ++$i; } $#{$data} = $i - 1; } ); $visitor->visit($obj); } # check an arrayref to see if it contains statuses sub _contains_statuses { my ($self, $arrayref) = @_; my $e = $arrayref->[0] || return; return unless ref $e && reftype $e eq 'HASH'; return exists $e->{created_at} && exists $e->{text} && exists $e->{id}; } sub _user_or_undef { my ( $self, $orig, $type, @rest ) = @_; return try { $orig->($self, @rest); } catch { die $_ unless /The specified user is not a $type of this list/; undef; }; } 1; __END__ =for Pod::Coverage BUILD credentials =head1 NAME Net::Twitter::Core - Net::Twitter implementation =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter::Core; my $nt = Net::Twitter::Core->new_with_traits(traits => [qw/API::Search/]); my $tweets = $nt->search('perl twitter') =head1 DESCRIPTION This module implements the core features of C. See L for full documentation. Although this module can be used directly, you are encouraged to use C instead. =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2009 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/Error.pm000644 000766 000024 00000015014 13227713560 020535 0ustar00marcstaff000000 000000 package Net::Twitter::Error; $Net::Twitter::Error::VERSION = '4.01043'; use Moose; use Try::Tiny; use Devel::StackTrace; use overload ( # We can't use 'error' directly, because overloads are called with three # arguments ($self, undef, '') resulting in an error: # Cannot assign a value to a read-only accessor '""' => sub { shift->error }, fallback => 1, ); has http_response => ( isa => 'HTTP::Response', is => 'ro', required => 1, handles => [qw/code message/], ); has twitter_error => ( is => 'ro', predicate => 'has_twitter_error', ); has stack_trace => ( is => 'ro', init_arg => undef, builder => '_build_stack_trace', handles => { stack_frame => 'frame', }, ); sub _build_stack_trace { my $seen; my $this_sub = (caller 0)[3]; Devel::StackTrace->new(frame_filter => sub { my $caller = shift->{caller}; my $in_nt = $caller->[0] =~ /^Net::Twitter::/ || $caller->[3] eq $this_sub; ($seen ||= $in_nt) && !$in_nt || 0; }); } has error => ( is => 'ro', init_arg => undef, lazy => 1, builder => '_build_error', ); sub _build_error { my $self = shift; my $error = $self->twitter_error_text || $self->http_response->status_line; my ($location) = $self->stack_frame(0)->as_string =~ /( at .*)/; return $error . ($location || ''); } sub twitter_error_text { my $self = shift; # Twitter does not return a consistent error structure, so we have to # try each known (or guessed) variant to find a suitable message... return '' unless $self->has_twitter_error; my $e = $self->twitter_error; return ref $e eq 'HASH' && ( # the newest variant: array of errors exists $e->{errors} && ref $e->{errors} eq 'ARRAY' && exists $e->{errors}[0] && ref $e->{errors}[0] eq 'HASH' && exists $e->{errors}[0]{message} && $e->{errors}[0]{message} # it's single error variant || exists $e->{error} && ref $e->{error} eq 'HASH' && exists $e->{error}{message} && $e->{error}{message} # the original error structure (still applies to some endpoints) || exists $e->{error} && $e->{error} # or maybe it's not that deep (documentation would be helpful, here, # Twitter!) || exists $e->{message} && $e->{message} ) || ''; # punt } sub twitter_error_code { my $self = shift; return $self->has_twitter_error && exists $self->twitter_error->{errors} && exists $self->twitter_error->{errors}[0] && exists $self->twitter_error->{errors}[0]{code} && $self->twitter_error->{errors}[0]{code} || 0; } __PACKAGE__->meta->make_immutable; no Moose; 1; __END__ =head1 NAME Net::Twitter::Error - A Net::Twitter exception object =head1 VERSION version 4.01043 =head1 SYNOPSIS use Scalar::Util qw/blessed/; use Try::Tiny; my $nt = Net::Twitter->new(@options); my $followers = try { $nt->followers; } catch { die $_ unless blessed($_) && $_->isa('Net::Twitter::Error'); warn "HTTP Response Code: ", $_->code, "\n", "HTTP Message......: ", $_->message, "\n", "Twitter error.....: ", $_->error, "\n", "Stack Trace.......: ", $_->stack_trace->as_string, "\n"; }; =head1 DESCRIPTION B encapsulates the C and Twitter error HASH (if any) resulting from a failed API call. =head1 METHODS =over 4 =item new Constructs a C object. It accepts the following parameters: =over 4 =item http_response An C object, required. =item twitter_error The error returned by Twitter as a HASH ref. Optional, since some API errors do not include a response from Twitter. They may, instead, be the result of network timeouts, proxy errors, or some other problem that prevents an API response. =back =item twitter_error Get or set the Twitter error HASH. =item http_response Get or set the C object. =item code Returns the HTTP response code. =item message Returns the HTTP response message. =item has_twitter_error Returns true if the object contains a Twitter error HASH. =item error Returns the C value from the C HASH ref if there is one. Otherwise, it returns the string "[unknown]". Includes a stack trace. =item twitter_error_text Returns the C value from the C HASH ref if there is one. Otherwise, returns an empty string =item twitter_error_code Returns the first numeric twitter error code from the JSON response body, if there is one. Otherwise, it returns 0 so the result should always be safe use in a numeric test. See L for a list of defined error codes. =item stack_trace Returns a L object. =item stack_frame($i) Returns the C<$i>th stack frame as a L object. =back =head1 SEE ALSO =over 4 =item L =back =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/Manual/000755 000766 000024 00000000000 13227713560 020322 5ustar00marcstaff000000 000000 Net-Twitter-4.01043/lib/Net/Twitter/OAuth.pm000644 000766 000024 00000003345 13227713560 020470 0ustar00marcstaff000000 000000 package Net::Twitter::OAuth; $Net::Twitter::OAuth::VERSION = '4.01043'; use Moose; extends 'Net::Twitter::Core'; with map "Net::Twitter::Role::$_", qw/Legacy OAuth/; no Moose; __PACKAGE__->meta->make_immutable; 1; __END__ =head1 NAME Net::Twitter::OAuth - Net::Twitter with 'Legacy' and 'OAuth' roles for backwards compatibility =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter::OAuth->new(consumer_key => $key, consumer_secret => $secret); =head1 DESCRIPTION This module simply creates an instance of C with the C and C traits applied. It is provided as a transparent backwards compatibility layer for earlier versions of Net::Twitter::OAuth which subclassed Net::Twitter. See L and L for full documentation. =head1 DEPRECATION NOTICE This module is deprecated. Use L instead. use Net::Twitter; # Just the REST API; exceptions thrown on error $nt = Net::Twitter->new(traits => [qw/API::RESTv1_1 OAuth/]); # Just the REST API; errors wrapped - use $nt->get_error $nt = Net::Twitter->new(traits => [qw/API::RESTv1_1 WrapError/]); # Or, for code that uses legacy Net::Twitter idioms $nt = Net::Twitter->new(traits => [qw/Legacy OAuth/]); =head1 METHODS =over 4 =item new Creates a C object with the C and C traits. See L for C options. =back =head1 SEE ALSO L, L =head1 AUTHORS Marc Mims Tatsuhiko Miyagawa =head1 LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Net-Twitter-4.01043/lib/Net/Twitter/Role/000755 000766 000024 00000000000 13227713560 020006 5ustar00marcstaff000000 000000 Net-Twitter-4.01043/lib/Net/Twitter/Search.pm000644 000766 000024 00000006023 13227713560 020651 0ustar00marcstaff000000 000000 package Net::Twitter::Search; $Net::Twitter::Search::VERSION = '4.01043'; use Moose; extends 'Net::Twitter::Core'; with "Net::Twitter::Role::Legacy"; no Moose; __PACKAGE__->meta->make_immutable; 1; __END__ =head1 NAME Net::Twitter::Search - A perl interface to the Twitter Search API =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; $nt = Net::Twitter::Search->new; $tweets = $nt->search('perl_api'); =head1 DESCRIPTION This module simply creates an instance of C with the C trait for backwards compatibility with prior versions. Consider L if you need a lighter, non-Moose alternative. See L for full documentation. =head1 DEPRECATION NOTICE This module is deprecated. Use L instead. use Net::Twitter; # Just the Search API; exceptions thrown on error $nt = Net::Twitter->new(traits => [qw/API::Search/]); # Just the Search API; errors wrapped - use $nt->get_error $nt = Net::Twitter->new(traits => [qw/API::Search WrapError/]); # Or, for code that uses legacy Net::Twitter idioms $nt = Net::Twitter->new(traits => [qw/Legacy/]); $tweets = $nt->search('pot of gold'); =head1 METHODS =over 4 =item new Creates a C object with the C trait. See L for C options. =back =head1 SEE ALSO =over 4 =item L Full documentation. =back =head1 AUTHORS Marc Mims Chris Thompson Brenda Wallace =head1 LICENSE Copyright (c) 2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2009 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/Types.pm000644 000766 000024 00000000574 13227713560 020555 0ustar00marcstaff000000 000000 package Net::Twitter::Types; $Net::Twitter::Types::VERSION = '4.01043'; use Moose::Util::TypeConstraints; use URI; class_type 'Net::Twitter::Types::URI', { class => 'URI' }; coerce 'Net::Twitter::Types::URI' => from 'Str' => via { URI->new($_) }; 1; __END__ =pod =head1 NAME Net::Twitter::Types - types and coercions for Net::Twitter =head1 VERSION version 4.01043 =cut Net-Twitter-4.01043/lib/Net/Twitter/WrappedResult.pm000644 000766 000024 00000005403 13227713560 022246 0ustar00marcstaff000000 000000 package Net::Twitter::WrappedResult; $Net::Twitter::WrappedResult::VERSION = '4.01043'; use Moose; # decoded JSON Twitter API response has result => ( is => 'ro', required => 1, ); has http_response => ( is => 'ro', isa => 'HTTP::Response', required => 1, ); # private method my $limit = sub { my ( $self, $which ) = @_; my $res = $self->http_response; # I'd like to use //, but...old perls. Sigh. my $value = $res->header("X-Rate-Limit-$which"); return defined $value ? $value # TODO: is FeatureRateLimit still a thing? : $res->header("X-FeatureRateLimit-$which"); }; sub rate_limit { shift->$limit('Limit') } sub rate_limit_remaining { shift->$limit('Remaining') } sub rate_limit_reset { shift->$limit('Reset') } no Moose; 1; __END__ =head1 NAME Net::Twitter::WrappedResult - Wrap an HTTP response and Twitter result =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter->new( traits => [ qw/API::RESTv1_1 WrapResult/ ], %other_new_options, ); my $r = $nt->verify_credentials; my $http_response = $r->http_response; my $twitter_result = $r->result; my $rate_limit_remaining = $r->rate_limit_remaining; =head1 DESCRIPTION Often, the result of a Twitter API call, inflated from the JSON body of the HTTP response does not contain all the information you need. Twitter includes meta data, such as rate limiting information, in HTTP response headers. This object wraps both the inflated Twitter result and the HTTP response giving the caller full access to all the meta data. It also provides accessors for the rate limit information. =head1 METHODS =over 4 =item new(result => $twitter_result, http_response => $http_response) Constructs an object wrapping the Twitter result and HTTP response. =item result Returns the Twitter API result, i.e., the decode JSON response body. =item http_response Returns the L object for the API call. =item rate_limit Returns the rate limit, per 15 minute window, for the API endpoint called. Returns undef if no suitable rate limit header is available. =item rate_limit_remaining Returns the calls remaining in the current 15 minute window for the API endpoint called. Returns undef if no suitable header is available. =item rate_limit_reset Returns the Unix epoch time time of the next 15 minute window, i.e., when the rate limit will be reset, for the API endpoint called. Returns undef if no suitable header is available. =back =head1 AUTHOR Marc Mims =head1 COPYRIGHT & LICENSE Copyright (c) 2016 Marc Mims This program is free software; you can redistribute it and/or modify it under the same terms as perl itself. Net-Twitter-4.01043/lib/Net/Twitter/Role/API/000755 000766 000024 00000000000 13227713560 020417 5ustar00marcstaff000000 000000 Net-Twitter-4.01043/lib/Net/Twitter/Role/AppAuth.pm000644 000766 000024 00000010142 13227713560 021704 0ustar00marcstaff000000 000000 package Net::Twitter::Role::AppAuth; $Net::Twitter::Role::AppAuth::VERSION = '4.01043'; use Moose::Role; use Carp::Clan qw/^(?:Net::Twitter|Moose|Class::MOP)/; use HTTP::Request::Common qw/POST/; use Net::Twitter::Types; requires qw/_add_authorization_header ua from_json/; use namespace::autoclean; # flatten oauth_urls with defaults around BUILDARGS => sub { my $orig = shift; my $class = shift; my $args = $class->$orig(@_); my $oauth_urls = delete $args->{oauth_urls} || { request_token_url => "https://api.twitter.com/oauth2/token", invalidate_token_url => "https://api.twitter.com/oauth2/invalidate_token", }; return { %$oauth_urls, %$args }; }; has [ qw/consumer_key consumer_secret/ ] => ( isa => 'Str', is => 'ro', required => 1, ); # url attributes has [ qw/request_token_url invalidate_token_url/ ] => ( isa => 'Net::Twitter::Types::URI', is => 'ro', required => 1, coerce => 1, ); has access_token => ( isa => 'Str', is => 'rw', clearer => "clear_access_token", predicate => "authorized", ); sub _add_consumer_auth_header { my ( $self, $req ) = @_; $req->headers->authorization_basic( $self->consumer_key, $self->consumer_secret); } sub request_access_token { my $self = shift; my $req = POST($self->request_token_url, 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8', Content => { grant_type => 'client_credentials' }, ); $self->_add_consumer_auth_header($req); my $res = $self->ua->request($req); croak "request_token failed: ${ \$res->code }: ${ \$res->message }" unless $res->is_success; my $r = $self->from_json($res->decoded_content); croak "unexpected token type: $$r{token_type}" unless $$r{token_type} eq 'bearer'; return $self->access_token($$r{access_token}); } sub invalidate_token { my $self = shift; croak "no access_token" unless $self->authorized; my $req = POST($self->invalidate_token_url, 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8', Content => join '=', access_token => $self->access_token, ); $self->_add_consumer_auth_header($req); my $res = $self->ua->request($req); croak "invalidate_token failed: ${ \$res->code }: ${ \$res->message }" unless $res->is_success; $self->clear_access_token; } around _prepare_request => sub { my $orig = shift; my $self = shift; my ($http_method, $uri, $args, $authenticate) = @_; delete $args->{source}; $self->$orig(@_); }; override _add_authorization_header => sub { my ( $self, $msg ) = @_; return unless $self->authorized; $msg->header(authorization => join ' ', Bearer => $self->access_token); }; 1; __END__ =encoding utf-8 =for stopwords =head1 NAME Net::Twitter::Role::AppAuth - OAuth2 Application Only Authentication =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter->new( traits => ['API::RESTv1_1', 'AppAuth'], consumer_key => "YOUR-CONSUMER-KEY", consumer_secret => "YOUR-CONSUMER-SECRET", ); $nt->request_token; my $tweets = $nt->user_timeline({ screen_name => 'Twitter' }); =head1 DESCRIPTION Net::Twitter::Role::OAuth is a Net::Twitter role that provides OAuth authentication instead of the default Basic Authentication. Note that this client only works with APIs that are compatible to OAuth authentication. =head1 METHODS =over 4 =item authorized True if the client has an access_token. This does not check the validity of the access token, so requests may fail if it is invalid. =item request_access_token Request an access token. Returns the token as well as saving it in the object. =item access_token Get or set the access token. =item invalidate_token Invalidates and clears the access_token. Note: There seems to be a Twitter bug preventing this from working---perhaps a documentation bug. E.g., see: L =back =cut Net-Twitter-4.01043/lib/Net/Twitter/Role/AutoCursor.pm000644 000766 000024 00000012376 13227713560 022463 0ustar00marcstaff000000 000000 package Net::Twitter::Role::AutoCursor; $Net::Twitter::Role::AutoCursor::VERSION = '4.01043'; use MooseX::Role::Parameterized; parameter max_calls => isa => 'Int', default => 16; parameter array_accessor => isa => 'Str', default => 'ids'; parameter force_cursor => isa => 'Bool', default => 0; parameter methods => isa => 'ArrayRef[Str]', default => sub { [qw/friends_ids followers_ids/] }; role { my $p = shift; requires @{$p->methods}; my $around = sub { my $orig = shift; my $self = shift; my $args = ref $_[-1] eq ref {} ? pop : {}; # backwards compat: all synthetic args use dash (-) prefix, now for ( qw/force_cursor max_calls/ ) { $args->{"-$_"} = delete $args->{$_} if exists $args->{$_}; } # no change in behavior if the user passed a cursor return $self->$orig(@_, $args) if exists $args->{cursor}; $args->{id} = shift if @_; my $force_cursor = exists $args->{-force_cursor} ? $args->{-force_cursor} : $p->force_cursor; $args->{cursor} = -1 if !exists $args->{cursor} && $force_cursor; my $max_calls = exists $args->{-max_calls} ? $args->{-max_calls} : $p->max_calls; my $calls = 0; my $results; if ( !exists $args->{cursor} ) { # try the old style, non-cursored call my $r = $orig->($self, $args); return $r if ref $r eq ref []; ++$calls; # If Twitter forces a cursored call, we'll get a HASH instead of an ARRAY $results = $r->{$p->array_accessor}; $args->{cursor} = $r->{next_cursor}; } while ( $args->{cursor} && $calls++ < $max_calls ) { my $r = $self->$orig($args); push @$results, @{$r->{$p->array_accessor}}; $args->{cursor} = $r->{next_cursor}; } return $results; }; around $_, $around for @{$p->methods}; }; 1; __END__ =head1 NAME Net::Twitter::Role::AutoCursor - Help transition to cursor based access to friends_ids and followers_ids methods =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter->new( traits => [qw/AutoCursor API::RESTv1_1 RetryOnError OAuth/], # additional ags... ); # Get friends_ids or followers_ids without worrying about cursors my $ids = $nt->followers_ids; my $nt = Net::Twitter->new( traits => [ qw/API::RESTv1_1 RetryOnError OAuth/ AutoCursor => { max_calls => 32 }, AutoCursor => { max_calls => 4, force_cursor => 1, array_accessor => 'users', methods => [qw/friends followers/], }, ], # additional args ); # works with any Twitter call that takes a cursor parameter my $friends = $nt->friends; =head1 DESCRIPTION On 25-Mar-2011, Twitter announced a change to C and C API methods: [Soon] followers/ids and friends/ids is being updated to set the cursor to -1 if it isn't supplied during the request. This changes the default response format This will break a lot of existing code. The C trait was created to help users transition to cursor based access for these methods. With default parameters, the C trait attempts a non-cursored call for C and C. If it detects a cursored response from Twitter, it continues to call the underlying Twitter API method, with the next cursor, until it has received all results or 16 calls have been made (yielding 80,000 results). It returns an ARRAY reference to the combined results. If the C parameter is passed to C or C, C assumes the user is handling cursoring and does not modify behavior or results. The C trait is parameterized, allowing it to work with any Twitter API method that expects cursors, returning combined results for up to the maximum number of calls specified. C can be applied multiple times to handle different sets of API methods. =head1 PARAMETERS =over 4 =item max_calls An integer specifying the maximum number of API calls to make. Default is 16. C can be overridden on a per-call basis by passing a C argument to the API method. =item force_cursor If true, when the caller does not provide a C parameter, C will use up to C cursored calls rather than attempting an initial non-cursored call. Default is 0. =item array_accessor The name of the HASH key used to access the ARRAY ref of results in the data structure returned by Twitter. Default is C. =item methods A reference to an ARRAY containing the names of Twitter API methods to which C will be applied. =back =head1 METHOD CALLS Synthetic parameter C<-max_calls> can be passed for individual method calls to override the default: $r = $nt->followers_ids({ -max_calls => 200 }); # get up to 1 million ids Synthetic parameter C<-force_cursor> can be passed to override the C default. =head1 AUTHOR Marc Mims =head1 COPYRIGHT Copyright (c) 2016 Marc Mims =head1 LICENSE This library is free software and may be distributed under the same terms as perl itself. =cut Net-Twitter-4.01043/lib/Net/Twitter/Role/InflateObjects.pm000644 000766 000024 00000007676 13227713560 023260 0ustar00marcstaff000000 000000 package Net::Twitter::Role::InflateObjects; $Net::Twitter::Role::InflateObjects::VERSION = '4.01043'; use Moose::Role; use namespace::autoclean; use Data::Visitor::Callback; use Digest::SHA; =head1 NAME Net::Twitter::Role::InflateObjects - Inflate Twitter API return values to Moose objects =head1 VERSION version 4.01043 =cut requires qw/_inflate_objects/; has _class_map => ( traits => ['Hash'], isa => 'HashRef', default => sub { {} }, handles => { set_cached_class => 'set', get_cached_class => 'get', }, ); override _inflate_objects => sub { my ($self, $datetime_parser, $obj) = @_; return unless ref $obj; my $visitor = Data::Visitor::Callback->new( hash => sub { $self->_hash_to_object($datetime_parser, $_[1]) }, ); $visitor->visit($obj); }; sub _attribute_inflator { my ($self, $datetime_parser, $name, $value) = @_; return URI->new($value) if $name =~ /url$/; return $datetime_parser->parse_datetime($value) if $name =~ /^created_at|reset_time$/; return $value; } sub _hash_to_object { my ($self, $datetime_parser, $href) = @_; my $signature = Digest::SHA::sha1_hex( join ',' => sort keys %$href ); my $class = $self->get_cached_class($signature); unless ( $class ) { $class = Moose::Meta::Class->create_anon_class; for my $name ( keys %$href ) { $class->add_attribute( $name, reader => { $name => sub { $self->_attribute_inflator($datetime_parser, $name, shift->{$name}) }, }, ); } if ( exists $href->{created_at} ) { $class->add_method(relative_created_at => sub { my $self = shift; my $delta = time - $self->created_at->epoch; return "less than a minute ago" if $delta < 60; return "about a minute ago" if $delta < 120; return int($delta / 60) . " minutes ago" if $delta < 45 * 60; return "about an hour ago" if $delta < 120 * 60; return int($delta / 3600) . " hours ago" if $delta < 24 * 60 * 60; return "1 day ago" if $delta < 48 * 60 * 60; return int($delta / (3600*24)) . " days ago"; }); } $class->make_immutable; $self->set_cached_class($signature, $class); } bless $href, $class->name; } 1; __END__ =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter->new(traits => [qw/InflateObjects API::Rest/]); $nt->credentials($username, $password); $r = $nt->friends_timeline; $r->[0]->user->name; # return values are objects with read accessors $r->[0]->created_at; # dates are inflated to DateTime objects $r->[0]->relative_created_at; # "6 minutes ago" =head1 DESCRIPTION This role provides inflation of HASH refs, returned by the Twitter API, into Moose objects. URLs are inflated to URI objects. Dates are inflated to DateTime objects. Objects that have a C attribute also have a C method that prints times in the same style as the Twitter web interface. All HASH members have read accessors, so $r->[0]->{user}{screen_name} Can be accessed as $r->[0]->user->screen_name =head1 CAVEATS An accessor is created for each HASH key returned by Twitter. As Twitter adds new attributes, InflateObjects will create accessors for them. However, InflateObjects will also drop accessors if Twitter drops the corresponding HASH element. So, code that relies on HASH element will fail loudly if Twitter drops support for it. (This may be a feature!) =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2009 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Net-Twitter-4.01043/lib/Net/Twitter/Role/Legacy.pm000644 000766 000024 00000007377 13227713560 021566 0ustar00marcstaff000000 000000 package Net::Twitter::Role::Legacy; $Net::Twitter::Role::Legacy::VERSION = '4.01043'; use Moose::Role; use namespace::autoclean; with map "Net::Twitter::Role::$_", qw/ API::REST API::Search API::TwitterVision WrapError /; has arrayref_on_error => ( isa => 'Bool', is => 'rw', default => 0, trigger => \&_set_error_return_val ); has twittervision => ( isa => 'Bool', is => 'rw', default => 0 ); sub _set_error_return_val { my $self = shift; $self->_error_return_val($self->arrayref_on_error ? [] : undef); } # Legacy Net::Twitter does not make the call unless twittervision is true. # Bug or feature? around 'update_twittervision' => sub { my $next = shift; my $self = shift; return unless $self->twittervision; return $next->($self, @_); }; sub clone { my $self = shift; return bless { %{$self} }, ref $self; } 1; __END__ =head1 NAME Net::Twitter::Role::Legacy - A Net::Twitter legacy compatibility layer as a Moose role =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter->new( username => $username, password => $password, traits => [qw/Legacy/], ); my $followers = $nt->followers; if ( !followers ) { warn $nt->http_message; } =head1 DESCRIPTION This module provides a B compatibility layer for Net::Twitter. It pulls in the additional traits: C, C, C, and C. =head1 METHODS =over 4 =item new This method takes the same parameters as L. In addition, it also support the options: =over 4 =item arrayref_on_error When set to 1, on error, rather than returning undef, the API methods will return an empty ARRAY ref. Defaults to 0. =item twittervision When set to 1, enables the C call. Defaults to 0. =back =item clone Creates a shallow copy of the C object. This was useful, in legacy versions of C for handling concurrent requests (for instance with L). Since errors are wrapped in the C concurrent requests each needed their own object. C served that purpose. The recommended approach for concurrent requests is to use C's ability throw exceptions, now. =back =head1 SEE ALSO L =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/Role/OAuth.pm000644 000766 000024 00000035304 13227713560 021371 0ustar00marcstaff000000 000000 package Net::Twitter::Role::OAuth; $Net::Twitter::Role::OAuth::VERSION = '4.01043'; use Moose::Role; use HTTP::Request::Common; use Carp::Clan qw/^(?:Net::Twitter|Moose|Class::MOP)/; use URI; use Digest::SHA; use List::Util qw/first/; use Net::Twitter::Types; requires qw/_add_authorization_header ua/; use namespace::autoclean; use Net::OAuth; $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A; # flatten oauth_urls with defaults around BUILDARGS => sub { my $orig = shift; my $class = shift; my $args = $class->$orig(@_); my $oauth_urls = delete $args->{oauth_urls} || { request_token_url => "https://api.twitter.com/oauth/request_token", authentication_url => "https://api.twitter.com/oauth/authenticate", authorization_url => "https://api.twitter.com/oauth/authorize", access_token_url => "https://api.twitter.com/oauth/access_token", xauth_url => "https://api.twitter.com/oauth/access_token", }; return { %$oauth_urls, %$args }; }; has consumer_key => ( isa => 'Str', is => 'ro', required => 1 ); has consumer_secret => ( isa => 'Str', is => 'ro', required => 1 ); # URI attributes has [ qw/authentication_url authorization_url request_token_url access_token_url xauth_url/ ] => ( isa => 'Net::Twitter::Types::URI', is => 'ro', required => 1, coerce => 1, ); # token attributes for my $attribute ( qw/access_token access_token_secret request_token request_token_secret/ ) { has $attribute => ( isa => 'Str', is => 'rw', clearer => "clear_$attribute", predicate => "has_$attribute", ); } # simple check to see if we have access tokens; does not check to see if they are valid sub authorized { my $self = shift; return defined $self->has_access_token && $self->has_access_token_secret; } # get the authorization or authentication url sub _get_auth_url { my ($self, $which_url, %params ) = @_; my $callback = delete $params{callback} || 'oob'; $self->_request_request_token(callback => $callback); my $uri = $self->$which_url; $uri->query_form(oauth_token => $self->request_token, %params); return $uri; } # get the authentication URL from Twitter sub get_authentication_url { return shift->_get_auth_url(authentication_url => @_) } # get the authorization URL from Twitter sub get_authorization_url { return shift->_get_auth_url(authorization_url => @_) } # common portion of all oauth requests sub _make_oauth_request { my ($self, $type, %params) = @_; my $class = $type =~ s/^\+// ? $type : Net::OAuth->request($type); my $request = $class->new( version => '1.0', consumer_key => $self->{consumer_key}, consumer_secret => $self->{consumer_secret}, request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => time, nonce => Digest::SHA::sha1_base64(time . $$ . rand), %params, ); $request->sign; return $request; } # called by get_authorization_url to obtain request tokens sub _request_request_token { my ($self, %params) = @_; my $uri = $self->request_token_url; my $request = $self->_make_oauth_request( 'request token', request_url => $uri, %params, ); my $msg = HTTP::Request->new(GET => $uri); $msg->header(authorization => $request->to_authorization_header); my $res = $self->_send_request($msg); croak "GET $uri failed: ".$res->status_line unless $res->is_success; # reuse $uri to extract parameters from the response content $uri->query($res->content); my %res_param = $uri->query_form; $self->request_token($res_param{oauth_token}); $self->request_token_secret($res_param{oauth_token_secret}); } # exchange request tokens for access tokens; call with (verifier => $verifier) sub request_access_token { my ($self, %params ) = @_; my $uri = $self->access_token_url; my $request = $self->_make_oauth_request( 'access token', request_url => $uri, token => $self->request_token, token_secret => $self->request_token_secret, %params, # verifier => $verifier ); my $msg = HTTP::Request->new(GET => $uri); $msg->header(authorization => $request->to_authorization_header); my $res = $self->_send_request($msg); croak "GET $uri failed: ".$res->status_line unless $res->is_success; # discard request tokens, they're no longer valid $self->clear_request_token; $self->clear_request_token_secret; # reuse $uri to extract parameters from content $uri->query($res->content); my %res_param = $uri->query_form; return ( $self->access_token($res_param{oauth_token}), $self->access_token_secret($res_param{oauth_token_secret}), $res_param{user_id}, $res_param{screen_name}, ); } around _prepare_request => sub { my $orig = shift; my ($self, $http_method, $uri, $args, $authenticate) = @_; delete $args->{source}; $orig->(@_); }; override _add_authorization_header => sub { my ( $self, $msg, $args ) = @_; return unless $self->authorized; my $is_multipart = grep { ref } %$args; local $Net::OAuth::SKIP_UTF8_DOUBLE_ENCODE_CHECK = 1; my $uri = $msg->uri->clone; $uri->query(undef); my $request = $self->_make_oauth_request( 'protected resource', request_url => $uri, request_method => $msg->method, token => $self->access_token, token_secret => $self->access_token_secret, extra_params => $is_multipart ? {} : $args, ); $msg->header(authorization => $request->to_authorization_header); }; sub xauth { my ( $self, $username, $password ) = @_; my @args = ( x_auth_username => $username, x_auth_password => $password, x_auth_mode => 'client_auth', ); my $uri = $self->xauth_url; my $request = $self->_make_oauth_request( 'XauthAccessToken', request_url => $uri, request_method => 'POST', @args, ); my $res = $self->ua->request( POST $uri, \@args, Authorization => $request->to_authorization_header); die "POST $uri failed: ".$res->status_line unless $res->is_success; # reuse $uri to extract parameters from content $uri->query($res->content); my %res_param = $uri->query_form; return ( $self->access_token($res_param{oauth_token}), $self->access_token_secret($res_param{oauth_token_secret}), $res_param{user_id}, $res_param{screen_name}, ); } # shortcuts defined in early releases # DEPRECATED sub oauth_token { my($self, @tokens) = @_; carp "DEPRECATED: use access_token and access_token_secret instead"; $self->access_token($tokens[0]); $self->access_token_secret($tokens[1]); return @tokens; } sub is_authorized { carp "DEPRECATED: use authorized instead"; shift->authorized(@_) } sub oauth_authorization_url { carp "DEPRECATED: use get_authorization_url instead"; shift->get_authorization_url(@_) } sub oauth { carp "DEPRECATED: call this method on Net::Twitter itself, rather than through the oauth accessor"; shift } 1; __END__ =encoding utf-8 =for stopwords =head1 NAME Net::Twitter::Role::OAuth - Net::Twitter role that provides OAuth instead of Basic Authentication =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter->new( traits => ['API::RESTv1_1', 'OAuth'], consumer_key => "YOUR-CONSUMER-KEY", consumer_secret => "YOUR-CONSUMER-SECRET", ); # Do some Authentication work. See EXAMPLES my $tweets = $nt->friends_timeline; my $res = $nt->update({ status => "I CAN HAZ OAUTH!" }); =head1 DESCRIPTION Net::Twitter::Role::OAuth is a Net::Twitter role that provides OAuth authentication instead of the default Basic Authentication. Note that this client only works with APIs that are compatible to OAuth authentication. =head1 IMPORTANT Beginning with version 3.02, it is necessary for web applications to pass the C parameter to C. In the absence of a callback parameter, when the user authorizes the application a PIN number is displayed rather than redirecting the user back to your site. =head1 EXAMPLES See the C directory in this distribution for working examples of both desktop and web applications. Here's how to authorize users as a desktop app mode: use Net::Twitter; my $nt = Net::Twitter->new( traits => ['API::RESTv1_1', 'OAuth'], consumer_key => "YOUR-CONSUMER-KEY", consumer_secret => "YOUR-CONSUMER-SECRET", ); # You'll save the token and secret in cookie, config file or session database my($access_token, $access_token_secret) = restore_tokens(); if ($access_token && $access_token_secret) { $nt->access_token($access_token); $nt->access_token_secret($access_token_secret); } unless ( $nt->authorized ) { # The client is not yet authorized: Do it now print "Authorize this app at ", $nt->get_authorization_url, " and enter the PIN#\n"; my $pin = ; # wait for input chomp $pin; my($access_token, $access_token_secret, $user_id, $screen_name) = $nt->request_access_token(verifier => $pin); save_tokens($access_token, $access_token_secret); # if necessary } # Everything's ready In a web application mode, you need to save the oauth_token and oauth_token_secret somewhere when you redirect the user to the OAuth authorization URL. sub twitter_authorize : Local { my($self, $c) = @_; my $nt = Net::Twitter->new(traits => [qw/API::RESTv1_1 OAuth/], %param); my $url = $nt->get_authorization_url(callback => $callbackurl); $c->response->cookies->{oauth} = { value => { token => $nt->request_token, token_secret => $nt->request_token_secret, }, }; $c->response->redirect($url); } And when the user returns back, you'll reset those request token and secret to upgrade the request token to access token. sub twitter_auth_callback : Local { my($self, $c) = @_; my %cookie = $c->request->cookies->{oauth}->value; my $verifier = $c->req->params->{oauth_verifier}; my $nt = Net::Twitter->new(traits => [qw/API::RESTv1_1 OAuth/], %param); $nt->request_token($cookie{token}); $nt->request_token_secret($cookie{token_secret}); my($access_token, $access_token_secret, $user_id, $screen_name) = $nt->request_access_token(verifier => $verifier); # Save $access_token and $access_token_secret in the database associated with $c->user } Later on, you can retrieve and reset those access token and secret before calling any Twitter API methods. sub make_tweet : Local { my($self, $c) = @_; my($access_token, $access_token_secret) = ...; my $nt = Net::Twitter->new(traits => [qw/API::RESTv1_1 OAuth/], %param); $nt->access_token($access_token); $nt->access_token_secret($access_token_secret); # Now you can call any Net::Twitter API methods on $nt my $status = $c->req->param('status'); my $res = $nt->update({ status => $status }); } =head1 METHODS =over 4 =item authorized Whether the client has the necessary credentials to be authorized. Note that the credentials may be wrong and so the request may fail. =item request_access_token(verifier => $verifier) Request the access token, access token secret, user id and screen name for this user. You must pass the PIN# (for desktop applications) or the C value, provided as a parameter to the oauth callback (for web applications) as C<$verifier>. The user must have authorized this app at the url given by C first. Returns the access_token, access_token_secret, user_id, and screen_name in a list. Also sets them internally so that after calling this method, you can immediately call API methods requiring authentication. =item xauth($username, $password) Exchanges the C<$username> and C<$password> for access tokens. This method has the same return value as C: access_token, access_token_secret, user_id, and screen_name in a list. Also, like C, it sets the access_token and access_secret, internally, so you can immediately call API methods requiring authentication. =item get_authorization_url(callback => $callback_url) Get the URL used to authorize the user. Returns a C object. For web applications, pass your applications callback URL as the C parameter. No arguments are required for desktop applications (C defaults to C, out-of-band). =item get_authentication_url(callback => $callback_url) Get the URL used to authenticate the user with "Sign in with Twitter" authentication flow. Returns a C object. For web applications, pass your applications callback URL as the C parameter. No arguments are required for desktop applications (C defaults to C, out-of-band). =item access_token Get or set the access token. =item access_token_secret Get or set the access token secret. =item request_token Get or set the request token. =item request_token_secret Get or set the request token secret. =back =head1 DEPRECATED METHODS =over 4 =item oauth Prior versions used Net::OAuth::Simple. This method provided access to the contained Net::OAuth::Simple object. Beginning with Net::Twitter 3.00, the OAuth methods were delegated to Net::OAuth::Simple. They have since made first class methods. Net::Simple::OAuth is no longer used. A warning will be displayed when accessing OAuth methods via the method. The C method will be removed in a future release. =item is_authorized Use C instead. =item oauth_authorization_url Use C instead. =item oauth_token $nt->oauth_token($access_token, $access_token_secret); Use C and C instead: $nt->access_token($access_token); $nt->access_token_secret($access_token_secret); =back =head1 ACKNOWLEDGEMENTS This module was originally authored by Tatsuhiko Miyagawa as C, a subclass of the C 2.x. It was refactored into a Moose Role for use in C 3.0 and above by Marc Mims. Many thanks to Tatsuhiko for the original work on both code and documentation. =head1 AUTHORS Marc Mims Emarc@questright.comE Tatsuhiko Miyagawa Emiyagawa@bulknews.netE =head1 LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L, L =cut Net-Twitter-4.01043/lib/Net/Twitter/Role/RateLimit.pm000644 000766 000024 00000013044 13227713560 022240 0ustar00marcstaff000000 000000 package Net::Twitter::Role::RateLimit; $Net::Twitter::Role::RateLimit::VERSION = '4.01043'; use Moose::Role; use namespace::autoclean; use Try::Tiny; use Scalar::Util qw/weaken/; =head1 NAME Net::Twitter::Role::RateLimit - Rate limit features for Net::Twitter =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter->new( traits => [qw/API::REST RateLimit/], %other_options, ); #...later sleep $nt->until_rate(1.0) || $minimum_wait; =head1 NOTE! RateLimit only works with Twitter API v1. The rate limiting strategy of Twitter API v1.1 is very different. A v1.1 compatible RateLimit role may be coming, but isn't available, yet. It's interface will necessarily be different. =head1 DESCRIPTION This provides utility methods that return information about the current rate limit status. =cut requires qw/ua rate_limit_status/; # Rate limiting changed so dramatically with v1.1 this Role simply won't work with it excludes 'Net::Twitter::Role::API::RESTv1_1'; has _rate_limit_status => ( isa => 'HashRef[Int]', is => 'rw', init_arg => undef, lazy => 1, default => sub { my %h; @h{qw/rate_limit rate_reset rate_remaining/} = (0,0,0); \%h }, ); around rate_limit_status => sub { my $orig = shift; my $self = shift; my $r = $self->$orig(@_) || return; @{$self->_rate_limit_status}{qw/rate_remaining rate_reset rate_limit/} = @{$r}{qw/remaining_hits reset_time_in_seconds hourly_limit/}; return $r; }; for my $method ( qw/rate_remaining rate_limit/ ) { around $method => sub { my $orig = shift; my $self = shift; $self->rate_reset; # force a call to rate_limit_satus if necessary; return $self->$orig(@_); }; } after BUILD => sub { my $self = shift; weaken $self; $self->ua->add_handler(response_done => sub { my $res = shift; my @values = map { $res->header($_) } qw/x-ratelimit-remaining x-ratelimit-reset x-ratelimit-limit/; return unless @values == 3; @{$self->_rate_limit_status}{qw/rate_remaining rate_reset rate_limit/} = @values; }); }; =head1 METHODS If current rate limit data is not resident, these methods will force a call to C. Therefore, any of these methods can throw an error. =over 4 =item rate_remaining Returns the number of API calls available before the next reset. =cut sub rate_remaining { shift->_rate_limit_status->{rate_remaining} } =item rate_reset Returns the Unix epoch time of the next reset. =cut sub rate_reset { my $self = shift; # If rate_reset is in the past, we need to refresh it $self->rate_limit_status if $self->_rate_limit_status->{rate_reset} < time; # HACK! Prevent a loop on clock mismatch my $time = time; if ( $self->_rate_limit_status->{rate_reset} < $time ) { $self->_rate_limit_status->{rate_reset} = $time + 1; } return $self->_rate_limit_status->{rate_reset}; } =item rate_limit Returns the current hourly rate limit. =cut sub rate_limit { shift->_rate_limit_status->{rate_limit} } =item rate_ratio Returns remaining API call limit, divided by the time remaining before the next reset, as a ratio of the total rate limit per hour. For example, if C is 150, the total rate is 150 API calls per hour. If C is 75, and there 1800 seconds (1/2 hour) remaining before the next reset, C returns 1.0, because there are exactly enough API calls remaining to maintain he full rate of 150 calls per hour. If C is 30 and there are 360 seconds remaining before reset, C returns 2.0, because there are enough API calls remaining to maintain twice the full rate of 150 calls per hour. As a final example, if C is 15, and there are 7200 seconds remaining before reset, C returns 0.5, because there are only enough API calls remaining to maintain half the full rate of 150 calls per hour. =cut sub rate_ratio { my $self = shift; my $full_rate = $self->rate_limit / 3600; my $current_rate = try { $self->rate_remaining / ($self->rate_reset - time) } || 0; return $current_rate / $full_rate; } =item until_rate($target_ratio) Returns the number of seconds to wait before making another rate limited API call such that C<$target_ratio> of the full rate would be available. It always returns a number greater than, or equal to zero. Use a target rate of 1.0 in a timeline polling loop to get a steady polling rate, using all the allocated calls, and adjusted for other API calls as they occur. Use a target rate E 1.0 to allow a process to make calls as fast as possible but not consume all of the calls available, too soon. For example, if you have a process building a large social graph, you may want to allow it make as many calls as possible, with no wait, until 20% of the available rate remains. Use a value of 0.2 for that purpose. A target rate E than 1.0 can be used for a process that should only use "extra" available API calls. This is useful for an application that requires most of it's rate limit for normal operation. =cut sub until_rate { my ( $self, $target_rate ) = @_; my $s = $self->rate_reset - time - 3600 * $self->rate_remaining / $target_rate / $self->rate_limit; return $s > 0 ? $s : 0; }; 1; __END__ =back =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Net-Twitter-4.01043/lib/Net/Twitter/Role/RetryOnError.pm000644 000766 000024 00000006742 13227713560 022771 0ustar00marcstaff000000 000000 package Net::Twitter::Role::RetryOnError; $Net::Twitter::Role::RetryOnError::VERSION = '4.01043'; use Moose::Role; use namespace::autoclean; use Time::HiRes; requires '_send_request'; =head1 NAME Net::Twitter::Role::RetryOnError - Retry Twitter API calls on error =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; $nt = Net::Twitter->new( traits => ['API::RESTv1_1', 'RetryOnError'] max_retries => 3, ); =head1 DESCRIPTION Temporary errors are not uncommon when calling the Twitter API. When applied to L this role will provide automatic retries of API calls in a very configurable way. It only retries when the response status code is E= 500. Other error codes indicate a permanent error. If the maximum number of retries is reached, without success, an exception is thrown, as usual. =head1 OPTIONS This role adds the following options to C: =over 4 =item initial_retry_delay A floating point number specifying the initial delay, after an error, before retrying. Default: 0.25 (250 milliseconds). =cut has initial_retry_delay => ( is => 'rw', isa => 'Num', default => 0.250, # 250 milliseconds ); =item max_retry_delay A floating point number specifying the maximum delay between retries. Default: 4.0 =cut has max_retry_delay => ( is => 'rw', isa => 'Num', default => 4.0, # 4 seconds ); =item retry_delay_multiplier On the second and subsequent retries, a new delay is calculated by multiplying the previous delay by C. Default: 2.0 =cut has retry_delay_multiplier => ( is => 'rw', isa => 'Num', default => 2, # double the prior delay ); =item max_retries The maximum number of consecutive retries before giving up and throwing an exception. If set to 0, it the API call will be retried indefinitely. Default 5. =cut has max_retries => ( is => 'rw', isa => 'Int', default => 5, # 0 = try forever ); =item retry_delay_code A code reference that will be called to handle the delay. It is passed a single argument: a floating point number specifying the number of seconds to delay. By default, L is called. If you're using a non-blocking user agent, like L, you should use this option to provide a non-blocking delay. =cut has retry_delay_code => ( is => 'rw', isa => 'CodeRef', default => sub { sub { Time::HiRes::sleep(shift) }; }, ); =back =cut around _send_request => sub { my ( $orig, $self, $msg ) = @_; my $is_oauth = do { my $auth_header = $msg->header('authorization'); $auth_header && $auth_header =~ /^OAuth /; }; my $delay = $self->initial_retry_delay; my $retries = $self->max_retries; while () { my $res = $self->$orig($msg); return $res if $res->is_success || $retries-- == 0 || $res->code < 500; $self->retry_delay_code->($delay); $delay *= $self->retry_delay_multiplier; $delay = $self->max_retry_delay if $delay > $self->max_retry_delay; # If this is an OAuth request, we need a new Authorization header # (the nonce may be invalid, now). $self->_add_authorization_header($msg) if $is_oauth; } }; 1; __END__ =head1 AUTHOR Marc Mims =head1 COPYRIGHT Copyright (c) 2016 Marc Mims =head1 LICENSE This library is free software and may be distributed under the same terms as perl itself. =cut Net-Twitter-4.01043/lib/Net/Twitter/Role/SimulateCursors.pm000644 000766 000024 00000003316 13227713560 023513 0ustar00marcstaff000000 000000 package Net::Twitter::Role::SimulateCursors; $Net::Twitter::Role::SimulateCursors::VERSION = '4.01043'; use Moose::Role; use namespace::autoclean; requires qw/_json_request/; around _json_request => sub { my $orig = shift; my $self = shift; my ($http_method, $uri, $args, $authenticate) = @_; if ( defined(my $cursor = delete $args->{cursor}) ) { my $page = $cursor == -1 ? 1 : $cursor; my $r = $self->$orig($http_method, $uri, { %$args, page => $page }, $authenticate); my $key = $uri =~ qr`/ids\.` ? 'ids' : 'users'; my $next_cursor = @$r ? $page + 1 : 0; my $previous_cursor = $page == 1 ? 0 : $page - 1; return { next_cursor => $next_cursor, next_cursor_str => "$next_cursor", previous_cursor => $previous_cursor, previous_cursor_str => "$previous_cursor", $key => $r, }; } return $self->$orig(@_); }; 1; __END__ =head1 NAME Net::Twitter::Role::SimulateCursors - Make paging work like cursoring =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter->new( traits => ['API::RESTv1_1', 'SimulateCursors'], ); =head1 DESCRIPTION This role simulates the cursoring method used by some Twitter API methods. It's useful for providing compatibility with Identi.ca, for instance, that does not support cursoring and requires paging, instead. =head1 METHODS =over 4 =back =head1 AUTHOR Marc Mims Emarc@questright.comE =head1 LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L =cut Net-Twitter-4.01043/lib/Net/Twitter/Role/WrapError.pm000644 000766 000024 00000010730 13227713560 022270 0ustar00marcstaff000000 000000 package Net::Twitter::Role::WrapError; $Net::Twitter::Role::WrapError::VERSION = '4.01043'; use Moose::Role; use Try::Tiny; use Scalar::Util qw/blessed/; requires qw/_parse_result/; use namespace::autoclean; has _http_response => ( isa => 'HTTP::Response', is => 'rw', handles => { http_message => 'message', http_code => 'code', } ); has _twitter_error => ( isa => 'HashRef|Object', is => 'rw', predicate => 'has_error', clearer => '_clear_error' ); has _error_return_val => ( isa => 'Maybe[ArrayRef]', is => 'rw', default => undef ); sub get_error { my $self = shift; return unless $self->has_error; return $self->_twitter_error; } around _parse_result => sub { my ($next, $self, $res, $sythetic_args, $datetime_parser) = @_; $self->_clear_error; $self->_http_response($res); my $r = try { $next->($self, $res, $sythetic_args, $datetime_parser) } catch { die $_ unless blessed $_ && $_->isa('Net::Twitter::Error'); $self->_twitter_error($_->has_twitter_error ? $_->twitter_error : $self->_inflate_objects( $datetime_parser, { error => "TWITTER RETURNED ERROR MESSAGE BUT PARSING OF JSON RESPONSE FAILED - " . $res->message } ) ); return $self->_error_return_val; }; return $r; }; 1; __END__ =head1 NAME Net::Twitter::Role::WrapError - Wraps Net::Twitter exceptions =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter->new(username => $username, password => $password); my $followers = $nt->followers; if ( !followers ) { warn $nt->http_message; } =head1 DESCRIPTION This module provides an alternate error handling strategy for C. Rather than throwing exceptions, API methods return C and error information is available through method calls on the C object. This is the error handling strategy used when C C is used. It was the error handling strategy employed by C prior to version 3.00. =head1 METHODS =over 4 =item new This method takes the same parameters as L. =item get_error Returns undef if there was no error or a HASH ref containing the Twitter error response. Occasionally, a Twitter API call results in an error with no error content returned from Twitter. When that occurs, get_error returns a simulated error HASH ref. NOTE: Versions of C prior to 3.0 sometimes returned a string rather than a HASH ref, on error. This was a bug. Always expect undef on success and a HASH ref on error. =item http_code Returns the HTTP response code the most recent API method call if it ended in error. =item http_message Returns the HTTP message for the most recent API method call if it ended in error. =back =head1 SEE ALSO L =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/Role/WrapResult.pm000644 000766 000024 00000003040 13227713560 022451 0ustar00marcstaff000000 000000 package Net::Twitter::Role::WrapResult; $Net::Twitter::Role::WrapResult::VERSION = '4.01043'; use Moose::Role; use Net::Twitter::WrappedResult; requires '_parse_result'; around _parse_result => sub { my ( $next, $self ) = splice @_, 0, 2; my $http_response = $_[0]; my $result = $self->$next(@_); return Net::Twitter::WrappedResult->new( result => $result, http_response => $http_response, ); }; no Moose::Role; 1; __END__ =head1 NAME Net::Twitter::Role::WrapResult - Wrap Twitter API response and HTTP Response =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter->new( traits => [ qw/API::RESTv1_1 WrapResult/ ], %other_new_options, ); my $r = $nt->verify_credentials; my $http_response = $r->http_response; my $twitter_result = $r->result; my $rate_limit_remaining = $r->rate_limit_remaining; =head1 DESCRIPTION Normally, Net::Twitter API methods return the decoded JSON body from the HTTP response. Some useful information, notably rate limit information, is included in HTTP response headers. With this role applied, API methods will return a L object that includes both the HTTP response and the decoded JSON response body. See L for details. =head1 AUTHOR Marc Mims =head1 COPYRIGHT Copyright (c) 2016 Marc Mims =head1 LICENSE This library is free software and may be distributed under the same terms as perl itself. =cut Net-Twitter-4.01043/lib/Net/Twitter/Role/API/Lists.pm000644 000766 000024 00000030116 13227713560 022054 0ustar00marcstaff000000 000000 package Net::Twitter::Role::API::Lists; $Net::Twitter::Role::API::Lists::VERSION = '4.01043'; use Moose::Role; use Net::Twitter::API; use DateTime::Format::Strptime; use Try::Tiny; with 'Net::Twitter::Role::API::REST'; =head1 NAME Net::Twitter::Role::API::Lists - Twitter Lists API support for Net::Twitter =head1 VERSION version 4.01043 =head1 SYNOPSIS use Net::Twitter; my $nt = Net::Twitter->new(traits => ['API::Lists'], ...); $list = $nt->create_list($owner, { name => $name, description => $desc }); $list = $nt->update_list($owner, $list_id, { description => $desc }); $lists = $nt->get_lists($owner); $lists = $nt->list_lists($owner); $list = $nt->get_list($owner, $list_id); $list = $nt->delete_list($owner, $list_id); $statuses = $nt->list_statuses($owner, $list_id); $lists = $nt->list_memberships($owner); $lists = $nt->list_subscriptions($owner); $users = $nt->list_members($owner, $list_id); $user_or_undef = $nt->list_members($owner, $list_id, { id => $user_id }); $user = $nt->add_list_member($owner, $list_id, $user_id); $users = $nt->add_list_members($owner, $list_id, { screen_name => \@screen_names }); $user = $nt->delete_list_member($owner, $list_id, $user_id); $user = $nt->remove_list_member($owner, $list_id, $user_id); $user_or_undef = $nt->is_list_member($owner, $list_id, $user_id); $users = $nt->list_subscribers($owner, $list_id); $list = $nt->subscribe_list($owner, $list_id); $list = $nt->unsubscribe_list($owner, $list_id); $user_or_undef = $nt->is_subscribed_list($owner, $list_id, $user_id); $user_or_undef = $nt->is_list_subscriber($owner, $list_id, $user_id); ############################# # With the cursor parameter # ############################# $r = $nt->get_list($user, $list_id, { cursor => $cursor }); $lists = $r->{lists}; $r = $nt->list_memberships($user, { cursor => $cursor }); $lists = $r->{lists}; $r = $nt->list_subscriptions($user, { cursor => $cursor }); $lists = $r->{lists}; $r = $nt->list_members($owner, $list_id, { cursor => $cursor }); $users = $r->{users}; $r = $nt->list_subscribers($owner, $list_id, { cursor => $cursor }); $users = $r->{users}; =head1 DEPRECATION NOTICE This module implements methods for the original Twitter Lists API. Twitter has deprecated these API methods and reimplemented them with a saner semantics. The new methods are implemented in the API::REST trait, L. This module provides backwards compatibility for code written to use the original Lists API. To use the new API methods, simply remove this trait from your code and change the arguments to its methods to match the new semantics. This module may be dropped from L in a future release. It will remain as long as Twitter still provides the underlying API end-points. =head1 DESCRIPTION This module adds support to L for the Twitter Lists API. =cut requires qw/username ua/; =head1 DESCRIPTION B provides a trait for the Twitter Lists API methods. See L for full documentation. =cut has lists_api_url => ( isa => 'Str', is => 'rw', default => 'http://api.twitter.com/1' ); base_url 'lists_api_url'; authenticate 1; our $DATETIME_PARSER = DateTime::Format::Strptime->new(pattern => '%a %b %d %T %z %Y'); datetime_parser $DATETIME_PARSER; after BUILD => sub { my $self = shift; $self->{lists_api_url} =~ s/^http:/https:/ if $self->ssl; }; twitter_api_method legacy_create_list => ( path => ':user/lists', method => 'POST', params => [qw/user name mode description/], required => [qw/user name/], returns => 'HashRef', description => <<'', Creates a new list for the authenticated user. The C parameter may be either C or C. If not specified, it defaults to C. ); twitter_api_method legacy_update_list => ( path => ':user/lists/:list_id', method => 'POST', params => [qw/user list_id name mode description/], required => [qw/user list_id/], returns => 'HashRef', description => <<'', Updates a list to change the name, mode, description, or any combination thereof. ); twitter_api_method legacy_get_lists => ( path => ':user/lists', method => 'GET', params => [qw/user cursor/], required => [qw/user/], returns => 'ArrayRef[List]', aliases => [qw/legacy_list_lists/], description => <<'EOT', Returns a reference to an array of lists owned by the specified user. If the user is the authenticated user, it returns both public and private lists. Otherwise, it only returns public lists. When the C parameter is used, a hash reference is returned; the lists are returned in the C element of the hash. EOT ); twitter_api_method legacy_get_list => ( path => ':user/lists/:list_id', method => 'GET', params => [qw/user list_id/], required => [qw/user list_id/], returns => 'HashRef', description => <<'', Returns the specified list as a hash reference. ); twitter_api_method legacy_delete_list => ( path => ':user/lists/:list_id', method => 'DELETE', params => [qw/user list_id/], required => [qw/user list_id/], description => <<'', Deletes a list owned by the authenticating user. Returns the list as a hash reference. ); twitter_api_method legacy_list_statuses => ( path => ':user/lists/:list_id/statuses', method => 'GET', params => [qw/user list_id since_id max_id per_page page/], required => [qw/user list_id/], returns => 'ArrayRef[Status]', description => <<'', Returns a timeline of list member statuses as an array reference. ); twitter_api_method legacy_list_memberships => ( path => ':user/lists/memberships', method => 'GET', params => [qw/user cursor/], required => [qw/user/], description => <<'EOT', Returns the lists the specified user is a member of as an array reference. When the C parameter is used, a hash reference is returned; the lists are returned in the C element of the hash. EOT ); twitter_api_method legacy_list_subscriptions => ( path => ':user/lists/subscriptions', method => 'GET', params => [qw/user cursor/], required => [qw/user/], description => <<'EOT', Returns a lists to which the specified user is subscribed as an array reference. When the C parameter is used, a hash reference is returned; the lists are returned in the C element of the hash. EOT ); twitter_api_method legacy_list_members => ( path => ':user/:list_id/members', method => 'GET', params => [qw/user list_id id cursor/], required => [qw/user list_id/], returns => 'ArrayRef[User]', description => <<'EOT', Returns the list members as an array reference. The optional C parameter can be used to determine if the user specified by C is a member of the list. If so, the user is returned as a hash reference; if not, C is returned. When the C parameter is used, a hash reference is returned; the members are returned in the C element of the hash. EOT ); around legacy_list_members => sub { my $orig = shift; my $self = shift; $self->_user_or_undef($orig, 'member', @_); }; twitter_api_method legacy_is_list_member => ( path => ':user/:list_id/members/:id', method => 'GET', params => [qw/user list_id id/], required => [qw/user list_id id/], returns => 'ArrayRef[User]', description => <<'EOT', Returns the list member as a HASH reference if C is a member of the list. Otherwise, returns undef. EOT ); around legacy_is_list_member => sub { my $orig = shift; my $self = shift; $self->_user_or_undef($orig, 'member', @_); }; twitter_api_method legacy_add_list_member => ( path => ':user/:list_id/members', method => 'POST', returns => 'User', params => [qw/user list_id id/], required => [qw/user list_id id/], description => <<'EOT', Adds the user identified by C to the list. Returns a reference the added user as a hash reference. EOT ); twitter_api_method legacy_members_create_all => ( aliases => [qw/legacy_add_list_members/], path => ':user/:list_id/members/create_all', method => 'POST', returns => 'ArrayRef[User]', params => [qw/user list_id screen_name user_id/], required => [qw/user list_id/], description => <<'EOT', Adds multiple users C to the list. Users are specified with the C or C parameter with a reference to an ARRAY of values. Returns a reference the added user as a hash reference. EOT ); twitter_api_method legacy_delete_list_member => ( path => ':user/:list_id/members', method => 'DELETE', params => [qw/user list_id id/], required => [qw/user list_id id/], aliases => [qw/legacy_remove_list_member/], description => <<'EOT', Deletes the user identified by C from the specified list. Returns the deleted user as a hash reference. EOT ); twitter_api_method legacy_list_subscribers => ( path => ':user/:list_id/subscribers', method => 'GET', params => [qw/user list_id id cursor/], required => [qw/user list_id/], returns => 'ArrayRef[User]', description => <<'EOT', Returns the subscribers to a list as an array reference. When the C parameter is used, a hash reference is returned; the subscribers are returned in the C element of the hash. EOT ); around legacy_list_subscribers => sub { my $orig = shift; my $self = shift; $self->_user_or_undef($orig, 'subscriber', @_); }; twitter_api_method legacy_is_list_subscriber => ( path => ':user/:list_id/subscribers/:id', method => 'GET', params => [qw/user list_id id/], required => [qw/user list_id id/], returns => 'ArrayRef[User]', aliases => [qw/legacy_is_subscribed_list/], description => <<'EOT', Returns the subscriber as a HASH reference if C is a subscriber to the list. Otherwise, returns undef. EOT ); around legacy_is_list_subscriber => sub { my $orig = shift; my $self = shift; $self->_user_or_undef($orig, 'subscriber', @_); }; twitter_api_method legacy_subscribe_list => ( path => ':user/:list_id/subscribers', method => 'POST', returns => 'List', params => [qw/user list_id/], required => [qw/user list_id/], description => <<'', Subscribes the authenticated user to the specified list. ); twitter_api_method legacy_unsubscribe_list => ( path => ':user/:list_id/subscribers', method => 'DELETE', returns => 'List', params => [qw/user list_id/], required => [qw/user list_id/], description => <<'', Unsubscribes the authenticated user from the specified list. ); for my $method ( qw/ create_list update_list get_lists get_list delete_list list_statuses list_memberships list_subscriptions list_members is_list_member add_list_member members_create_all delete_list_member list_subscribers is_list_subscriber subscribe_list unsubscribe_list list_lists add_list_members remove_list_member is_subscribed_list / ) { my $legacy_method = "legacy_$method"; around $method => sub { my $orig = shift; my $self = shift; my $args = ref $_[-1] eq 'HASH' ? pop : {}; my $legacy = exists $args->{-legacy_lists_api} ? delete $args->{-legacy_lists_api} : 1; return $self->$legacy_method(@_, $args) if $legacy; $self->$orig(@_, $args); }; } 1; __END__ =head1 SEE ALSO L =head1 AUTHOR Marc Mims =head1 COPYRIGHT Copyright (c) 2009-2016 Marc Mims =head1 LICENSE This library is free software. You may redistribute and modify it under the same terms as Perl itself. =cut Net-Twitter-4.01043/lib/Net/Twitter/Role/API/REST.pm000644 000766 000024 00000166157 13227713560 021552 0ustar00marcstaff000000 000000 package Net::Twitter::Role::API::REST; $Net::Twitter::Role::API::REST::VERSION = '4.01043'; use Moose::Role; use Carp::Clan qw/^(?:Net::Twitter|Moose|Class::MOP)/; use Net::Twitter::API; use DateTime::Format::Strptime; use URI; requires qw/ua username password credentials/; with 'Net::Twitter::Role::API::Upload'; has apiurl => ( isa => 'Str', is => 'ro', default => 'http://api.twitter.com/1' ); has apihost => ( isa => 'Str', is => 'ro', lazy => 1, builder => '_build_apihost' ); has apirealm => ( isa => 'Str', is => 'ro', default => 'Twitter API' ); sub _build_apihost { my $uri = URI->new(shift->apiurl); join ':', $uri->host, $uri->port; } after BUILD => sub { my $self = shift; $self->{apiurl} =~ s/^http:/https:/ if $self->ssl; }; base_url 'apiurl'; authenticate 1; our $DATETIME_PARSER = DateTime::Format::Strptime->new(pattern => '%a %b %d %T %z %Y'); datetime_parser $DATETIME_PARSER; twitter_api_method public_timeline => ( description => <<'EOT', Returns the 20 most recent statuses from non-protected users who have set a custom user icon. Does not require authentication. Note that the public timeline is cached for 60 seconds so requesting it more often than that is a waste of resources. If user credentials are provided, C calls are authenticated, so they count against the authenticated user's rate limit. Use C<< ->public_timeline({ authenticate => 0 }) >> to make an unauthenticated call which will count against the calling IP address' rate limit, instead. EOT path => 'statuses/public_timeline', method => 'GET', returns => 'ArrayRef[Status]', params => [qw/skip_user trim_user include_entities/], booleans => [qw/skip_user trim_user include_entities/], required => [], ); twitter_api_method home_timeline => ( description => <<'', Returns the 20 most recent statuses, including retweets, posted by the authenticating user and that user's friends. This is the equivalent of /timeline/home on the Web. path => 'statuses/home_timeline', method => 'GET', params => [qw/since_id max_id count page skip_user exclude_replies contributor_details include_rts include_entities trim_user include_my_retweet/], booleans => [qw/skip_user exclude_replies contributor_details include_rts include_entities trim_user include_my_retweet/], required => [], returns => 'ArrayRef[Status]', ); twitter_api_method retweet => ( description => <<'', Retweets a tweet. Requires the id parameter of the tweet you are retweeting. Returns the original tweet with retweet details embedded. path => 'statuses/retweet/:id', method => 'POST', params => [qw/id include_entities trim_user/], booleans => [qw/include_entities trim_user/], required => [qw/id/], returns => 'Status', ); twitter_api_method retweets => ( description => <<'', Returns up to 100 of the first retweets of a given tweet. path => 'statuses/retweets/:id', method => 'GET', params => [qw/id count trim_user include_entities/], booleans => [qw/trim_user include_entities/], required => [qw/id/], returns => 'Arrayref[Status]', ); twitter_api_method retweeted_by_me => ( description => <<'', Returns the 20 most recent retweets posted by the authenticating user. path => 'statuses/retweeted_by_me', method => 'GET', params => [qw/since_id max_id count page trim_user include_entities/], booleans => [qw/trim_user include_entities/], required => [], returns => 'ArrayRef[Status]', ); twitter_api_method retweeted_to_me => ( description => <<'', Returns the 20 most recent retweets posted by the authenticating user's friends. path => 'statuses/retweeted_to_me', method => 'GET', params => [qw/since_id max_id count page/], required => [], returns => 'ArrayRef[Status]', ); twitter_api_method retweets_of_me => ( description => <<'', Returns the 20 most recent tweets of the authenticated user that have been retweeted by others. aliases => [qw/retweeted_of_me/], path => 'statuses/retweets_of_me', method => 'GET', params => [qw/since_id max_id count page trim_user include_entities/], booleans => [qw/trim_user include_entities/], required => [], returns => 'ArrayRef[Status]', ); twitter_api_method friends_timeline => ( deprecated => 1, description => <<'', Returns the 20 most recent statuses posted by the authenticating user and that user's friends. This is the equivalent of /home on the Web. aliases => [qw/following_timeline/], path => 'statuses/friends_timeline', method => 'GET', params => [qw/since_id max_id count page skip_user trim_user include_entities include_rts/], booleans => [qw/skip_user trim_user include_entities include_rts/], required => [], returns => 'ArrayRef[Status]', ); twitter_api_method user_timeline => ( description => <<'', Returns the 20 most recent statuses posted from the authenticating user. It's also possible to request another user's timeline via the id parameter. This is the equivalent of the Web /archive page for your own user, or the profile page for a third party. path => 'statuses/user_timeline/:id', method => 'GET', params => [qw/id user_id screen_name since_id max_id count page skip_user trim_user include_entities include_rts/], booleans => [qw/skip_user trim_user include_entities include_rts/], required => [], returns => 'ArrayRef[Status]', ); # TODO: URL should be 'mentions', not 'replies', but the Laconica API doesn't # recognize 'mentions' yet, so we'll cheat, as long as Twitter plays along and # keeps 'replies' active or until Laconica/Identica is fixed. # (Fixed in Laconi.ca 0.7.4.) twitter_api_method mentions => ( description => <<'', Returns the 20 most recent mentions (statuses containing @username) for the authenticating user. aliases => [qw/replies/], path => 'statuses/mentions', method => 'GET', params => [qw/since_id max_id count page trim_user include_rts include_entities/], booleans => [qw/trim_user include_rts include_entities/], required => [], returns => 'ArrayRef[Status]', ); twitter_api_method show_status => ( description => <<'', Returns a single status, specified by the id parameter. The status's author will be returned inline. path => 'statuses/show/:id', method => 'GET', params => [qw/id trim_user include_entities/], booleans => [qw/trim_user include_entities/], required => [qw/id/], returns => 'Status', ); twitter_api_method update => ( path => 'statuses/update', method => 'POST', params => [qw/status lat long place_id display_coordinates in_reply_to_status_id trim_user include_entities/], required => [qw/status/], booleans => [qw/display_coordinates trim_user include_entities/], add_source => 1, returns => 'Status', description => <<'EOT', Updates the authenticating user's status. Requires the status parameter specified. A status update with text identical to the authenticating user's current status will be ignored. =over 4 =item status Required. The text of your status update. URL encode as necessary. Statuses over 140 characters will cause a 403 error to be returned from the API. =item in_reply_to_status_id Optional. The ID of an existing status that the update is in reply to. o Note: This parameter will be ignored unless the author of the tweet this parameter references is mentioned within the status text. Therefore, you must include @username, where username is the author of the referenced tweet, within the update. =item lat Optional. The location's latitude that this tweet refers to. The valid ranges for latitude is -90.0 to +90.0 (North is positive) inclusive. This parameter will be ignored if outside that range, if it is not a number, if geo_enabled is disabled, or if there not a corresponding long parameter with this tweet. =item long Optional. The location's longitude that this tweet refers to. The valid ranges for longitude is -180.0 to +180.0 (East is positive) inclusive. This parameter will be ignored if outside that range, if it is not a number, if geo_enabled is disabled, or if there not a corresponding lat parameter with this tweet. =item place_id Optional. The place to attach to this status update. Valid place_ids can be found by querying C. =item display_coordinates Optional. By default, geo-tweets will have their coordinates exposed in the status object (to remain backwards compatible with existing API applications). To turn off the display of the precise latitude and longitude (but keep the contextual location information), pass C 0> on the status update. =back EOT ); twitter_api_method destroy_status => ( description => <<'', Destroys the status specified by the required ID parameter. The authenticating user must be the author of the specified status. path => 'statuses/destroy/:id', method => 'POST', params => [qw/id trim_user include_entities/], booleans => [qw/trim_user include_entities/], required => [qw/id/], returns => 'Status', ); twitter_api_method friends => ( deprecated => 1, description => <<'EOT', This method has been deprecated. Twitter intends to stop support for it on May 14, 2012. Use C and C instead. Returns a reference to an array of the user's friends. If C, C, or C is not specified, the friends of the authenticating user are returned. The returned users are ordered from most recently followed to least recently followed. Use the optional C parameter to retrieve users in pages of 100. When the C parameter is used, the return value is a reference to a hash with keys C, C, and C. The value of C is a reference to an array of the user's friends. The result set isn't guaranteed to be 100 every time as suspended users will be filtered out. Set the optional C parameter to -1 to get the first page of users. Set it to the prior return's value of C or C to page forward or backwards. When there are no prior pages, the value of C will be 0. When there are no subsequent pages, the value of C will be 0. EOT aliases => [qw/following/], path => 'statuses/friends/:id', method => 'GET', params => [qw/id user_id screen_name cursor include_entities/], booleans => [qw/include_entities/], required => [qw//], returns => 'Hashref|ArrayRef[User]', ); twitter_api_method followers => ( deprecated => 1, description => <<'EOT', This method has been deprecated. Twitter intends to stop support for it on May 14, 2012. Use C and C instead. Returns a reference to an array of the user's followers. If C, C, or C is not specified, the followers of the authenticating user are returned. The returned users are ordered from most recently followed to least recently followed. Use the optional C parameter to retrieve users in pages of 100. When the C parameter is used, the return value is a reference to a hash with keys C, C, and C. The value of C is a reference to an array of the user's friends. The result set isn't guaranteed to be 100 every time as suspended users will be filtered out. Set the optional C parameter to -1 to get the first page of users. Set it to the prior return's value of C or C to page forward or backwards. When there are no prior pages, the value of C will be 0. When there are no subsequent pages, the value of C will be 0. EOT path => 'statuses/followers/:id', method => 'GET', params => [qw/id user_id screen_name cursor include_entities/], booleans => [qw/include_entities/], required => [qw//], returns => 'HashRef|ArrayRef[User]', ); twitter_api_method show_user => ( description => <<'', Returns extended information of a given user, specified by ID or screen name as per the required id parameter. This information includes design settings, so third party developers can theme their widgets according to a given user's preferences. You must be properly authenticated to request the page of a protected user. path => 'users/show/:id', method => 'GET', params => [qw/id screen_name include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'ExtendedUser', ); twitter_api_method contributees => ( path => 'users/contributees', method => 'GET', params => [qw/user_id screen_name include_entities skip_satus/], required => [], booleans => [qw/include_entities skip_satus/], returns => 'ArrayRef[User]', description => <<'', Returns an array of users that the specified user can contribute to. ); twitter_api_method contributors => ( path => 'users/contributors', method => 'GET', params => [qw/user_id screen_name include_entities skip_satus/], required => [], booleans => [qw/include_entities skip_satus/], returns => 'ArrayRef[User]', description => <<'', Returns an array of users who can contribute to the specified account. ); twitter_api_method direct_messages => ( description => <<'', Returns a list of the 20 most recent direct messages sent to the authenticating user including detailed information about the sending and recipient users. path => 'direct_messages', method => 'GET', params => [qw/since_id max_id count page include_entities/], required => [qw/include_entities/], returns => 'ArrayRef[DirectMessage]', ); twitter_api_method sent_direct_messages => ( description => <<'', Returns a list of the 20 most recent direct messages sent by the authenticating user including detailed information about the sending and recipient users. path => 'direct_messages/sent', method => 'GET', params => [qw/since_id max_id page count include_entities/], booleans => [qw/include_entities/], required => [qw//], returns => 'ArrayRef[DirectMessage]', ); twitter_api_method new_direct_message => ( description => <<'', Sends a new direct message to the specified user from the authenticating user. Requires both the user and text parameters. Returns the sent message when successful. In order to support numeric screen names, the C or C parameters may be used instead of C. path => 'direct_messages/new', method => 'POST', params => [qw/user text screen_name user_id include_entities/], booleans => [qw/include_entities/], required => [qw/user text/], returns => 'DirectMessage', ); twitter_api_method destroy_direct_message => ( description => <<'', Destroys the direct message specified in the required ID parameter. The authenticating user must be the recipient of the specified direct message. path => 'direct_messages/destroy/:id', method => 'POST', params => [qw/id include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'DirectMessage', ); twitter_api_method show_friendship => ( description => <<'', Returns detailed information about the relationship between two users. aliases => [qw/show_relationship/], path => 'friendships/show', method => 'GET', params => [qw/source_id source_screen_name target_id target_id_name/], required => [qw/id/], returns => 'Relationship', ); twitter_api_method create_friend => ( description => <<'', Befriends the user specified in the ID parameter as the authenticating user. Returns the befriended user when successful. Returns a string describing the failure condition when unsuccessful. aliases => [qw/follow_new/], path => 'friendships/create/:id', method => 'POST', params => [qw/id user_id screen_name follow include_entities/], booleans => [qw/include_entities follow/], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method destroy_friend => ( description => <<'', Discontinues friendship with the user specified in the ID parameter as the authenticating user. Returns the un-friended user when successful. Returns a string describing the failure condition when unsuccessful. aliases => [qw/unfollow/], path => 'friendships/destroy/:id', method => 'POST', params => [qw/id user_id screen_name include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method friendship_exists => ( aliases => [qw/relationship_exists follows/], # Net::Twitter description => <<'EOT', Tests for the existence of friendship between two users. Will return true if user_a follows user_b, otherwise will return false. Use of C and C is deprecated. It has been preserved for backwards compatibility, and is used for the two-argument positional form: $nt->friendship_exists($user_a, $user_b); Instead, you should use one of the named argument forms: $nt->friendship_exists({ user_id_a => $id1, user_id_b => $id2 }); $nt->friendship_exists({ screen_name_a => $name1, screen_name_b => $name2 }); Consider using C instead. EOT path => 'friendships/exists', method => 'GET', params => [qw/user_id_a user_id_b screen_name_a screen_name_b user_a user_b/], required => [qw/user_a user_b/], returns => 'Bool', ); twitter_api_method no_retweet_ids => ( description => <<'', Returns an ARRAY ref of user IDs for which the authenticating user does not want to receive retweets. path => 'friendships/no_retweet_ids', method => 'GET', params => [], required => [], returns => 'ArrayRef[UserIDs]', ); twitter_api_method friends_ids => ( description => <<'EOT', Returns a reference to an array of numeric IDs for every user followed by the specified user. The order of the IDs is reverse chronological. Use the optional C parameter to retrieve IDs in pages of 5000. When the C parameter is used, the return value is a reference to a hash with keys C, C, and C. The value of C is a reference to an array of IDS of the user's friends. Set the optional C parameter to -1 to get the first page of IDs. Set it to the prior return's value of C or C to page forward or backwards. When there are no prior pages, the value of C will be 0. When there are no subsequent pages, the value of C will be 0. EOT aliases => [qw/following_ids/], path => 'friends/ids/:id', method => 'GET', params => [qw/id user_id screen_name cursor/], required => [qw/id/], returns => 'HashRef|ArrayRef[Int]', ); twitter_api_method followers_ids => ( description => <<'EOT', Returns a reference to an array of numeric IDs for every user following the specified user. The order of the IDs may change from call to call. To obtain the screen names, pass the arrayref to L. Use the optional C parameter to retrieve IDs in pages of 5000. When the C parameter is used, the return value is a reference to a hash with keys C, C, and C. The value of C is a reference to an array of IDS of the user's followers. Set the optional C parameter to -1 to get the first page of IDs. Set it to the prior return's value of C or C to page forward or backwards. When there are no prior pages, the value of C will be 0. When there are no subsequent pages, the value of C will be 0. EOT path => 'followers/ids/:id', method => 'GET', params => [qw/id user_id screen_name cursor/], required => [qw/id/], returns => 'HashRef|ArrayRef[Int]', ); twitter_api_method verify_credentials => ( description => <<'', Returns an HTTP 200 OK response code and a representation of the requesting user if authentication was successful; returns a 401 status code and an error message if not. Use this method to test if supplied user credentials are valid. path => 'account/verify_credentials', method => 'GET', params => [qw/include_entities/], booleans => [qw/include_entities/], required => [qw//], returns => 'ExtendedUser', ); twitter_api_method end_session => ( description => <<'', Ends the session of the authenticating user, returning a null cookie. Use this method to sign users out of client-facing applications like widgets. path => 'account/end_session', method => 'POST', params => [qw//], required => [qw//], returns => 'Error', # HTTP Status: 200, error content. Silly! ); twitter_api_method update_location => ( description => <<'', This method has been deprecated in favor of the update_profile method. Its URL will continue to work, but please consider migrating to the newer and more comprehensive method of updating profile attributes. deprecated => 1, path => 'account/update_location', method => 'POST', params => [qw/location/], required => [qw/location/], returns => 'BasicUser', ); twitter_api_method update_delivery_device => ( description => <<'', Sets which device Twitter delivers updates to for the authenticating user. Sending none as the device parameter will disable IM or SMS updates. path => 'account/update_delivery_device', method => 'POST', params => [qw/device/], required => [qw/device/], returns => 'BasicUser', ); twitter_api_method update_profile_colors => ( description => <<'', Sets one or more hex values that control the color scheme of the authenticating user's profile page on twitter.com. These values are also returned in the /users/show API method. path => 'account/update_profile_colors', method => 'POST', params => [qw/ profile_background_color profile_text_color profile_link_color profile_sidebar_fill_color profile_sidebar_border_color /], required => [qw//], returns => 'ExtendedUser', ); twitter_api_method update_profile_image => ( description => <<'EOT', Updates the authenticating user's profile image. The C parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array (C<$file>) is the name of a file to open. The second value (C<$filename>) is the name given to Twitter for the file. If C<$filename> is not provided, the basename portion of C<$file> is used. If C<$mime_type> is not provided, it will be provided automatically using L. C<$raw_image_data> can be provided, rather than opening a file, by passing C as the first array value. EOT path => 'account/update_profile_image', method => 'POST', params => [qw/image/], required => [qw/image/], returns => 'ExtendedUser', ); twitter_api_method update_profile_background_image => ( description => <<'', Updates the authenticating user's profile background image. The C parameter must be an arrayref with the same interpretation as the C parameter in the C method. The C parameter allows you to specify whether to use the uploaded profile background or not. See that method's documentation for details. path => 'account/update_profile_background_image', method => 'POST', params => [qw/image use/], required => [qw/image/], booleans => [qw/use/], returns => 'ExtendedUser', ); twitter_api_method rate_limit_status => ( description => <<'EOT', Returns the remaining number of API requests available to the authenticated user before the API limit is reached for the current hour. Use C<< ->rate_limit_status({ authenticate => 0 }) >> to force an unauthenticated call, which will return the status for the IP address rather than the authenticated user. (Note: for a web application, this is the server's IP address.) EOT path => 'account/rate_limit_status', method => 'GET', params => [qw//], required => [qw//], returns => 'RateLimitStatus', ); twitter_api_method update_profile => ( description => <<'', Sets values that users are able to set under the "Account" tab of their settings page. Only the parameters specified will be updated; to only update the "name" attribute, for example, only include that parameter in your request. path => 'account/update_profile', method => 'POST', params => [qw/ name email url location description include_entities/], booleans => [qw/include_entities/], required => [qw//], returns => 'ExtendedUser', ); twitter_api_method favorites => ( description => <<'', Returns the 20 most recent favorite statuses for the authenticating user or user specified by the ID parameter. path => 'favorites/:id', method => 'GET', params => [qw/id page include_entities/], booleans => [qw/include_entities/], required => [qw//], returns => 'ArrayRef[Status]', ); twitter_api_method create_favorite => ( description => <<'', Favorites the status specified in the ID parameter as the authenticating user. Returns the favorite status when successful. path => 'favorites/create/:id', method => 'POST', params => [qw/id include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'Status', ); twitter_api_method destroy_favorite => ( description => <<'', Un-favorites the status specified in the ID parameter as the authenticating user. Returns the un-favorited status. path => 'favorites/destroy/:id', method => 'POST', params => [qw/id include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'Status', ); twitter_api_method enable_notifications => ( description => <<'', Enables notifications for updates from the specified user to the authenticating user. Returns the specified user when successful. path => 'notifications/follow/:id', method => 'POST', params => [qw/id screen_name include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method disable_notifications => ( description => <<'', Disables notifications for updates from the specified user to the authenticating user. Returns the specified user when successful. path => 'notifications/leave/:id', method => 'POST', params => [qw/id screen_name include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method create_block => ( description => <<'', Blocks the user specified in the ID parameter as the authenticating user. Returns the blocked user when successful. You can find out more about blocking in the Twitter Support Knowledge Base. path => 'blocks/create/:id', method => 'POST', params => [qw/id user_id screen_name include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method destroy_block => ( description => <<'', Un-blocks the user specified in the ID parameter as the authenticating user. Returns the un-blocked user when successful. path => 'blocks/destroy/:id', method => 'POST', params => [qw/id user_id screen_name/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method block_exists => ( description => <<'', Returns if the authenticating user is blocking a target user. Will return the blocked user's object if a block exists, and error with HTTP 404 response code otherwise. path => 'blocks/exists/:id', method => 'GET', params => [qw/id user_id screen_name include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method blocking => ( description => <<'', Returns an array of user objects that the authenticating user is blocking. path => 'blocks/blocking', method => 'GET', params => [qw/page include_entities/], booleans => [qw/include_entities/], required => [qw//], returns => 'ArrayRef[BasicUser]', ); twitter_api_method blocking_ids => ( description => <<'', Returns an array of numeric user ids the authenticating user is blocking. path => 'blocks/blocking/ids', method => 'GET', params => [qw//], required => [qw//], returns => 'ArrayRef[Int]', ); twitter_api_method test => ( description => <<'', Returns the string "ok" status code. path => 'help/test', method => 'GET', params => [qw//], required => [qw//], returns => 'Str', ); twitter_api_method downtime_schedule => ( description => <<'', Returns the same text displayed on L when a maintenance window is scheduled. deprecated => 1, path => 'help/downtime_schedule', method => 'GET', params => [qw//], required => [qw//], returns => 'Str', ); twitter_api_method get_configuration => ( path => 'help/configuration', method => 'GET', params => [], required => [], returns => 'HashRef', description => <<'EOT', Returns the current configuration used by Twitter including twitter.com slugs which are not usernames, maximum photo resolutions, and t.co URL lengths. It is recommended applications request this endpoint when they are loaded, but no more than once a day. EOT ); twitter_api_method get_languages => ( path => 'help/languages', method => 'GET', params => [], required => [], returns => 'ArrayRef[Lanugage]', description => <<'', Returns the list of languages supported by Twitter along with their ISO 639-1 code. The ISO 639-1 code is the two letter value to use if you include lang with any of your requests. ); twitter_api_method saved_searches => ( description => <<'', Returns the authenticated user's saved search queries. path => 'saved_searches', method => 'GET', params => [], required => [], returns => 'ArrayRef[SavedSearch]', ); twitter_api_method show_saved_search => ( description => <<'', Retrieve the data for a saved search, by C, owned by the authenticating user. path => 'saved_searches/show/:id', method => 'GET', params => [qw/id/], required => [qw/id/], returns => 'SavedSearch', ); twitter_api_method create_saved_search => ( description => <<'', Creates a saved search for the authenticated user. path => 'saved_searches/create', method => 'POST', params => [qw/query/], required => [qw/query/], returns => 'SavedSearch', ); twitter_api_method destroy_saved_search => ( description => <<'', Destroys a saved search. The search, specified by C, must be owned by the authenticating user. path => 'saved_searches/destroy/:id', method => 'POST', params => [qw/id/], required => [qw/id/], returns => 'SavedSearch', ); twitter_api_method report_spam => ( description => <<'', The user specified in the id is blocked by the authenticated user and reported as a spammer. path => 'report_spam', method => 'POST', params => [qw/id user_id screen_name include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'User', ); twitter_api_method users_search => ( aliases => [qw/find_people search_users/], path => 'users/search', method => 'GET', params => [qw/q per_page page include_entities/], booleans => [qw/include_entities/], required => [qw/q/], returns => 'ArrayRef[Users]', description => <<'', Run a search for users similar to Find People button on Twitter.com; the same results returned by people search on Twitter.com will be returned by using this API (about being listed in the People Search). It is only possible to retrieve the first 1000 matches from this API. ); twitter_api_method trends_available => ( path => 'trends/available', method => 'GET', params => [qw/lat long/], required => [], authenticate => 0, returns => 'ArrayRef[Location]', description => <) and some other human-readable information such as a the location's canonical name and country. When the optional C and C parameters are passed, the available trend locations are sorted by distance from that location, nearest to farthest. Use the WOEID returned in the location object to query trends for a specific location. EOT ); twitter_api_method trends_location => ( path => 'trends/:woeid', method => 'GET', params => [qw/woeid/], required => [qw/woeid/], returns => 'ArrayRef[Trend]', authenticate => 0, description => <<'', Returns the top 10 trending topics for a specific location. The response is an array of "trend" objects that encode the name of the trending topic, the query parameter that can be used to search for the topic on Search, and the direct URL that can be issued against Search. This information is cached for five minutes, and therefore users are discouraged from querying these endpoints faster than once every five minutes. Global trends information is also available from this API by using a WOEID of 1. ); twitter_api_method trends => ( description => <<'', Returns the top ten queries that are currently trending on Twitter. The response includes the time of the request, the name of each trending topic, and the url to the Twitter Search results page for that topic. path => 'trends', method => 'GET', params => [qw//], required => [qw//], authenticate => 0, returns => 'ArrayRef[Query]', deprecated => 1, ); my $trends_deprecation_warned = 0; around trends => sub { my $orig = shift; my $self = shift; my $args = ref $_[-1] eq ref {} ? pop : {}; $trends_deprecation_warned ||= do { local $Carp::CarpLevel = 3; carp "The 'trends' API method has been deprecated; instead, use trends_location({ woeid => 1 })"; 1; }; $args->{woeid} = 1; return $self->trends_location(@_, $args); }; twitter_api_method trends_current => ( description => <<'', Returns the current top ten trending topics on Twitter. The response includes the time of the request, the name of each trending topic, and query used on Twitter Search results page for that topic. path => 'trends/current', method => 'GET', params => [qw/exclude/], required => [qw//], authenticate => 0, returns => 'HashRef', ); twitter_api_method trends_daily => ( description => <<'', Returns the top 20 trending topics for each hour in a given day. path => 'trends/daily', method => 'GET', params => [qw/date exclude/], required => [qw//], authenticate => 0, returns => 'HashRef', ); twitter_api_method trends_weekly => ( description => <<'', Returns the top 30 trending topics for each day in a given week. path => 'trends/weekly', method => 'GET', params => [qw/date exclude/], required => [qw//], authenticate => 0, returns => 'HashRef', ); twitter_api_method reverse_geocode => ( path => 'geo/reverse_geocode', method => 'GET', params => [qw/lat long accuracy granularity max_results/], required => [qw/lat long/], returns => 'HashRef', description => <<'EOT', Search for places (cities and neighborhoods) that can be attached to a statuses/update. Given a latitude and a longitude, return a list of all the valid places that can be used as a place_id when updating a status. Conceptually, a query can be made from the user's location, retrieve a list of places, have the user validate the location he or she is at, and then send the ID of this location up with a call to statuses/update. There are multiple granularities of places that can be returned -- "neighborhoods", "cities", etc. At this time, only United States data is available through this method. =over 4 =item lat Required. The latitude to query about. Valid ranges are -90.0 to +90.0 (North is positive) inclusive. =item long Required. The longitude to query about. Valid ranges are -180.0 to +180.0 (East is positive) inclusive. =item accuracy Optional. A hint on the "region" in which to search. If a number, then this is a radius in meters, but it can also take a string that is suffixed with ft to specify feet. If this is not passed in, then it is assumed to be 0m. If coming from a device, in practice, this value is whatever accuracy the device has measuring its location (whether it be coming from a GPS, WiFi triangulation, etc.). =item granularity Optional. The minimal granularity of data to return. If this is not passed in, then C is assumed. C can also be passed. =item max_results Optional. A hint as to the number of results to return. This does not guarantee that the number of results returned will equal max_results, but instead informs how many "nearby" results to return. Ideally, only pass in the number of places you intend to display to the user here. =back EOT ); twitter_api_method geo_id => ( path => 'geo/id/:id', method => 'GET', params => [qw/id/], required => [qw/id/], returns => 'HashRef', description => <<'EOT', Returns details of a place returned from the C method. EOT ); twitter_api_method geo_search => ( path => 'geo/search', method => 'GET', params => [qw/ lat long query ip granularity accuracy max_results contained_within attribute:street_address callback /], required => [], returns => 'HashRef', description => <<'EOT', Search for places that can be attached to a statuses/update. Given a latitude and a longitude pair, an IP address, or a name, this request will return a list of all the valid places that can be used as the place_id when updating a status. Conceptually, a query can be made from the user's location, retrieve a list of places, have the user validate the location he or she is at, and then send the ID of this location with a call to statuses/update. This is the recommended method to use find places that can be attached to statuses/update. Unlike geo/reverse_geocode which provides raw data access, this endpoint can potentially re-order places with regards to the user who is authenticated. This approach is also preferred for interactive place matching with the user. EOT ); twitter_api_method similar_places => ( path => 'geo/similar_places', method => 'GET', params => [qw/lat long name contained_within attribute:street_address callback/], required => [qw/lat long name/], returns => 'HashRef', description => <<'EOT', Locates places near the given coordinates which are similar in name. Conceptually you would use this method to get a list of known places to choose from first. Then, if the desired place doesn't exist, make a request to C to create a new one. The token contained in the response is the token needed to be able to create a new place. EOT ); twitter_api_method add_place => ( path => 'geo/place', method => 'POST', params => [qw/name contained_within token lat long attribute:street_address callback/], required => [qw/name contained_within token lat long/], returns => 'Place', description => <<'EOT', Creates a new place object at the given latitude and longitude. Before creating a place you need to query C with the latitude, longitude and name of the place you wish to create. The query will return an array of places which are similar to the one you wish to create, and a token. If the place you wish to create isn't in the returned array you can use the token with this method to create a new one. EOT ); twitter_api_method lookup_users => ( path => 'users/lookup', method => 'GET', params => [qw/user_id screen_name include_entities/], booleans => [qw/include_entities/], required => [], returns => 'ArrayRef[User]', description => <<'EOT' Return up to 100 users worth of extended information, specified by either ID, screen name, or combination of the two. The author's most recent status (if the authenticating user has permission) will be returned inline. This method is rate limited to 1000 calls per hour. This method will accept user IDs or screen names as either a comma delimited string, or as an ARRAY ref. It will also accept arguments in the normal HASHREF form or as a simple list of named arguments. I.e., any of the following forms are acceptable: $nt->lookup_users({ user_id => '1234,6543,3333' }); $nt->lookup_users(user_id => '1234,6543,3333'); $nt->lookup_users({ user_id => [ 1234, 6543, 3333 ] }); $nt->lookup_users({ screen_name => 'fred,barney,wilma' }); $nt->lookup_users(screen_name => ['fred', 'barney', 'wilma']); $nt->lookup_users( screen_name => ['fred', 'barney' ], user_id => '4321,6789', ); EOT ); twitter_api_method retweeted_by => ( path => 'statuses/:id/retweeted_by', method => 'GET', params => [qw/id count page trim_user include_entities/], booleans => [qw/include_entities trim_user/], required => [qw/id/], returns => 'ArrayRef[User]', description => <<'' Returns up to 100 users who retweeted the status identified by C. ); twitter_api_method retweeted_by_ids => ( path => 'statuses/:id/retweeted_by/ids', method => 'GET', params => [qw/id count page trim_user include_entities/], booleans => [qw/include_entities trim_user/], required => [qw/id/], returns => 'ArrayRef[User]', description => <<'' Returns the IDs of up to 100 users who retweeted the status identified by C. ); twitter_api_method friendships_incoming => ( path => 'friendships/incoming', method => 'GET', params => [qw/cursor/], required => [qw/cursor/], returns => 'HashRef', description => <<'', Returns an HASH ref with an array of numeric IDs in the C element for every user who has a pending request to follow the authenticating user. ); twitter_api_method friendships_outgoing => ( path => 'friendships/outgoing', method => 'GET', params => [qw/cursor/], required => [qw/cursor/], returns => 'HashRef', description => <<'', Returns an HASH ref with an array of numeric IDs in the C element for every protected user for whom the authenticating user has a pending follow request. ); # new in 3.17001 2010-10-19 twitter_api_method account_totals => ( path => 'account/totals', method => 'GET', params => [], required => [], returns => 'HashRef', description => <<'' Returns the current count of friends, followers, updates (statuses) and favorites of the authenticating user. ); twitter_api_method account_settings => ( path => 'account/settings', method => 'GET', params => [], required => [], returns => 'HashRef', description => <<'' Returns the current trend, geo and sleep time information for the authenticating user. ); twitter_api_method suggestion_categories => ( path => 'users/suggestions', method => 'GET', params => [], required => [], returns => 'ArrayRef', description => <<'' Returns the list of suggested user categories. The category slug can be used in the C API method get the users in that category . Does not require authentication. ); twitter_api_method user_suggestions => ( aliases => [qw/follow_suggestions/], path => 'users/suggestions/:category/members', method => 'GET', params => [qw/category lang/], required => [qw/category/], returns => 'ArrayRef', description => <<'' Access the users in a given category of the Twitter suggested user list and return their most recent status if they are not a protected user. Currently supported values for optional parameter C are C, C, C, C, C. Does not require authentication. ); twitter_api_method show_direct_message => ( path => 'direct_messages/show/:id', method => 'GET', params => [qw/id include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'HashRef', description => <<'' Returns a single direct message, specified by an id parameter. Like the C request, this method will include the user objects of the sender and recipient. Requires authentication. ); twitter_api_method retweeted_to_user => ( path => 'statuses/retweeted_to_user', method => 'GET', params => [qw/id user_id screen_name/], required => [qw/id/], returns => 'ArrayRef', description => <<'' Returns the 20 most recent retweets posted by users the specified user follows. The user is specified using the user_id or screen_name parameters. This method is identical to C except you can choose the user to view. Does not require authentication, unless the user is protected. ); twitter_api_method retweeted_by_user => ( path => 'statuses/retweeted_by_user', method => 'GET', params => [qw/id user_id screen_name/], required => [qw/id/], returns => 'ArrayRef', description => <<'' Returns the 20 most recent retweets posted by the specified user. The user is specified using the user_id or screen_name parameters. This method is identical to C except you can choose the user to view. Does not require authentication, unless the user is protected. ); twitter_api_method lookup_friendships => ( path => 'friendships/lookup', method => 'GET', params => [qw/user_id screen_name/], required => [], returns => 'ArrayRef', description => <<'' Returns the relationship of the authenticating user to the comma separated list or ARRAY ref of up to 100 screen_names or user_ids provided. Values for connections can be: following, following_requested, followed_by, none. Requires authentication. ); twitter_api_method update_friendship => ( path => 'friendships/update', method => 'POST', params => [qw/id user_id screen_name device retweets/], required => [qw/id/], booleans => [qw/device retweets/], returns => 'HashRef', description => <<'' Allows you enable or disable retweets and device notifications from the specified user. All other values are assumed to be false. Requires authentication. ); twitter_api_method related_results => ( path => 'related_results/show/:id', method => 'GET', params => [qw/id/], required => [qw/id/], returns => 'ArrayRef[Status]', description => <<'' If available, returns an array of replies and mentions related to the specified status. There is no guarantee there will be any replies or mentions in the response. This method is only available to users who have access to #newtwitter. Requires authentication. ); ### Lists ### twitter_api_method all_subscriptions => ( path => 'lists/all', method => 'GET', params => [qw/user_id screen_name count cursor/], required => [], returns => 'ArrayRef[List]', aliases => [qw/all_lists list_subscriptions/], description => <<'', Returns all lists the authenticating or specified user subscribes to, including their own. The user is specified using the user_id or screen_name parameters. If no user is given, the authenticating user is used. ); twitter_api_method list_statuses => ( path => 'lists/statuses', method => 'GET', params => [qw/ list_id slug owner_screen_name owner_id since_id max_id per_page page include_entities include_rts /], required => [], booleans => [qw/include_entities include_rts/], returns => 'ArrayRef[Status]', description => <<'', Returns tweet timeline for members of the specified list. Historically, retweets were not available in list timeline responses but you can now use the include_rts=true parameter to additionally receive retweet objects. ); twitter_api_method delete_list_member => ( path => 'lists/members/destroy', method => 'POST', params => [qw/list_id slug user_id screen_name owner_screen_name owner_id/], required => [], returns => 'User', aliases => [qw/remove_list_member/], description => <<'', Removes the specified member from the list. The authenticated user must be the list's owner to remove members from the list. ); twitter_api_method list_memberships => ( path => 'lists/memberships', method => 'GET', params => [qw/user_id screen_name cursor filter_to_owned_lists/], required => [], booleans => [qw/filter_to_owned_lists/], returns => 'Hashref', description => <<'', Returns the lists the specified user has been added to. If user_id or screen_name are not provided the memberships for the authenticating user are returned. ); twitter_api_method list_subscribers => ( path => 'lists/subscribers', method => 'GET', params => [qw/list_id slug owner_screen_name owner_id cursor include_entities skip_status/], required => [], booleans => [qw/include_entities skip_status/], returns => 'Hashref', description => <<'', Returns the subscribers of the specified list. Private list subscribers will only be shown if the authenticated user owns the specified list. ); twitter_api_method subscribe_list => ( path => 'lists/subscribers/create', method => 'POST', params => [qw/owner_screen_name owner_id list_id slug/], required => [], returns => 'List', description => <<'', Subscribes the authenticated user to the specified list. ); twitter_api_method is_list_subscriber => ( path => 'lists/subscribers/show', method => 'GET', params => [qw/ owner_screen_name owner_id list_id slug user_id screen_name include_entities skip_status /], required => [], booleans => [qw/include_entities skip_status/], returns => 'Maybe[User]', aliases => [qw/is_subscribed_list/], description => <<'', Check if the specified user is a subscriber of the specified list. Returns the user or undef. ); around [qw/is_list_subscriber is_subscribed_list/] => sub { my $orig = shift; my $self = shift; $self->_user_or_undef($orig, 'subscriber', @_); }; twitter_api_method unsubscribe_list => ( path => 'lists/subscribers/destroy', method => 'POST', params => [qw/list_id slug owner_screen_name owner_id/], required => [], returns => 'List', description => <<'', Unsubscribes the authenticated user from the specified list. ); twitter_api_method members_create_all => ( path => 'lists/members/create_all', method => 'POST', params => [qw/list_id slug owner_screen_name owner_id/], required => [], returns => 'List', aliases => [qw/add_list_members/], description => <<'', Adds multiple members to a list, by specifying a reference to an array or a comma-separated list of member ids or screen names. The authenticated user must own the list to be able to add members to it. Note that lists can't have more than 500 members, and you are limited to adding up to 100 members to a list at a time with this method. ); twitter_api_method members_destroy_all => ( path => 'lists/members/destroy_all', method => 'POST', params => [qw/list_id slug user_id screen_name owner_screen_name owner_id/], required => [], returns => 'List', aliases => [qw/remove_list_members/], description => <<'EOT', Removes multiple members from a list, by specifying a reference to an array of member ids or screen names, or a string of comma separated user ids or screen names. The authenticated user must own the list to be able to remove members from it. Note that lists can't have more than 500 members, and you are limited to removing up to 100 members to a list at a time with this method. Please note that there can be issues with lists that rapidly remove and add memberships. Take care when using these methods such that you are not too rapidly switching between removals and adds on the same list. EOT ); twitter_api_method is_list_member => ( path => 'lists/members/show', method => 'GET', params => [qw/ owner_screen_name owner_id list_id slug user_id screen_name include_entities skip_status /], required => [], booleans => [qw/include_entities skip_status/], returns => 'Maybe[User]', description => <<'', Check if the specified user is a member of the specified list. Returns the user or undef. ); around is_list_member => sub { my $orig = shift; my $self = shift; $self->_user_or_undef($orig, 'member', @_); }; twitter_api_method list_members => ( path => 'lists/members', method => 'GET', params => [qw/ list_id slug owner_screen_name owner_id cursor include_entities skip_status /], required => [], booleans => [qw/include_entities skip_status/], returns => 'Hashref', description => <<'', Returns the members of the specified list. Private list members will only be shown if the authenticated user owns the specified list. ); twitter_api_method add_list_member => ( path => 'lists/members/create', method => 'POST', params => [qw/list_id slug user_id screen_name owner_screen_name owner_id/], required => [], returns => 'User', description => <<'', Add a member to a list. The authenticated user must own the list to be able to add members to it. Note that lists can't have more than 500 members. ); twitter_api_method delete_list => ( path => 'lists/destroy', method => 'POST', params => [qw/owner_screen_name owner_id list_id slug/], required => [], returns => 'List', description => <<'', Deletes the specified list. The authenticated user must own the list to be able to destroy it. ); twitter_api_method update_list => ( path => 'lists/update', method => 'POST', params => [qw/list_id slug name mode description owner_screen_name owner_id/], required => [], returns => 'List', description => <<'', Updates the specified list. The authenticated user must own the list to be able to update it. ); twitter_api_method create_list => ( path => 'lists/create', method => 'POST', params => [qw/list_id slug name mode description owner_screen_name owner_id/], required => [], returns => 'List', description => <<'', Creates a new list for the authenticated user. Note that you can't create more than 20 lists per account. ); twitter_api_method get_lists => ( path => 'lists', method => 'GET', params => [qw/user_id screen_name cursor/], required => [], returns => 'Hashref', aliases => [qw/list_lists/], description => <<'', Returns the lists of the specified (or authenticated) user. Private lists will be included if the authenticated user is the same as the user whose lists are being returned. ); twitter_api_method get_list => ( path => 'lists/show', method => 'GET', params => [qw/list_id slug owner_screen_name owner_id/], required => [], returns => 'List', description => <<'', Returns the specified list. Private lists will only be shown if the authenticated user owns the specified list. ); twitter_api_method subscriptions => ( path => 'lists/subscriptions', method => 'GET', params => [qw/user_id screen_name count cursor/], required => [], returns => 'ArrayRef[List]', aliases => [], description => <<'', Obtain a collection of the lists the specified user is subscribed to, 20 lists per page by default. Does not include the user's own lists. ); ### Legal ### twitter_api_method get_privacy_policy => ( path => 'legal/privacy', method => 'GET', params => [], required => [], returns => 'HashRef', description => <<'', Returns Twitter's privacy policy. ); twitter_api_method get_tos => ( path => 'legal/tos', method => 'GET', params => [], required => [], returns => 'HashRef', description => <<'', Returns the Twitter Terms of Service. These are not the same as the Developer Rules of the Road. ); 1; __END__ =head1 NAME Net::Twitter::Role::API::REST - A definition of the Twitter REST API as a Moose role =head1 VERSION version 4.01043 =head1 SYNOPSIS package My::Twitter; use Moose; with 'Net::Twitter::API::REST'; =head1 DESCRIPTION B provides definitions for all the Twitter REST API methods. Applying this role to any class provides methods for all of the Twitter REST API methods. =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2009 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/Role/API/RESTv1_1.pm000644 000766 000024 00000222032 13227713560 022222 0ustar00marcstaff000000 000000 package Net::Twitter::Role::API::RESTv1_1; $Net::Twitter::Role::API::RESTv1_1::VERSION = '4.01043'; use Moose::Role; use Carp::Clan qw/^(?:Net::Twitter|Moose|Class::MOP)/; use Net::Twitter::API; use DateTime::Format::Strptime; use URI; with 'Net::Twitter::Role::API::UploadMedia'; # API v1.1 incorporates the Search and Upload APIs excludes map "Net::Twitter::Role::$_", qw/API::Search API::Upload Net::Twitter::Role::RateLimit/; has apiurl => ( isa => 'Str', is => 'ro', default => 'http://api.twitter.com/1.1' ); has apihost => ( isa => 'Str', is => 'ro', lazy => 1, builder => '_build_apihost' ); has apirealm => ( isa => 'Str', is => 'ro', default => 'Twitter API' ); sub _build_apihost { my $uri = URI->new(shift->apiurl); join ':', $uri->host, $uri->port; } after BUILD => sub { my $self = shift; $self->{apiurl} =~ s/^http:/https:/ if $self->ssl; }; base_url 'apiurl'; authenticate 1; our $DATETIME_PARSER = DateTime::Format::Strptime->new(pattern => '%a %b %d %T %z %Y'); datetime_parser $DATETIME_PARSER; twitter_api_method mentions => ( description => <<'', Returns the 20 most recent mentions (statuses containing @username) for the authenticating user. aliases => [qw/replies mentions_timeline/], path => 'statuses/mentions_timeline', method => 'GET', params => [qw/since_id max_id count trim_user include_entities contributor_details/], booleans => [qw/trim_user include_entities contributor_details/], required => [], returns => 'ArrayRef[Status]', ); twitter_api_method user_timeline => ( description => <<'', Returns the 20 most recent statuses posted by the authenticating user, or the user specified by C or C. path => 'statuses/user_timeline', method => 'GET', params => [qw/user_id screen_name since_id max_id count trim_user exclude_replies include_rts contributor_details/], booleans => [qw/trim_user exclude_replies include_rts contributor_details/], required => [], returns => 'ArrayRef[Status]', ); twitter_api_method home_timeline => ( description => <<'', Returns the 20 most recent statuses, including retweets, posted by the authenticating user and that user's friends. path => 'statuses/home_timeline', method => 'GET', params => [qw/since_id max_id count exclude_replies contributor_details include_entities trim_user/], booleans => [qw/skip_user exclude_replies contributor_details include_rts include_entities trim_user include_my_retweet/], required => [], returns => 'ArrayRef[Status]', ); twitter_api_method friends_timeline => ( description => <<'', Returns the 20 most recent statuses, including retweets, posted by the authenticating user and that user's friends. path => 'statuses/home_timeline', aliases => [qw/following_timeline/], method => 'GET', params => [qw/since_id max_id count exclude_replies contributor_details include_entities trim_user/], booleans => [qw/skip_user exclude_replies contributor_details include_rts include_entities trim_user include_my_retweet/], required => [], returns => 'ArrayRef[Status]', deprecated => sub { carp "$_[0] DEPRECATED: using home_timeline instead" }, ); twitter_api_method retweets => ( description => <<'', Returns up to 100 of the first retweets of a given tweet. path => 'statuses/retweets/:id', method => 'GET', params => [qw/id count trim_user/], booleans => [qw/trim_user/], required => [qw/id/], returns => 'Arrayref[Status]', ); twitter_api_method show_status => ( description => <<'', Returns a single status, specified by the id parameter. The status's author will be returned inline. path => 'statuses/show/:id', method => 'GET', params => [qw/id trim_user include_entities include_my_retweet/], booleans => [qw/trim_user include_entities include_my_retweet/], required => [qw/id/], returns => 'Status', ); twitter_api_method destroy_status => ( description => <<'', Destroys the status specified by the required ID parameter. The authenticating user must be the author of the specified status. path => 'statuses/destroy/:id', method => 'POST', params => [qw/id trim_user/], booleans => [qw/trim_user/], required => [qw/id/], returns => 'Status', ); twitter_api_method update => ( path => 'statuses/update', method => 'POST', params => [qw/ attachment_url display_coordinates in_reply_to_status_id lat long media_ids place_id status trim_user /], required => [qw/status/], booleans => [qw/display_coordinates trim_user/], add_source => 1, returns => 'Status', description => <. \=item display_coordinates Optional. By default, geo-tweets will have their coordinates exposed in the status object (to remain backwards compatible with existing API applications). To turn off the display of the precise latitude and longitude (but keep the contextual location information), pass C 0> on the status update. \=back EOT ); twitter_api_method retweet => ( description => <<'', Retweets a tweet. path => 'statuses/retweet/:id', method => 'POST', params => [qw/idtrim_user/], booleans => [qw/trim_user/], required => [qw/id/], returns => 'Status', ); twitter_api_method update_with_media => ( deprecated => 1, path => 'statuses/update_with_media', method => 'POST', params => [qw/ status media[] possibly_sensitive in_reply_to_status_id lat long place_id display_coordinates /], required => [qw/status media[]/], booleans => [qw/possibly_sensitive display_coordinates/], returns => 'Status', description => <<'EOT', Updates the authenticating user's status and attaches media for upload. Note that Twitter has marked this endpoint as B, and recommends instead calling C, then (optionally) C, then C. The C parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array (C<$file>) is the name of a file to open. The second value (C<$filename>) is the name given to Twitter for the file. If C<$filename> is not provided, the basename portion of C<$file> is used. If C<$mime_type> is not provided, it will be provided automatically using L. C<$raw_image_data> can be provided, rather than opening a file, by passing C as the first array value. The Tweet text will be rewritten to include the media URL(s), which will reduce the number of characters allowed in the Tweet text. If the URL(s) cannot be appended without text truncation, the tweet will be rejected and this method will return an HTTP 403 error. EOT ); twitter_api_method oembed => ( description => <<'EOT', Returns information allowing the creation of an embedded representation of a Tweet on third party sites. See the L specification for information about the response format. While this endpoint allows a bit of customization for the final appearance of the embedded Tweet, be aware that the appearance of the rendered Tweet may change over time to be consistent with Twitter's L. Do not rely on any class or id parameters to stay constant in the returned markup. EOT method => 'GET', path => 'statuses/oembed', params => [qw/id url maxwidth hide_media hide_thread omit_script align related lang/], required => [qw//], booleans => [qw/hide_media hide_thread omit_script/], returns => 'Status', ); twitter_api_method retweeters_ids => ( description => <<'EOT', Returns a collection of up to 100 user IDs belonging to users who have retweeted the tweet specified by the id parameter. This method offers similar data to C and replaces API v1's C method. EOT method => 'GET', path => 'statuses/retweeters/ids', params => [qw/id cursor stringify_ids/], required => [qw/id/], booleans => [qw/stringify_ids/], returns => 'HashRef', ); twitter_api_method search => ( description => <<'EOT', Returns a HASH reference with some meta-data about the query including the C, C, and C. The statuses are returned in C. To iterate over the results, use something similar to: my $r = $nt->search($search_term); for my $status ( @{$r->{statuses}} ) { print "$status->{text}\n"; } EOT path => 'search/tweets', method => 'GET', params => [qw/q count callback lang locale rpp since_id max_id until geocode result_type include_entities/], required => [qw/q/], booleans => [qw/include_entities/], returns => 'HashRef', ); twitter_api_method direct_messages => ( description => <<'EOT', Returns a list of the 20 most recent direct messages sent to the authenticating user including detailed information about the sending and recipient users. Important: this method requires an access token with RWD (read, write, and direct message) permissions. EOT path => 'direct_messages', method => 'GET', params => [qw/since_id max_id count page include_entities skip_status/], required => [], booleans => [qw/include_entities skip_status/], returns => 'ArrayRef[DirectMessage]', ); twitter_api_method sent_direct_messages => ( description => <<'EOT', Returns a list of the 20 most recent direct messages sent by the authenticating user including detailed information about the sending and recipient users. Important: this method requires an access token with RWD (read, write, and direct message) permissions. EOT aliases => [qw/direct_messages_sent/], path => 'direct_messages/sent', method => 'GET', params => [qw/since_id max_id page count include_entities/], booleans => [qw/include_entities/], required => [qw//], returns => 'ArrayRef[DirectMessage]', ); twitter_api_method show_direct_message => ( description => <<'EOT', Returns a single direct message, specified by an id parameter. Like the C request, this method will include the user objects of the sender and recipient. Requires authentication. Important: this method requires an access token with RWD (read, write, and direct message) permissions. EOT path => 'direct_messages/show', method => 'GET', params => [qw/id/], booleans => [], required => [qw/id/], returns => 'HashRef', ); twitter_api_method destroy_direct_message => ( description => <<'EOT', Destroys the direct message specified in the required ID parameter. The authenticating user must be the recipient of the specified direct message. Important: this method requires an access token with RWD (read, write, and direct message) permissions. EOT path => 'direct_messages/destroy', method => 'POST', params => [qw/id include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'DirectMessage', ); twitter_api_method new_direct_message => ( description => <<'EOT', Sends a new direct message to the specified user from the authenticating user. Requires both the user and text parameters. Returns the sent message when successful. In order to support numeric screen names, the C or C parameters may be used instead of C. Important: this method requires an access token with RWD (read, write, and direct message) permissions. EOT path => 'direct_messages/new', method => 'POST', params => [qw/user_id screen_name text/], booleans => [qw//], required => [qw/text/], returns => 'DirectMessage', ); around new_direct_message => sub { my $orig = shift; my $self = shift; my $args = ref $_[-1] eq ref {} ? pop : {}; $args->{user} = shift unless exists $args->{user} || exists $args->{screen_name} || exists $args->{user_id}; $args->{text} = shift unless exists $args->{text}; croak "too many args" if @_; if ( my $user = delete $args->{user} ) { warn "user argument to new_direct_message deprecated; use screen_name or user_id"; if ( $user =~ /^\d+$/ ) { $args->{user_id} = $user; } else { $args->{screen_name} = $user; } } return $self->$orig($args); }; twitter_api_method friends_ids => ( description => <<'EOT', Returns a reference to an array of numeric IDs for every user followed by the specified user. The order of the IDs is reverse chronological. Use the optional C parameter to retrieve IDs in pages of 5000. When the C parameter is used, the return value is a reference to a hash with keys C, C, and C. The value of C is a reference to an array of IDS of the user's friends. Set the optional C parameter to -1 to get the first page of IDs. Set it to the prior return's value of C or C to page forward or backwards. When there are no prior pages, the value of C will be 0. When there are no subsequent pages, the value of C will be 0. EOT aliases => [qw/following_ids/], path => 'friends/ids', method => 'GET', params => [qw/user_id screen_name cursor stringify_ids/], required => [qw//], booleans => [qw/stringify_ids/], returns => 'HashRef|ArrayRef[Int]', ); twitter_api_method followers => ( description => <<'', Returns a cursored collection of user objects for users following the specified user. aliases => [qw/followers_list/], path => 'followers/list', method => 'GET', params => [qw/user_id screen_name cursor/], required => [qw//], returns => 'HashRef', ); twitter_api_method friends => ( description => <<'', Returns a cursored collection of user objects for users followed by the specified user. aliases => [qw/friends_list/], path => 'friends/list', method => 'GET', params => [qw/user_id screen_name cursor/], required => [qw//], returns => 'HashRef', ); twitter_api_method followers_ids => ( description => <<'EOT', Returns a reference to an array of numeric IDs for every user following the specified user. The order of the IDs may change from call to call. To obtain the screen names, pass the arrayref to L. Use the optional C parameter to retrieve IDs in pages of 5000. When the C parameter is used, the return value is a reference to a hash with keys C, C, and C. The value of C is a reference to an array of IDS of the user's followers. Set the optional C parameter to -1 to get the first page of IDs. Set it to the prior return's value of C or C to page forward or backwards. When there are no prior pages, the value of C will be 0. When there are no subsequent pages, the value of C will be 0. EOT path => 'followers/ids', method => 'GET', params => [qw/user_id screen_name cursor/], params => [qw/user_id screen_name cursor stringify_ids/], required => [qw//], booleans => [qw/stringify_ids/], returns => 'HashRef|ArrayRef[Int]', ); twitter_api_method lookup_friendships => ( path => 'friendships/lookup', method => 'GET', params => [qw/user_id screen_name/], required => [], returns => 'ArrayRef', description => <<'' Returns the relationship of the authenticating user to the comma separated list or ARRAY ref of up to 100 screen_names or user_ids provided. Values for connections can be: following, following_requested, followed_by, none. Requires authentication. ); twitter_api_method friendships_incoming => ( description => <<'EOT', Returns an HASH ref with an array of numeric IDs in the C element for every user who has a pending request to follow the authenticating user. EOT aliases => [qw/incoming_friendships/], path => 'friendships/incoming', method => 'GET', params => [qw/cursor stringify_ids/], required => [], booleans => [qw/stringify_ids/], returns => 'HashRef', ); twitter_api_method friendships_outgoing => ( description => <<'EOT', Returns an HASH ref with an array of numeric IDs in the C element for every protected user for whom the authenticating user has a pending follow request. EOT aliases => [qw/outgoing_friendships/], path => 'friendships/outgoing', method => 'GET', params => [qw/cursor stringify_ids/], required => [], booleans => [qw/stringify_ids/], returns => 'HashRef', ); twitter_api_method create_friend => ( description => <<'', Follows the user specified in the C or C parameter as the authenticating user. Returns the befriended user when successful. Returns a string describing the failure condition when unsuccessful. aliases => [qw/follow follow_new create_friendship/], path => 'friendships/create', method => 'POST', params => [qw/user_id screen_name follow/], booleans => [qw/follow/], required => [qw//], returns => 'BasicUser', ); twitter_api_method destroy_friend => ( description => <<'', Discontinues friendship with the user specified in the C or C parameter as the authenticating user. Returns the un-friended user when successful. Returns a string describing the failure condition when unsuccessful. aliases => [qw/unfollow destroy_friendship/], path => 'friendships/destroy', method => 'POST', params => [qw/user_id screen_name/], booleans => [qw//], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method update_friendship => ( path => 'friendships/update', method => 'POST', params => [qw/user_id screen_name device retweets/], required => [qw//], booleans => [qw/device retweets/], returns => 'HashRef', description => <<'' Allows you enable or disable retweets and device notifications from the specified user. All other values are assumed to be false. Requires authentication. ); twitter_api_method show_friendship => ( description => <<'', Returns detailed information about the relationship between two users. aliases => [qw/show_relationship/], path => 'friendships/show', method => 'GET', params => [qw/source_id source_screen_name target_id target_screen_name/], required => [qw//], returns => 'Relationship', ); # infer source and target from positional args for convenience around show_friendship => sub { my $orig = shift; my $self = shift; my $args = ref $_[-1] eq ref {} ? pop : {}; if ( @_ == 2 ) { for ( qw/source target/ ) { my $id = shift; $$args{$id =~ /^\d+$/ ? "${_}_id" : "${_}_screen_name"} = $id; } } return $self->$orig(@_, $args); }; # provided for backwards compatibility twitter_api_method friendship_exists => ( description => <<'EOT', This method is provided for backwards compatibility with Twitter API V1.0. Twitter API V1.1 does not provide an endpoint for this call. Instead, C is called, the result is inspected, and an appropriate value is returned which can be evaluated in a boolean context. Tests for the existence of friendship between two users. Will return true if user_a follows user_b, otherwise will return false. Use of C and C is deprecated. It has been preserved for backwards compatibility, and is used for the two-argument positional form: $nt->friendship_exists($user_a, $user_b); Instead, you should use one of the named argument forms: $nt->friendship_exists({ user_id_a => $id1, user_id_b => $id2 }); $nt->friendship_exists({ screen_name_a => $name1, screen_name_b => $name2 }); Consider using C instead. EOT aliases => [qw/relationship_exists follows/], path => 'friendships/show', method => 'GET', params => [qw/user_id_a user_id_b screen_name_a screen_name_b user_a user_b/], required => [qw/user_a user_b/], returns => 'Bool', deprecated => sub { carp "$_[0] DEPRECATED: using show_friendship instead" }, ); around [qw/friendship_exists relationship_exists follows/] => sub { my $orig = shift; my $self = shift; my $args = ref $_[-1] eq ref {} ? pop : {}; my ( $user_a, $user_b ) = @_; # default ags, if they exist if ( $user_a ||= delete $$args{user_a} ) { if ( $user_a =~ /^\d+$/ ) { $$args{source_id} = $user_a; } else { $$args{source_screen_name} = $user_a; } } elsif ( $user_a = delete $$args{screen_name_a} ) { $$args{source_screen_name} = $user_a; } elsif ( $user_a = delete $$args{user_id_a} ) { $$args{source_user_id} = $user_a; } else { croak "source user not specified"; } if ( $user_b ||= delete $$args{user_b} ) { if ( $user_b =~ /^\d+$/ ) { $$args{target_id} = $user_b; } else { $$args{target_screen_name} = $user_b; } } elsif ( $user_b = delete $$args{screen_name_b} ) { $$args{target_screen_name} = $user_b; } elsif ( $user_b = delete $$args{user_id_b} ) { $$args{target_user_id} = $user_b; } else { croak "target user not specified"; } my $r = $self->$orig($args); return !!$$r{relationship}{target}{followed_by}; }; twitter_api_method account_settings => ( description => <<'', Returns the current trend, geo and sleep time information for the authenticating user. path => 'account/settings', method => 'GET', params => [], required => [], returns => 'HashRef', ); twitter_api_method verify_credentials => ( description => <<'', Returns an HTTP 200 OK response code and a representation of the requesting user if authentication was successful; returns a 401 status code and an error message if not. Use this method to test if supplied user credentials are valid. path => 'account/verify_credentials', method => 'GET', params => [qw/include_entities skip_status include_email/], booleans => [qw/include_entities skip_status include_email/], required => [qw//], returns => 'ExtendedUser', ); twitter_api_method update_account_settings => ( description => <<'', Updates the authenticating user's settings. path => 'account/settings', method => 'POST', params => [qw/trend_location_woid sleep_time_enabled start_sleep_time end_sleep_time time_zone lang/], required => [], booleans => [qw/sleep_time_enabled/], returns => 'HashRef', ); twitter_api_method update_delivery_device => ( description => <<'', Sets which device Twitter delivers updates to for the authenticating user. Sending none as the device parameter will disable SMS updates. path => 'account/update_delivery_device', method => 'POST', params => [qw/device include_entities/], required => [qw/device/], booleans => [qw/include_entities/], returns => 'BasicUser', ); twitter_api_method update_profile => ( description => <<'', Sets values that users are able to set under the "Account" tab of their settings page. Only the parameters specified will be updated; to only update the "name" attribute, for example, only include that parameter in your request. path => 'account/update_profile', method => 'POST', params => [qw/name url location description include_entities skip_status/], required => [qw//], booleans => [qw/include_entities skip_status/], returns => 'ExtendedUser', ); twitter_api_method update_location => ( description => <<'', This method has been deprecated in favor of the update_profile method. Its URL will continue to work, but please consider migrating to the newer and more comprehensive method of updating profile attributes. path => 'account/update_profile', method => 'POST', params => [qw/location/], required => [qw/location/], returns => 'BasicUser', deprecated => sub { carp "$_[0] DEPRECATED: using update_profile instead" }, ); twitter_api_method update_profile_background_image => ( description => <<'', Updates the authenticating user's profile background image. The C parameter must be an arrayref with the same interpretation as the C parameter in the C method. See that method's documentation for details. The C parameter allows you to specify whether to use the uploaded profile background or not. path => 'account/update_profile_background_image', method => 'POST', params => [qw/image tile include_entities skip_status use/], required => [qw//], booleans => [qw/include_entities skip_status use/], returns => 'ExtendedUser', ); twitter_api_method update_profile_colors => ( description => <<'', Sets one or more hex values that control the color scheme of the authenticating user's profile page on twitter.com. These values are also returned in the /users/show API method. path => 'account/update_profile_colors', method => 'POST', params => [qw/ profile_background_color profile_text_color profile_link_color profile_sidebar_fill_color profile_sidebar_border_color include_entities skip_status /], required => [qw//], booleans => [qw/include_entities skip_status/], returns => 'ExtendedUser', ); twitter_api_method update_profile_image => ( description => <<'EOT', Updates the authenticating user's profile image. The C parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array (C<$file>) is the name of a file to open. The second value (C<$filename>) is the name given to Twitter for the file. If C<$filename> is not provided, the basename portion of C<$file> is used. If C<$mime_type> is not provided, it will be provided automatically using L. C<$raw_image_data> can be provided, rather than opening a file, by passing C as the first array value. EOT path => 'account/update_profile_image', method => 'POST', params => [qw/image include_entities skip_status/], required => [qw/image/], booleans => [qw/include_entities skip_status/], returns => 'ExtendedUser', ); twitter_api_method blocking => ( description => <<'', Returns an array of user objects that the authenticating user is blocking. path => 'blocks/list', aliases => [qw/blocks_list/], method => 'GET', params => [qw/cursor include_entities skip_status/], required => [qw//], returns => 'ArrayRef[BasicUser]', ); twitter_api_method blocking_ids => ( description => <<'', Returns an array of numeric user ids the authenticating user is blocking. path => 'blocks/ids', aliases => [qw/blocks_ids/], method => 'GET', params => [qw/cursor stringify_ids/], required => [qw//], booleans => [qw/stringify_ids/], returns => 'ArrayRef[Int]', ); twitter_api_method create_block => ( description => <<'', Blocks the user specified in the C or C parameter as the authenticating user. Returns the blocked user when successful. You can find out more about blocking in the Twitter Support Knowledge Base. path => 'blocks/create', method => 'POST', params => [qw/user_id screen_name include_entities skip_status/], booleans => [qw/include_entities skip_status/], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method destroy_block => ( description => <<'', Un-blocks the user specified in the C or C parameter as the authenticating user. Returns the un-blocked user when successful. path => 'blocks/destroy', method => 'POST', params => [qw/user_id screen_name include_entities skip_status/], booleans => [qw/include_entities skip_status/], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method lookup_users => ( description => <<'EOT', Return up to 100 users worth of extended information, specified by either ID, screen name, or combination of the two. The author's most recent status (if the authenticating user has permission) will be returned inline. This method is rate limited to 1000 calls per hour. This method will accept user IDs or screen names as either a comma delimited string, or as an ARRAY ref. It will also accept arguments in the normal HASHREF form or as a simple list of named arguments. I.e., any of the following forms are acceptable: $nt->lookup_users({ user_id => '1234,6543,3333' }); $nt->lookup_users(user_id => '1234,6543,3333'); $nt->lookup_users({ user_id => [ 1234, 6543, 3333 ] }); $nt->lookup_users({ screen_name => 'fred,barney,wilma' }); $nt->lookup_users(screen_name => ['fred', 'barney', 'wilma']); $nt->lookup_users( screen_name => ['fred', 'barney' ], user_id => '4321,6789', ); EOT path => 'users/lookup', method => 'GET', params => [qw/user_id screen_name include_entities/], booleans => [qw/include_entities/], required => [], returns => 'ArrayRef[User]', ); twitter_api_method show_user => ( description => <<'', Returns extended information of a given user, specified by ID or screen name as per the required id parameter. This information includes design settings, so third party developers can theme their widgets according to a given user's preferences. You must be properly authenticated to request the page of a protected user. path => 'users/show', method => 'GET', params => [qw/user_id screen_name include_entities/], booleans => [qw/include_entities/], required => [qw//], returns => 'ExtendedUser', ); twitter_api_method users_search => ( description => <<'', Run a search for users similar to Find People button on Twitter.com; the same results returned by people search on Twitter.com will be returned by using this API (about being listed in the People Search). It is only possible to retrieve the first 1000 matches from this API. aliases => [qw/find_people search_users/], path => 'users/search', method => 'GET', params => [qw/q per_page page count include_entities/], booleans => [qw/include_entities/], required => [qw/q/], returns => 'ArrayRef[Users]', ); twitter_api_method contributees => ( deprecated => 1, path => 'users/contributees', method => 'GET', params => [qw/user_id screen_name include_entities skip_satus/], required => [], booleans => [qw/include_entities skip_satus/], returns => 'ArrayRef[User]', description => <<'', Returns an array of users that the specified user can contribute to. ); twitter_api_method contributors => ( deprecated => 1, path => 'users/contributors', method => 'GET', params => [qw/user_id screen_name include_entities skip_satus/], required => [], booleans => [qw/include_entities skip_satus/], returns => 'ArrayRef[User]', description => <<'', Returns an array of users who can contribute to the specified account. ); twitter_api_method suggestion_categories => ( path => 'users/suggestions', method => 'GET', params => [], required => [], returns => 'ArrayRef', description => <<'' Returns the list of suggested user categories. The category slug can be used in the C API method get the users in that category . Does not require authentication. ); twitter_api_method user_suggestions_for => ( aliases => [qw/follow_suggestions_for/], path => 'users/suggestions/:slug', method => 'GET', params => [qw/slug lang/], required => [qw/slug/], returns => 'ArrayRef', description => <<'' Access the users in a given slug (category) of the Twitter suggested user list. ); twitter_api_method user_suggestions => ( aliases => [qw/follow_suggestions/], path => 'users/suggestions/:slug/members', method => 'GET', params => [qw/slug lang/], required => [qw/slug/], returns => 'ArrayRef', description => <<'' Access the users in a given slug (category) of the Twitter suggested user list and return their most recent status if they are not a protected user. Currently supported values for optional parameter C are C, C, C, C, C. Does not require authentication. ); # backwards compatibility: Twitter renamed "category" to "slug" around [ qw/follow_suggestions follow_suggestions_for user_suggestions user_suggestions_for/ ] => sub { my ( $next, $self ) = splice @_, 0, 2; my $args = ref $_[-1] eq 'HASH' ? pop : {}; if ( exists $args->{category} ) { $args->{slug} = delete $args->{category}; } return $self->$next(@_, $args); }; twitter_api_method favorites => ( description => <<'', Returns the 20 most recent favorite statuses for the authenticating user or user specified by the ID parameter. path => 'favorites/list', method => 'GET', params => [qw/user_id screen_name count since_id max_id include_entities/], booleans => [qw/include_entities/], required => [qw//], returns => 'ArrayRef[Status]', ); twitter_api_method destroy_favorite => ( description => <<'', Un-favorites the status specified in the ID parameter as the authenticating user. Returns the un-favorited status. path => 'favorites/destroy', method => 'POST', params => [qw/id include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'Status', ); twitter_api_method create_favorite => ( description => <<'', Favorites the status specified in the ID parameter as the authenticating user. Returns the favorite status when successful. path => 'favorites/create', method => 'POST', params => [qw/id include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'Status', ); ### Lists ### twitter_api_method get_lists => ( description => <<'EOT', Returns all lists the authenticating or specified user subscribes to, including their own. The user is specified using the user_id or screen_name parameters. If no user is given, the authenticating user is used. A maximum of 100 results will be returned by this call. Subscribed lists are returned first, followed by owned lists. This means that if a user subscribes to 90 lists and owns 20 lists, this method returns 90 subscriptions and 10 owned lists. The reverse method returns owned lists first, so with C 1>, 20 owned lists and 80 subscriptions would be returned. If your goal is to obtain every list a user owns or subscribes to, use and/or C instead. EOT path => 'lists/list', aliases => [qw/list_lists all_subscriptions/], method => 'GET', params => [qw/user_id screen_name reverse/], required => [], returns => 'Hashref', ); twitter_api_method list_statuses => ( description => <<'', Returns tweet timeline for members of the specified list. Historically, retweets were not available in list timeline responses but you can now use the include_rts=true parameter to additionally receive retweet objects. path => 'lists/statuses', method => 'GET', params => [qw/ list_id slug owner_screen_name owner_id since_id max_id count include_entities include_rts /], required => [], booleans => [qw/include_entities include_rts/], returns => 'ArrayRef[Status]', ); twitter_api_method delete_list_member => ( description => <<'', Removes the specified member from the list. The authenticated user must be the list's owner to remove members from the list. path => 'lists/members/destroy', method => 'POST', params => [qw/list_id slug user_id screen_name owner_screen_name owner_id/], required => [], returns => 'User', aliases => [qw/remove_list_member/], ); twitter_api_method list_memberships => ( description => <<'', Returns the lists the specified user has been added to. If user_id or screen_name are not provided the memberships for the authenticating user are returned. path => 'lists/memberships', method => 'GET', params => [qw/user_id screen_name cursor filter_to_owned_lists/], required => [], booleans => [qw/filter_to_owned_lists/], returns => 'Hashref', ); twitter_api_method list_subscribers => ( path => 'lists/subscribers', method => 'GET', params => [qw/list_id slug owner_screen_name owner_id cursor include_entities skip_status/], required => [], booleans => [qw/include_entities skip_status/], returns => 'Hashref', description => <<'', Returns the subscribers of the specified list. Private list subscribers will only be shown if the authenticated user owns the specified list. ); twitter_api_method subscribe_list => ( description => <<'', Subscribes the authenticated user to the specified list. path => 'lists/subscribers/create', method => 'POST', params => [qw/owner_screen_name owner_id list_id slug/], required => [], returns => 'List', ); twitter_api_method show_list_subscriber => ( description => <<'', Returns the user if they are a subscriber. path => 'lists/subscribers/show', aliases => [qw/is_list_subscriber is_subscriber_lists/], method => 'GET', params => [qw/ owner_screen_name owner_id list_id slug user_id screen_name include_entities skip_status /], required => [], booleans => [qw/include_entities skip_status/], returns => 'User', ); around [qw/is_list_subscriber is_subscriber_lists/] => sub { my $orig = shift; my $self = shift; $self->_user_or_undef($orig, 'subscriber', @_); }; twitter_api_method unsubscribe_list => ( description => <<'', Unsubscribes the authenticated user from the specified list. path => 'lists/subscribers/destroy', method => 'POST', params => [qw/list_id slug owner_screen_name owner_id/], required => [], returns => 'List', ); twitter_api_method members_create_all => ( description => <<'', Adds multiple members to a list, by specifying a reference to an array or a comma-separated list of member ids or screen names. The authenticated user must own the list to be able to add members to it. Note that lists can't have more than 500 members, and you are limited to adding up to 100 members to a list at a time with this method. path => 'lists/members/create_all', method => 'POST', params => [qw/list_id slug owner_screen_name owner_id/], required => [], returns => 'List', aliases => [qw/add_list_members/], ); twitter_api_method show_list_member => ( description => <<'', Check if the specified user is a member of the specified list. Returns the user or undef. path => 'lists/members/show', aliases => [qw/is_list_member/], method => 'GET', params => [qw/ owner_screen_name owner_id list_id slug user_id screen_name include_entities skip_status /], required => [], booleans => [qw/include_entities skip_status/], returns => 'Maybe[User]', ); around is_list_member => sub { my $orig = shift; my $self = shift; $self->_user_or_undef($orig, 'member', @_); }; twitter_api_method list_members => ( description => <<'', Returns the members of the specified list. Private list members will only be shown if the authenticated user owns the specified list. path => 'lists/members', method => 'GET', params => [qw/ list_id slug owner_screen_name owner_id cursor include_entities skip_status /], required => [], booleans => [qw/include_entities skip_status/], returns => 'Hashref', ); twitter_api_method add_list_member => ( description => <<'', Add a member to a list. The authenticated user must own the list to be able to add members to it. Note that lists can't have more than 500 members. path => 'lists/members/create', method => 'POST', params => [qw/list_id slug user_id screen_name owner_screen_name owner_id/], required => [], returns => 'User', ); twitter_api_method delete_list => ( description => <<'', Deletes the specified list. The authenticated user must own the list to be able to destroy it. path => 'lists/destroy', method => 'POST', params => [qw/owner_screen_name owner_id list_id slug/], required => [], returns => 'List', ); twitter_api_method update_list => ( description => <<'', Updates the specified list. The authenticated user must own the list to be able to update it. path => 'lists/update', method => 'POST', params => [qw/list_id slug name mode description owner_screen_name owner_id/], required => [], returns => 'List', ); twitter_api_method create_list => ( description => <<'', Creates a new list for the authenticated user. Note that you can't create more than 20 lists per account. path => 'lists/create', method => 'POST', params => [qw/list_id slug name mode description owner_screen_name owner_id/], required => [qw/name/], returns => 'List', ); twitter_api_method get_list => ( description => <<'', Returns the specified list. Private lists will only be shown if the authenticated user owns the specified list. aliases => [qw/show_list/], path => 'lists/show', method => 'GET', params => [qw/list_id slug owner_screen_name owner_id/], required => [], returns => 'List', ); twitter_api_method list_subscriptions => ( description => <<'', Obtain a collection of the lists the specified user is subscribed to, 20 lists per page by default. Does not include the user's own lists. path => 'lists/subscriptions', method => 'GET', params => [qw/user_id screen_name count cursor/], required => [], returns => 'ArrayRef[List]', aliases => [qw/subscriptions/], ); twitter_api_method members_destroy_all => ( description => <<'EOT', Removes multiple members from a list, by specifying a reference to an array of member ids or screen names, or a string of comma separated user ids or screen names. The authenticated user must own the list to be able to remove members from it. Note that lists can't have more than 500 members, and you are limited to removing up to 100 members to a list at a time with this method. Please note that there can be issues with lists that rapidly remove and add memberships. Take care when using these methods such that you are not too rapidly switching between removals and adds on the same list. EOT path => 'lists/members/destroy_all', aliases => [qw/remove_list_members/], method => 'POST', params => [qw/list_id slug user_id screen_name owner_screen_name owner_id/], required => [], returns => 'List', ); twitter_api_method list_ownerships => ( description => <<'', Obtain a collection of the lists owned by the specified Twitter user. Private lists will only be shown if the authenticated user is also the owner of the lists. path => 'lists/ownerships', method => 'GET', params => [qw/user_id screen_name count cursor/], required => [], returns => 'ArrayRef[List]', aliases => [], ); ## saved searches ## twitter_api_method saved_searches => ( description => <<'', Returns the authenticated user's saved search queries. path => 'saved_searches/list', method => 'GET', params => [], required => [], returns => 'ArrayRef[SavedSearch]', ); twitter_api_method show_saved_search => ( description => <<'', Retrieve the data for a saved search, by C, owned by the authenticating user. path => 'saved_searches/show/:id', method => 'GET', params => [qw/id/], required => [qw/id/], returns => 'SavedSearch', ); twitter_api_method create_saved_search => ( description => <<'', Creates a saved search for the authenticated user. path => 'saved_searches/create', method => 'POST', params => [qw/query/], required => [qw/query/], returns => 'SavedSearch', ); twitter_api_method destroy_saved_search => ( description => <<'', Destroys a saved search. The search, specified by C, must be owned by the authenticating user. aliases => [qw/delete_saved_search/], path => 'saved_searches/destroy/:id', method => 'POST', params => [qw/id/], required => [qw/id/], returns => 'SavedSearch', ); ## geo ## twitter_api_method geo_id => ( description => <<'', Returns details of a place returned from the C method. path => 'geo/id/:place_id', method => 'GET', params => [qw/place_id/], required => [qw/place_id/], returns => 'HashRef', ); # backwards compat for 'geo/id/:id' # recast to 'geo/id/:place_id around geo_id => sub { my ( $next, $self ) = splice @_, 0, 2; my $args = ref $_[-1] eq 'HASH' ? pop @_ : {}; if ( exists $args->{id} ) { $args->{place_id} = delete $args->{id}; } return $self->$next(@_, $args); }; twitter_api_method reverse_geocode => ( description => < is assumed. C can also be passed. \=item max_results Optional. A hint as to the number of results to return. This does not guarantee that the number of results returned will equal max_results, but instead informs how many "nearby" results to return. Ideally, only pass in the number of places you intend to display to the user here. \=back EOT path => 'geo/reverse_geocode', method => 'GET', params => [qw/lat long accuracy granularity max_results callback/], required => [qw/lat long/], returns => 'HashRef', ); twitter_api_method geo_search => ( description => <<'EOT', Search for places that can be attached to a statuses/update. Given a latitude and a longitude pair, an IP address, or a name, this request will return a list of all the valid places that can be used as the place_id when updating a status. Conceptually, a query can be made from the user's location, retrieve a list of places, have the user validate the location he or she is at, and then send the ID of this location with a call to statuses/update. This is the recommended method to use find places that can be attached to statuses/update. Unlike geo/reverse_geocode which provides raw data access, this endpoint can potentially re-order places with regards to the user who is authenticated. This approach is also preferred for interactive place matching with the user. EOT path => 'geo/search', method => 'GET', params => [qw/ lat long query ip granularity accuracy max_results contained_within attribute:street_address callback /], required => [], returns => 'HashRef', ); twitter_api_method similar_places => ( description => <<'EOT', Locates places near the given coordinates which are similar in name. Conceptually you would use this method to get a list of known places to choose from first. Then, if the desired place doesn't exist, make a request to C to create a new one. The token contained in the response is the token needed to be able to create a new place. EOT path => 'geo/similar_places', method => 'GET', params => [qw/lat long name contained_within attribute:street_address callback/], required => [qw/lat long name/], returns => 'HashRef', ); twitter_api_method add_place => ( description => <<'EOT', Creates a new place object at the given latitude and longitude. Before creating a place you need to query C with the latitude, longitude and name of the place you wish to create. The query will return an array of places which are similar to the one you wish to create, and a token. If the place you wish to create isn't in the returned array you can use the token with this method to create a new one. EOT path => 'geo/place', method => 'POST', params => [qw/name contained_within token lat long attribute:street_address callback/], required => [qw/name contained_within token lat long/], returns => 'Place', ); ## trends ## twitter_api_method trends_place => ( description => <<'', Returns the top 10 trending topics for a specific WOEID. The response is an array of "trend" objects that encode the name of the trending topic, the query parameter that can be used to search for the topic on Search, and the direct URL that can be issued against Search. This information is cached for five minutes, and therefore users are discouraged from querying these endpoints faster than once every five minutes. Global trends information is also available from this API by using a WOEID of 1. path => 'trends/place', aliases => [qw/trends_location/], method => 'GET', params => [qw/id exclude/], required => [qw/id/], returns => 'ArrayRef[Trend]', ); # accept woeid parameter for backwards compatibility with old trends/location endpoint around trends_location => sub { my $orig = shift; my $self = shift; carp "trends_location DEPRECATED: using trends_place({ id => ... }) instead"; my $args = ref $_[-1] eq ref {} ? pop : {}; $$args{id} = delete $$args{woeid} || shift; return $self->$orig($args); }; twitter_api_method trends_available => ( description => <) and some other human-readable information such as a the location's canonical name and country. For backwards compatibility, this method accepts optional C and C parameters. You should call C directly, instead. Use the WOEID returned in the location object to query trends for a specific location. EOT path => 'trends/available', method => 'GET', params => [], required => [], returns => 'ArrayRef[Location]', ); around trends_available => sub { my $orig = shift; my $self = shift; my $args = ref $_[-1] eq ref {} ? pop : {}; my $method = exists $$args{lat} || exists $$args{long} ? 'trends_closest' : $orig; return $self->$method(@_, $args); }; twitter_api_method trends_closest => ( description => <) and some other human-readable information such as a the location's canonical name and country. The results are sorted by distance from that location, nearest to farthest. Use the WOEID returned in the location object to query trends for a specific location. EOT path => 'trends/closest', method => 'GET', params => [qw/lat long/], required => [], returns => 'ArrayRef[Location]', ); ## spam reporting ## twitter_api_method report_spam => ( description => <<'', The user specified in the id is blocked by the authenticated user and reported as a spammer. path => 'users/report_spam', method => 'POST', params => [qw/user_id screen_name/], required => [qw/id/], returns => 'User', ); twitter_api_method get_languages => ( description => <<'', Returns the list of languages supported by Twitter along with their ISO 639-1 code. The ISO 639-1 code is the two letter value to use if you include lang with any of your requests. path => 'help/languages', method => 'GET', params => [], required => [], returns => 'ArrayRef[Lanugage]', ); ## Help ## twitter_api_method get_configuration => ( description => <<'EOT', Returns the current configuration used by Twitter including twitter.com slugs which are not usernames, maximum photo resolutions, and t.co URL lengths. It is recommended applications request this endpoint when they are loaded, but no more than once a day. EOT path => 'help/configuration', method => 'GET', params => [], required => [], returns => 'HashRef', ); twitter_api_method get_privacy_policy => ( description => <<'', Returns Twitter's privacy policy. path => 'help/privacy', method => 'GET', params => [], required => [], returns => 'HashRef', ); twitter_api_method get_tos => ( description => <<'', Returns the Twitter Terms of Service. These are not the same as the Developer Rules of the Road. path => 'help/tos', method => 'GET', params => [], required => [], returns => 'HashRef', ); twitter_api_method rate_limit_status => ( description => <<'EOT', Returns the remaining number of API requests available to the authenticated user before the API limit is reached for the current hour. Use C<< ->rate_limit_status({ authenticate => 0 }) >> to force an unauthenticated call, which will return the status for the IP address rather than the authenticated user. (Note: for a web application, this is the server's IP address.) EOT path => 'application/rate_limit_status', method => 'GET', params => [qw/resources/], required => [qw//], returns => 'RateLimitStatus', ); # translate resources arrayref to a comma separated string around rate_limit_status => sub { my $orig = shift; my $self = shift; my $args = ref $_[-1] eq ref {} ? pop : {}; croak "too many arguments" if @_; if ( exists $args->{resources} && ref $args->{resources} eq ref [] ) { $args->{resources} = join ',' => @{$args->{resources}}; } return $self->$orig($args); }; twitter_api_method test => ( description => <<'', Returns the string "ok" status code. path => 'account/verify_credentials', method => 'GET', params => [qw//], required => [qw//], returns => 'Hash', deprecated => sub { carp "$_[0] DEPRECATED: using verify_credentials instead" }, ); ## not included in API v1.1 ## twitter_api_method retweeted_by_me => ( description => <<'', Returns the 20 most recent retweets posted by the authenticating user. path => 'statuses/retweeted_by_me', method => 'GET', params => [qw/since_id max_id count page trim_user include_entities/], booleans => [qw/trim_user include_entities/], required => [], returns => 'ArrayRef[Status]', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); twitter_api_method retweeted_to_me => ( description => <<'', Returns the 20 most recent retweets posted by the authenticating user's friends. path => 'statuses/retweeted_to_me', method => 'GET', params => [qw/since_id max_id count page/], required => [], returns => 'ArrayRef[Status]', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); twitter_api_method retweets_of_me => ( description => <<'', Returns the 20 most recent tweets of the authenticated user that have been retweeted by others. aliases => [qw/retweeted_of_me/], path => 'statuses/retweets_of_me', method => 'GET', params => [qw/since_id max_id count trim_user include_entities include_user_entities/], booleans => [qw/trim_user include_entities/], required => [], returns => 'ArrayRef[Status]', ); twitter_api_method no_retweet_ids => ( description => <<'', Returns an ARRAY ref of user IDs for which the authenticating user does not want to receive retweets. aliases => [qw/no_retweets_ids/], path => 'friendships/no_retweets/ids', method => 'GET', params => [], required => [], returns => 'ArrayRef[UserIDs]', ); twitter_api_method end_session => ( description => <<'', Ends the session of the authenticating user, returning a null cookie. Use this method to sign users out of client-facing applications like widgets. path => 'account/end_session', method => 'POST', params => [qw//], required => [qw//], returns => 'Error', # HTTP Status: 200, error content. Silly! deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); twitter_api_method enable_notifications => ( description => <<'', Enables notifications for updates from the specified user to the authenticating user. Returns the specified user when successful. path => 'notifications/follow/:id', method => 'POST', params => [qw/id screen_name include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'BasicUser', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); around enable_notifications => sub { my $orig = shift; my $self = shift; return $self->_enable_disable_notifications(1, @_); }; sub _enable_disable_notifications { my $self = shift; my $enable = shift; carp "enable_notifications/disable_notifications DEPRECATED: using update_friendship instead"; my $args = ref $_[-1] eq ref {} ? pop : {}; $$args{device} = $enable; return $self->update_friendship(@_, $args); }; twitter_api_method disable_notifications => ( description => <<'', Disables notifications for updates from the specified user to the authenticating user. Returns the specified user when successful. path => 'notifications/leave/:id', method => 'POST', params => [qw/id screen_name include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'BasicUser', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); around disable_notifications => sub { my $orig = shift; my $self = shift; return $self->_enable_disable_notifications(0, @_); }; twitter_api_method block_exists => ( description => <<'', Returns if the authenticating user is blocking a target user. Will return the blocked user's object if a block exists, and error with HTTP 404 response code otherwise. path => 'blocks/exists/:id', method => 'GET', params => [qw/id user_id screen_name include_entities/], booleans => [qw/include_entities/], required => [qw/id/], returns => 'BasicUser', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); twitter_api_method trends_current => ( description => <<'', Returns the current top ten trending topics on Twitter. The response includes the time of the request, the name of each trending topic, and query used on Twitter Search results page for that topic. path => 'trends/current', method => 'GET', params => [qw/exclude/], required => [qw//], returns => 'HashRef', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); around trends_current => sub { my $orig = shift; my $self = shift; carp "trends_current DEPRECATED: using trends_place({ id => 1 }) instead"; my $args = ref $_[-1] eq ref {} ? pop : {}; $$args{id} = 1; return $self->trends_place($args); }; twitter_api_method trends_daily => ( description => <<'', Returns the top 20 trending topics for each hour in a given day. path => 'trends/daily', method => 'GET', params => [qw/date exclude/], required => [qw//], returns => 'HashRef', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); twitter_api_method trends_weekly => ( description => <<'', Returns the top 30 trending topics for each day in a given week. path => 'trends/weekly', method => 'GET', params => [qw/date exclude/], required => [qw//], returns => 'HashRef', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); twitter_api_method retweeted_by => ( description => <<'', Returns up to 100 users who retweeted the status identified by C. path => 'statuses/:id/retweeted_by', method => 'GET', params => [qw/id count page trim_user include_entities/], booleans => [qw/include_entities trim_user/], required => [qw/id/], returns => 'ArrayRef[User]', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); twitter_api_method retweeted_by_ids => ( description => <<'', Returns the IDs of up to 100 users who retweeted the status identified by C. path => 'statuses/:id/retweeted_by/ids', method => 'GET', params => [qw/id count page trim_user include_entities/], booleans => [qw/include_entities trim_user/], required => [qw/id/], returns => 'ArrayRef[User]', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); # new in 3.17001 2010-10-19 twitter_api_method account_totals => ( description => <<'', Returns the current count of friends, followers, updates (statuses) and favorites of the authenticating user. path => 'account/totals', method => 'GET', params => [], required => [], returns => 'HashRef', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); twitter_api_method retweeted_to_user => ( description => <<'', Returns the 20 most recent retweets posted by users the specified user follows. The user is specified using the user_id or screen_name parameters. This method is identical to C except you can choose the user to view. Does not require authentication, unless the user is protected. path => 'statuses/retweeted_to_user', method => 'GET', params => [qw/id user_id screen_name/], required => [qw/id/], returns => 'ArrayRef', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); twitter_api_method retweeted_by_user => ( description => <<'', Returns the 20 most recent retweets posted by the specified user. The user is specified using the user_id or screen_name parameters. This method is identical to C except you can choose the user to view. Does not require authentication, unless the user is protected. path => 'statuses/retweeted_by_user', method => 'GET', params => [qw/id user_id screen_name/], required => [qw/id/], returns => 'ArrayRef', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); twitter_api_method related_results => ( description => <<'', If available, returns an array of replies and mentions related to the specified status. There is no guarantee there will be any replies or mentions in the response. This method is only available to users who have access to #newtwitter. Requires authentication. path => 'related_results/show/:id', method => 'GET', params => [qw/id/], required => [qw/id/], returns => 'ArrayRef[Status]', deprecated => sub { croak "$_[0] not available in Twitter API V1.1" }, ); twitter_api_method remove_profile_banner => ( description => <<'', Removes the uploaded profile banner for the authenticating user. path => 'account/remove_profile_banner', method => 'POST', params => [qw//], required => [qw//], returns => 'Nothing', ); twitter_api_method update_profile_banner => ( description => <<'EOT', Uploads a profile banner on behalf of the authenticating user. The C parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array (C<$file>) is the name of a file to open. The second value (C<$filename>) is the name given to Twitter for the file. If C<$filename> is not provided, the basename portion of C<$file> is used. If C<$mime_type> is not provided, it will be provided automatically using L. C<$raw_image_data> can be provided, rather than opening a file, by passing C as the first array value. EOT path => 'account/update_profile_banner', method => 'POST', params => [qw/banner width height offset_left offset_top/], required => [qw/banner/], returns => 'Nothing', ); twitter_api_method profile_banner => ( description => <<'', Returns a hash reference mapping available size variations to URLs that can be used to retrieve each variation of the banner. path => 'users/profile_banner', method => 'GET', params => [qw/user_id screen_name/], required => [qw//], returns => 'HashRef', ); twitter_api_method mutes => ( description => <<'', Returns an array of numeric user ids the authenticating user has muted. path => 'mutes/users/ids', aliases => [qw/muting_ids muted_ids/], method => 'GET', params => [qw/cursor/], required => [qw//], booleans => [qw//], returns => 'ArrayRef[Int]', ); twitter_api_method muting => ( description => <<'', Returns an array of user objects that the authenticating user is muting. path => 'mutes/users/list', aliases => [qw/mutes_list/], method => 'GET', params => [qw/cursor include_entities skip_status/], required => [qw//], returns => 'ArrayRef[BasicUser]', ); twitter_api_method create_mute => ( description => <<'', Mutes the user specified in the C or C parameter as the authenticating user. Returns the muted user when successful. You can find out more about muting in the Twitter Support Knowledge Base. path => 'mutes/users/create', method => 'POST', params => [qw/user_id screen_name/], booleans => [qw//], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method destroy_mute => ( description => <<'', Un-mutes the user specified in the C or C parameter as the authenticating user. Returns the un-muted user when successful. path => 'mutes/users/destroy', method => 'POST', params => [qw/user_id screen_name/], booleans => [qw//], required => [qw/id/], returns => 'BasicUser', ); twitter_api_method lookup_statuses => ( description => <<'', Returns a hash reference of tweets from an arbitrary set of ids. path => 'statuses/lookup', method => 'GET', params => [qw/id include_entities trim_user map/], required => [qw/id/], returns => 'HashRef', ); twitter_api_method create_media_metadata => ( path => 'media/metadata/create', method => 'POST', params => [qw/media_id alt_text/], required => [qw/media_id/], returns => 'HashRef', content_type => 'application/json', description => <<'EOT', Adds metadata -- alt text, in particular -- to a previously uploaded media object, specified by its ID. (One knows this ID via the return value of the preceding C call.) The C parameter must have as its value a hashref containing a single key-value pair. The key must be C, and the value is the alt text to assign to the media object. The text must be 400 characters or fewer in length. EOT ); # infer screen_name or user_id from positional args for backwards compatibility # and convenience around [qw/ show_user create_friend follow_new destroy_friend unfollow friends_ids following_ids followers_ids create_block destroy_block block_exists report_spam retweeted_by_user update_friendship /] => sub { my $orig = shift; my $self = shift; my $args = ref $_[-1] eq ref {} ? pop : {}; if ( @_ && !exists $$args{user_id} && !exists $$args{screen_name} ) { my $id = shift; $$args{$id =~ /^\d+\$/ ? 'user_id' : 'screen_name' } = $id; } return $self->$orig(@_, $args); }; 1; __END__ =head1 NAME Net::Twitter::Role::API::RESTv1_1 - A definition of the Twitter REST API v1.1 as a Moose role =head1 VERSION version 4.01043 =head1 SYNOPSIS package My::Twitter; use Moose; with 'Net::Twitter::API::RESTv1_1'; =head1 DESCRIPTION B provides definitions for all the Twitter REST API v1.1 methods. Applying this role to any class provides methods for all of the Twitter REST API methods. =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2009 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/Role/API/Search/000755 000766 000024 00000000000 13227713560 021624 5ustar00marcstaff000000 000000 Net-Twitter-4.01043/lib/Net/Twitter/Role/API/Search.pm000644 000766 000024 00000006407 13227713560 022171 0ustar00marcstaff000000 000000 package Net::Twitter::Role::API::Search; $Net::Twitter::Role::API::Search::VERSION = '4.01043'; use Moose::Role; use Net::Twitter::API; use DateTime::Format::Strptime; with 'Net::Twitter::Role::API::Search::Trends'; excludes 'Net::Twitter::Role::API::RESTv1_1'; has searchapiurl => ( isa => 'Str', is => 'rw', default => 'http://search.twitter.com' ); after BUILD => sub { my $self = shift; $self->{searchapiurl} =~ s/^http:/https:/ if $self->ssl; }; base_url 'searchapiurl'; authenticate 0; our $DATETIME_PARSER = DateTime::Format::Strptime->new(pattern => '%a, %d %b %Y %T %z'); datetime_parser $DATETIME_PARSER; twitter_api_method search => ( description => <<'EOT', Returns a HASH reference with some meta-data about the query including the C, C, and C. The statuses are returned in C. To iterate over the results, use something similar to: my $r = $nt->search($search_term); my $r = $nt->search({ q => $search_term, count => 10 }) for my $status ( @{$r->{results}} ) { print "$status->{text}\n"; } EOT path => 'search', method => 'GET', params => [qw/q geocode lang locale result_type count until since_id max_id include_entities callback/], required => [qw/q/], returns => 'HashRef', ); 1; __END__ =head1 NAME Net::Twitter::Role::API::Search - A definition of the Twitter Search API as a Moose role =head1 VERSION version 4.01043 =head1 SYNOPSIS package My::Twitter; use Moose; with 'Net::Twitter::API::Search'; =head1 DESCRIPTION B provides definitions for all the Twitter Search API methods. Applying this role to any class provides methods for all of the Twitter Search API methods. =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2009 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/Role/API/TwitterVision.pm000644 000766 000024 00000007320 13227713560 023611 0ustar00marcstaff000000 000000 package Net::Twitter::Role::API::TwitterVision; $Net::Twitter::Role::API::TwitterVision::VERSION = '4.01043'; use Moose::Role; requires qw/credentials/; use Net::Twitter::API; has tvurl => ( isa => 'Str', is => 'ro', default => 'http://twittervision.com' ); has tvhost => ( isa => 'Str', is => 'ro', default => 'twittervision.com:80' ); has tvrealm => ( isa => 'Str', is => 'ro', default => 'Web Password' ); requires qw/ua username password/; base_url 'tvurl'; authenticate 1; twitter_api_method current_status => ( description => <<'', Get the current location and status of a user. path => 'user/current_status/id', method => 'GET', params => [qw/id callback/], required => [qw/id/], returns => 'HashRef', ); twitter_api_method update_twittervision => ( description => <<'', Updates the location for the authenticated user. path => 'user/update_location', method => 'POST', params => [qw/location/], required => [qw/location/], returns => 'HashRef', ); 1; __END__ =head1 NAME Net::Twitter::Role::API::TwitterVision - A definition of the TwitterVision API as a Moose role =head1 VERSION version 4.01043 =head1 SYNOPSIS package My::Twitter; use Moose; with 'Net::Twitter::API::TwitterVision'; =head1 DEPRECATION NOTICE The public link to the TwitterVision API is no longer accessible, and my inquires to TwitterVision have gone unanswered. I don't know if the service still supports the API. So, use this role at your own risk. =head1 DESCRIPTION B provides definitions for all the TwitterVision API methods. Applying this role to any class provides methods for all of the TwitterVision API methods. =head1 METHODS =over 4 =item new Adds the following options to L: =over 4 =item tvurl A string containing the base URL for the TwitterVision API. Defaults to "http://twittervision.com". =item tvhost A string containing the TwitterVision API host. Defaults to "twittervision.com:80". =item tvrealm A string containing the TwitterVision Basic Authentication Realm name. Defaults to "Web Password". =back =back =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2009 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/Role/API/Upload.pm000644 000766 000024 00000005140 13227713560 022201 0ustar00marcstaff000000 000000 package Net::Twitter::Role::API::Upload; $Net::Twitter::Role::API::Upload::VERSION = '4.01043'; use Moose::Role; use Net::Twitter::API; use DateTime::Format::Strptime; use URI; has upload_url => isa => 'Str', is => 'ro', default => 'http://upload.twitter.com/1'; after BUILD => sub { my $self = shift; $self->{upload_url} =~ s/^http:/https:/ if $self->ssl; }; base_url 'upload_url'; authenticate 1; our $DATETIME_PARSER = DateTime::Format::Strptime->new(pattern => '%a %b %d %T %z %Y'); datetime_parser $DATETIME_PARSER; twitter_api_method update_with_media => ( path => 'statuses/update_with_media', method => 'POST', params => [qw/ status media[] possibly_sensitive in_reply_to_status_id lat long place_id display_coordinates /], required => [qw/status media/], booleans => [qw/possibly_sensitive display_coordinates/], returns => 'Status', description => <<'EOT', Updates the authenticating user's status and attaches media for upload. The C parameter is an arrayref with the following interpretation: [ $file ] [ $file, $filename ] [ $file, $filename, Content_Type => $mime_type ] [ undef, $filename, Content_Type => $mime_type, Content => $raw_image_data ] The first value of the array (C<$file>) is the name of a file to open. The second value (C<$filename>) is the name given to Twitter for the file. If C<$filename> is not provided, the basename portion of C<$file> is used. If C<$mime_type> is not provided, it will be provided automatically using L. C<$raw_image_data> can be provided, rather than opening a file, by passing C as the first array value. The Tweet text will be rewritten to include the media URL(s), which will reduce the number of characters allowed in the Tweet text. If the URL(s) cannot be appended without text truncation, the tweet will be rejected and this method will return an HTTP 403 error. EOT ); 1; __END__ =head1 NAME Net::Twitter::Role::API::Upload - A definition of the Twitter Upload API as a Moose role =head1 VERSION version 4.01043 =head1 SYNOPSIS package My::Twitter; use Moose; with 'Net::Twitter::API::Upload'; =head1 DESCRIPTION This module provides definitions the Twitter Upload API methods. =head1 AUTHOR Allen Haim Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2011 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Net-Twitter-4.01043/lib/Net/Twitter/Role/API/UploadMedia.pm000644 000766 000024 00000003134 13227713560 023142 0ustar00marcstaff000000 000000 package Net::Twitter::Role::API::UploadMedia; $Net::Twitter::Role::API::UploadMedia::VERSION = '4.01043'; use Moose::Role; use Net::Twitter::API; use DateTime::Format::Strptime; use URI; has upload_url => isa => 'Str', is => 'ro', default => 'http://upload.twitter.com/1.1'; after BUILD => sub { my $self = shift; $self->{upload_url} =~ s/^http:/https:/ if $self->ssl; }; base_url 'upload_url'; authenticate 1; twitter_api_method upload => ( path => 'media/upload', method => 'POST', params => [qw/media/], required => [qw/media/], booleans => [qw/possibly_sensitive display_coordinates/], returns => 'HashRef', description => <<'', Uploads an image to twitter without immediately posting it to the authenticating user's timeline. Its return-value hashref notably contains a C value that's useful as a parameter value in various other endpoint calls, such as C and C. ); twitter_api_method upload_status => ( path => 'media/upload', method => 'GET', params => [qw/media_id command/], required => [qw/media_id command/], booleans => [qw//], returns => 'status', description => 'Check the status for async video uploads.' ); 1; __END__ =head1 NAME Net::Twitter::Role::API::UploadImage - A definition of the Twitter Upload API as a Moose role =head1 VERSION version 4.01043 =head1 SYNOPSIS package My::Twitter; use Moose; with 'Net::Twitter::API::UploadImage'; =head1 DESCRIPTION This module provides definitions the Twitter Upload API methods. Net-Twitter-4.01043/lib/Net/Twitter/Role/API/Search/Trends.pm000644 000766 000024 00000004540 13227713560 023424 0ustar00marcstaff000000 000000 package Net::Twitter::Role::API::Search::Trends; $Net::Twitter::Role::API::Search::Trends::VERSION = '4.01043'; use Moose::Role; after BUILD => sub { my $self = shift; unless ( $self->can('trends') || $ENV{NET_TWITTER_NO_TRENDS_WARNING} ) { warn <new(taits => [qw/API::Search API::REST/], ...); =head1 DESCRIPTION The C methods have been move to the C trait. =head1 AUTHOR Marc Mims =head1 LICENSE Copyright (c) 2016 Marc Mims The Twitter API itself, and the description text used in this module is: Copyright (c) 2009 Twitter This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Net-Twitter-4.01043/lib/Net/Twitter/Manual/MigratingToV1_1.pod000644 000766 000024 00000011202 13227713560 023675 0ustar00marcstaff000000 000000 =head1 NAME Net::Twitter::Manual::MigratingToV1_1 - Migrating from Twitter API v1 to v1.1 =head1 VERSION version 4.01043 =head1 SYNOPSIS 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, ); =head1 DESCRIPTION Net::Twitter prior to version 4.0 used Twitter API version 1. Twitter API v1.1 introduced changes that are not entirely backwards compatible, requiring some changes to calling code. 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 API v1.1. =head1 FIRST =head2 Include the API::RESTv1_1 trait Wherever you create a Net::Twitter object by calling C, replace trait C with C. For most applications, that's all that is required. =head1 EXCEPTIONS =over 4 =item Trait RateLimit incompatible with API::RESTv1_1 The C trait is incompatible with Twitter API v1.1. Rate limiting is one of the most extensive changes in v1.1. In v1 there were two hourly rate limits, one per IP address for unauthenticated calls, and one per-user/application for authenticated calls. In v1.1, all calls must be authenticated, and each API endpoint (i.e., each method) has it's own rate limit. Rather than hourly, the new rate limits operate on a 15 minute window. If your code currently uses the C role, you'll need to write some custom code provide equivalent functionality. =item rate_limit_status The return value for C is entirely different. See Twitter's API L documentation for details. =item blocking =item blocking_ids =item friends =item followers With API v1.1, these methods use cursor based paging. If you do not pass a C parameter, Twitter assumes C -1>>. Existing code that expects an arrayref return value must be modified to expect a hashref and dereference the C slot: # With API v1 my $r = $nt->friends; my @friends = @$r; # With API v1.1 my $r = $nt->friends; my @friends = @{$r->{users}}; =item search The C method semantics and return value are substantially different between Twitter API v1 and v1.1. In v1, C was provided by the C trait. In v1.1, C is included in the C trait. So, first, drop C from your calls to C. The C trait is incompatible with C. In v1, Twitter returned a hashref with several keys containing meta data. The actual array of results were contained in the C slot: # With Twitter API v1 my $nt = Net::Twitter->new(traits => [qw/API::REST API::Search/]); my $r = $nt->search('perl hacker'); for my $status ( @{$r->{results} ) { # process each status... } In v1.1, Twitter returns a hash with 2 slots: C and C. # With Twitter API v1.1 my $nt = Net::Twitter->new(traits => [qw/API::RESTv1_1/], %oauth_credentials); my $r = $nt->search('perl hacker'); for my $status ( @{$r->{statuses} ) { # process each status... } Paging through search results works differently in v1.1. In v1, Twitter offered a C parameter: # 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... } In v1.1, use C and C to get paged results: # 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... } =back =head2 DEPRECATED METHODS Some Twitter API v1 methods are not available in v1.1: =over 4 =item friends_timeline Use C instead. =item friendship_exists =item relationship_exists =item follows C and it's aliases are not supported in API v1.1. Use C instead: 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 } =back Net-Twitter-4.01043/examples/oauth_desktop.pl000755 000766 000024 00000002467 13227713560 021207 0ustar00marcstaff000000 000000 #!/usr/bin/perl # # Net::Twitter - OAuth desktop app example # use warnings; use strict; use Net::Twitter; use File::Spec; use Storable; use Data::Dumper; # You can replace the consumer tokens with your own; # these tokens are for the Net::Twitter example app. my %consumer_tokens = ( consumer_key => 'v8t3JILkStylbgnxGLOQ', consumer_secret => '5r31rSMc0NPtBpHcK8MvnCLg2oAyFLx5eGOMkXM', ); # $datafile = oauth_desktop.dat my (undef, undef, $datafile) = File::Spec->splitpath($0); $datafile =~ s/\..*/.dat/; my $nt = Net::Twitter->new(traits => [qw/API::RESTv1_1/], %consumer_tokens); my $access_tokens = eval { retrieve($datafile) } || []; if ( @$access_tokens ) { $nt->access_token($access_tokens->[0]); $nt->access_token_secret($access_tokens->[1]); } else { my $auth_url = $nt->get_authorization_url; print "\n1. Authorize the Twitter App at: $auth_url\n2. Enter the returned PIN to complete the Twitter App authorization process: "; my $pin = ; # wait for input chomp $pin; print "\n"; # request_access_token stores the tokens in $nt AND returns them my @access_tokens = $nt->request_access_token(verifier => $pin); # save the access tokens store \@access_tokens, $datafile; } my $status = $nt->user_timeline({ count => 1 }); print Dumper $status; print "\n"; Net-Twitter-4.01043/examples/oauth_webapp.pl000644 000766 000024 00000010140 13227713560 020774 0ustar00marcstaff000000 000000 #!/usr/bin/perl # # Net::Twitter - OAuth webapp example # package MyWebApp; use warnings; use strict; use base qw/HTTP::Server::Simple::CGI/; use Net::Twitter; use Data::Dumper; # You can replace the consumer tokens with your own; # these tokens are for the Net::Twitter example app. my %consumer_tokens = ( consumer_key => 'v8t3JILkStylbgnxGLOQ', consumer_secret => '5r31rSMc0NPtBpHcK8MvnCLg2oAyFLx5eGOMkXM', ); my $server_port = 8080; sub twitter { shift->{twitter} ||= Net::Twitter->new(traits => [qw/API::RESTv1_1/], %consumer_tokens) } my %dispatch = ( '/oauth_callback' => \&oauth_callback, '/' => \&my_last_tweet, ); # all request start here sub handle_request { my ($self, $q) = @_; my $request = $q->path_info; warn "Handling request for $request\n"; my $handler = $dispatch{$request} || \¬_found; $self->$handler($q); } # Display the authenicated user's last tweet in all its naked glory sub my_last_tweet { my ($self, $q) = @_; # if the user is authorized, we'll get access tokens from a cookie my %sess = $q->cookie('sess'); unless ( exists $sess{access_token_secret} ) { warn "User has no access_tokens\n"; return $self->authorize($q); } warn <<""; Using access tokens: access_token => $sess{access_token} access_token_secret => $sess{access_token_secret} my $nt = $self->twitter; # pass the access tokens to Net::Twitter $nt->access_token($sess{access_token}); $nt->access_token_secret($sess{access_token_secret}); # attempt to get the user's last tweet my $status = eval { $nt->user_timeline({ count => 1 }) }; if ( $@ ) { warn "$@\n"; # if we got a 401 response, our access tokens were invalid; get new ones return $self->authorize($q) if $@ =~ /\b401\b/; # something bad happened; show the user the error $status = $@; } print $q->header(-nph => 1), $q->start_html, $q->pre(Dumper $status), $q->end_html; } # send the user to Twitter to authorize us sub authorize { my ($self, $q) = @_; my $auth_url = $self->twitter->get_authorization_url(callback => "$ENV{SERVER_URL}oauth_callback"); # we'll store the request tokens in a session cookie my $cookie = $q->cookie(-name => 'sess', -value => { request_token => $self->twitter->request_token, request_token_secret => $self->twitter->request_token_secret, }); warn "Sending user to: $auth_url\n"; print $q->redirect(-nph => 1, -uri => $auth_url, -cookie => $cookie); } # Twitter returns the user here sub oauth_callback { my ($self, $q) = @_; my $request_token = $q->param('oauth_token'); my $verifier = $q->param('oauth_verifier'); my %sess = $q->cookie(-name => 'sess'); die "Something is horribly wrong" unless $sess{request_token} eq $request_token; $self->twitter->request_token($request_token); $self->twitter->request_token_secret($sess{request_token_secret}); warn <<""; User returned from Twitter with: oauth_token => $request_token oauth_verifier => $verifier # exchange the request token for access tokens my @access_tokens = $self->twitter->request_access_token(verifier => $verifier); warn <<""; Exchanged request tokens for access tokens: access_token => $access_tokens[0] access_token_secret => $access_tokens[1] # we'll store the access tokens in a session cookie my $cookie = $q->cookie(-name => 'sess', -value => { access_token => $access_tokens[0], access_token_secret => $access_tokens[1], }); warn "redirecting newly authorized user to $ENV{SERVER_URL}\n"; print $q->redirect(-nph => 1, -uri => "$ENV{SERVER_URL}", -cookie => $cookie); } # display a 404 Not found for any request we don't expect sub not_found { my ($self, $q) = @_; print $q->header(-nph => 1, -type => 'text/html', -status => '404 Not found'), $q->start_html, $q->h1('Not Found'), $q->p('You appear to be lost. Try going home.'); } my $app = MyWebApp->new($server_port); $app->run;