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