8 Commits
v1.2 ... v1.4

Author SHA1 Message Date
Torsten Stelling
c68878c9ea fixed Mr.Reader support
fixed debugging options
2013-06-28 11:12:08 +02:00
Torsten Stelling
3edbe9db82 added more info for the current Mr.Reader state 2013-06-27 23:24:29 +02:00
Torsten Stelling
a96310a9c0 added link to FAQ from Mr.Reader 2013-06-27 23:10:54 +02:00
Torsten Stelling
f4d09169c0 removed copyright link 2013-06-27 22:52:59 +02:00
Torsten Stelling
cabb42f722 Fixes in documentation 2013-06-27 22:41:06 +02:00
Torsten Stelling
c11edb8149 added first version which works with Mr.Reader 2.0 2013-06-27 22:38:38 +02:00
Torsten Stelling
28ecc6ab70 added first readme file 2013-06-27 22:08:39 +02:00
Torsten Stelling
0b1bcf2e2e formatting changes 2013-06-27 22:04:49 +02:00
4 changed files with 248 additions and 140 deletions

63
README.md Normal file
View File

@@ -0,0 +1,63 @@
# TinyTinyRSS Fever API plugin
## Description
This plugin is an open source module for TinyTinyRSS which simulates the Fever API for reading the RSS Feeds with your Fever clients.
- - -
* <a href="#features">Features</a>
* <a href="#download">Downloads</a>
* <a href="#supported">Supported/Tested Clients</a>
* <a href="#installation">Installation</a>
* <a href="#license">License</a>
* <a href="#changelog">Changelog</a>
## <a name="features">Features</a>
Following Features are implemented:
* getting new RSS items
* getting starred RSS items
* setting read marker for item(s)
* setting starred marker for item(s)
* hot is **not** supported
## <a name="downloads">Downloads</a>
Please click the ```ZIP``` Button to download current version. ;)
## <a name="supported">Supported/Tested Clients</a>
These clients should be working fine with this API emulation.
* Reeder - iPhone
* Mr.Reader - iPad
## <a name="installation">Installation</a>
Upload the ```fever``` folder in the ```plugins``` folder of your TinyTinyRSS installation. Enable the plugin in the preferences and set your password for the Fever API.
See [here](http://tt-rss.org/forum/viewtopic.php?f=22&t=1981) for more detailed informations.
## <a name="license">License</a>
Licensed under GNU GPL version 2 (<- I think this is okay for this plugin…)
## <a name="changelog">Changelog</a>
v1.0-v1.2 - 2013/5/27 - DigitalDJ version
* see this [thread](http://tt-rss.org/forum/viewtopic.php?f=22&t=1981) in the TinyTinyRSS Forum
v1.3 - 2013/6/27
* fixed several bugs in json output from the plugin
* added a small fix for Mr.Reader 2.0 so it can complete loading of all items (see [FAQ](http://www.curioustimes.de/mrreader/faq/))
* added first Mr.Reader compatiblity without marking items read/starred
* changed the field ```date_entered``` to ```updated``` for better reading experience
v1.4 - 2013/6/28
* fixed authentication with Mr.Reader 2.0
* fixed debugging options

View File

@@ -1,4 +1,5 @@
<?php
class FeverAPI extends Handler {
const API_LEVEL = 3;
@@ -6,6 +7,10 @@ class FeverAPI extends Handler {
const STATUS_OK = 1;
const STATUS_ERR = 0;
// debugging only functions with JSON
const DEBUG = false; // enable if you need some debug output in your tinytinyrss root
const DEBUG_USER = 0; // your user id you need to debug - look it up in your mysql database and set it to a value bigger than 0
private $xml;
// always include api_version, status as 'auth'
@@ -17,9 +22,9 @@ class FeverAPI extends Handler {
if ($status == self::STATUS_OK)
{
$arr["last_refreshed_on_time"] = $this->lastRefreshedOnTime()."";
if (!empty($reply) && is_array($reply))
$arr = array_merge($arr, $reply);
$arr["last_refreshed_on_time"] = $this->lastRefreshedOnTime();
}
if ($this->xml)
@@ -29,6 +34,10 @@ class FeverAPI extends Handler {
else
{
print json_encode($arr);
if (self::DEBUG) {
// debug output
file_put_contents('./debug_fever.txt','answer : '.json_encode($arr)."\n",FILE_APPEND);
}
}
}
@@ -107,16 +116,43 @@ class FeverAPI extends Handler {
// find the user in the db with a particular api key
private function setUser()
{
if (isset($_REQUEST["api_key"]))
$apikey = isset($_REQUEST["api_key"])?$_REQUEST["api_key"]:'';
// here comes Mr.Reader special API for logging in
if ((strlen($apikey)==0)&&
(isset($_REQUEST["action"]))&&
($_REQUEST["action"]=='login')&&
(isset($_REQUEST["email"]))&&
(isset($_REQUEST["password"]))) {
$email = $_REQUEST["email"];
$password = $_REQUEST["password"];
$apikey = md5($email.":".db_escape_string($password));
setcookie('fever_auth',$apikey,time()+60*60*24*30);
if (self::DEBUG) {
// debug output
$output = array();
$output['email'] = $username;
$output['password'] = $password;
$output['apikey'] = $apikey;
file_put_contents('./debug_fever.txt','auth POST: '.json_encode($output)."\n",FILE_APPEND);
}
}
if ((strlen($apikey)==0)&&isset($_REQUEST['fever_auth'])) { // override for Mr.Reader when doing some stuff
$apikey = $_REQUEST['fever_auth'];
}
if (strlen($apikey)>0)
{
$result = $this->dbh->query("SELECT owner_uid
FROM ttrss_plugin_storage
WHERE content = '" . db_escape_string('a:1:{s:8:"password";s:32:"') . db_escape_string(strtolower($_REQUEST["api_key"])) . db_escape_string('";}') . "'");
WHERE content = '" . db_escape_string('a:1:{s:8:"password";s:32:"') . db_escape_string(strtolower($apikey)) . db_escape_string('";}') . "'");
if ($this->dbh->num_rows($result) > 0)
{
$_SESSION["uid"] = $this->dbh->fetch_result($result, 0, "owner_uid");
}
if (self::DEBUG&&self::DEBUG_USER>0) {
$_SESSION["uid"] = self::DEBUG_USER; // always authenticate and set debug user
}
}
}
@@ -136,7 +172,7 @@ class FeverAPI extends Handler {
foreach ($groupsToGroups[$index] as $item)
{
$id = substr($item, strpos($item, "-") + 1);
array_push($groups, array("id" => $id, "title" => $groupsToTitle[$id]));
array_push($groups, array("id" => intval($id), "title" => $groupsToTitle[$id]));
if (isset($groupsToGroups[$id]))
$this->flattenGroups($groupsToGroups, $groups, $groupsToTitle, $id);
}
@@ -201,8 +237,8 @@ class FeverAPI extends Handler {
while ($line = $this->dbh->fetch_assoc($result))
{
array_push($feeds, array("id" => $line["id"],
"favicon_id" => $line["id"],
array_push($feeds, array("id" => intval($line["id"]),
"favicon_id" => intval($line["id"]),
"title" => $line["title"],
"url" => $line["feed_url"],
"site_url" => $line["site_url"],
@@ -228,7 +264,7 @@ class FeverAPI extends Handler {
$filename = "feed-icons/" . $line["id"] . ".ico";
if (file_exists($filename))
{
array_push($favicons, array("id" => $line["id"],
array_push($favicons, array("id" => intval($line["id"]),
"data" => image_type_to_mime_type(exif_imagetype($filename)) . ";base64," . base64_encode(file_get_contents($filename))
));
}
@@ -360,7 +396,8 @@ class FeverAPI extends Handler {
if ($since_id)
{
if (!empty($where)) $where .= " AND ";
$where .= "id > " . db_escape_string($since_id) . " ";
//$where .= "id > " . db_escape_string($since_id) . " ";
$where .= "id > " . db_escape_string($since_id*1000) . " "; // NASTY hack for Mr. Reader 2.0 on iOS and TinyTiny RSS Fever
}
else if (empty($where))
{
@@ -374,21 +411,21 @@ class FeverAPI extends Handler {
$where .= " LIMIT " . $item_limit;
// id, feed_id, title, author, html, url, is_saved, is_read, created_on_time
$result = $this->dbh->query("SELECT ref_id, feed_id, title, link, content, id, marked, unread, author, date_entered
$result = $this->dbh->query("SELECT ref_id, feed_id, title, link, content, id, marked, unread, author, updated
FROM ttrss_entries, ttrss_user_entries
WHERE " . $where);
while ($line = $this->dbh->fetch_assoc($result))
{
array_push($items, array("id" => $line["id"],
"feed_id" => $line["feed_id"],
array_push($items, array("id" => intval($line["id"]),
"feed_id" => intval($line["feed_id"]),
"title" => $line["title"],
"author" => $line["author"],
"html" => $line["content"],
"url" => $line["link"],
"is_saved" => (sql_bool_to_bool($line["marked"]) ? 1 : 0),
"is_read" => ( (!sql_bool_to_bool($line["unread"])) ? 1 : 0),
"created_on_time" => strtotime($line["date_entered"])
"created_on_time" => strtotime($line["updated"])
));
}
@@ -451,7 +488,7 @@ class FeverAPI extends Handler {
$unreadItemIdsCSV = "";
$result = $this->dbh->query("SELECT ref_id, unread
FROM ttrss_user_entries
WHERE owner_uid = '" . db_escape_string($_SESSION["uid"]) . "'");
WHERE owner_uid = '" . db_escape_string($_SESSION["uid"]) . "'"); // ORDER BY red_id DESC
while ($line = $this->dbh->fetch_assoc($result))
{
@@ -676,6 +713,10 @@ class FeverAPI extends Handler {
// validate the api_key, user preferences
function before($method) {
if (parent::before($method)) {
if (self::DEBUG) {
// add request to debug log
file_put_contents('./debug_fever.txt','parameter: '.json_encode($_REQUEST)."\n",FILE_APPEND);
}
// set the user from the db
$this->setUser();

View File

@@ -1,4 +1,5 @@
<?php
// do not support refresh command, this could take ages.
if (isset($_REQUEST["refresh"]))
{
@@ -47,4 +48,5 @@
}
ob_end_flush();
?>

View File

@@ -1,11 +1,12 @@
<?php
class Fever extends Plugin {
private $host;
function about() {
return array(1.2,
"Emulates the Fever API for Tiny Tiny RSS",
"digitaldj");
"digitaldj & murphy");
}
function init($host) {
@@ -83,4 +84,5 @@ class Fever extends Plugin {
return 2;
}
}
?>