unmark_published.pl 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #!/usr/bin/perl -w
  2. # vim: ts=8 sts=4 sw=4 et :
  3. use strict;
  4. use warnings;
  5. use diagnostics;
  6. use Getopt::Std;
  7. use JSON::PP;
  8. use LWP::UserAgent;
  9. use MIME::Base64;
  10. #--------------------------------------------------------------------------
  11. # Utility for Tiny-Tiny-RSS:
  12. # Un-mark published entries using the API.
  13. # Demonstrates API usage from Perl.
  14. #
  15. # Gregory Margo
  16. # gmargo _at_ yahoo _dot_ com
  17. #
  18. # unmark_published: Unmark published articles in Tiny-Tiny-RSS using the API.
  19. # Copyright (C) 2012 Gregory H. Margo
  20. # License: GPLv2 or later. See bottom of file for info.
  21. #--------------------------------------------------------------------------
  22. sub Usage
  23. {
  24. print "$0 -u userid -p password URL\n";
  25. print "$0 -s sid URL\n";
  26. print " -u: User ID\n";
  27. print " -p: Password\n";
  28. print " -s: Session ID\n";
  29. print " Provide either userid and password for a new session,\n";
  30. print " or a session id to use an existing session.\n";
  31. print " The URL should point to Tiny-Tiny-RSS's API interface,\n";
  32. print " i.e. \"http://example.com/tt-rss/api/\"\n";
  33. exit 1;
  34. }
  35. #--------------------------------------------------------------------------
  36. # Command line processing.
  37. our ($opt_u, $opt_p, $opt_s) = ("","","");
  38. Usage() unless getopts('u:p:s:');
  39. Usage() unless (($opt_u ne "" && $opt_p ne "" && $opt_s eq "") # Supply userid/password
  40. || ($opt_u eq "" && $opt_p eq "" && $opt_s ne "")); # or session id.
  41. Usage() unless $#ARGV == 0; # Supply api URL.
  42. my $url = $ARGV[0];
  43. #--------------------------------------------------------------------------
  44. # Globals for message processing.
  45. my $ua = LWP::UserAgent->new();
  46. #--------------------------------------------------------------------------
  47. # Pass in a location and a json hash.
  48. # Fetch and return the decoded response.
  49. sub fetch_json
  50. {
  51. my ($loc, $jsonHash) = @_;
  52. my $json_text = encode_json($jsonHash);
  53. my $response = $ua->post($url, Content => $json_text);
  54. die("$loc POST error: ".$response->status) if !$response->is_success;
  55. my $resp = decode_json($response->decoded_content);
  56. die("$loc Error: ".$resp->{content}->{error}) if $resp->{status} != 0;
  57. return $resp;
  58. }
  59. #--------------------------------------------------------------------------
  60. # Login if needed.
  61. if ($opt_u ne "")
  62. {
  63. my $encoded_password = encode_base64($opt_p); # doesn't really hide anything
  64. my $resp = fetch_json("Login", {op => 'login', user => $opt_u, password => $encoded_password});
  65. $opt_s = $resp->{content}->{session_id};
  66. print "Session ID = $opt_s\n";
  67. }
  68. #--------------------------------------------------------------------------
  69. # Check the SID value if not just logging in.
  70. if ($opt_u eq "")
  71. {
  72. my $resp = fetch_json("CheckSID", {sid => $opt_s, op => "isLoggedIn"});
  73. if (! $resp->{content}->{status})
  74. {
  75. print "Session ID check FAILED, not logged in\n";
  76. exit 2;
  77. }
  78. }
  79. #--------------------------------------------------------------------------
  80. # Just a few experiments.
  81. if (0)
  82. {
  83. my $resp = fetch_json("getVersion", {sid => $opt_s, op => "getVersion"});
  84. print "Version = ".$resp->{content}->{version}."\n";
  85. }
  86. if (0)
  87. {
  88. # Don't use fetch_json() since status!=0 is valid for getApiLevel.
  89. my $json_text = encode_json({sid => $opt_s, op => "getApiLevel"});
  90. my $response = $ua->post($url, Content => $json_text);
  91. die("getApiLevel POST error: ".$response->status) if !$response->is_success;
  92. my $resp = decode_json($response->decoded_content);
  93. if ($resp->{status} != 0)
  94. {
  95. print "This version does not support 'getApiLevel'\n";
  96. }
  97. else
  98. {
  99. print "ApiLevel = ".$resp->{content}->{level}."\n";
  100. }
  101. }
  102. if (0)
  103. {
  104. my $resp = fetch_json("getUnread", {sid => $opt_s, op => "getUnread"});
  105. print "Unread = ".$resp->{content}->{unread}."\n";
  106. }
  107. #--------------------------------------------------------------------------
  108. # Unpublish articles
  109. if (1)
  110. {
  111. # Process the published articles in groups.
  112. # (limit defaults to 60 but has no "unlimited" setting)
  113. my $total_unpublished = 0;
  114. my $donthang = 1000; # Just in case, don't really use an infinite loop.
  115. while ($donthang--)
  116. {
  117. my $resp = fetch_json("getHeadlines", {sid => $opt_s, op => "getHeadlines",
  118. feed_id => -2, # -2 == published
  119. limit => 60,
  120. is_cat => JSON::PP::false,
  121. show_excerpt => JSON::PP::false,
  122. show_content => JSON::PP::false,
  123. view_mode => "all_articles",
  124. include_attachments => JSON::PP::false});
  125. # Loop through the array to build a list of article ids.
  126. my @published_articles;
  127. push @published_articles, $_->{id} foreach @{$resp->{content}};
  128. # Unpublish a block of articles.
  129. if (@published_articles)
  130. {
  131. my $id_list = join(",", @published_articles);
  132. my $resp = fetch_json("updateArticle", {sid => $opt_s, op => "updateArticle",
  133. article_ids => "$id_list",
  134. mode => 0, # mode 0 == set to false
  135. field => 1}); # field 1 == published
  136. warn("updateArticle Problem: status = ".$resp->{content}->{status}." for article_ids=$id_list")
  137. if $resp->{content}->{status} ne "OK";
  138. #print "Cleared "[email protected]_articles." published articles this pass\n";
  139. $total_unpublished += @published_articles;
  140. }
  141. else
  142. {
  143. last; # No more published articles.
  144. }
  145. }
  146. print "Cleared $total_unpublished published articles\n";
  147. }
  148. exit 0;
  149. # GPL V2 disclosure:
  150. #
  151. # unmark_published: Unmark published articles in Tiny-Tiny-RSS using the API.
  152. # Copyright (C) 2012 Gregory H. Margo
  153. #
  154. # This program is free software; you can redistribute it and/or
  155. # modify it under the terms of the GNU General Public License
  156. # as published by the Free Software Foundation; either version 2
  157. # of the License, or (at your option) any later version.
  158. #
  159. # This program is distributed in the hope that it will be useful,
  160. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  161. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  162. # GNU General Public License for more details.
  163. #
  164. # You should have received a copy of the GNU General Public License
  165. # along with this program; if not, write to the Free Software
  166. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.