Changes in protocols/twitter/twitter_lib.c [bbff22d:ed83279]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/twitter/twitter_lib.c
rbbff22d red83279 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; … … 312 314 td = ic->proto_data; 313 315 316 txl = g_new0(struct twitter_xml_list, 1); 317 txl->list = td->follow_ids; 318 314 319 // Parse the data. 315 320 if (!(parsed = twitter_parse_response(ic, req))) { 316 321 return; 317 322 } 318 319 txl = g_new0(struct twitter_xml_list, 1);320 txl->list = td->follow_ids;321 323 322 324 twitter_xt_get_friends_id_list(parsed, txl); … … 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; … … 388 390 } 389 391 392 txl = g_new0(struct twitter_xml_list, 1); 393 txl->list = NULL; 394 390 395 // Get the user list from the parsed xml feed. 391 396 if (!(parsed = twitter_parse_response(ic, req))) { 392 397 return; 393 398 } 394 395 txl = g_new0(struct twitter_xml_list, 1);396 txl->list = NULL;397 398 399 twitter_xt_get_users(parsed, txl); 399 400 json_value_free(parsed); … … 411 412 } 412 413 413 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) 414 415 { 415 416 struct twitter_xml_user *txu; 416 json_value *jv; 417 418 if (!node) 419 return NULL; 417 420 418 421 txu = g_new0(struct twitter_xml_user, 1); 419 txu->name = g_strdup(json_o_str(node, "name")); 420 txu->screen_name = g_strdup(json_o_str(node, "screen_name")); 421 422 jv = json_o_get(node, "id"); 423 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"); 424 425 425 426 return txu; … … 431 432 * - all <user>s from the <users> element. 432 433 */ 433 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) 434 435 { 435 436 struct twitter_xml_user *txu; … … 439 440 txl->type = TXL_USER; 440 441 441 if ( !node || node->type != json_array) {442 if (json_type(node) != JSONArray) { 442 443 return FALSE; 443 444 } 444 445 445 446 // The root <users> node should hold the list of users <user> 446 447 // Walk over the nodes children. 447 for (i = 0; i < node->u.array.length; i++) { 448 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); 449 454 if (txu) { 450 455 txl->list = g_slist_prepend(txl->list, txu); … … 461 466 #endif 462 467 463 static void expand_entities(char **text, const json_value*node);468 static void expand_entities(char **text, const JSON_Object *node); 464 469 465 470 /** … … 471 476 * - the user in a twitter_xml_user struct. 472 477 */ 473 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) 474 479 { 475 480 struct twitter_xml_status *txs; 476 const json_value*rt = NULL;477 478 if ( node->type != json_object) {481 const JSON_Object *rt = NULL; 482 483 if (!node) { 479 484 return FALSE; 480 485 } … … 482 487 483 488 JSON_O_FOREACH(node, k, v) { 484 if (strcmp("text", k) == 0 && v->type == json_string) {485 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.. 486 491 strip_html(txs->text); 487 } else if (strcmp("retweeted_status", k) == 0 && v->type == json_object) {488 rt = v;489 } 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) { 490 495 struct tm parsed; 491 496 … … 493 498 this field. :-( Also assumes the timezone used 494 499 is UTC since C time handling functions suck. */ 495 if (strptime( v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {500 if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) { 496 501 txs->created_at = mktime_utc(&parsed); 497 502 } 498 } else if (strcmp("user", k) == 0 && v->type == json_object) {499 txs->user = twitter_xt_get_user( v);500 } else if (strcmp("id", k) == 0 && v->type == json_integer) {501 txs->rt_id = txs->id = v->u.integer;502 } else if (strcmp("in_reply_to_status_id", k) == 0 && v->type == json_integer) {503 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); 504 509 } 505 510 } … … 530 535 * Function to fill a twitter_xml_status struct (DM variant). 531 536 */ 532 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) 533 538 { 534 539 struct twitter_xml_status *txs; 535 540 536 if ( node->type != json_object) {541 if (!node) { 537 542 return FALSE; 538 543 } … … 540 545 541 546 JSON_O_FOREACH(node, k, v) { 542 if (strcmp("text", k) == 0 && v->type == json_string) { 543 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)))) { 544 548 strip_html(txs->text); 545 } else if (strcmp("created_at", k) == 0 && v->type == json_string) {549 } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) { 546 550 struct tm parsed; 547 551 … … 549 553 this field. :-( Also assumes the timezone used 550 554 is UTC since C time handling functions suck. */ 551 if (strptime( v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {555 if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) { 552 556 txs->created_at = mktime_utc(&parsed); 553 557 } 554 } else if (strcmp("sender", k) == 0 && v->type == json_object) {555 txs->user = twitter_xt_get_user( v);556 } else if (strcmp("id", k) == 0 && v->type == json_integer) {557 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); 558 562 } 559 563 } … … 569 573 } 570 574 571 static void expand_entities(char **text, const json_value*node)572 { 573 json_value*entities, *quoted;575 static void expand_entities(char **text, const JSON_Object *node) 576 { 577 JSON_Object *entities, *quoted; 574 578 char *quote_url = NULL, *quote_text = NULL; 575 579 576 if (!( (entities = json_o_get(node, "entities")) && entities->type == json_object))577 return; 578 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"))) { 579 583 /* New "retweets with comments" feature. Note that this info 580 584 * seems to be included in the streaming API only! Grab the … … 592 596 int i; 593 597 594 if ( v->type != json_array) {598 if (json_type(v) != JSONArray) { 595 599 continue; 596 600 } … … 599 603 } 600 604 601 for (i = 0; i < v->u.array.length; i++) {605 for (i = 0; i < json_array_get_count(json_array(v)); i++) { 602 606 const char *format = "%s%s <%s>%s"; 603 604 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) { 605 610 continue; 606 611 } 607 612 608 const char *kort = json_o _str(v->u.array.values[i], "url");609 const char *disp = json_o _str(v->u.array.values[i], "display_url");610 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"); 611 616 char *pos, *new; 612 617 … … 637 642 * - the next_cursor. 638 643 */ 639 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, 640 645 struct twitter_xml_list *txl) 641 646 { … … 646 651 txl->type = TXL_STATUS; 647 652 648 if ( node->type != json_array) {653 if (json_type(node) != JSONArray) { 649 654 return FALSE; 650 655 } … … 652 657 // The root <statuses> node should hold the list of statuses <status> 653 658 // Walk over the nodes children. 654 for (i = 0; i < node->u.array.length; i++) {655 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)); 656 661 if (!txs) { 657 662 continue; … … 859 864 } 860 865 861 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); 862 867 863 868 static void twitter_http_stream(struct http_request *req) … … 865 870 struct im_connection *ic = req->data; 866 871 struct twitter_data *td; 867 json_value *parsed;872 JSON_Value *parsed; 868 873 int len = 0; 869 874 char c, *nl; … … 903 908 req->reply_body[len] = '\0'; 904 909 905 if ((parsed = json_parse (req->reply_body, req->body_size))) {910 if ((parsed = json_parse_string(req->reply_body))) { 906 911 from_filter = (req == td->filter_stream); 907 twitter_stream_handle_object(ic, parsed, from_filter);912 twitter_stream_handle_object(ic, json_object(parsed), from_filter); 908 913 } 909 914 json_value_free(parsed); … … 919 924 } 920 925 921 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); 922 927 static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs); 923 928 924 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) 925 930 { 926 931 struct twitter_data *td = ic->proto_data; 927 932 struct twitter_xml_status *txs; 928 json_value*c;933 JSON_Object *c; 929 934 930 935 if ((txs = twitter_xt_get_status(o))) { … … 933 938 txs_free(txs); 934 939 return ret; 935 } else if ((c = json_o _get(o, "direct_message")) &&940 } else if ((c = json_object_get_object(o, "direct_message")) && 936 941 (txs = twitter_xt_get_dm(c))) { 937 942 if (g_strcasecmp(txs->user->screen_name, td->user) != 0) { … … 941 946 txs_free(txs); 942 947 return TRUE; 943 } else if ( (c = json_o_get(o, "event")) && c->type == json_string) {948 } else if (json_object_get_string(o, "event")) { 944 949 twitter_stream_handle_event(ic, o); 945 950 return TRUE; 946 } else if ((c = json_o _get(o, "disconnect")) && c->type == json_object) {951 } else if ((c = json_object_get_object(o, "disconnect"))) { 947 952 /* HACK: Because we're inside an event handler, we can't just 948 953 disconnect here. Instead, just change the HTTP status string 949 954 into a Twitter status string. */ 950 char *reason = json_o_strdup(c, "reason");955 char *reason = g_strdup(json_object_get_string(c, "reason")); 951 956 if (reason) { 952 957 g_free(td->stream->status_string); … … 987 992 } 988 993 989 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o) 990 { 991 struct twitter_data *td = ic->proto_data; 992 json_value *source = json_o_get(o, "source"); 993 json_value *target = json_o_get(o, "target"); 994 const char *type = json_o_str(o, "event"); 995 996 if (!type || !source || source->type != json_object 997 || !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) { 998 1002 return FALSE; 999 1003 } … … 1092 1096 struct twitter_filter *tf; 1093 1097 GList *users = NULL; 1094 json_value *parsed; 1095 json_value *id; 1096 const char *name; 1098 JSON_Value *parsed; 1097 1099 GString *fstr; 1098 1100 GSList *l; … … 1119 1121 } 1120 1122 1121 if ( parsed->type != json_array) {1123 if (json_type(parsed) != JSONArray) { 1122 1124 goto finish; 1123 1125 } 1124 1126 1125 for (i = 0; i < parsed->u.array.length; i++) { 1126 id = json_o_get(parsed->u.array.values[i], "id"); 1127 name = json_o_str(parsed->u.array.values[i], "screen_name"); 1128 1129 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) { 1130 1133 continue; 1131 1134 } … … 1135 1138 1136 1139 if (g_strcasecmp(tf->text, name) == 0) { 1137 tf->uid = id ->u.integer;1140 tf->uid = id; 1138 1141 users = g_list_delete_link(users, u); 1139 1142 break; … … 1376 1379 struct im_connection *ic = req->data; 1377 1380 struct twitter_data *td; 1378 json_value *parsed;1381 JSON_Value *parsed; 1379 1382 struct twitter_xml_list *txl; 1380 1383 … … 1385 1388 1386 1389 td = ic->proto_data; 1390 1391 txl = g_new0(struct twitter_xml_list, 1); 1392 txl->list = NULL; 1387 1393 1388 1394 // The root <statuses> node should hold the list of statuses <status> … … 1390 1396 goto end; 1391 1397 } 1398 twitter_xt_get_status_list(ic, parsed, txl); 1399 json_value_free(parsed); 1400 1401 td->home_timeline_obj = txl; 1402 1403 end: 1404 if (!g_slist_find(twitter_connections, ic)) { 1405 return; 1406 } 1407 1408 td->flags |= TWITTER_GOT_TIMELINE; 1409 1410 twitter_flush_timeline(ic); 1411 } 1412 1413 /** 1414 * Callback for getting mentions. 1415 */ 1416 static void twitter_http_get_mentions(struct http_request *req) 1417 { 1418 struct im_connection *ic = req->data; 1419 struct twitter_data *td; 1420 JSON_Value *parsed; 1421 struct twitter_xml_list *txl; 1422 1423 // Check if the connection is still active. 1424 if (!g_slist_find(twitter_connections, ic)) { 1425 return; 1426 } 1427 1428 td = ic->proto_data; 1392 1429 1393 1430 txl = g_new0(struct twitter_xml_list, 1); 1394 1431 txl->list = NULL; 1395 1396 twitter_xt_get_status_list(ic, parsed, txl);1397 json_value_free(parsed);1398 1399 td->home_timeline_obj = txl;1400 1401 end:1402 if (!g_slist_find(twitter_connections, ic)) {1403 return;1404 }1405 1406 td->flags |= TWITTER_GOT_TIMELINE;1407 1408 twitter_flush_timeline(ic);1409 }1410 1411 /**1412 * Callback for getting mentions.1413 */1414 static void twitter_http_get_mentions(struct http_request *req)1415 {1416 struct im_connection *ic = req->data;1417 struct twitter_data *td;1418 json_value *parsed;1419 struct twitter_xml_list *txl;1420 1421 // Check if the connection is still active.1422 if (!g_slist_find(twitter_connections, ic)) {1423 return;1424 }1425 1426 td = ic->proto_data;1427 1432 1428 1433 // The root <statuses> node should hold the list of statuses <status> … … 1430 1435 goto end; 1431 1436 } 1432 1433 txl = g_new0(struct twitter_xml_list, 1);1434 txl->list = NULL;1435 1436 1437 twitter_xt_get_status_list(ic, parsed, txl); 1437 1438 json_value_free(parsed); … … 1457 1458 struct im_connection *ic = req->data; 1458 1459 struct twitter_data *td; 1459 json_value *parsed, *id; 1460 JSON_Value *parsed; 1461 jint id; 1460 1462 1461 1463 // Check if the connection is still active. … … 1471 1473 } 1472 1474 1473 if ((id = json_o _get(parsed, "id")) && id->type == json_integer) {1474 td->last_status_id = id ->u.integer;1475 if ((id = json_object_get_integer(json_object(parsed), "id"))) { 1476 td->last_status_id = id; 1475 1477 } 1476 1478 … … 1580 1582 { 1581 1583 struct im_connection *ic = req->data; 1582 json_value *parsed, *id; 1584 JSON_Value *parsed; 1585 uint64_t id; 1583 1586 const char *name; 1584 1587 … … 1592 1595 } 1593 1596 1594 /* for the parson branch:1595 1597 name = json_object_dotget_string(json_object(parsed), "user.screen_name"); 1596 1598 id = json_object_get_integer(json_object(parsed), "id"); 1597 */ 1598 1599 name = json_o_str(json_o_get(parsed, "user"), "screen_name"); 1600 id = json_o_get(parsed, "id"); 1601 1602 if (name && id && id->type == json_integer) { 1603 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); 1604 1602 } else { 1605 1603 twitter_log(ic, "Error: could not fetch tweet url.");
Note: See TracChangeset
for help on using the changeset viewer.