summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2015-08-12 12:36:17 +0300
committerAndrew Dolgov <[email protected]>2015-08-12 12:36:17 +0300
commit7322d6ce651b4607cf1315fedfead0968824547e (patch)
tree8a34f64642382110bbe258eee1820a3bf6e63ef2
migrate example plugins
-rw-r--r--example-plugins/example/example.js3
-rw-r--r--example-plugins/example/init.php85
-rw-r--r--example-plugins/example_api/init.php34
-rw-r--r--example-plugins/example_article/init.js0
-rw-r--r--example-plugins/example_article/init.php34
-rw-r--r--example-plugins/example_feed/init.php32
-rw-r--r--example-plugins/example_filter/init.php33
-rw-r--r--example-plugins/example_query_headlines/init.js0
-rw-r--r--example-plugins/example_query_headlines/init.php50
-rw-r--r--example-plugins/example_routing/init.php56
-rw-r--r--example-plugins/example_vfeed/init.php52
-rw-r--r--examples/unmark_published.pl182
12 files changed, 561 insertions, 0 deletions
diff --git a/example-plugins/example/example.js b/example-plugins/example/example.js
new file mode 100644
index 0000000..a31f2c2
--- /dev/null
+++ b/example-plugins/example/example.js
@@ -0,0 +1,3 @@
+function example(value) {
+ alert("Value saved: " + value);
+}
diff --git a/example-plugins/example/init.php b/example-plugins/example/init.php
new file mode 100644
index 0000000..67f5027
--- /dev/null
+++ b/example-plugins/example/init.php
@@ -0,0 +1,85 @@
+<?php
+class Example extends Plugin {
+
+ // Demonstrates how to add a separate panel to the preferences screen and inject Javascript/save data using Dojo forms.
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Example plugin #1",
+ "fox",
+ true,
+ "http://site.com");
+ }
+
+ function init($host) {
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_PREFS_TAB, $this);
+ }
+
+ function save() {
+ $example_value = db_escape_string($_POST["example_value"]);
+
+ $this->host->set($this, "example", $example_value);
+
+ echo "Value set to $example_value";
+ }
+
+ function get_prefs_js() {
+ return file_get_contents(dirname(__FILE__) . "/example.js");
+ }
+
+ function hook_prefs_tab($args) {
+ if ($args != "prefPrefs") return;
+
+ print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__("Example Pane")."\">";
+
+ print "<br/>";
+
+// print_r($this->host->set($this, "example", rand(0,100)));
+// print_r($this->host->get_all($this));
+
+ $value = $this->host->get($this, "example");
+
+ print "<form dojoType=\"dijit.form.Form\">";
+
+ print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
+ evt.preventDefault();
+ if (this.validate()) {
+ console.log(dojo.objectToQuery(this.getValues()));
+ new Ajax.Request('backend.php', {
+ parameters: dojo.objectToQuery(this.getValues()),
+ onComplete: function(transport) {
+ notify_info(transport.responseText);
+ }
+ });
+ //this.reset();
+ }
+ </script>";
+
+ print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pluginhandler\">";
+ print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"save\">";
+ print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin\" value=\"example\">";
+
+ print "<table width=\"100%\" class=\"prefPrefsList\">";
+
+ print "<tr><td width=\"40%\">".__("Sample value")."</td>";
+ print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"example_value\" value=\"$value\"></td></tr>";
+
+ print "</table>";
+
+ print "<p><button dojoType=\"dijit.form.Button\" type=\"submit\">".
+ __("Set value")."</button>";
+
+ print "</form>";
+
+ print "</div>"; #pane
+ }
+
+ function api_version() {
+ return 2;
+ }
+
+}
+?>
diff --git a/example-plugins/example_api/init.php b/example-plugins/example_api/init.php
new file mode 100644
index 0000000..1f896ba
--- /dev/null
+++ b/example-plugins/example_api/init.php
@@ -0,0 +1,34 @@
+<?php
+class Example_Api extends Plugin {
+
+ // Demonstrates adding a method to the API
+ // Plugin methods return an array containint
+ // 1. status (STATUS_OK or STATUS_ERR)
+ // 2. arbitrary payload
+
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Example plugin adding an API method",
+ "fox",
+ true,
+ "http://tt-rss.org/");
+ }
+
+ function init($host) {
+ $this->host = $host;
+
+ $host->add_api_method("example_testmethod", $this);
+ }
+
+ function example_testmethod() {
+ return array(API::STATUS_OK, array("current_time" => time()));
+ }
+
+ function api_version() {
+ return 2;
+ }
+
+}
+?>
diff --git a/example-plugins/example_article/init.js b/example-plugins/example_article/init.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/example-plugins/example_article/init.js
diff --git a/example-plugins/example_article/init.php b/example-plugins/example_article/init.php
new file mode 100644
index 0000000..69902cb
--- /dev/null
+++ b/example-plugins/example_article/init.php
@@ -0,0 +1,34 @@
+<?php
+class Example_Article extends Plugin {
+
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Example plugin for HOOK_RENDER_ARTICLE",
+ "fox",
+ true);
+ }
+
+ function init($host) {
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_RENDER_ARTICLE, $this);
+ }
+
+ function get_prefs_js() {
+ return file_get_contents(dirname(__FILE__) . "/init.js");
+ }
+
+ function hook_render_article($article) {
+ $article["content"] = "Content changed: " . $article["content"];
+
+ return $article;
+ }
+
+ function api_version() {
+ return 2;
+ }
+
+}
+?>
diff --git a/example-plugins/example_feed/init.php b/example-plugins/example_feed/init.php
new file mode 100644
index 0000000..1d653a9
--- /dev/null
+++ b/example-plugins/example_feed/init.php
@@ -0,0 +1,32 @@
+<?php
+class Example_Feed extends Plugin {
+
+ // Demonstrates how to query data from the parsed feed object (SimplePie)
+ // don't enable unless debugging feed through f D hotkey or manually.
+
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Example feed plugin",
+ "fox",
+ true);
+ }
+
+ function init($host) {
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_FEED_PARSED, $this);
+ }
+
+ function hook_feed_parsed($feed) {
+ _debug("I'm a little feed short and stout, here's my title: " . $feed->get_title());
+ _debug("... here's my link element: " . $feed->get_link());
+ }
+
+ function api_version() {
+ return 2;
+ }
+
+}
+?>
diff --git a/example-plugins/example_filter/init.php b/example-plugins/example_filter/init.php
new file mode 100644
index 0000000..c07dd8b
--- /dev/null
+++ b/example-plugins/example_filter/init.php
@@ -0,0 +1,33 @@
+<?php
+class Example_Filter extends Plugin {
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Example Filter plugin",
+ "fox");
+ }
+
+ function init($host) {
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_FILTER_ACTION, $this);
+
+ $host->add_filter_action($this, "action_example", "Example action");
+ $host->add_filter_action($this, "action_another", "Another action");
+ }
+
+ function hook_article_filter_action($article, $action) {
+ // if ($action == "...") { .... }
+
+ $article["title"] = "[EXAMPLE FILTER WAS HERE: $action] " . $article["title"];
+
+ return $article;
+ }
+
+ function api_version() {
+ return 2;
+ }
+
+}
+?>
diff --git a/example-plugins/example_query_headlines/init.js b/example-plugins/example_query_headlines/init.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/example-plugins/example_query_headlines/init.js
diff --git a/example-plugins/example_query_headlines/init.php b/example-plugins/example_query_headlines/init.php
new file mode 100644
index 0000000..5d71d03
--- /dev/null
+++ b/example-plugins/example_query_headlines/init.php
@@ -0,0 +1,50 @@
+<?php
+class Query_Headlines extends Plugin {
+ // example of the use of the HOOK_QUERY_HEADLINES
+ // this example will change the author and tags to be empty string so they don't display
+ // the arguements are:
+ // - the array of elements that are returned by queryFeedHeadlines
+ // - the length that the caller wants to truncate the content preview to
+ // - a boolean that indicates if the caller is from an API call
+ // The field content_preview has been shortened and sanitized, as appropriate
+ // before the plugin is called. If you want to do your own preview handling
+ // use the content field and create the preview from that
+ //NOTE:**** You have to make this a system plugin if you want it to also work
+ // on API calls. If you just make it a user plugin it will work on web page output
+ // but not on API calls
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Example of use of HOOK_QUERY_HEADLINES",
+ "justauser" );
+ }
+
+ function init($host) {
+ $this->host = $host;
+ $host->add_hook($host::HOOK_QUERY_HEADLINES, $this);
+ }
+
+ // passes in the array for an item
+ // second argument is the length of the preview the caller is using
+ // create a key called "modified_preview" if you change the preview and don't want
+ // caller to override with their default
+
+ function hook_query_headlines($line, $preview_length = 100,$api_call=false) {
+ //make the author field empty
+ $line["author"] = "";
+
+ // and toss tags, since I don't use
+ $line["tag_cache"] = "";
+ return $line;
+
+
+ }
+
+
+ function api_version() {
+ return 2;
+ }
+
+}
+?>
diff --git a/example-plugins/example_routing/init.php b/example-plugins/example_routing/init.php
new file mode 100644
index 0000000..a7b19d7
--- /dev/null
+++ b/example-plugins/example_routing/init.php
@@ -0,0 +1,56 @@
+<?php
+class Example_Routing extends Plugin implements IHandler {
+
+ // Demonstrates adding a custom handler and method:
+ // backend.php?op=test&method=example
+ // and masking a system builtin public method:
+ // public.php?op=getUnread
+
+ // Plugin class must implelement IHandler interface and has
+ // a public method of same name as being registered.
+ //
+ // Any system method may be masked by plugins. You can mask
+ // entire handler by supplying "*" instead of a method name.
+
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Example routing plugin",
+ "fox",
+ true);
+ }
+
+ function init($host) {
+ $this->host = $host;
+
+ $host->add_handler("test", "example", $this);
+ $host->add_handler("public", "getunread", $this);
+ }
+
+ function getunread() {
+ print rand(0,100); # yeah right
+ }
+
+ function example() {
+ print "example method called";
+ }
+
+ function csrf_ignore($method) {
+ return true;
+ }
+
+ function before($method) {
+ return true;
+ }
+
+ function after() {
+ return true;
+ }
+
+ function api_version() {
+ return 2;
+ }
+
+}
+?>
diff --git a/example-plugins/example_vfeed/init.php b/example-plugins/example_vfeed/init.php
new file mode 100644
index 0000000..3107619
--- /dev/null
+++ b/example-plugins/example_vfeed/init.php
@@ -0,0 +1,52 @@
+<?php
+class Example_VFeed extends Plugin {
+
+ // Demonstrates how to create a dummy special feed and chain
+ // headline generation to queryFeedHeadlines();
+
+ // Not implemented yet: stuff for 3 panel mode
+
+ private $host;
+ private $dummy_id;
+
+ function about() {
+ return array(1.0,
+ "Example vfeed plugin",
+ "fox",
+ false);
+ }
+
+ function init($host) {
+ $this->host = $host;
+
+ $this->dummy_id = $host->add_feed(-1, 'Dummy feed', 'images/pub_set.svg', $this);
+ }
+
+ function get_unread($feed_id) {
+ return 1234;
+ }
+
+ function get_headlines($feed_id, $options) {
+ $qfh_ret = queryFeedHeadlines(-4,
+ $options['limit'],
+ $options['view_mode'], $options['cat_view'],
+ $options['search'],
+ $options['search_mode'],
+ $options['override_order'],
+ $options['offset'],
+ $options['owner_uid'],
+ $options['filter'],
+ $options['since_id'],
+ $options['include_children']);
+
+ $qfh_ret[1] = 'Dummy feed';
+
+ return $qfh_ret;
+ }
+
+ function api_version() {
+ return 2;
+ }
+
+}
+?>
diff --git a/examples/unmark_published.pl b/examples/unmark_published.pl
new file mode 100644
index 0000000..63cc58e
--- /dev/null
+++ b/examples/unmark_published.pl
@@ -0,0 +1,182 @@
+#!/usr/bin/perl -w
+# vim: ts=8 sts=4 sw=4 et :
+use strict;
+use warnings;
+use diagnostics;
+
+use Getopt::Std;
+use JSON::PP;
+use LWP::UserAgent;
+use MIME::Base64;
+
+#--------------------------------------------------------------------------
+# Utility for Tiny-Tiny-RSS:
+# Un-mark published entries using the API.
+# Demonstrates API usage from Perl.
+#
+# Gregory Margo
+# gmargo _at_ yahoo _dot_ com
+#
+# unmark_published: Unmark published articles in Tiny-Tiny-RSS using the API.
+# Copyright (C) 2012 Gregory H. Margo
+# License: GPLv2 or later. See bottom of file for info.
+#--------------------------------------------------------------------------
+
+sub Usage
+{
+ print "$0 -u userid -p password URL\n";
+ print "$0 -s sid URL\n";
+ print " -u: User ID\n";
+ print " -p: Password\n";
+ print " -s: Session ID\n";
+ print " Provide either userid and password for a new session,\n";
+ print " or a session id to use an existing session.\n";
+ print " The URL should point to Tiny-Tiny-RSS's API interface,\n";
+ print " i.e. \"http://example.com/tt-rss/api/\"\n";
+ exit 1;
+}
+
+#--------------------------------------------------------------------------
+# Command line processing.
+our ($opt_u, $opt_p, $opt_s) = ("","","");
+Usage() unless getopts('u:p:s:');
+Usage() unless (($opt_u ne "" && $opt_p ne "" && $opt_s eq "") # Supply userid/password
+ || ($opt_u eq "" && $opt_p eq "" && $opt_s ne "")); # or session id.
+Usage() unless $#ARGV == 0; # Supply api URL.
+my $url = $ARGV[0];
+
+#--------------------------------------------------------------------------
+# Globals for message processing.
+my $ua = LWP::UserAgent->new();
+
+#--------------------------------------------------------------------------
+# Pass in a location and a json hash.
+# Fetch and return the decoded response.
+sub fetch_json
+{
+ my ($loc, $jsonHash) = @_;
+ my $json_text = encode_json($jsonHash);
+ my $response = $ua->post($url, Content => $json_text);
+ die("$loc POST error: ".$response->status) if !$response->is_success;
+ my $resp = decode_json($response->decoded_content);
+ die("$loc Error: ".$resp->{content}->{error}) if $resp->{status} != 0;
+ return $resp;
+}
+
+#--------------------------------------------------------------------------
+# Login if needed.
+if ($opt_u ne "")
+{
+ my $encoded_password = encode_base64($opt_p); # doesn't really hide anything
+ my $resp = fetch_json("Login", {op => 'login', user => $opt_u, password => $encoded_password});
+ $opt_s = $resp->{content}->{session_id};
+ print "Session ID = $opt_s\n";
+}
+
+#--------------------------------------------------------------------------
+# Check the SID value if not just logging in.
+if ($opt_u eq "")
+{
+ my $resp = fetch_json("CheckSID", {sid => $opt_s, op => "isLoggedIn"});
+ if (! $resp->{content}->{status})
+ {
+ print "Session ID check FAILED, not logged in\n";
+ exit 2;
+ }
+}
+
+#--------------------------------------------------------------------------
+# Just a few experiments.
+if (0)
+{
+ my $resp = fetch_json("getVersion", {sid => $opt_s, op => "getVersion"});
+ print "Version = ".$resp->{content}->{version}."\n";
+}
+if (0)
+{
+ # Don't use fetch_json() since status!=0 is valid for getApiLevel.
+ my $json_text = encode_json({sid => $opt_s, op => "getApiLevel"});
+ my $response = $ua->post($url, Content => $json_text);
+ die("getApiLevel POST error: ".$response->status) if !$response->is_success;
+ my $resp = decode_json($response->decoded_content);
+
+ if ($resp->{status} != 0)
+ {
+ print "This version does not support 'getApiLevel'\n";
+ }
+ else
+ {
+ print "ApiLevel = ".$resp->{content}->{level}."\n";
+ }
+}
+if (0)
+{
+ my $resp = fetch_json("getUnread", {sid => $opt_s, op => "getUnread"});
+ print "Unread = ".$resp->{content}->{unread}."\n";
+}
+
+#--------------------------------------------------------------------------
+# Unpublish articles
+if (1)
+{
+ # Process the published articles in groups.
+ # (limit defaults to 60 but has no "unlimited" setting)
+
+ my $total_unpublished = 0;
+ my $donthang = 1000; # Just in case, don't really use an infinite loop.
+ while ($donthang--)
+ {
+ my $resp = fetch_json("getHeadlines", {sid => $opt_s, op => "getHeadlines",
+ feed_id => -2, # -2 == published
+ limit => 60,
+ is_cat => JSON::PP::false,
+ show_excerpt => JSON::PP::false,
+ show_content => JSON::PP::false,
+ view_mode => "all_articles",
+ include_attachments => JSON::PP::false});
+
+ # Loop through the array to build a list of article ids.
+ my @published_articles;
+ push @published_articles, $_->{id} foreach @{$resp->{content}};
+
+ # Unpublish a block of articles.
+ if (@published_articles)
+ {
+ my $id_list = join(",", @published_articles);
+ my $resp = fetch_json("updateArticle", {sid => $opt_s, op => "updateArticle",
+ article_ids => "$id_list",
+ mode => 0, # mode 0 == set to false
+ field => 1}); # field 1 == published
+ warn("updateArticle Problem: status = ".$resp->{content}->{status}." for article_ids=$id_list")
+ if $resp->{content}->{status} ne "OK";
+ #print "Cleared ".@published_articles." published articles this pass\n";
+ $total_unpublished += @published_articles;
+ }
+ else
+ {
+ last; # No more published articles.
+ }
+ }
+ print "Cleared $total_unpublished published articles\n";
+}
+
+exit 0;
+
+# GPL V2 disclosure:
+#
+# unmark_published: Unmark published articles in Tiny-Tiny-RSS using the API.
+# Copyright (C) 2012 Gregory H. Margo
+#
+# 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 2
+# of the License, 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.