From afb875ccd704dec355b73eecb2ded23f047414d8 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Wed, 20 Apr 2011 12:06:30 +0400 Subject: add rpc method to export feedbrowser data; update schema --- modules/backend-rpc.php | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'modules/backend-rpc.php') diff --git a/modules/backend-rpc.php b/modules/backend-rpc.php index f21ca5814..8b4fb04c7 100644 --- a/modules/backend-rpc.php +++ b/modules/backend-rpc.php @@ -834,6 +834,38 @@ return; } + if ($subop == "fbExport") { + + // TODO: change to _POST + $access_key = db_escape_string($_REQUEST["key"]); + + // TODO: rate limit checking using last_connected + $result = db_query($link, "SELECT id FROM ttrss_linked_instances + WHERE access_key = '$access_key'"); + + if (db_num_rows($result) == 1) { + + $instance_id = db_fetch_result($result, 0, "id"); + + $result = db_query($link, "SELECT feed_url, title, subscribers + FROM ttrss_feedbrowser_cache ORDER BY subscribers DESC LIMIT 100"); + + $feeds = array(); + + while ($line = db_fetch_assoc($result)) { + array_push($feeds, $line); + } + + db_query($link, "UPDATE ttrss_linked_instances SET last_connected = NOW() + WHERE id = '$instance_id'"); + + print json_encode(array("feeds" => $feeds)); + } else { + print json_encode(array("error" => array("code" => 6))); + } + return; + } + print json_encode(array("error" => array("code" => 7, "message" => "Unknown method: $subop"))); } -- cgit v1.2.3-54-g00ecf From 9104a3e65afdb884dd2a6289ac62161d8176c555 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Wed, 20 Apr 2011 14:11:15 +0400 Subject: implement instance edit & save --- modules/backend-rpc.php | 7 +++++ modules/pref-instances.php | 64 +++++++++++++++++++++++++++++++++++++++++++++- prefs.js | 24 +++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) (limited to 'modules/backend-rpc.php') diff --git a/modules/backend-rpc.php b/modules/backend-rpc.php index 8b4fb04c7..2ff9a6312 100644 --- a/modules/backend-rpc.php +++ b/modules/backend-rpc.php @@ -866,6 +866,13 @@ return; } + if ($subop == "genHash") { + $hash = sha1(uniqid(rand(), true)); + + print json_encode(array("hash" => $hash)); + return; + } + print json_encode(array("error" => array("code" => 7, "message" => "Unknown method: $subop"))); } diff --git a/modules/pref-instances.php b/modules/pref-instances.php index 0671944d3..c57b46f35 100644 --- a/modules/pref-instances.php +++ b/modules/pref-instances.php @@ -5,8 +5,70 @@ if ($subop == "edit") { - print "TODO: function not implemented."; + $id = db_escape_string($_REQUEST["id"]); + $result = db_query($link, "SELECT * FROM ttrss_linked_instances WHERE + id = '$id'"); + + print ""; + print ""; + print ""; + + print "
".__("Instance")."
"; + + print "
"; + + /* URL */ + + $access_url = htmlspecialchars(db_fetch_result($result, 0, "access_url")); + + print __("URL:") . " "; + + print ""; + + print "
"; + + $access_key = htmlspecialchars(db_fetch_result($result, 0, "access_key")); + + /* Access key */ + + print __("Access key:") . " "; + + print ""; + + print "
"; + + print "
+
+ +
+ +
"; + + return; + } + + if ($subop == "editSave") { + $id = db_escape_string($_REQUEST["id"]); + $access_url = db_escape_string($_REQUEST["access_url"]); + $access_key = db_escape_string($_REQUEST["access_key"]); + + db_query($link, "UPDATE ttrss_linked_instances SET + access_key = '$access_key', access_url = '$access_url' + WHERE id = '$id'"); return; } diff --git a/prefs.js b/prefs.js index c13f0e0d4..5c7131d2f 100644 --- a/prefs.js +++ b/prefs.js @@ -1810,6 +1810,30 @@ function editInstance(id, event) { id: "instanceEditDlg", title: __("Edit Instance"), style: "width: 600px", + regenKey: function() { + new Ajax.Request("backend.php", { + parameters: "?op=rpc&subop=genHash", + onComplete: function(transport) { + var reply = JSON.parse(transport.responseText); + if (reply) + dijit.byId('instance_edit_key').attr('value', reply.hash); + + } }); + }, + execute: function() { + if (this.validate()) { +// console.warn(dojo.objectToQuery(this.attr('value'))); + + notify_progress('Saving data...', true); + new Ajax.Request("backend.php", { + parameters: dojo.objectToQuery(this.attr('value')), + onComplete: function(transport) { + dialog.hide(); + notify(''); + updateInstanceList(); + } }); + } + }, href: query, }); -- cgit v1.2.3-54-g00ecf From ae5f7bb11a7698a84c9352436c144286f7c81630 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Wed, 20 Apr 2011 15:21:00 +0400 Subject: implement fetching and exporting of shared feeds --- backend.php | 33 ++++++++++++++++- functions.php | 90 +++++++++++++++++++++++++++++++++++++++++++++- modules/backend-rpc.php | 32 ----------------- modules/popup-dialog.php | 2 ++ modules/pref-instances.php | 16 ++++++--- update.php | 5 +++ update_daemon2.php | 3 ++ 7 files changed, 143 insertions(+), 38 deletions(-) (limited to 'modules/backend-rpc.php') diff --git a/backend.php b/backend.php index e63d5abd7..c4edd92ea 100644 --- a/backend.php +++ b/backend.php @@ -60,7 +60,7 @@ if (!($_SESSION["uid"] && validate_session($link)) && $op != "globalUpdateFeeds" && $op != "rss" && $op != "getUnread" && $op != "getProfiles" && - $op != "logout" && $op != "pubsub") { + $op != "fbexport" && $op != "logout" && $op != "pubsub") { header("Content-Type: text/plain"); print json_encode(array("error" => array("code" => 6))); @@ -583,6 +583,37 @@ header("Location: tt-rss.php"); break; // logout + case "fbexport": + + // TODO: change to _POST + $access_key = db_escape_string($_REQUEST["key"]); + + // TODO: rate limit checking using last_connected + $result = db_query($link, "SELECT id FROM ttrss_linked_instances + WHERE access_key = '$access_key'"); + + if (db_num_rows($result) == 1) { + + $instance_id = db_fetch_result($result, 0, "id"); + + $result = db_query($link, "SELECT feed_url, title, subscribers + FROM ttrss_feedbrowser_cache ORDER BY subscribers DESC LIMIT 100"); + + $feeds = array(); + + while ($line = db_fetch_assoc($result)) { + array_push($feeds, $line); + } + + db_query($link, "UPDATE ttrss_linked_instances SET last_connected = NOW(), + last_status_in = 1 WHERE id = '$instance_id'"); + + print json_encode(array("feeds" => $feeds)); + } else { + print json_encode(array("error" => array("code" => 6))); + } + break; // fbexport + default: header("Content-Type: text/plain"); print json_encode(array("error" => array("code" => 7))); diff --git a/functions.php b/functions.php index 0da69094a..e0c2a664b 100644 --- a/functions.php +++ b/functions.php @@ -358,7 +358,7 @@ } } - function fetch_file_contents($url, $type = false, $login = false, $pass = false) { + function fetch_file_contents($url, $type = false, $login = false, $pass = false, $post_query = false) { $login = urlencode($login); $pass = urlencode($pass); @@ -374,6 +374,11 @@ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + if ($post_query) { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $post_query); + } + if ($login && $pass) curl_setopt($ch, CURLOPT_USERPWD, "$login:$pass"); @@ -7351,4 +7356,87 @@ return $query; } + + // Status codes: + // -1 - never connected + // 0 - no data received + // 1 - data received successfully + // 2 - did not receive valid data + // >10 - server error, code + 10 (e.g. 16 means server error 6) + + function get_linked_feeds($link, $instance_id = false) { + if ($instance_id) + $instance_qpart = "id = '$instance_id' AND "; + else + $instance_qpart = ""; + + if (DB_TYPE == "pgsql") { + $date_qpart = "last_connected < NOW() - INTERVAL '1 second'"; + } else { + $date_qpart = "last_connected < DATE_SUB(NOW(), INTERVAL 6 HOUR"; + } + + $result = db_query($link, "SELECT id, access_key, access_url FROM ttrss_linked_instances + WHERE $instance_qpart $date_qpart ORDER BY last_connected"); + + while ($line = db_fetch_assoc($result)) { + $id = $line['id']; + + _debug("Updating: " . $line['access_url'] . " ($id)"); + + $fetch_url = $line['access_url'] . '/backend.php?op=fbexport'; + $post_query = 'key=' . $line['access_key']; + + $feeds = fetch_file_contents($fetch_url, false, false, false, $post_query); + + if ($feeds) { + $feeds = json_decode($feeds, true); + + if ($feeds) { + if ($feeds['error']) { + $status = $feeds['error']['code'] + 10; + } else { + $status = 1; + + if (count($feeds['feeds']) > 0) { + + db_query($link, "DELETE FROM ttrss_linked_feeds + WHERE instance_id = '$id'"); + + foreach ($feeds['feeds'] as $feed) { + $feed_url = db_escape_string($feed['feed_url']); + $title = db_escape_string($feed['title']); + $subscribers = db_escape_string($feed['subscribers']); + + db_query($link, "INSERT INTO ttrss_linked_feeds + (feed_url, title, subscribers, instance_id, created, updated) + VALUES + ('$feed_url', '$title', '$subscribers', '$id', NOW(), NOW())"); + } + } else { + // received 0 feeds, this might indicate that + // the instance on the other hand is rebuilding feedbrowser cache + // we will try again later + + // TODO: maybe perform expiration based on updated here? + } + + _debug("Processed " . count($feeds['feeds']) . " feeds."); + } + } else { + $status = 2; + } + + } else { + $status = 0; + } + + _debug("Status: $status"); + + db_query($link, "UPDATE ttrss_linked_instances SET + last_status_out = '$status', last_connected = NOW() WHERE id = '$id'"); + + } + + } ?> diff --git a/modules/backend-rpc.php b/modules/backend-rpc.php index 2ff9a6312..75ce6886a 100644 --- a/modules/backend-rpc.php +++ b/modules/backend-rpc.php @@ -834,38 +834,6 @@ return; } - if ($subop == "fbExport") { - - // TODO: change to _POST - $access_key = db_escape_string($_REQUEST["key"]); - - // TODO: rate limit checking using last_connected - $result = db_query($link, "SELECT id FROM ttrss_linked_instances - WHERE access_key = '$access_key'"); - - if (db_num_rows($result) == 1) { - - $instance_id = db_fetch_result($result, 0, "id"); - - $result = db_query($link, "SELECT feed_url, title, subscribers - FROM ttrss_feedbrowser_cache ORDER BY subscribers DESC LIMIT 100"); - - $feeds = array(); - - while ($line = db_fetch_assoc($result)) { - array_push($feeds, $line); - } - - db_query($link, "UPDATE ttrss_linked_instances SET last_connected = NOW() - WHERE id = '$instance_id'"); - - print json_encode(array("feeds" => $feeds)); - } else { - print json_encode(array("error" => array("code" => 6))); - } - return; - } - if ($subop == "genHash") { $hash = sha1(uniqid(rand(), true)); diff --git a/modules/popup-dialog.php b/modules/popup-dialog.php index f5a30a06e..6cb60eef4 100644 --- a/modules/popup-dialog.php +++ b/modules/popup-dialog.php @@ -1023,6 +1023,8 @@ style=\"width: 20em\" name=\"access_key\" id=\"instance_add_key\" value=\"$access_key\">"; + print "

" . __("Use one access key for both linked instances."); + print ""; print "

diff --git a/modules/pref-instances.php b/modules/pref-instances.php index 45df2eb39..d3510c287 100644 --- a/modules/pref-instances.php +++ b/modules/pref-instances.php @@ -24,8 +24,9 @@ if (db_num_rows($result) == 0) { db_query($link, "INSERT INTO ttrss_linked_instances - (access_url, access_key, last_connected) VALUES - ('$access_url', '$access_key', '1970-01-01')"); + (access_url, access_key, last_connected, last_status_in, last_status_out) + VALUES + ('$access_url', '$access_key', '1970-01-01', -1, -1)"); } @@ -74,6 +75,8 @@ style=\"width: 20em\" name=\"access_key\" id=\"instance_edit_key\" value=\"$access_key\">"; + print "

" . __("Use one access key for both linked instances."); + print "

"; print "
@@ -131,7 +134,10 @@ print "
"; #toolbar - $result = db_query($link, "SELECT * FROM ttrss_linked_instances + $result = db_query($link, "SELECT *, + (SELECT COUNT(*) FROM ttrss_linked_feeds + WHERE instance_id = ttrss_linked_instances.id) AS num_feeds + FROM ttrss_linked_instances ORDER BY $sort"); print "

" . __("You can connect other instances of Tiny Tiny RSS to this one to share Popular feeds. Link to this instance of Tiny Tiny RSS by using this URL:"); @@ -144,7 +150,8 @@   ".__('Instance URL')." ".__('Access key')." - ".__('Last connected')." + ".__('Last connected')." + ".__('Stored feeds')." "; $lnum = 0; @@ -170,6 +177,7 @@ print "" . htmlspecialchars($line['access_url']) . ""; print "" . htmlspecialchars($access_key) . ""; print "" . htmlspecialchars($line['last_connected']) . ""; + print "" . htmlspecialchars($line['num_feeds']) . ""; print ""; diff --git a/update.php b/update.php index 9c9c6ae8d..92e2ce6ef 100755 --- a/update.php +++ b/update.php @@ -22,6 +22,7 @@ print " -feedbrowser - update feedbrowser\n"; print " -daemon - start single-process update daemon\n"; print " -cleanup-tags - perform tags table maintenance\n"; + print " -get-feeds - receive popular feeds from linked instances\n"; print " -help - show this help\n"; return; } @@ -110,6 +111,10 @@ print "$rc tags deleted.\n"; } + if ($op == "-get-feeds") { + get_linked_feeds($link); + } + db_close($link); unlink(LOCK_DIRECTORY . "/$lock_filename"); diff --git a/update_daemon2.php b/update_daemon2.php index 6ccdbcb10..9ad914307 100755 --- a/update_daemon2.php +++ b/update_daemon2.php @@ -219,6 +219,9 @@ _debug("Cleaned $rc cached tags."); + _debug("Updating linked feeds..."); + get_linked_feeds($link); + } _debug("Elapsed time: " . (time() - $start_timestamp) . " second(s)"); -- cgit v1.2.3-54-g00ecf