Changes in protocols/twitter/twitter_lib.c [ed83279:bbff22d]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/twitter/twitter_lib.c
red83279 rbbff22d 36 36 #include "base64.h" 37 37 #include "twitter_lib.h" 38 #include " parson.h"38 #include "json_util.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++)70 66 71 67 /** … … 170 166 { 171 167 static char *ret = NULL; 172 JSON_Value *root, *err;168 json_value *root, *err; 173 169 174 170 g_free(ret); … … 176 172 177 173 if (req->body_size > 0) { 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"); 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"); 184 179 if (msg) { 185 180 ret = g_strdup_printf("%s (%s)", req->status_string, msg); … … 194 189 /* WATCH OUT: This function might or might not destroy your connection. 195 190 Sub-optimal indeed, but just be careful when this returns NULL! */ 196 static JSON_Value *twitter_parse_response(struct im_connection *ic, struct http_request *req)191 static json_value *twitter_parse_response(struct im_connection *ic, struct http_request *req) 197 192 { 198 193 gboolean logging_in = !(ic->flags & OPT_LOGGED_IN); 199 194 gboolean periodic; 200 195 struct twitter_data *td = ic->proto_data; 201 JSON_Value *ret;196 json_value *ret; 202 197 char path[64] = "", *s; 203 198 … … 237 232 } 238 233 239 if ((ret = json_parse _string(req->reply_body)) == NULL) {234 if ((ret = json_parse(req->reply_body, req->body_size)) == NULL) { 240 235 imcb_error(ic, "Could not retrieve %s: %s", 241 236 path, "XML parse error"); … … 264 259 * Fill a list of ids. 265 260 */ 266 static gboolean twitter_xt_get_friends_id_list( JSON_Value *node, struct twitter_xml_list *txl)267 { 268 JSON_Array*c;261 static gboolean twitter_xt_get_friends_id_list(json_value *node, struct twitter_xml_list *txl) 262 { 263 json_value *c; 269 264 int i; 270 265 … … 272 267 txl->type = TXL_ID; 273 268 274 if (!(c = json_object_get_array(json_object(node), "ids"))) { 269 c = json_o_get(node, "ids"); 270 if (!c || c->type != json_array) { 275 271 return FALSE; 276 272 } 277 273 278 for (i = 0; i < json_array_get_count(c); i++) { 279 jint id = json_array_get_integer(c, i); 274 for (i = 0; i < c->u.array.length; i++) { 275 if (c->u.array.values[i]->type != json_integer) { 276 continue; 277 } 280 278 281 279 txl->list = g_slist_prepend(txl->list, 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);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; 288 286 } else { 289 287 txl->next_cursor = -1; … … 301 299 { 302 300 struct im_connection *ic; 303 JSON_Value *parsed;301 json_value *parsed; 304 302 struct twitter_xml_list *txl; 305 303 struct twitter_data *td; … … 314 312 td = ic->proto_data; 315 313 314 // Parse the data. 315 if (!(parsed = twitter_parse_response(ic, req))) { 316 return; 317 } 318 316 319 txl = g_new0(struct twitter_xml_list, 1); 317 320 txl->list = td->follow_ids; 318 319 // Parse the data.320 if (!(parsed = twitter_parse_response(ic, req))) {321 return;322 }323 321 324 322 twitter_xt_get_friends_id_list(parsed, txl); … … 339 337 } 340 338 341 static gboolean twitter_xt_get_users( JSON_Value *node, struct twitter_xml_list *txl);339 static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list *txl); 342 340 static void twitter_http_get_users_lookup(struct http_request *req); 343 341 … … 380 378 { 381 379 struct im_connection *ic = req->data; 382 JSON_Value *parsed;380 json_value *parsed; 383 381 struct twitter_xml_list *txl; 384 382 GSList *l = NULL; … … 390 388 } 391 389 390 // Get the user list from the parsed xml feed. 391 if (!(parsed = twitter_parse_response(ic, req))) { 392 return; 393 } 394 392 395 txl = g_new0(struct twitter_xml_list, 1); 393 396 txl->list = NULL; 394 397 395 // Get the user list from the parsed xml feed.396 if (!(parsed = twitter_parse_response(ic, req))) {397 return;398 }399 398 twitter_xt_get_users(parsed, txl); 400 399 json_value_free(parsed); … … 412 411 } 413 412 414 struct twitter_xml_user *twitter_xt_get_user(const JSON_Object*node)413 struct twitter_xml_user *twitter_xt_get_user(const json_value *node) 415 414 { 416 415 struct twitter_xml_user *txu; 417 418 if (!node) 419 return NULL; 416 json_value *jv; 420 417 421 418 txu = g_new0(struct twitter_xml_user, 1); 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"); 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; 425 424 426 425 return txu; … … 432 431 * - all <user>s from the <users> element. 433 432 */ 434 static gboolean twitter_xt_get_users( JSON_Value *node, struct twitter_xml_list *txl)433 static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list *txl) 435 434 { 436 435 struct twitter_xml_user *txu; … … 440 439 txl->type = TXL_USER; 441 440 442 if ( json_type(node) != JSONArray) {441 if (!node || node->type != json_array) { 443 442 return FALSE; 444 443 } 445 444 446 445 // The root <users> node should hold the list of users <user> 447 446 // Walk over the nodes children. 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); 447 for (i = 0; i < node->u.array.length; i++) { 448 txu = twitter_xt_get_user(node->u.array.values[i]); 454 449 if (txu) { 455 450 txl->list = g_slist_prepend(txl->list, txu); … … 466 461 #endif 467 462 468 static void expand_entities(char **text, const JSON_Object*node);463 static void expand_entities(char **text, const json_value *node); 469 464 470 465 /** … … 476 471 * - the user in a twitter_xml_user struct. 477 472 */ 478 static struct twitter_xml_status *twitter_xt_get_status(const JSON_Object*node)473 static struct twitter_xml_status *twitter_xt_get_status(const json_value *node) 479 474 { 480 475 struct twitter_xml_status *txs; 481 const JSON_Object*rt = NULL;482 483 if ( !node) {476 const json_value *rt = NULL; 477 478 if (node->type != json_object) { 484 479 return FALSE; 485 480 } … … 487 482 488 483 JSON_O_FOREACH(node, k, v) { 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..484 if (strcmp("text", k) == 0 && v->type == json_string) { 485 txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1); 491 486 strip_html(txs->text); 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) {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) { 495 490 struct tm parsed; 496 491 … … 498 493 this field. :-( Also assumes the timezone used 499 494 is UTC since C time handling functions suck. */ 500 if (strptime( json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) {495 if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) { 501 496 txs->created_at = mktime_utc(&parsed); 502 497 } 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);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; 509 504 } 510 505 } … … 535 530 * Function to fill a twitter_xml_status struct (DM variant). 536 531 */ 537 static struct twitter_xml_status *twitter_xt_get_dm(const JSON_Object*node)532 static struct twitter_xml_status *twitter_xt_get_dm(const json_value *node) 538 533 { 539 534 struct twitter_xml_status *txs; 540 535 541 if ( !node) {536 if (node->type != json_object) { 542 537 return FALSE; 543 538 } … … 545 540 546 541 JSON_O_FOREACH(node, k, v) { 547 if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(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); 548 544 strip_html(txs->text); 549 } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) {545 } else if (strcmp("created_at", k) == 0 && v->type == json_string) { 550 546 struct tm parsed; 551 547 … … 553 549 this field. :-( Also assumes the timezone used 554 550 is UTC since C time handling functions suck. */ 555 if (strptime( json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) {551 if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) { 556 552 txs->created_at = mktime_utc(&parsed); 557 553 } 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);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; 562 558 } 563 559 } … … 573 569 } 574 570 575 static void expand_entities(char **text, const JSON_Object*node)576 { 577 JSON_Object*entities, *quoted;571 static void expand_entities(char **text, const json_value *node) 572 { 573 json_value *entities, *quoted; 578 574 char *quote_url = NULL, *quote_text = NULL; 579 575 580 if (!( entities = json_object_get_object(node, "entities")))581 return; 582 if ((quoted = json_o bject_get_object(node, "quoted_status"))) {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) { 583 579 /* New "retweets with comments" feature. Note that this info 584 580 * seems to be included in the streaming API only! Grab the … … 596 592 int i; 597 593 598 if ( json_type(v) != JSONArray) {594 if (v->type != json_array) { 599 595 continue; 600 596 } … … 603 599 } 604 600 605 for (i = 0; i < json_array_get_count(json_array(v)); i++) {601 for (i = 0; i < v->u.array.length; i++) { 606 602 const char *format = "%s%s <%s>%s"; 607 JSON_Object *r = json_array_get_object(json_array(v), i); 608 609 if (!r) { 603 604 if (v->u.array.values[i]->type != json_object) { 610 605 continue; 611 606 } 612 607 613 const char *kort = json_o bject_get_string(r, "url");614 const char *disp = json_o bject_get_string(r, "display_url");615 const char *full = json_o bject_get_string(r, "expanded_url");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"); 616 611 char *pos, *new; 617 612 … … 642 637 * - the next_cursor. 643 638 */ 644 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const JSON_Value *node,639 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const json_value *node, 645 640 struct twitter_xml_list *txl) 646 641 { … … 651 646 txl->type = TXL_STATUS; 652 647 653 if ( json_type(node) != JSONArray) {648 if (node->type != json_array) { 654 649 return FALSE; 655 650 } … … 657 652 // The root <statuses> node should hold the list of statuses <status> 658 653 // Walk over the nodes children. 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));654 for (i = 0; i < node->u.array.length; i++) { 655 txs = twitter_xt_get_status(node->u.array.values[i]); 661 656 if (!txs) { 662 657 continue; … … 864 859 } 865 860 866 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object*o, gboolean from_filter);861 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o, gboolean from_filter); 867 862 868 863 static void twitter_http_stream(struct http_request *req) … … 870 865 struct im_connection *ic = req->data; 871 866 struct twitter_data *td; 872 JSON_Value *parsed;867 json_value *parsed; 873 868 int len = 0; 874 869 char c, *nl; … … 908 903 req->reply_body[len] = '\0'; 909 904 910 if ((parsed = json_parse _string(req->reply_body))) {905 if ((parsed = json_parse(req->reply_body, req->body_size))) { 911 906 from_filter = (req == td->filter_stream); 912 twitter_stream_handle_object(ic, json_object(parsed), from_filter);907 twitter_stream_handle_object(ic, parsed, from_filter); 913 908 } 914 909 json_value_free(parsed); … … 924 919 } 925 920 926 static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object*o);921 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o); 927 922 static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs); 928 923 929 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object*o, gboolean from_filter)924 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o, gboolean from_filter) 930 925 { 931 926 struct twitter_data *td = ic->proto_data; 932 927 struct twitter_xml_status *txs; 933 JSON_Object*c;928 json_value *c; 934 929 935 930 if ((txs = twitter_xt_get_status(o))) { … … 938 933 txs_free(txs); 939 934 return ret; 940 } else if ((c = json_o bject_get_object(o, "direct_message")) &&935 } else if ((c = json_o_get(o, "direct_message")) && 941 936 (txs = twitter_xt_get_dm(c))) { 942 937 if (g_strcasecmp(txs->user->screen_name, td->user) != 0) { … … 946 941 txs_free(txs); 947 942 return TRUE; 948 } else if ( json_object_get_string(o, "event")) {943 } else if ((c = json_o_get(o, "event")) && c->type == json_string) { 949 944 twitter_stream_handle_event(ic, o); 950 945 return TRUE; 951 } else if ((c = json_o bject_get_object(o, "disconnect"))) {946 } else if ((c = json_o_get(o, "disconnect")) && c->type == json_object) { 952 947 /* HACK: Because we're inside an event handler, we can't just 953 948 disconnect here. Instead, just change the HTTP status string 954 949 into a Twitter status string. */ 955 char *reason = g_strdup(json_object_get_string(c, "reason"));950 char *reason = json_o_strdup(c, "reason"); 956 951 if (reason) { 957 952 g_free(td->stream->status_string); … … 992 987 } 993 988 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) { 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) { 1002 998 return FALSE; 1003 999 } … … 1096 1092 struct twitter_filter *tf; 1097 1093 GList *users = NULL; 1098 JSON_Value *parsed; 1094 json_value *parsed; 1095 json_value *id; 1096 const char *name; 1099 1097 GString *fstr; 1100 1098 GSList *l; … … 1121 1119 } 1122 1120 1123 if ( json_type(parsed) != JSONArray) {1121 if (parsed->type != json_array) { 1124 1122 goto finish; 1125 1123 } 1126 1124 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) { 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) { 1133 1130 continue; 1134 1131 } … … 1138 1135 1139 1136 if (g_strcasecmp(tf->text, name) == 0) { 1140 tf->uid = id ;1137 tf->uid = id->u.integer; 1141 1138 users = g_list_delete_link(users, u); 1142 1139 break; … … 1379 1376 struct im_connection *ic = req->data; 1380 1377 struct twitter_data *td; 1381 JSON_Value *parsed;1378 json_value *parsed; 1382 1379 struct twitter_xml_list *txl; 1383 1380 … … 1388 1385 1389 1386 td = ic->proto_data; 1390 1391 txl = g_new0(struct twitter_xml_list, 1);1392 txl->list = NULL;1393 1387 1394 1388 // The root <statuses> node should hold the list of statuses <status> … … 1396 1390 goto end; 1397 1391 } 1392 1393 txl = g_new0(struct twitter_xml_list, 1); 1394 txl->list = NULL; 1395 1398 1396 twitter_xt_get_status_list(ic, parsed, txl); 1399 1397 json_value_free(parsed); … … 1418 1416 struct im_connection *ic = req->data; 1419 1417 struct twitter_data *td; 1420 JSON_Value *parsed;1418 json_value *parsed; 1421 1419 struct twitter_xml_list *txl; 1422 1420 … … 1427 1425 1428 1426 td = ic->proto_data; 1429 1430 txl = g_new0(struct twitter_xml_list, 1);1431 txl->list = NULL;1432 1427 1433 1428 // The root <statuses> node should hold the list of statuses <status> … … 1435 1430 goto end; 1436 1431 } 1432 1433 txl = g_new0(struct twitter_xml_list, 1); 1434 txl->list = NULL; 1435 1437 1436 twitter_xt_get_status_list(ic, parsed, txl); 1438 1437 json_value_free(parsed); … … 1458 1457 struct im_connection *ic = req->data; 1459 1458 struct twitter_data *td; 1460 JSON_Value *parsed; 1461 jint id; 1459 json_value *parsed, *id; 1462 1460 1463 1461 // Check if the connection is still active. … … 1473 1471 } 1474 1472 1475 if ((id = json_o bject_get_integer(json_object(parsed), "id"))) {1476 td->last_status_id = id ;1473 if ((id = json_o_get(parsed, "id")) && id->type == json_integer) { 1474 td->last_status_id = id->u.integer; 1477 1475 } 1478 1476 … … 1582 1580 { 1583 1581 struct im_connection *ic = req->data; 1584 JSON_Value *parsed; 1585 uint64_t id; 1582 json_value *parsed, *id; 1586 1583 const char *name; 1587 1584 … … 1595 1592 } 1596 1593 1594 /* for the parson branch: 1597 1595 name = json_object_dotget_string(json_object(parsed), "user.screen_name"); 1598 1596 id = json_object_get_integer(json_object(parsed), "id"); 1599 1600 if (name && id) { 1601 twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, 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); 1602 1604 } else { 1603 1605 twitter_log(ic, "Error: could not fetch tweet url.");
Note: See TracChangeset
for help on using the changeset viewer.