2
* @file ttrss_source_feed_list.c tt-rss feed list handling routines.
4
* Copyright (C) 2010-2011 Lars Lindner <lars.lindner@gmail.com>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
#include "ttrss_source_feed_list.h"
34
#include "subscription.h"
35
#include "fl_sources/opml_source.h"
36
#include "fl_sources/ttrss_source.h"
39
ttrss_source_merge_feed (ttrssSourcePtr source, const gchar *url, const gchar *title, gint64 id)
45
/* check if node to be merged already exists */
46
iter = source->root->children;
48
node = (nodePtr)iter->data;
49
if (g_str_equal (node->subscription->source, url))
51
iter = g_slist_next (iter);
54
debug2 (DEBUG_UPDATE, "adding %s (%s)", title, url);
55
node = node_new (feed_get_node_type ());
56
node_set_title (node, title);
57
node_set_data (node, feed_new ());
59
node_set_subscription (node, subscription_new (url, NULL, NULL));
60
node->subscription->type = &ttrssSourceFeedSubscriptionType;
62
/* Save tt-rss feed id which we need to fetch items... */
63
tmp = g_strdup_printf ("%lld", id);
64
metadata_list_set (&node->subscription->metadata, "ttrss-feed-id", tmp);
67
node_set_parent (node, source->root, -1);
68
feedlist_node_imported (node);
71
* @todo mark the ones as read immediately after this is done
72
* the feed as retrieved by this has the read and unread
75
subscription_update (node->subscription, FEED_REQ_RESET_TITLE | FEED_REQ_PRIORITY_HIGH);
76
subscription_update_favicon (node->subscription);
78
/* Important: we must not loose the feed id! */
79
db_subscription_update (node->subscription);
82
/* source subscription type implementation */
85
ttrss_subscription_cb (subscriptionPtr subscription, const struct updateResult * const result, updateFlags flags)
87
ttrssSourcePtr source = (ttrssSourcePtr) subscription->node->data;
89
debug1 (DEBUG_UPDATE,"ttrss_subscription_cb(): %s", result->data);
91
if (result->data && result->httpstatus == 200) {
92
JsonParser *parser = json_parser_new ();
94
if (json_parser_load_from_data (parser, result->data, -1, NULL)) {
95
JsonArray *array = json_node_get_array (json_get_node (json_parser_get_root (parser), "content"));
96
GList *iter = json_array_get_elements (array);
99
/* We expect something like this:
101
[ {"feed_url":"http://feeds.arstechnica.com/arstechnica/everything",
102
"title":"Ars Technica",
107
"last_updated":1287853210},
108
{"feed_url":"http://rss.slashdot.org/Slashdot/slashdot",
114
"last_updated":1287853206},
119
/* Add all new nodes we find */
121
JsonNode *node = (JsonNode *)iter->data;
123
/* ignore everything without a feed url */
124
if (json_get_string (node, "feed_url")) {
125
ttrss_source_merge_feed (source,
126
json_get_string (node, "feed_url"),
127
json_get_string (node, "title"),
128
json_get_int (node, "id"));
130
iter = g_list_next (iter);
133
/* Remove old nodes we cannot find anymore */
134
siter = source->root->children;
136
nodePtr node = (nodePtr)siter->data;
137
gboolean found = FALSE;
139
iter = json_array_get_elements (array);
141
JsonNode *json_node = (JsonNode *)iter->data;
142
if (g_str_equal (node->subscription->source, json_get_string (json_node, "feed_url"))) {
143
debug1 (DEBUG_UPDATE, "node: %s", node->subscription->source);
147
iter = g_list_next (iter);
151
feedlist_node_removed (node);
153
siter = g_slist_next (siter);
156
opml_source_export (subscription->node); /* save new feeds to feed list */
157
subscription->node->available = TRUE;
160
g_warning ("Invalid JSON returned on tt-rss request! >>>%s<<<", result->data);
163
subscription->node->available = FALSE;
164
debug0 (DEBUG_UPDATE, "ttrss_subscription_cb(): ERROR: failed to get subscription list!");
167
if (!(flags & TTRSS_SOURCE_UPDATE_ONLY_LIST))
168
node_foreach_child_data (subscription->node, node_update_subscription, GUINT_TO_POINTER (0));
173
ttrss_subscription_process_update_result (subscriptionPtr subscription, const struct updateResult * const result, updateFlags flags)
175
debug0 (DEBUG_UPDATE, "ttrss_subscription_process_update_result");
176
ttrss_subscription_cb (subscription, result, flags);
180
ttrss_subscription_prepare_update_request (subscriptionPtr subscription, struct updateRequest *request)
182
debug0 (DEBUG_UPDATE, "ttrs_subscription_prepare_update_request");
183
ttrssSourcePtr source = (ttrssSourcePtr) subscription->node->data;
186
if (source->loginState == TTRSS_SOURCE_STATE_NONE) {
187
debug0 (DEBUG_UPDATE, "TtRssSource: login");
188
ttrss_source_login (source, 0);
191
debug1 (DEBUG_UPDATE, "updating tt-rss subscription (node id %s)", subscription->node->id);
193
// FIXME: if (!source->selfUpdating) trigger remote update first!
195
update_request_set_source (request, g_strdup_printf (TTRSS_SUBSCRIPTION_LIST_URL, metadata_list_get (subscription->metadata, "ttrss-url"), source->session_id));
200
/* OPML subscription type definition */
202
struct subscriptionType ttrssSourceSubscriptionType = {
203
ttrss_subscription_prepare_update_request,
204
ttrss_subscription_process_update_result