ae4a1c9ad1559a5c2cb608bedc03da4f4ba2b7a4
[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 void ws_request_add_att_str(json_object *rq, const char *k, const char *str)
35 {
36         json_object_object_add(rq, k, json_object_new_string(str));
37 }
38
39 void ws_request_add_att_int(json_object *rq, const char *k, int v)
40 {
41         json_object_object_add(rq, k, json_object_new_int(v));
42 }
43
44 struct json_object *ws_request_new(const char *op)
45 {
46         struct json_object *rq;
47
48         rq = json_object_new_object();
49
50         ws_request_add_att_str(rq, "op", op);
51
52         if (session_id)
53                 ws_request_add_att_str(rq, "sid", session_id);
54
55         return rq;
56 }
57
58 void ws_init(const char *url, const char *user, const char *pwd)
59 {
60         char *tmp;
61
62         if (session_id)
63                 session_id = NULL;
64
65         if (session_user)
66                 free(session_user);
67         session_user = strdup(user);
68
69         if (session_pwd)
70                 free(session_pwd);
71         session_pwd = strdup(pwd);
72
73         if (session_url)
74                 free(session_url);
75
76         tmp = url_normalize(url);
77         session_url = malloc(strlen(tmp) + strlen("/api/") + 1);
78         strcpy(session_url, tmp);
79         strcat(session_url, "/api/");
80         free(tmp);
81 }
82
83 struct json_object *ws_reply_get_content(struct json_object *rp)
84 {
85         return json_object_object_get(rp, "content");
86 }
87
88 struct json_object *ws_execute(struct json_object *rq)
89 {
90         struct json_object *rp, *content;
91
92         rp = http_json_get(session_url, rq);
93
94         if (rp) {
95                 content = ws_reply_get_content(rp);
96
97                 if (content && !json_object_object_get(rp, "error"))
98                         return content;
99
100                 json_object_put(rp);
101         }
102
103         return NULL;
104 }
105
106 int ws_get_api_version()
107 {
108         struct json_object *rp, *rq, *j;
109         int v;
110
111         rq = ws_request_new("getApiLevel");
112
113         rp = ws_execute(rq);
114
115         json_object_put(rq);
116
117         if (rp) {
118                 j = json_object_object_get(rp, "level");
119
120                 if (j)
121                         v = json_object_get_int(j);
122                 else
123                         v = 0;
124
125                 json_object_put(rp);
126         } else {
127                 v = 0;
128         }
129
130         return v;
131 }
132
133 char *ws_login()
134 {
135         struct json_object *rq, *rp, *j;
136         char *str;
137
138         rq = ws_request_new("login");
139         ws_request_add_att_str(rq, "user", session_user);
140         ws_request_add_att_str(rq, "password", session_pwd);
141
142         rp = ws_execute(rq);
143         json_object_put(rq);
144
145         if (rp) {
146                 j = json_object_object_get(rp, "session_id");
147
148                 if (j)
149                         str = strdup(json_object_get_string(j));
150                 else
151                         str = NULL;
152
153                 json_object_put(rp);
154         } else {
155                 str = NULL;
156         }
157
158         return str;
159 }
160
161 int ws_open_session()
162 {
163         int version, result;
164
165         if (session_id)
166                 free(session_id);
167
168         session_id = ws_login();
169
170         if (session_id) {
171                 version = ws_get_api_version();
172                 printf("API version: %d\n", version);
173
174                 if (version > 0) {
175                         result = 1;
176                 } else {
177                         free(session_id);
178                         session_id = NULL;
179                         result = 0;
180                 }
181         } else {
182                 result =  0;
183         }
184
185         return result;
186 }
187
188 const char *ttrss_get_headline_content(struct headline *h)
189 {
190         struct json_object *rp, *rq, *content, *array, *item;
191
192         printf("get_headlines %d\n", h->id);
193
194         if (!h->content) {
195                 rq = ws_request_new("getArticle");
196                 json_object_object_add(rq, "article_id",
197                                        json_object_new_int(h->id));
198                 
199                 rp = http_json_get(session_url, rq);
200                 
201                 json_object_put(rq);
202                 
203                 array = json_object_object_get(rp, "content");
204
205                 if (!array)
206                         goto release;
207
208                 item = json_object_array_get_idx(array, 0);
209
210                 if (!item)
211                         goto release;
212
213                 content = json_object_object_get(item, "content");
214
215                 h->content = strdup(json_object_get_string(content));
216                         
217         release:
218                 json_object_put(rp);
219         }
220         return h->content;
221 }
222
223 static struct headline **get_headlines(int feed_id)
224 {
225         struct json_object *rp, *rq, *content, *jheadline, *j;
226         int i, n;
227         struct headline **headlines, *h;
228
229         printf("get_headlines %d\n", feed_id);
230
231         rq = ws_request_new("getHeadlines");
232         json_object_object_add(rq, "feed_id", json_object_new_int(feed_id));
233
234         rp = http_json_get(session_url, rq);
235
236         json_object_put(rq);
237
238         content = json_object_object_get(rp, "content");
239
240         if (content) {
241                 n = json_object_array_length(content);
242                 headlines = malloc((n+1)*sizeof(struct headline *));
243                 for (i = 0; i < n; i++) {
244                         jheadline = json_object_array_get_idx(content, i);
245
246                         h = malloc(sizeof(struct headline));
247
248                         j = json_object_object_get(jheadline, "id");
249                         h->id = json_object_get_int(j);
250
251                         j = json_object_object_get(jheadline, "title");
252                         h->title = strdup(json_object_get_string(j));
253
254                         j = json_object_object_get(jheadline, "link");
255                         h->url = strdup(json_object_get_string(j));
256
257                         h->excerpt = NULL;
258                         h->content = NULL;
259
260                         j = json_object_object_get(jheadline, "unread");
261                         h->unread = json_object_get_boolean(j);
262
263                         headlines[i] = h;
264                 }
265                 headlines[n] = NULL;
266         } else {
267                 headlines = NULL;
268         }
269
270         json_object_put(rp);
271
272         printf("get_headlines %d end\n", feed_id);
273
274         return headlines;
275 }
276
277 static int feeds_length(struct feed **list)
278 {
279         int n;
280
281         if (!list)
282                 return 0;
283         
284         n = 0;
285         while(*list) {
286                 n++;
287                 list++;
288         }
289
290         return n;
291 }
292
293 static struct feed **feeds_add(struct feed **feeds, struct feed *feed)
294 {
295         int n;
296         struct feed **result;
297
298         n = feeds_length(feeds);
299
300         result = malloc((n + 1 + 1) * sizeof(struct feed *));
301
302         if (feeds)
303                 memcpy(result, feeds, n * sizeof(struct feed *));
304
305         result[n] = feed;
306         result[n + 1] = NULL;
307
308         return result;
309 }
310
311 struct feed **ttrss_get_feeds()
312 {
313         struct json_object *rp, *rq, *content, *jfeed, *j;
314         int i, n;
315         struct feed **feeds, *feed, **tmp;
316
317         printf("ttrss_get_feeds\n");
318
319         rq = ws_request_new("getFeeds");
320
321         rp = http_json_get(session_url, rq);
322         json_object_put(rq);
323
324         content = json_object_object_get(rp, "content");
325
326         if (content) {
327                 n = json_object_array_length(content);
328
329                 feeds = NULL;
330                 for (i = 0; i < n; i++) {
331                         jfeed = json_object_array_get_idx(content, i);
332
333                         feed = malloc(sizeof(struct feed));
334
335                         j = json_object_object_get(jfeed, "title");
336                         feed->title = strdup(json_object_get_string(j));
337
338                         j = json_object_object_get(jfeed, "feed_url");
339                         feed->url = strdup(json_object_get_string(j));
340
341                         j = json_object_object_get(jfeed, "id");
342                         feed->id = json_object_get_int(j);
343
344                         j = json_object_object_get(jfeed, "unread");
345                         feed->unread = json_object_get_int(j);
346
347                         feed->headlines = NULL;
348
349                         tmp = feeds_add(feeds, feed);
350                         free(feeds);
351                         feeds = tmp;
352                 }
353         } else {
354                 feeds = NULL;
355         }
356
357         json_object_put(rp);
358
359         printf("ttrss_get_feeds ended\n");
360
361         return feeds;
362 }
363
364 struct headline **ttrss_get_headlines(struct feed *f)
365 {
366         if (!f->headlines)
367                 f->headlines = get_headlines(f->id);
368
369         return f->headlines;
370 }
371
372 void ttrss_set_article_unread(int id, int unread)
373 {
374         struct json_object *rp, *rq;
375
376         printf("ttrss_set_article_unread %d %d\n", id, unread);
377
378         rq = ws_request_new("updateArticle");
379         json_object_object_add(rq, "article_ids", json_object_new_int(id));
380         json_object_object_add(rq, "field", json_object_new_int(2));
381         json_object_object_add(rq, "mode", json_object_new_int(unread));
382
383         rp = http_json_get(session_url, rq);
384         
385         json_object_put(rq);
386         json_object_put(rp);
387 }