Browse Source

migrate example plugins

Andrew Dolgov 4 years ago
commit
7322d6ce65

+ 3 - 0
example-plugins/example/example.js

@@ -0,0 +1,3 @@
+function example(value) {
+	alert("Value saved: " + value);
+}

+ 85 - 0
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;
+	}
+
+}
+?>

+ 34 - 0
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;
+	}
+
+}
+?>

+ 0 - 0
example-plugins/example_article/init.js


+ 34 - 0
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;
+	}
+
+}
+?>

+ 32 - 0
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;
+	}
+
+}
+?>

+ 33 - 0
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;
+	}
+
+}
+?>

+ 0 - 0
example-plugins/example_query_headlines/init.js


+ 50 - 0
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;
+	}
+
+}
+?>

+ 56 - 0
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;
+	}
+
+}
+?>

+ 52 - 0
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;
+	}
+
+}
+?>

+ 182 - 0
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 "[email protected]_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.