Changeset 537d9b9 for protocols/twitter
- Timestamp:
- 2016-11-20T08:40:36Z (8 years ago)
- Children:
- 3f44e43
- Parents:
- ba52ac5 (diff), 9f03c47 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- protocols/twitter
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/twitter/twitter.c
rba52ac5 r537d9b9 345 345 imcb_log(ic, "Getting contact list"); 346 346 twitter_get_friends_ids(ic, -1); 347 twitter_get_mutes_ids(ic, -1); 348 twitter_get_noretweets_ids(ic, -1); 347 349 } else { 348 350 twitter_main_loop_start(ic); … … 469 471 g_regex_match(regex, msg, 0, &match_info); 470 472 while (g_match_info_matches(match_info)) { 471 gchar * s, *url;473 gchar *url; 472 474 473 475 url = g_match_info_fetch(match_info, 2); 474 476 url_len_diff += target_len - g_utf8_strlen(url, -1); 475 477 476 /* Add another character for https://t.co/... URLs */477 if ((s = g_match_info_fetch(match_info, 3))) {478 url_len_diff += 1;479 g_free(s);480 }481 478 g_free(url); 482 479 g_match_info_next(match_info, NULL); … … 541 538 if (strcmp(acc->prpl->name, "twitter") == 0) { 542 539 def_url = TWITTER_API_URL; 543 def_tul = "2 2";540 def_tul = "23"; 544 541 def_mentions = "true"; 545 542 } else { /* if( strcmp( acc->prpl->name, "identica" ) == 0 ) */ … … 690 687 } 691 688 689 g_slist_foreach(td->mutes_ids, (GFunc) g_free, NULL); 690 g_slist_free(td->mutes_ids); 691 692 g_slist_foreach(td->noretweets_ids, (GFunc) g_free, NULL); 693 g_slist_free(td->noretweets_ids); 694 692 695 http_close(td->stream); 693 696 twitter_filter_remove_all(ic); … … 948 951 } else if ((g_strcasecmp(cmd[0], "favourite") == 0 || 949 952 g_strcasecmp(cmd[0], "favorite") == 0 || 950 g_strcasecmp(cmd[0], "fav") == 0) && cmd[1]) { 953 g_strcasecmp(cmd[0], "fav") == 0 || 954 g_strcasecmp(cmd[0], "like") == 0) && cmd[1]) { 951 955 if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL))) { 952 956 twitter_favourite_tweet(ic, id); … … 960 964 } else if (g_strcasecmp(cmd[0], "unfollow") == 0 && cmd[1]) { 961 965 twitter_remove_buddy(ic, cmd[1], NULL); 966 goto eof; 967 } else if (g_strcasecmp(cmd[0], "mute") == 0 && cmd[1]) { 968 twitter_mute_create_destroy(ic, cmd[1], 1); 969 goto eof; 970 } else if (g_strcasecmp(cmd[0], "unmute") == 0 && cmd[1]) { 971 twitter_mute_create_destroy(ic, cmd[1], 0); 962 972 goto eof; 963 973 } else if ((g_strcasecmp(cmd[0], "report") == 0 || … … 1082 1092 struct prpl *ret = g_new0(struct prpl, 1); 1083 1093 1084 ret->options = OPT_NOOTR;1094 ret->options = PRPL_OPT_NOOTR | PRPL_OPT_NO_PASSWORD; 1085 1095 ret->name = "twitter"; 1086 1096 ret->login = twitter_login; … … 1109 1119 ret = g_memdup(ret, sizeof(struct prpl)); 1110 1120 ret->name = "identica"; 1121 ret->options = PRPL_OPT_NOOTR; 1111 1122 register_protocol(ret); 1112 1123 } -
protocols/twitter/twitter.h
rba52ac5 r537d9b9 61 61 62 62 GSList *follow_ids; 63 GSList *mutes_ids; 64 GSList *noretweets_ids; 63 65 GSList *filters; 64 66 -
protocols/twitter/twitter_http.c
rba52ac5 r537d9b9 79 79 g_string_printf(request, "%s %s%s%s%s HTTP/1.1\r\n" 80 80 "Host: %s\r\n" 81 "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n",81 "User-Agent: BitlBee " BITLBEE_VERSION "\r\n", 82 82 is_post ? "POST" : "GET", 83 83 base_url ? base_url->file : td->url_path, -
protocols/twitter/twitter_lib.c
rba52ac5 r537d9b9 245 245 246 246 static void twitter_http_get_friends_ids(struct http_request *req); 247 static void twitter_http_get_mutes_ids(struct http_request *req); 248 static void twitter_http_get_noretweets_ids(struct http_request *req); 247 249 248 250 /** … … 257 259 args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor); 258 260 twitter_http(ic, TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, args, 2); 261 262 g_free(args[1]); 263 } 264 265 /** 266 * Get the muted users ids. 267 */ 268 void twitter_get_mutes_ids(struct im_connection *ic, gint64 next_cursor) 269 { 270 char *args[2]; 271 272 args[0] = "cursor"; 273 args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor); 274 twitter_http(ic, TWITTER_MUTES_IDS_URL, twitter_http_get_mutes_ids, ic, 0, args, 2); 275 276 g_free(args[1]); 277 } 278 279 /** 280 * Get the ids for users from whom we should ignore retweets. 281 */ 282 void twitter_get_noretweets_ids(struct im_connection *ic, gint64 next_cursor) 283 { 284 char *args[2]; 285 286 args[0] = "cursor"; 287 args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor); 288 twitter_http(ic, TWITTER_NORETWEETS_IDS_URL, twitter_http_get_noretweets_ids, ic, 0, args, 2); 259 289 260 290 g_free(args[1]); … … 334 364 twitter_get_users_lookup(ic); 335 365 } 366 367 txl->list = NULL; 368 txl_free(txl); 369 } 370 371 /** 372 * Callback for getting the mutes ids. 373 */ 374 static void twitter_http_get_mutes_ids(struct http_request *req) 375 { 376 struct im_connection *ic = req->data; 377 JSON_Value *parsed; 378 struct twitter_xml_list *txl; 379 struct twitter_data *td; 380 381 // Check if the connection is stil active 382 if (!g_slist_find(twitter_connections, ic)) { 383 return; 384 } 385 386 td = ic->proto_data; 387 388 if (req->status_code != 200) { 389 /* Fail silently */ 390 return; 391 } 392 393 // Parse the data. 394 if (!(parsed = twitter_parse_response(ic, req))) { 395 return; 396 } 397 398 txl = g_new0(struct twitter_xml_list, 1); 399 txl->list = td->mutes_ids; 400 401 /* mute ids API response is similar enough to friends response 402 to reuse this method */ 403 twitter_xt_get_friends_id_list(parsed, txl); 404 json_value_free(parsed); 405 406 td->mutes_ids = txl->list; 407 if (txl->next_cursor) { 408 /* Recurse while there are still more pages */ 409 twitter_get_mutes_ids(ic, txl->next_cursor); 410 } 411 412 txl->list = NULL; 413 txl_free(txl); 414 } 415 416 /** 417 * Callback for getting the no-retweets ids. 418 */ 419 static void twitter_http_get_noretweets_ids(struct http_request *req) 420 { 421 struct im_connection *ic = req->data; 422 JSON_Value *parsed; 423 struct twitter_xml_list *txl; 424 struct twitter_data *td; 425 426 // Check if the connection is stil active 427 if (!g_slist_find(twitter_connections, ic)) { 428 return; 429 } 430 431 if (req->status_code != 200) { 432 /* Fail silently */ 433 return; 434 } 435 436 td = ic->proto_data; 437 438 // Parse the data. 439 if (!(parsed = twitter_parse_response(ic, req))) { 440 return; 441 } 442 443 txl = g_new0(struct twitter_xml_list, 1); 444 txl->list = td->noretweets_ids; 445 446 // Process the retweet ids 447 txl->type = TXL_ID; 448 if (json_type(parsed) == JSONArray) { 449 JSON_Array *arr = json_array(parsed); 450 unsigned int i; 451 for (i = 0; i < json_array_get_count(arr); i++) { 452 jint id = json_array_get_integer(arr, i); 453 txl->list = g_slist_prepend(txl->list, 454 g_strdup_printf("%lld", id)); 455 } 456 } 457 458 json_value_free(parsed); 459 td->noretweets_ids = txl->list; 336 460 337 461 txl->list = NULL; … … 467 591 #endif 468 592 469 static void expand_entities(char **text, const JSON_Object *node );593 static void expand_entities(char **text, const JSON_Object *node, const JSON_Object *extended_node); 470 594 471 595 /** … … 479 603 static struct twitter_xml_status *twitter_xt_get_status(const JSON_Object *node) 480 604 { 481 struct twitter_xml_status *txs ;605 struct twitter_xml_status *txs = {0}; 482 606 const JSON_Object *rt = NULL; 607 const JSON_Value *text_value = NULL; 608 const JSON_Object *extended_node = NULL; 483 609 484 610 if (!node) { … … 488 614 489 615 JSON_O_FOREACH(node, k, v) { 490 if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) { 491 // TODO: Huh strip html? In json? Not sure whether I have to.. 492 strip_html(txs->text); 616 if (strcmp("text", k) == 0 && json_type(v) == JSONString && text_value == NULL) { 617 text_value = v; 618 } else if (strcmp("full_text", k) == 0 && json_type(v) == JSONString) { 619 text_value = v; 620 } else if (strcmp("extended_tweet", k) == 0 && json_type(v) == JSONObject) { 621 text_value = json_object_get_value(json_object(v), "full_text"); 622 extended_node = json_object(v); 493 623 } else if (strcmp("retweeted_status", k) == 0 && (rt = json_object(v))) { 494 624 // Handling below. … … 516 646 struct twitter_xml_status *rtxs = twitter_xt_get_status(rt); 517 647 if (rtxs) { 518 g_free(txs->text);519 648 txs->text = g_strdup_printf("RT @%s: %s", rtxs->user->screen_name, rtxs->text); 520 649 txs->id = rtxs->id; 521 650 txs_free(rtxs); 522 651 } 523 } else { 524 expand_entities(&txs->text, node); 652 } else if (text_value && json_type(text_value) == JSONString) { 653 txs->text = g_strdup(json_string(text_value)); 654 strip_html(txs->text); 655 expand_entities(&txs->text, node, extended_node); 525 656 } 526 657 … … 564 695 } 565 696 566 expand_entities(&txs->text, node );697 expand_entities(&txs->text, node, NULL); 567 698 568 699 if (txs->text && txs->user && txs->id) { … … 574 705 } 575 706 576 static void expand_entities(char **text, const JSON_Object *node )577 { 578 JSON_Object *entities, * quoted;707 static void expand_entities(char **text, const JSON_Object *node, const JSON_Object *extended_node) 708 { 709 JSON_Object *entities, *extended_entities, *quoted; 579 710 char *quote_url = NULL, *quote_text = NULL; 580 711 … … 594 725 } 595 726 727 if (extended_node) { 728 extended_entities = json_object_get_object(extended_node, "entities"); 729 if (extended_entities) { 730 entities = extended_entities; 731 } 732 } 733 596 734 JSON_O_FOREACH(entities, k, v) { 597 735 int i; … … 837 975 struct twitter_data *td = ic->proto_data; 838 976 char *last_id_str; 977 char *uid_str; 839 978 840 979 if (status->user == NULL || status->text == NULL) { 980 return; 981 } 982 983 /* Check this is not a tweet that should be muted */ 984 uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, status->user->uid); 985 986 if (g_slist_find_custom(td->mutes_ids, uid_str, (GCompareFunc)strcmp)) { 987 g_free(uid_str); 988 return; 989 } 990 if (status->id != status->rt_id && g_slist_find_custom(td->noretweets_ids, uid_str, (GCompareFunc)strcmp)) { 991 g_free(uid_str); 841 992 return; 842 993 } … … 863 1014 set_setstr(&ic->acc->set, "_last_tweet", last_id_str); 864 1015 g_free(last_id_str); 1016 g_free(uid_str); 865 1017 } 866 1018 … … 880 1032 } 881 1033 882 ic->flags |= OPT_PONGED;883 1034 td = ic->proto_data; 884 1035 … … 896 1047 imc_logout(ic, TRUE); 897 1048 return; 1049 } 1050 1051 if (req == td->stream) { 1052 ic->flags |= OPT_PONGED; 898 1053 } 899 1054 … … 999 1154 JSON_Object *target = json_object_get_object(o, "target"); 1000 1155 const char *type = json_object_get_string(o, "event"); 1156 struct twitter_xml_user *us = NULL; 1157 struct twitter_xml_user *ut = NULL; 1001 1158 1002 1159 if (!type || !source || !target) { … … 1005 1162 1006 1163 if (strcmp(type, "follow") == 0) { 1007 struct twitter_xml_user *us = twitter_xt_get_user(source);1008 struct twitter_xml_user *ut = twitter_xt_get_user(target);1164 us = twitter_xt_get_user(source); 1165 ut = twitter_xt_get_user(target); 1009 1166 if (g_strcasecmp(us->screen_name, td->user) == 0) { 1010 1167 twitter_add_buddy(ic, ut->screen_name, ut->name); 1011 1168 } 1012 txu_free(us); 1013 txu_free(ut); 1014 } 1169 } else if (strcmp(type, "mute") == 0) { 1170 GSList *found; 1171 char *uid_str; 1172 ut = twitter_xt_get_user(target); 1173 uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, ut->uid); 1174 if (!(found = g_slist_find_custom(td->mutes_ids, uid_str, 1175 (GCompareFunc)strcmp))) { 1176 td->mutes_ids = g_slist_prepend(td->mutes_ids, uid_str); 1177 } 1178 twitter_log(ic, "Muted user %s", ut->screen_name); 1179 if (getenv("BITLBEE_DEBUG")) { 1180 fprintf(stderr, "New mute: %s %"G_GUINT64_FORMAT"\n", 1181 ut->screen_name, ut->uid); 1182 } 1183 } else if (strcmp(type, "unmute") == 0) { 1184 GSList *found; 1185 char *uid_str; 1186 ut = twitter_xt_get_user(target); 1187 uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, ut->uid); 1188 if ((found = g_slist_find_custom(td->mutes_ids, uid_str, 1189 (GCompareFunc)strcmp))) { 1190 char *found_str = found->data; 1191 td->mutes_ids = g_slist_delete_link(td->mutes_ids, found); 1192 g_free(found_str); 1193 } 1194 g_free(uid_str); 1195 twitter_log(ic, "Unmuted user %s", ut->screen_name); 1196 if (getenv("BITLBEE_DEBUG")) { 1197 fprintf(stderr, "New unmute: %s %"G_GUINT64_FORMAT"\n", 1198 ut->screen_name, ut->uid); 1199 } 1200 } 1201 1202 txu_free(us); 1203 txu_free(ut); 1015 1204 1016 1205 return TRUE; … … 1309 1498 td->flags &= ~TWITTER_GOT_TIMELINE; 1310 1499 1311 char *args[ 6];1500 char *args[8]; 1312 1501 args[0] = "cursor"; 1313 1502 args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor); 1314 1503 args[2] = "include_entities"; 1315 1504 args[3] = "true"; 1505 args[4] = "tweet_mode"; 1506 args[5] = "extended"; 1316 1507 if (td->timeline_id) { 1317 args[ 4] = "since_id";1318 args[ 5] = g_strdup_printf("%" G_GUINT64_FORMAT, td->timeline_id);1508 args[6] = "since_id"; 1509 args[7] = g_strdup_printf("%" G_GUINT64_FORMAT, td->timeline_id); 1319 1510 } 1320 1511 1321 1512 if (twitter_http(ic, TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, args, 1322 td->timeline_id ? 6 : 4) == NULL) {1513 td->timeline_id ? 8 : 6) == NULL) { 1323 1514 if (++td->http_fails >= 5) { 1324 1515 imcb_error(ic, "Could not retrieve %s: %s", … … 1331 1522 g_free(args[1]); 1332 1523 if (td->timeline_id) { 1333 g_free(args[ 5]);1524 g_free(args[7]); 1334 1525 } 1335 1526 } … … 1346 1537 td->flags &= ~TWITTER_GOT_MENTIONS; 1347 1538 1348 char *args[ 6];1539 char *args[8]; 1349 1540 args[0] = "cursor"; 1350 1541 args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor); … … 1358 1549 args[5] = g_strdup_printf("%d", set_getint(&ic->acc->set, "show_old_mentions")); 1359 1550 } 1551 args[6] = "tweet_mode"; 1552 args[7] = "extended"; 1360 1553 1361 1554 if (twitter_http(ic, TWITTER_MENTIONS_URL, twitter_http_get_mentions, 1362 ic, 0, args, 6) == NULL) {1555 ic, 0, args, 8) == NULL) { 1363 1556 if (++td->http_fails >= 5) { 1364 1557 imcb_error(ic, "Could not retrieve %s: %s", … … 1529 1722 } 1530 1723 1724 /** 1725 * Mute or unmute a user 1726 */ 1727 void twitter_mute_create_destroy(struct im_connection *ic, char *who, int create) 1728 { 1729 char *args[2]; 1730 1731 args[0] = "screen_name"; 1732 args[1] = who; 1733 twitter_http(ic, create ? TWITTER_MUTES_CREATE_URL : TWITTER_MUTES_DESTROY_URL, 1734 twitter_http_post, ic, 1, args, 2); 1735 } 1736 1531 1737 void twitter_status_destroy(struct im_connection *ic, guint64 id) 1532 1738 { -
protocols/twitter/twitter_lib.h
rba52ac5 r537d9b9 63 63 #define TWITTER_FRIENDS_IDS_URL "/friends/ids.json" 64 64 #define TWITTER_FOLLOWERS_IDS_URL "/followers/ids.json" 65 #define TWITTER_MUTES_IDS_URL "/mutes/users/ids.json" 66 #define TWITTER_NORETWEETS_IDS_URL "/friendships/no_retweets/ids.json" 65 67 66 68 /* Account URLs */ … … 76 78 #define TWITTER_BLOCKS_DESTROY_URL "/blocks/destroy/" 77 79 80 /* Mute URLs */ 81 #define TWITTER_MUTES_CREATE_URL "/mutes/users/create.json" 82 #define TWITTER_MUTES_DESTROY_URL "/mutes/users/destroy.json" 83 78 84 /* Report spam */ 79 85 #define TWITTER_REPORT_SPAM_URL "/users/report_spam.json" … … 87 93 gboolean twitter_get_timeline(struct im_connection *ic, gint64 next_cursor); 88 94 void twitter_get_friends_ids(struct im_connection *ic, gint64 next_cursor); 95 void twitter_get_mutes_ids(struct im_connection *ic, gint64 next_cursor); 96 void twitter_get_noretweets_ids(struct im_connection *ic, gint64 next_cursor); 89 97 void twitter_get_statuses_friends(struct im_connection *ic, gint64 next_cursor); 90 98 … … 92 100 void twitter_direct_messages_new(struct im_connection *ic, char *who, char *message); 93 101 void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int create); 102 void twitter_mute_create_destroy(struct im_connection *ic, char *who, int create); 94 103 void twitter_status_destroy(struct im_connection *ic, guint64 id); 95 104 void twitter_status_retweet(struct im_connection *ic, guint64 id);
Note: See TracChangeset
for help on using the changeset viewer.