static void ttrss_source_check_node_for_removal (nodePtr node, gpointer user_data) { JsonArray *array = (JsonArray *)user_data; GList *iter, *elements; gboolean found = FALSE; if (IS_FOLDER (node)) { // FIXME: check folders too node_foreach_child_data (node, ttrss_source_check_node_for_removal, user_data); } else { elements = iter = json_array_get_elements (array); while (iter) { JsonNode *json_node = (JsonNode *)iter->data; if (g_str_equal (node->subscription->source, json_get_string (json_node, "feed_url"))) { debug1 (DEBUG_UPDATE, "node: %s", node->subscription->source); found = TRUE; break; } iter = g_list_next (iter); } g_list_free (elements); if (!found) feedlist_node_removed (node); } }
void node_reset_update_counter (nodePtr node, GTimeVal *now) { subscription_reset_update_counter (node->subscription, now); node_foreach_child_data (node, node_reset_update_counter, now); }
static void google_subscription_opml_cb (subscriptionPtr subscription, const struct updateResult * const result, updateFlags flags) { AolSourcePtr gsource = (AolSourcePtr) subscription->node->data; subscription->updateJob = NULL; if (result->data) { xmlDocPtr doc = xml_parse (result->data, result->size, NULL); if(doc) { xmlNodePtr root = xmlDocGetRootElement (doc); /* Go through all existing nodes and remove those whose URLs are not in new feed list. Also removes those URLs from the list that have corresponding existing nodes. */ node_foreach_child_data (subscription->node, aol_source_check_for_removal, (gpointer)root); node_foreach_child (subscription->node, aol_source_migrate_node); opml_source_export (subscription->node); /* save new feed list tree to disk to ensure correct document in next step */ xpath_foreach_match (root, "/object/list[@name='subscriptions']/object", aol_source_merge_feed, (gpointer)gsource); opml_source_export (subscription->node); /* save new feeds to feed list */ subscription->node->available = TRUE; xmlFreeDoc (doc); } else { /** @todo The session seems to have expired */ g_warning ("Unable to parse OPML list from google, the session might have expired.\n"); } } else { subscription->node->available = FALSE; debug0 (DEBUG_UPDATE, "google_subscription_opml_cb(): ERROR: failed to get subscription list!\n"); } if (!(flags & NODE_SOURCE_UPDATE_ONLY_LIST)) node_foreach_child_data (subscription->node, node_update_subscription, GUINT_TO_POINTER (0)); }
void feedlist_reset_update_counters (nodePtr node) { GTimeVal now; if (!node) node = feedlist_get_root (); g_get_current_time (&now); node_foreach_child_data (node, node_reset_update_counter, &now); }
void node_update_subscription (nodePtr node, gpointer user_data) { if (node->source->root == node) { node_source_update (node); return; } if (node->subscription) subscription_update (node->subscription, GPOINTER_TO_UINT (user_data)); node_foreach_child_data (node, node_update_subscription, user_data); }
static void theoldreader_source_check_for_removal (nodePtr node, gpointer user_data) { gchar *expr = NULL; if (IS_FEED (node)) { expr = g_strdup_printf ("/object/list[@name='subscriptions']/object/string[@name='id'][. = 'feed/%s']", node->subscription->source); } else if (IS_FOLDER (node)) { node_foreach_child_data (node, theoldreader_source_check_for_removal, user_data); expr = g_strdup_printf ("/object/list[@name='subscriptions']/object/list[@name='categories']/object[string='%s']", node->title); } else { g_warning ("theoldreader_source_check_for_removal(): This should never happen..."); return; } if (!xpath_find ((xmlNodePtr)user_data, expr)) { debug1 (DEBUG_UPDATE, "removing %s...", node_get_title (node)); feedlist_node_removed (node); } else { debug1 (DEBUG_UPDATE, "keeping %s...", node_get_title (node)); } g_free (expr); }
static void google_subscription_opml_cb (subscriptionPtr subscription, const struct updateResult * const result, updateFlags flags) { InoreaderSourcePtr source = (InoreaderSourcePtr) subscription->node->data; subscription->updateJob = NULL; // FIXME: the following code is very similar to ttrss! if (result->data && result->httpstatus == 200) { JsonParser *parser = json_parser_new (); if (json_parser_load_from_data (parser, result->data, -1, NULL)) { JsonArray *array = json_node_get_array (json_get_node (json_parser_get_root (parser), "subscriptions")); GList *iter, *elements; GSList *siter; /* We expect something like this: [{"id":"feed\/http:\/\/rss.slashdot.org\/Slashdot\/slashdot", "title":"Slashdot", "categories":[], "firstitemmsec":"1368112925514", "htmlUrl":"null"}, ... Note that the data doesn't contain an URL. We recover it from the id field. */ elements = iter = json_array_get_elements (array); /* Add all new nodes we find */ while (iter) { JsonNode *node = (JsonNode *)iter->data; /* ignore everything without a feed url */ if (json_get_string (node, "id")) { inoreader_source_merge_feed (source, json_get_string (node, "id") + 5, // FIXME: Unescape string! json_get_string (node, "title"), json_get_string (node, "id")); } iter = g_list_next (iter); } g_list_free (elements); /* Remove old nodes we cannot find anymore */ siter = source->root->children; while (siter) { nodePtr node = (nodePtr)siter->data; gboolean found = FALSE; elements = iter = json_array_get_elements (array); while (iter) { JsonNode *json_node = (JsonNode *)iter->data; // FIXME: Compare with unescaped string if (g_str_equal (node->subscription->source, json_get_string (json_node, "id") + 5)) { debug1 (DEBUG_UPDATE, "node: %s", node->subscription->source); found = TRUE; break; } iter = g_list_next (iter); } g_list_free (elements); if (!found) feedlist_node_removed (node); siter = g_slist_next (siter); } opml_source_export (subscription->node); /* save new feeds to feed list */ subscription->node->available = TRUE; //return; } else { g_warning ("Invalid JSON returned on Inoreader feed list request! >>>%s<<<", result->data); } g_object_unref (parser); } else { subscription->node->available = FALSE; debug0 (DEBUG_UPDATE, "inoreader_subscription_cb(): ERROR: failed to get subscription list!"); } if (!(flags & INOREADER_SOURCE_UPDATE_ONLY_LIST)) node_foreach_child_data (subscription->node, node_update_subscription, GUINT_TO_POINTER (0)); }
static void ttrss_source_subscription_list_cb (const struct updateResult * const result, gpointer user_data, guint32 flags) { subscriptionPtr subscription = (subscriptionPtr) user_data; ttrssSourcePtr source = (ttrssSourcePtr) subscription->node->data; debug1 (DEBUG_UPDATE,"ttrss_subscription_cb(): %s", result->data); subscription->updateJob = NULL; if (result->data && result->httpstatus == 200) { JsonParser *parser = json_parser_new (); if (json_parser_load_from_data (parser, result->data, -1, NULL)) { JsonNode *content = json_get_node (json_parser_get_root (parser), "content"); JsonArray *array; GList *iter, *elements; /* We expect something like this: [ {"feed_url":"http://feeds.arstechnica.com/arstechnica/everything", "title":"Ars Technica", "id":6, "unread":20, "has_icon":true, "cat_id":0, "last_updated":1287853210}, {"feed_url":"http://rss.slashdot.org/Slashdot/slashdot", "title":"Slashdot", "id":5, "unread":33, "has_icon":true, "cat_id":0, "last_updated":1287853206}, [...] Or an error message that could look like this: {"seq":null,"status":1,"content":{"error":"NOT_LOGGED_IN"}} */ if (!content || (JSON_NODE_TYPE (content) != JSON_NODE_ARRAY)) { debug0 (DEBUG_UPDATE, "ttrss_subscription_cb(): Failed to get subscription list!"); subscription->node->available = FALSE; return; } array = json_node_get_array (content); elements = iter = json_array_get_elements (array); /* Add all new nodes we find */ while (iter) { JsonNode *node = (JsonNode *)iter->data; /* ignore everything without a feed url */ if (json_get_string (node, "feed_url")) { ttrss_source_merge_feed (source, json_get_string (node, "feed_url"), json_get_string (node, "title"), json_get_int (node, "id")); } iter = g_list_next (iter); } g_list_free (elements); /* Remove old nodes we cannot find anymore */ node_foreach_child_data (source->root, ttrss_source_check_node_for_removal, array); /* Save new subscription tree to OPML cache file */ opml_source_export (subscription->node); subscription->node->available = TRUE; } else { g_warning ("Invalid JSON returned on TinyTinyRSSS request! >>>%s<<<", result->data); } g_object_unref (parser); } else { subscription->node->available = FALSE; debug0 (DEBUG_UPDATE, "ttrss_subscription_cb(): ERROR: failed to get TinyTinyRSS subscription list!"); } if (!(flags & TTRSS_SOURCE_UPDATE_ONLY_LIST)) node_foreach_child_data (subscription->node, node_update_subscription, GUINT_TO_POINTER (0)); }
static void theoldreader_subscription_cb (subscriptionPtr subscription, const struct updateResult * const result, updateFlags flags) { TheOldReaderSourcePtr source = (TheOldReaderSourcePtr) subscription->node->data; debug1 (DEBUG_UPDATE,"theoldreader_subscription_cb(): %s", result->data); // FIXME: the following code is very similar to ttrss! if (result->data && result->httpstatus == 200) { JsonParser *parser = json_parser_new (); if (json_parser_load_from_data (parser, result->data, -1, NULL)) { JsonArray *array = json_node_get_array (json_get_node (json_parser_get_root (parser), "subscriptions")); GList *iter, *elements; GSList *siter; /* We expect something like this: [{"id":"feed/51d49b79d1716c7b18000025", "title":"LZone", "categories":[], "sortid":"51d49b79d1716c7b18000025", "firstitemmsec":"1371403150181", "url":"http://lzone.de/rss.xml", "htmlUrl":"http://lzone.de", "iconUrl":"http://s.yeoldereader.com/system/uploads/feed/picture/5152/884a/4dce/57aa/7e00/icon_0a6a.ico"}, ... */ elements = iter = json_array_get_elements (array); /* Add all new nodes we find */ while (iter) { JsonNode *node = (JsonNode *)iter->data; /* ignore everything without a feed url */ if (json_get_string (node, "url")) { theoldreader_source_merge_feed (source, json_get_string (node, "url"), json_get_string (node, "title"), json_get_string (node, "id")); } iter = g_list_next (iter); } g_list_free (elements); /* Remove old nodes we cannot find anymore */ siter = source->root->children; while (siter) { nodePtr node = (nodePtr)siter->data; gboolean found = FALSE; elements = iter = json_array_get_elements (array); while (iter) { JsonNode *json_node = (JsonNode *)iter->data; if (g_str_equal (node->subscription->source, json_get_string (json_node, "url"))) { debug1 (DEBUG_UPDATE, "node: %s", node->subscription->source); found = TRUE; break; } iter = g_list_next (iter); } g_list_free (elements); if (!found) feedlist_node_removed (node); siter = g_slist_next (siter); } opml_source_export (subscription->node); /* save new feeds to feed list */ subscription->node->available = TRUE; //return; } else { g_warning ("Invalid JSON returned on TheOldReader request! >>>%s<<<", result->data); } g_object_unref (parser); } else { subscription->node->available = FALSE; debug0 (DEBUG_UPDATE, "theoldreader_subscription_cb(): ERROR: failed to get subscription list!"); } if (!(flags & THEOLDREADER_SOURCE_UPDATE_ONLY_LIST)) node_foreach_child_data (subscription->node, node_update_subscription, GUINT_TO_POINTER (0)); }
static void theoldreader_subscription_cb (subscriptionPtr subscription, const struct updateResult * const result, updateFlags flags) { TheOldReaderSourcePtr source = (TheOldReaderSourcePtr) subscription->node->data; debug1 (DEBUG_UPDATE,"theoldreader_subscription_cb(): %s", result->data); subscription->updateJob = NULL; // FIXME: the following code is very similar to ttrss! if (result->data && result->httpstatus == 200) { JsonParser *parser = json_parser_new (); if (json_parser_load_from_data (parser, result->data, -1, NULL)) { JsonArray *array = json_node_get_array (json_get_node (json_parser_get_root (parser), "subscriptions")); GList *iter, *elements, *citer, *celements; GSList *siter; /* We expect something like this: [{"id":"feed/51d49b79d1716c7b18000025", "title":"LZone", "categories":[{"id":"user/-/label/myfolder","label":"myfolder"}], "sortid":"51d49b79d1716c7b18000025", "firstitemmsec":"1371403150181", "url":"http://lzone.de/rss.xml", "htmlUrl":"http://lzone.de", "iconUrl":"http://s.yeoldereader.com/system/uploads/feed/picture/5152/884a/4dce/57aa/7e00/icon_0a6a.ico"}, ... */ elements = iter = json_array_get_elements (array); /* Add all new nodes we find */ while (iter) { JsonNode *categories, *node = (JsonNode *)iter->data; nodePtr folder = NULL; /* Check for categories, if there use first one as folder */ categories = json_get_node (node, "categories"); if (categories && JSON_NODE_TYPE (categories) == JSON_NODE_ARRAY) { citer = celements = json_array_get_elements (json_node_get_array (categories)); while (citer) { const gchar *label = json_get_string ((JsonNode *)citer->data, "label"); if (label) { folder = node_source_find_or_create_folder (source->root, label, label); /* Store category id also for folder (needed when subscribing new feeds) */ g_hash_table_insert (source->folderToCategory, g_strdup (folder->id), g_strdup (label)); break; } citer = g_list_next (citer); } g_list_free (celements); } /* ignore everything without a feed url */ if (json_get_string (node, "url")) { theoldreader_source_merge_feed (source, json_get_string (node, "url"), json_get_string (node, "title"), json_get_string (node, "id"), folder); } iter = g_list_next (iter); } g_list_free (elements); /* Remove old nodes we cannot find anymore */ node_foreach_child_data (source->root, theoldreader_source_check_node_for_removal, array); /* Save new subscription tree to OPML cache file */ opml_source_export (subscription->node); subscription->node->available = TRUE; } else { g_warning ("Invalid JSON returned on TheOldReader request! >>>%s<<<", result->data); } g_object_unref (parser); } else { subscription->node->available = FALSE; debug0 (DEBUG_UPDATE, "theoldreader_subscription_cb(): ERROR: failed to get subscription list!"); } if (!(flags & NODE_SOURCE_UPDATE_ONLY_LIST)) node_foreach_child_data (subscription->node, node_update_subscription, GUINT_TO_POINTER (0)); }
static void default_source_update (nodePtr node) { node_foreach_child_data (node, node_update_subscription, GUINT_TO_POINTER (0)); }