(no commit message)
[prss.git] / src / ttrss.c
1 /*
2  * Copyright (C) 2010-2013 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22
23 #include <json/json.h>
24
25 #include "http.h"
26 #include "ttrss.h"
27 #include "url.h"
28
29 static char *session_id;
30 static char *session_url;
31 static char *session_user;
32 static char *session_pwd;
33
34 static int list_length(void **list)
35 {
36         int n;
37
38         if (!list)
39                 return 0;
40         
41         n = 0;
42         while(*list) {
43                 n++;
44                 list++;
45         }
46
47         return n;
48 }
49
50 static void **list_add(void **list, void *item)
51 {
52         int n;
53         void **result;
54
55         n = list_length(list);
56
57         result = malloc((n + 1 + 1) * sizeof(void *));
58
59         if (list)
60                 memcpy(result, list, n * sizeof(void *));
61
62         result[n] = item;
63         result[n + 1] = NULL;
64
65         return result;
66 }
67
68
69 struct headline *feed_get_headline(struct feed *feed, int id)
70 {
71         struct headline **headlines;
72
73         headlines = feed->headlines;
74         if (headlines)
75                 while (*headlines) {
76                         if ((*headlines)->id == id)
77                                 return *headlines;
78                         headlines++;
79                 }
80
81         return NULL;
82 }
83
84 void ws_request_add_att_str(json_object *rq, const char *k, const char *str)
85 {
86         json_object_object_add(rq, k, json_object_new_string(str));
87 }
88
89 void ws_request_add_att_int(json_object *rq, const char *k, int v)
90 {
91         json_object_object_add(rq, k, json_object_new_int(v));
92 }
93
94 struct json_object *ws_request_new(const char *op)
95 {
96         struct json_object *rq;
97
98         rq = json_object_new_object();
99
100         ws_request_add_att_str(rq, "op", op);
101
102         if (session_id)
103                 ws_request_add_att_str(rq, "sid", session_id);
104
105         return rq;
106 }
107
108 void ws_init(const char *url, const char *user, const char *pwd)
109 {
110         char *tmp;
111
112         if (session_id)
113                 session_id = NULL;
114
115         if (session_user)
116                 free(session_user);
117         session_user = strdup(user);
118
119         if (session_pwd)
120                 free(session_pwd);
121         session_pwd = strdup(pwd);
122
123         if (session_url)
124                 free(session_url);
125
126         tmp = url_normalize(url);
127         session_url = malloc(strlen(tmp) + strlen("/api/") + 1);
128         strcpy(session_url, tmp);
129         strcat(session_url, "/api/");
130         free(tmp);
131 }
132
133 struct json_object *ws_reply_get_content(struct json_object *rp)
134 {
135         return json_object_object_get(rp, "content");
136 }
137
138 struct json_object *ws_execute(struct json_object *rq)
139 {
140         struct json_object *rp, *content;
141
142         rp = http_json_get(session_url, rq);
143
144         if (rp) {
145                 content = ws_reply_get_content(rp);
146
147                 if (content && !json_object_object_get(rp, "error")) {
148                         json_object_get(content);
149                         json_object_put(rp);
150                         return content;
151                 }
152
153                 json_object_put(rp);
154         }
155
156         return NULL;
157 }
158
159 int ws_get_api_version()
160 {
161         struct json_object *rp, *rq;
162         int v;
163
164         rq = ws_request_new("getApiLevel");
165
166         rp = ws_execute(rq);
167
168         json_object_put(rq);
169
170         if (rp) {
171                 v = json_object_get_int(json_object_object_get(rp, "level"));
172
173                 json_object_put(rp);
174         } else {
175                 v = 0;
176         }
177
178         return v;
179 }
180
181 char *ws_login()
182 {
183         struct json_object *rq, *rp, *j;
184         char *str;
185
186         rq = ws_request_new("login");
187         ws_request_add_att_str(rq, "user", session_user);
188         ws_request_add_att_str(rq, "password", session_pwd);
189
190         rp = ws_execute(rq);
191         json_object_put(rq);
192
193         if (rp) {
194                 j = json_object_object_get(rp, "session_id");
195                 str = strdup(json_object_get_string(j));
196
197                 json_object_put(rp);
198         } else {
199                 str = NULL;
200         }
201
202         return str;
203 }
204
205 int ws_open_session()
206 {
207         int version, result;
208
209         if (session_id)
210                 free(session_id);
211
212         session_id = ws_login();
213
214         if (session_id) {
215                 version = ws_get_api_version();
216                 printf("API version: %d\n", version);
217
218                 if (version > 0) {
219                         result = 1;
220                 } else {
221                         free(session_id);
222                         session_id = NULL;
223                         result = 0;
224                 }
225         } else {
226                 result =  0;
227         }
228
229         return result;
230 }
231
232 char *ws_get_article_content(int id)
233 {
234         struct json_object *rp, *rq, *content, *item;
235         char *str;
236
237         rq = ws_request_new("getArticle");
238         ws_request_add_att_int(rq, "article_id", id);
239         
240         rp = ws_execute(rq);
241         
242         json_object_put(rq);
243
244         str = NULL;
245
246         if (rp) {
247                 item = json_object_array_get_idx(rp, 0);
248                 
249                 if (item) {
250                         content = json_object_object_get(item, "content");
251                         
252                         str = strdup(json_object_get_string(content));
253                 }
254                 
255                 json_object_put(rp);
256         }
257
258         return str;
259 }
260
261 int ws_update_headlines(struct feed *feed)
262 {
263         struct json_object *rp, *rq, *jheadline, *j;
264         int i, n, err, hid;
265         struct headline *h, **tmp;
266
267         rq = ws_request_new("getHeadlines");
268         ws_request_add_att_int(rq, "feed_id", feed->id);
269
270         rp = ws_execute(rq);
271
272         json_object_put(rq);
273
274         if (rp) {
275                 n = json_object_array_length(rp);
276                 for (i = 0; i < n; i++) {
277                         jheadline = json_object_array_get_idx(rp, i);
278
279                         j = json_object_object_get(jheadline, "id");
280                         hid = json_object_get_int(j);
281                         h = feed_get_headline(feed, hid);
282                         
283                         if (!h) {
284                                 h = malloc(sizeof(struct headline));
285                                 h->id = hid;
286                                 h->excerpt = NULL;
287                                 h->content = NULL;
288                                 
289                                 tmp = (struct headline **)list_add((void **)feed->headlines, h);
290                                 if (feed->headlines)
291                                         free(feed->headlines);
292                                 feed->headlines = tmp;
293                         }
294
295                         j = json_object_object_get(jheadline, "title");
296                         h->title = strdup(json_object_get_string(j));
297
298                         j = json_object_object_get(jheadline, "link");
299                         h->url = strdup(json_object_get_string(j));
300
301                         j = json_object_object_get(jheadline, "unread");
302                         h->unread = json_object_get_boolean(j);
303                 }
304                 err = 0;
305         } else {
306                 err = 1;
307         }
308
309         json_object_put(rp);
310         return !err;
311 }
312
313 const char *ttrss_get_headline_content(struct headline *h)
314 {
315         if (!h->content)
316                 h->content = ws_get_article_content(h->id);
317
318         return h->content;
319 }
320
321
322 struct feed **ttrss_get_feeds()
323 {
324         struct json_object *rp, *rq, *content, *jfeed, *j;
325         int i, n;
326         struct feed **feeds, *feed, **tmp;
327
328         printf("ttrss_get_feeds\n");
329
330         rq = ws_request_new("getFeeds");
331
332         rp = http_json_get(session_url, rq);
333         json_object_put(rq);
334
335         content = json_object_object_get(rp, "content");
336
337         if (content) {
338                 n = json_object_array_length(content);
339
340                 feeds = NULL;
341                 for (i = 0; i < n; i++) {
342                         jfeed = json_object_array_get_idx(content, i);
343
344                         feed = malloc(sizeof(struct feed));
345
346                         j = json_object_object_get(jfeed, "title");
347                         feed->title = strdup(json_object_get_string(j));
348
349                         j = json_object_object_get(jfeed, "feed_url");
350                         feed->url = strdup(json_object_get_string(j));
351
352                         j = json_object_object_get(jfeed, "id");
353                         feed->id = json_object_get_int(j);
354
355                         j = json_object_object_get(jfeed, "unread");
356                         feed->unread = json_object_get_int(j);
357
358                         feed->headlines = NULL;
359
360                         tmp = (struct feed **)list_add((void **)feeds, feed);
361                         free(feeds);
362                         feeds = tmp;
363                 }
364         } else {
365                 feeds = NULL;
366         }
367
368         json_object_put(rp);
369
370         printf("ttrss_get_feeds ended\n");
371
372         return feeds;
373 }
374
375 struct headline **ttrss_get_headlines(struct feed *f)
376 {
377         if (!f->headlines)
378                 ws_update_headlines(f);
379
380         return f->headlines;
381 }
382
383 void ttrss_set_article_unread(int id, int unread)
384 {
385         struct json_object *rp, *rq;
386
387         printf("ttrss_set_article_unread %d %d\n", id, unread);
388
389         rq = ws_request_new("updateArticle");
390         json_object_object_add(rq, "article_ids", json_object_new_int(id));
391         json_object_object_add(rq, "field", json_object_new_int(2));
392         json_object_object_add(rq, "mode", json_object_new_int(unread));
393
394         rp = http_json_get(session_url, rq);
395         
396         json_object_put(rq);
397         json_object_put(rp);
398 }