Hook for basic feed info?

Since AP News might have discontinued their feeds I’m looking at extracting articles from the JSON their new site uses (e.g. https://afs-prod.appspot.com/api/v2/feed/tag?tags=apf-topnews ).

I have things more or less working through “HOOK_SUBSCRIBE_FEED” and “HOOK_FETCH_FEED”, however it looks like “RSSUtils::set_basic_feed_info” always attempts to get the feed title and site URL from the “feed_url”. In this case that URL isn’t a valid feed, so it fails and the title remains “[Unknown]”.

Would it make sense to have a “HOOK_FEED_BASIC_INFO” (reworking “RSSUtils::set_basic_feed_info” a bit) to allow plugins to provide basic info for “feeds” they provide?

yes, i think a special hook for this is a good idea.

If I recall this correctly, title and site url are taken from from corresponding elements in the feed xml and can be provided by the plugin there. Problem is that this information is not yet available at the time ttrss parses the xml for it, which can be mended with this patch (which is against rssfuncs, dunno if some other things changed apart from adding a class name around it).

---
 include/functions.php |  3 +-
 include/rssfuncs.php  | 99 +++++++++++++++++++++++++++------------------------
 2 files changed, 54 insertions(+), 48 deletions(-)

diff --git a/include/functions.php b/include/functions.php
index e94e04ad..2967f23f 100644
--- a/include/functions.php
+++ b/include/functions.php
@@ -1784,6 +1784,7 @@
 			}
 			//use feed url as new URL
 			$url = key($feedUrls);
+			$contents = '';
 		}
 
 		if ($cat_id == "0" || !$cat_id) {
@@ -1813,7 +1814,7 @@
 			$feed_id = db_fetch_result($result, 0, "id");
 
 			if ($feed_id) {
-				set_basic_feed_info($feed_id);
+				set_basic_feed_info($feed_id, $contents);
 			}
 
 			return array("code" => 1, "feed_id" => (int) $feed_id);
diff --git a/include/rssfuncs.php b/include/rssfuncs.php
index e26fc38b..5ffe2e2e 100644
--- a/include/rssfuncs.php
+++ b/include/rssfuncs.php
@@ -240,52 +240,61 @@
 	} // function update_daemon_common
 
 	// this is used when subscribing
-	function set_basic_feed_info($feed) {
-
+	/*
+	 * @param mixed $rss When this evaluates to false, stuff is fetched and loaded into FeedParser.
+	                     When it's a string, it gets feed to FeedParser.
+	                     When it's a FeedParser object, it is queried for basic feed information.
+	*/
+	function set_basic_feed_info($feed, $rss = NULL) {
 		$feed = db_escape_string($feed);
 
-		$result = db_query("SELECT feed_url,auth_pass,auth_login,auth_pass_encrypted
+		if(!$rss) {
+			$result = db_query("SELECT feed_url,auth_pass,auth_login,auth_pass_encrypted
 					FROM ttrss_feeds WHERE id = '$feed'");
 
-		$auth_pass_encrypted = sql_bool_to_bool(db_fetch_result($result,
-			0, "auth_pass_encrypted"));
+			$auth_pass_encrypted = sql_bool_to_bool(db_fetch_result($result,
+				0, "auth_pass_encrypted"));
 
-		$auth_login = db_fetch_result($result, 0, "auth_login");
-		$auth_pass = db_fetch_result($result, 0, "auth_pass");
-
-		if ($auth_pass_encrypted && function_exists("mcrypt_decrypt")) {
-			require_once "crypt.php";
-			$auth_pass = decrypt_string($auth_pass);
-		}
+			$auth_login = db_fetch_result($result, 0, "auth_login");
+			$auth_pass = db_fetch_result($result, 0, "auth_pass");
 
-		$fetch_url = db_fetch_result($result, 0, "feed_url");
+			if ($auth_pass_encrypted && function_exists("mcrypt_decrypt")) {
+				require_once "crypt.php";
+				$auth_pass = decrypt_string($auth_pass);
+			}
 
-		$feed_data = fetch_file_contents($fetch_url, false,
-			$auth_login, $auth_pass, false,
-			FEED_FETCH_TIMEOUT,
-			0);
+			$fetch_url = db_fetch_result($result, 0, "feed_url");
 
-		global $fetch_curl_used;
+			$feed_data = fetch_file_contents($fetch_url, false,
+				$auth_login, $auth_pass, false,
+				FEED_FETCH_TIMEOUT,
+				0);
 
-		if (!$fetch_curl_used) {
-			$tmp = @gzdecode($feed_data);
+			global $fetch_curl_used;
 
-			if ($tmp) $feed_data = $tmp;
-		}
+			if (!$fetch_curl_used) {
+				$tmp = @gzdecode($feed_data);
 
-		$feed_data = trim($feed_data);
+				if ($tmp) $feed_data = $tmp;
+			}
 
-		$rss = new FeedParser($feed_data);
-		$rss->init();
+			$feed_data = trim($feed_data);
 
-		if (!$rss->error()) {
+			$rss = new FeedParser($feed_data);
+			$rss->init();
+		} elseif (is_string($rss)) {
+			$rss = new FeedParser(trim($rss));
+			$rss->init();
+		}
 
-			$result = db_query("SELECT title, site_url FROM ttrss_feeds WHERE id = '$feed'");
+		if($rss && is_object($rss) && get_class($rss) === "FeedParser" && !$rss->error()) {
+			$result = db_query("SELECT title, site_url, feed_url FROM ttrss_feeds WHERE id = '$feed'");
 
 			$registered_title = db_fetch_result($result, 0, "title");
 			$orig_site_url = db_fetch_result($result, 0, "site_url");
 
-			$site_url = db_escape_string(mb_substr(rewrite_relative_url($fetch_url, $rss->get_link()), 0, 245));
+			$feed_url = db_fetch_result($result, 0, "feed_url");
+			$site_url = db_escape_string(mb_substr(rewrite_relative_url($feed_url, $rss->get_link()), 0, 245));
 			$feed_title = db_escape_string(mb_substr($rss->get_title(), 0, 199));
 
 			if ($feed_title && (!$registered_title || $registered_title == "[Unknown]")) {
@@ -308,24 +317,6 @@
 		_debug_suppress(!$debug_enabled);
 		_debug("start", $debug_enabled);
 
-		$result = db_query("SELECT title FROM ttrss_feeds
-			WHERE id = '$feed'");
-
-		if (db_num_rows($result) == 0) {
-			_debug("feed $feed NOT FOUND/SKIPPED", $debug_enabled);
-			user_error("Attempt to update unknown/invalid feed $feed", E_USER_WARNING);
-			return false;
-		}
-
-		$title = db_fetch_result($result, 0, "title");
-
-		// feed was batch-subscribed or something, we need to get basic info
-		// this is not optimal currently as it fetches stuff separately TODO: optimize
-		if ($title == "[Unknown]") {
-			_debug("setting basic feed info for $feed...");
-			set_basic_feed_info($feed);
-		}
-
 		$result = db_query("SELECT id,update_interval,auth_login,
 			feed_url,auth_pass,cache_images,
 			mark_unread_on_update, owner_uid,
@@ -333,6 +324,12 @@
 			feed_language
 			FROM ttrss_feeds WHERE id = '$feed'");
 
+		if (db_num_rows($result) == 0) {
+			_debug("feed $feed NOT FOUND/SKIPPED", $debug_enabled);
+			user_error("Attempt to update unknown/invalid feed $feed", E_USER_WARNING);
+			return false;
+		}
+
 		$owner_uid = db_fetch_result($result, 0, "owner_uid");
 		$mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result,
 			0, "mark_unread_on_update"));
@@ -478,10 +475,18 @@
 		$feed = db_escape_string($feed);
 
 		if (!$rss->error()) {
-
 			// We use local pluginhost here because we need to load different per-user feed plugins
 			$pluginhost->run_hooks(PluginHost::HOOK_FEED_PARSED, "hook_feed_parsed", $rss);
 
+			// feed was batch-subscribed or something, we need to get basic info
+			$result = db_query("SELECT title FROM ttrss_feeds
+				WHERE id = '$feed'");
+			$title = db_fetch_result($result, 0, "title");
+			if ($title == "[Unknown]") {
+				_debug("setting basic feed info for $feed...");
+				set_basic_feed_info($feed, $rss);
+			}
+
 			_debug("language: $feed_language", $debug_enabled);
 			_debug("processing feed data...", $debug_enabled);
 
-- 
2.13.0

this sure is an, uh, diff.

commented on your PR (i guess there’s no email notifications)