Changeset f85cb0b for protocols/twitter/twitter_lib.c
- Timestamp:
- 2015-09-04T04:23:35Z (9 years ago)
- Parents:
- f5bbaba
- git-author:
- Wilmer van der Gaast <wilmer@…> (04-09-15 04:23:35)
- git-committer:
- dequis <dx@…> (04-09-15 04:23:35)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/twitter/twitter_lib.c
rf5bbaba rf85cb0b 36 36 #include "base64.h" 37 37 #include "twitter_lib.h" 38 #include " json_util.h"38 #include "parson.h" 39 39 #include <ctype.h> 40 40 #include <errno.h> … … 64 64 gboolean from_filter; 65 65 }; 66 67 #define JSON_O_FOREACH(o, k, v) \ 68 const char *k; const JSON_Value *v; int __i; \ 69 for (__i = 0; json_object_get_tuple(o, __i, &k, &v); __i++) 66 70 67 71 /** … … 166 170 { 167 171 static char *ret = NULL; 168 json_value *root, *err;172 JSON_Value *root, *err; 169 173 170 174 g_free(ret); … … 172 176 173 177 if (req->body_size > 0) { 174 root = json_parse(req->reply_body, req->body_size); 175 err = json_o_get(root, "errors"); 176 if (err && err->type == json_array && (err = err->u.array.values[0]) && 177 err->type == json_object) { 178 const char *msg = json_o_str(err, "message"); 178 root = json_parse_string(req->reply_body); 179 err = json_object_get_value(json_object(root), "errors"); 180 if (err && json_type(err) == JSONArray && 181 (err = json_array_get_value(json_array(err), 0)) && 182 json_type(err) == JSONObject) { 183 const char *msg = json_object_get_string(json_object(err), "message"); 179 184 if (msg) { 180 185 ret = g_strdup_printf("%s (%s)", req->status_string, msg); … … 189 194 /* WATCH OUT: This function might or might not destroy your connection. 190 195 Sub-optimal indeed, but just be careful when this returns NULL! */ 191 static json_value *twitter_parse_response(struct im_connection *ic, struct http_request *req)196 static JSON_Value *twitter_parse_response(struct im_connection *ic, struct http_request *req) 192 197 { 193 198 gboolean logging_in = !(ic->flags & OPT_LOGGED_IN); 194 199 gboolean periodic; 195 200 struct twitter_data *td = ic->proto_data; 196 json_value *ret;201 JSON_Value *ret; 197 202 char path[64] = "", *s; 198 203 … … 232 237 } 233 238 234 if ((ret = json_parse (req->reply_body, req->body_size)) == NULL) {239 if ((ret = json_parse_string(req->reply_body)) == NULL) { 235 240 imcb_error(ic, "Could not retrieve %s: %s", 236 241 path, "XML parse error"); … … 259 264 * Fill a list of ids. 260 265 */ 261 static gboolean twitter_xt_get_friends_id_list( json_value *node, struct twitter_xml_list *txl)262 { 263 json_value*c;266 static gboolean twitter_xt_get_friends_id_list(JSON_Value *node, struct twitter_xml_list *txl) 267 { 268 JSON_Array *c; 264 269 int i; 265 270 … … 267 272 txl->type = TXL_ID; 268 273 269 c = json_o_get(node, "ids"); 270 if (!c || c->type != json_array) { 274 if (!(c = json_object_get_array(json_object(node), "ids"))) { 271 275 return FALSE; 272 276 } 273 277 274 for (i = 0; i < c->u.array.length; i++) { 275 if (c->u.array.values[i]->type != json_integer) { 276 continue; 277 } 278 for (i = 0; i < json_array_get_count(c); i++) { 279 jint id = json_array_get_integer(c, i); 278 280 279 281 txl->list = g_slist_prepend(txl->list, 280 g_strdup_printf("% " PRIu64, c->u.array.values[i]->u.integer));281 } 282 283 c = json_o_get(node, "next_cursor");284 if ( c && c->type == json_integer) {285 txl->next_cursor = c->u.integer;282 g_strdup_printf("%lld", id)); 283 } 284 285 JSON_Value *next = json_object_get_value(json_object(node), "next_cursor"); 286 if (next && json_type(next) == JSONInteger) { 287 txl->next_cursor = json_integer(next); 286 288 } else { 287 289 txl->next_cursor = -1; … … 299 301 { 300 302 struct im_connection *ic; 301 json_value *parsed;303 JSON_Value *parsed; 302 304 struct twitter_xml_list *txl; 303 305 struct twitter_data *td; … … 337 339 } 338 340 339 static gboolean twitter_xt_get_users( json_value *node, struct twitter_xml_list *txl);341 static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl); 340 342 static void twitter_http_get_users_lookup(struct http_request *req); 341 343 … … 378 380 { 379 381 struct im_connection *ic = req->data; 380 json_value *parsed;382 JSON_Value *parsed; 381 383 struct twitter_xml_list *txl; 382 384 GSList *l = NULL; … … 410 412 } 411 413 412 struct twitter_xml_user *twitter_xt_get_user(const json_value*node)414 struct twitter_xml_user *twitter_xt_get_user(const JSON_Object *node) 413 415 { 414 416 struct twitter_xml_user *txu; 415 json_value *jv; 417 418 if (!node) 419 return NULL; 416 420 417 421 txu = g_new0(struct twitter_xml_user, 1); 418 txu->name = g_strdup(json_o_str(node, "name")); 419 txu->screen_name = g_strdup(json_o_str(node, "screen_name")); 420 421 jv = json_o_get(node, "id"); 422 txu->uid = jv->u.integer; 422 txu->name = g_strdup(json_object_get_string(node, "name")); 423 txu->screen_name = g_strdup(json_object_get_string(node, "screen_name")); 424 txu->uid = json_object_get_integer(node, "id"); 423 425 424 426 return txu; … … 430 432 * - all <user>s from the <users> element. 431 433 */ 432 static gboolean twitter_xt_get_users( json_value *node, struct twitter_xml_list *txl)434 static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl) 433 435 { 434 436 struct twitter_xml_user *txu; … … 438 440 txl->type = TXL_USER; 439 441 440 if ( !node || node->type != json_array) {442 if (json_type(node) != JSONArray) { 441 443 return FALSE; 442 444 } 443 445 444 446 // The root <users> node should hold the list of users <user> 445 447 // Walk over the nodes children. 446 for (i = 0; i < node->u.array.length; i++) { 447 txu = twitter_xt_get_user(node->u.array.values[i]); 448 JSON_Array *arr = json_array(node); 449 for (i = 0; i < json_array_get_count(arr); i++) { 450 JSON_Object *o = json_array_get_object(arr, i); 451 if (!o) 452 continue; 453 txu = twitter_xt_get_user(o); 448 454 if (txu) { 449 455 txl->list = g_slist_prepend(txl->list, txu); … … 460 466 #endif 461 467 462 static void expand_entities(char **text, const json_value*node);468 static void expand_entities(char **text, const JSON_Object *node); 463 469 464 470 /** … … 470 476 * - the user in a twitter_xml_user struct. 471 477 */ 472 static struct twitter_xml_status *twitter_xt_get_status(const json_value*node)478 static struct twitter_xml_status *twitter_xt_get_status(const JSON_Object *node) 473 479 { 474 480 struct twitter_xml_status *txs; 475 const json_value*rt = NULL;476 477 if ( node->type != json_object) {481 const JSON_Object *rt = NULL; 482 483 if (!node) { 478 484 return FALSE; 479 485 } … … 481 487 482 488 JSON_O_FOREACH(node, k, v) { 483 if (strcmp("text", k) == 0 && v->type == json_string) {484 txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1);489 if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) { 490 // TODO: Huh strip html? In json? Not sure whether I have to.. 485 491 strip_html(txs->text); 486 } else if (strcmp("retweeted_status", k) == 0 && v->type == json_object) {487 rt = v;488 } else if (strcmp("created_at", k) == 0 && v->type == json_string) {492 } else if (strcmp("retweeted_status", k) == 0 && (rt = json_object(v))) { 493 // Handling below. 494 } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) { 489 495 struct tm parsed; 490 496 … … 492 498 this field. :-( Also assumes the timezone used 493 499 is UTC since C time handling functions suck. */ 494 if (strptime( v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {500 if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) { 495 501 txs->created_at = mktime_utc(&parsed); 496 502 } 497 } else if (strcmp("user", k) == 0 && v->type == json_object) {498 txs->user = twitter_xt_get_user( v);499 } else if (strcmp("id", k) == 0 && v->type == json_integer) {500 txs->rt_id = txs->id = v->u.integer;501 } else if (strcmp("in_reply_to_status_id", k) == 0 && v->type == json_integer) {502 txs->reply_to = v->u.integer;503 } else if (strcmp("user", k) == 0 && json_type(v) == JSONObject) { 504 txs->user = twitter_xt_get_user(json_object(v)); 505 } else if (strcmp("id", k) == 0 && json_type(v) == JSONInteger) { 506 txs->rt_id = txs->id = json_integer(v); 507 } else if (strcmp("in_reply_to_status_id", k) == 0 && json_type(v) == JSONInteger) { 508 txs->reply_to = json_integer(v); 503 509 } 504 510 } … … 529 535 * Function to fill a twitter_xml_status struct (DM variant). 530 536 */ 531 static struct twitter_xml_status *twitter_xt_get_dm(const json_value*node)537 static struct twitter_xml_status *twitter_xt_get_dm(const JSON_Object *node) 532 538 { 533 539 struct twitter_xml_status *txs; 534 540 535 if ( node->type != json_object) {541 if (!node) { 536 542 return FALSE; 537 543 } … … 539 545 540 546 JSON_O_FOREACH(node, k, v) { 541 if (strcmp("text", k) == 0 && v->type == json_string) { 542 txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1); 547 if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) { 543 548 strip_html(txs->text); 544 } else if (strcmp("created_at", k) == 0 && v->type == json_string) {549 } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) { 545 550 struct tm parsed; 546 551 … … 548 553 this field. :-( Also assumes the timezone used 549 554 is UTC since C time handling functions suck. */ 550 if (strptime( v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {555 if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) { 551 556 txs->created_at = mktime_utc(&parsed); 552 557 } 553 } else if (strcmp("sender", k) == 0 && v->type == json_object) {554 txs->user = twitter_xt_get_user( v);555 } else if (strcmp("id", k) == 0 && v->type == json_integer) {556 txs->id = v->u.integer;558 } else if (strcmp("sender", k) == 0 && json_type(v) == JSONObject) { 559 txs->user = twitter_xt_get_user(json_object(v)); 560 } else if (strcmp("id", k) == 0 && json_type(v) == JSONInteger) { 561 txs->id = json_integer(v); 557 562 } 558 563 } … … 568 573 } 569 574 570 static void expand_entities(char **text, const json_value*node)571 { 572 json_value*entities, *quoted;575 static void expand_entities(char **text, const JSON_Object *node) 576 { 577 JSON_Object *entities, *quoted; 573 578 char *quote_url = NULL, *quote_text = NULL; 574 579 575 if (!( (entities = json_o_get(node, "entities")) && entities->type == json_object))576 return; 577 if ((quoted = json_o _get(node, "quoted_status")) && quoted->type == json_object) {580 if (!(entities = json_object_get_object(node, "entities"))) 581 return; 582 if ((quoted = json_object_get_object(node, "quoted_status"))) { 578 583 /* New "retweets with comments" feature. Note that this info 579 584 * seems to be included in the streaming API only! Grab the … … 591 596 int i; 592 597 593 if ( v->type != json_array) {598 if (json_type(v) != JSONArray) { 594 599 continue; 595 600 } … … 598 603 } 599 604 600 for (i = 0; i < v->u.array.length; i++) {605 for (i = 0; i < json_array_get_count(json_array(v)); i++) { 601 606 const char *format = "%s%s <%s>%s"; 602 603 if (v->u.array.values[i]->type != json_object) { 607 JSON_Object *r = json_array_get_object(json_array(v), i); 608 609 if (!r) { 604 610 continue; 605 611 } 606 612 607 const char *kort = json_o _str(v->u.array.values[i], "url");608 const char *disp = json_o _str(v->u.array.values[i], "display_url");609 const char *full = json_o _str(v->u.array.values[i], "expanded_url");613 const char *kort = json_object_get_string(r, "url"); 614 const char *disp = json_object_get_string(r, "display_url"); 615 const char *full = json_object_get_string(r, "expanded_url"); 610 616 char *pos, *new; 611 617 … … 636 642 * - the next_cursor. 637 643 */ 638 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const json_value *node,644 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const JSON_Value *node, 639 645 struct twitter_xml_list *txl) 640 646 { … … 645 651 txl->type = TXL_STATUS; 646 652 647 if ( node->type != json_array) {653 if (json_type(node) != JSONArray) { 648 654 return FALSE; 649 655 } … … 651 657 // The root <statuses> node should hold the list of statuses <status> 652 658 // Walk over the nodes children. 653 for (i = 0; i < node->u.array.length; i++) {654 txs = twitter_xt_get_status( node->u.array.values[i]);659 for (i = 0; i < json_array_get_count(json_array(node)); i++) { 660 txs = twitter_xt_get_status(json_array_get_object(json_array(node), i)); 655 661 if (!txs) { 656 662 continue; … … 858 864 } 859 865 860 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value*o, gboolean from_filter);866 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter); 861 867 862 868 static void twitter_http_stream(struct http_request *req) … … 864 870 struct im_connection *ic = req->data; 865 871 struct twitter_data *td; 866 json_value *parsed;872 JSON_Value *parsed; 867 873 int len = 0; 868 874 char c, *nl; … … 902 908 req->reply_body[len] = '\0'; 903 909 904 if ((parsed = json_parse (req->reply_body, req->body_size))) {910 if ((parsed = json_parse_string(req->reply_body))) { 905 911 from_filter = (req == td->filter_stream); 906 twitter_stream_handle_object(ic, parsed, from_filter);912 twitter_stream_handle_object(ic, json_object(parsed), from_filter); 907 913 } 908 914 json_value_free(parsed); … … 918 924 } 919 925 920 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value*o);926 static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o); 921 927 static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs); 922 928 923 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value*o, gboolean from_filter)929 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter) 924 930 { 925 931 struct twitter_data *td = ic->proto_data; 926 932 struct twitter_xml_status *txs; 927 json_value*c;933 JSON_Object *c; 928 934 929 935 if ((txs = twitter_xt_get_status(o))) { … … 932 938 txs_free(txs); 933 939 return ret; 934 } else if ((c = json_o _get(o, "direct_message")) &&940 } else if ((c = json_object_get_object(o, "direct_message")) && 935 941 (txs = twitter_xt_get_dm(c))) { 936 942 if (g_strcasecmp(txs->user->screen_name, td->user) != 0) { … … 940 946 txs_free(txs); 941 947 return TRUE; 942 } else if ( (c = json_o_get(o, "event")) && c->type == json_string) {948 } else if (json_object_get_string(o, "event")) { 943 949 twitter_stream_handle_event(ic, o); 944 950 return TRUE; 945 } else if ((c = json_o _get(o, "disconnect")) && c->type == json_object) {951 } else if ((c = json_object_get_object(o, "disconnect"))) { 946 952 /* HACK: Because we're inside an event handler, we can't just 947 953 disconnect here. Instead, just change the HTTP status string 948 954 into a Twitter status string. */ 949 char *reason = json_o_strdup(c, "reason");955 char *reason = g_strdup(json_object_get_string(c, "reason")); 950 956 if (reason) { 951 957 g_free(td->stream->status_string); … … 986 992 } 987 993 988 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o) 989 { 990 struct twitter_data *td = ic->proto_data; 991 json_value *source = json_o_get(o, "source"); 992 json_value *target = json_o_get(o, "target"); 993 const char *type = json_o_str(o, "event"); 994 995 if (!type || !source || source->type != json_object 996 || !target || target->type != json_object) { 994 static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o) 995 { 996 struct twitter_data *td = ic->proto_data; 997 JSON_Object *source = json_object_get_object(o, "source"); 998 JSON_Object *target = json_object_get_object(o, "target"); 999 const char *type = json_object_get_string(o, "event"); 1000 1001 if (!type || !source || !target) { 997 1002 return FALSE; 998 1003 } … … 1091 1096 struct twitter_filter *tf; 1092 1097 GList *users = NULL; 1093 json_value *parsed; 1094 json_value *id; 1095 const char *name; 1098 JSON_Value *parsed; 1096 1099 GString *fstr; 1097 1100 GSList *l; … … 1118 1121 } 1119 1122 1120 if ( parsed->type != json_array) {1123 if (json_type(parsed) != JSONArray) { 1121 1124 goto finish; 1122 1125 } 1123 1126 1124 for (i = 0; i < parsed->u.array.length; i++) { 1125 id = json_o_get(parsed->u.array.values[i], "id"); 1126 name = json_o_str(parsed->u.array.values[i], "screen_name"); 1127 1128 if (!name || !id || id->type != json_integer) { 1127 for (i = 0; i < json_array_get_count(json_array(parsed)); i++) { 1128 JSON_Object *o = json_array_get_object(json_array(parsed), i); 1129 jint id = json_object_get_integer(o, "id"); 1130 const char *name = json_object_get_string(o, "screen_name"); 1131 1132 if (!name || !id) { 1129 1133 continue; 1130 1134 } … … 1134 1138 1135 1139 if (g_strcasecmp(tf->text, name) == 0) { 1136 tf->uid = id ->u.integer;1140 tf->uid = id; 1137 1141 users = g_list_delete_link(users, u); 1138 1142 break; … … 1375 1379 struct im_connection *ic = req->data; 1376 1380 struct twitter_data *td; 1377 json_value *parsed;1381 JSON_Value *parsed; 1378 1382 struct twitter_xml_list *txl; 1379 1383 … … 1414 1418 struct im_connection *ic = req->data; 1415 1419 struct twitter_data *td; 1416 json_value *parsed;1420 JSON_Value *parsed; 1417 1421 struct twitter_xml_list *txl; 1418 1422 … … 1454 1458 struct im_connection *ic = req->data; 1455 1459 struct twitter_data *td; 1456 json_value *parsed, *id; 1460 JSON_Value *parsed; 1461 jint id; 1457 1462 1458 1463 // Check if the connection is still active. … … 1468 1473 } 1469 1474 1470 if ((id = json_o _get(parsed, "id")) && id->type == json_integer) {1471 td->last_status_id = id ->u.integer;1475 if ((id = json_object_get_integer(json_object(parsed), "id"))) { 1476 td->last_status_id = id; 1472 1477 } 1473 1478 … … 1577 1582 { 1578 1583 struct im_connection *ic = req->data; 1579 json_value *parsed, *id; 1584 JSON_Value *parsed; 1585 uint64_t id; 1580 1586 const char *name; 1581 1587 … … 1589 1595 } 1590 1596 1591 /* for the parson branch:1592 1597 name = json_object_dotget_string(json_object(parsed), "user.screen_name"); 1593 1598 id = json_object_get_integer(json_object(parsed), "id"); 1594 */ 1595 1596 name = json_o_str(json_o_get(parsed, "user"), "screen_name"); 1597 id = json_o_get(parsed, "id"); 1598 1599 if (name && id && id->type == json_integer) { 1600 twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, id->u.integer); 1599 1600 if (name && id) { 1601 twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, id); 1601 1602 } else { 1602 1603 twitter_log(ic, "Error: could not fetch tweet url.");
Note: See TracChangeset
for help on using the changeset viewer.