diff options
author | Andrew Dolgov <[email protected]> | 2015-08-12 12:36:17 +0300 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2015-08-12 12:36:17 +0300 |
commit | 7322d6ce651b4607cf1315fedfead0968824547e (patch) | |
tree | 8a34f64642382110bbe258eee1820a3bf6e63ef2 |
migrate example plugins
-rw-r--r-- | example-plugins/example/example.js | 3 | ||||
-rw-r--r-- | example-plugins/example/init.php | 85 | ||||
-rw-r--r-- | example-plugins/example_api/init.php | 34 | ||||
-rw-r--r-- | example-plugins/example_article/init.js | 0 | ||||
-rw-r--r-- | example-plugins/example_article/init.php | 34 | ||||
-rw-r--r-- | example-plugins/example_feed/init.php | 32 | ||||
-rw-r--r-- | example-plugins/example_filter/init.php | 33 | ||||
-rw-r--r-- | example-plugins/example_query_headlines/init.js | 0 | ||||
-rw-r--r-- | example-plugins/example_query_headlines/init.php | 50 | ||||
-rw-r--r-- | example-plugins/example_routing/init.php | 56 | ||||
-rw-r--r-- | example-plugins/example_vfeed/init.php | 52 | ||||
-rw-r--r-- | examples/unmark_published.pl | 182 |
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. |