Changeset 5ebff60 for protocols/twitter/twitter.c
- Timestamp:
- 2015-02-20T22:50:54Z (9 years ago)
- Branches:
- master
- Children:
- 0b9daac, 3d45471, 7733b8c
- Parents:
- af359b4
- git-author:
- Indent <please@…> (19-02-15 05:47:20)
- git-committer:
- dequis <dx@…> (20-02-15 22:50:54)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/twitter/twitter.c
raf359b4 r5ebff60 91 91 struct twitter_data *td = c->ic->proto_data; 92 92 struct twitter_filter *tf = NULL; 93 struct twitter_filter tfc = { type, (char*) text};93 struct twitter_filter tfc = { type, (char *) text }; 94 94 GSList *l; 95 95 … … 97 97 tf = l->data; 98 98 99 if (twitter_filter_cmp(tf, &tfc) == 0) 99 if (twitter_filter_cmp(tf, &tfc) == 0) { 100 100 break; 101 } 101 102 102 103 tf = NULL; … … 110 111 } 111 112 112 if (!g_slist_find(tf->groupchats, c)) 113 if (!g_slist_find(tf->groupchats, c)) { 113 114 tf->groupchats = g_slist_prepend(tf->groupchats, c); 114 115 if (td->filter_update_id > 0) 115 } 116 117 if (td->filter_update_id > 0) { 116 118 b_event_remove(td->filter_update_id); 119 } 117 120 118 121 /* Wait for other possible filter changes to avoid request spam */ 119 122 td->filter_update_id = b_timeout_add(TWITTER_FILTER_UPDATE_WAIT, 120 123 twitter_filter_update, c->ic); 121 124 return tf; 122 125 } … … 149 152 } 150 153 151 if (td->filter_update_id > 0) 154 if (td->filter_update_id > 0) { 152 155 b_event_remove(td->filter_update_id); 156 } 153 157 154 158 /* Wait for other possible filter changes to avoid request spam */ 155 159 td->filter_update_id = b_timeout_add(TWITTER_FILTER_UPDATE_WAIT, 156 twitter_filter_update, c->ic);} 160 twitter_filter_update, c->ic); 161 } 157 162 158 163 static void twitter_filter_remove_all(struct im_connection *ic) … … 169 174 /* Build up a list of groupchats to be freed */ 170 175 for (p = tf->groupchats; p; p = g_slist_next(p)) { 171 if (!g_slist_find(chats, p->data)) 176 if (!g_slist_find(chats, p->data)) { 172 177 chats = g_slist_prepend(chats, p->data); 178 } 173 179 } 174 180 … … 217 223 218 224 for (f = fs; *f; f++) { 219 if ((v = strchr(*f, ':')) == NULL) 225 if ((v = strchr(*f, ':')) == NULL) { 220 226 continue; 227 } 221 228 222 229 *(v++) = 0; … … 229 236 } 230 237 231 if (t < 0 || strlen(v) == 0) 238 if (t < 0 || strlen(v) == 0) { 232 239 continue; 240 } 233 241 234 242 tf = twitter_filter_get(c, types[t], v); … … 248 256 249 257 // Check if we are still logged in... 250 if (!g_slist_find(twitter_connections, ic)) 258 if (!g_slist_find(twitter_connections, ic)) { 251 259 return FALSE; 260 } 252 261 253 262 // Do stuff.. … … 261 270 262 271 char *last_tweet = set_getstr(&ic->acc->set, "_last_tweet"); 263 if (last_tweet) 272 273 if (last_tweet) { 264 274 td->timeline_id = g_ascii_strtoull(last_tweet, NULL, 0); 275 } 265 276 266 277 /* Create the room now that we "logged in". */ 267 if (td->flags & TWITTER_MODE_CHAT) 278 if (td->flags & TWITTER_MODE_CHAT) { 268 279 twitter_groupchat_init(ic); 280 } 269 281 270 282 imcb_log(ic, "Getting initial statuses"); … … 273 285 // stream if available). 274 286 twitter_main_loop(ic, -1, 0); 275 287 276 288 if (set_getbool(&ic->acc->set, "stream")) { 277 289 /* That fetch was just to get backlog, the stream will give 278 290 us the rest. \o/ */ 279 291 twitter_open_stream(ic); 280 292 281 293 /* Stream sends keepalives (empty lines) or actual data at 282 294 least twice a minute. Disconnect if this stops. */ … … 286 298 fashioned way. :-( */ 287 299 td->main_loop_id = 288 b_timeout_add(set_getint(&ic->acc->set, "fetch_interval") * 1000,289 twitter_main_loop, ic);300 b_timeout_add(set_getint(&ic->acc->set, "fetch_interval") * 1000, 301 twitter_main_loop, ic); 290 302 } 291 303 } … … 298 310 GSList *l; 299 311 300 if (td->timeline_gc) 312 if (td->timeline_gc) { 301 313 return td->timeline_gc; 314 } 302 315 303 316 td->timeline_gc = gc = imcb_chat_new(ic, "twitter/timeline"); … … 309 322 for (l = ic->bee->users; l; l = l->next) { 310 323 bee_user_t *bu = l->data; 311 if (bu->ic == ic) 324 if (bu->ic == ic) { 312 325 imcb_chat_add_buddy(gc, bu->handle); 326 } 313 327 } 314 328 imcb_chat_add_buddy(gc, ic->acc->user); 315 329 316 330 return gc; 317 331 } … … 325 339 td->flags &= ~TWITTER_DOING_TIMELINE; 326 340 327 if (set_getbool(&ic->acc->set, "oauth") && !td->oauth_info) 341 if (set_getbool(&ic->acc->set, "oauth") && !td->oauth_info) { 328 342 twitter_oauth_start(ic); 329 else if (!(td->flags & TWITTER_MODE_ONE) &&330 !(td->flags & TWITTER_HAVE_FRIENDS)) {343 } else if (!(td->flags & TWITTER_MODE_ONE) && 344 !(td->flags & TWITTER_HAVE_FRIENDS)) { 331 345 imcb_log(ic, "Getting contact list"); 332 346 twitter_get_friends_ids(ic, -1); 333 } else 347 } else { 334 348 twitter_main_loop_start(ic); 349 } 335 350 } 336 351 … … 357 372 struct twitter_data *td = ic->proto_data; 358 373 359 if (strstr(td->url_host, "identi.ca")) 374 if (strstr(td->url_host, "identi.ca")) { 360 375 return &identica_oauth; 361 else376 } else { 362 377 return &twitter_oauth; 378 } 363 379 364 380 /* Could add more services, or allow configuring your own base URL + … … 372 388 373 389 imcb_log(ic, "Requesting OAuth request token"); 374 375 if (!strstr(url, "twitter.com") && !strstr(url, "identi.ca")) 390 391 if (!strstr(url, "twitter.com") && !strstr(url, "identi.ca")) { 376 392 imcb_log(ic, "Warning: OAuth only works with identi.ca and " 377 "Twitter."); 393 "Twitter."); 394 } 378 395 379 396 td->oauth_info = oauth_request_token(get_oauth_service(ic), twitter_oauth_callback, ic); … … 389 406 struct twitter_data *td; 390 407 391 if (!g_slist_find(twitter_connections, ic)) 408 if (!g_slist_find(twitter_connections, ic)) { 392 409 return FALSE; 410 } 393 411 394 412 td = ic->proto_data; … … 404 422 name = g_strdup_printf("%s_%s", td->prefix, ic->acc->user); 405 423 msg = g_strdup_printf("To finish OAuth authentication, please visit " 406 407 424 "%s and respond with the resulting PIN code.", 425 info->auth_url); 408 426 imcb_buddy_msg(ic, name, msg, 0, 0); 409 427 g_free(name); … … 411 429 } else if (info->stage == OAUTH_ACCESS_TOKEN) { 412 430 const char *sn; 413 431 414 432 if (info->token == NULL || info->token_secret == NULL) { 415 433 imcb_error(ic, "OAuth error: %s", twitter_parse_error(info->http)); … … 417 435 return FALSE; 418 436 } 419 437 420 438 if ((sn = oauth_params_get(&info->params, "screen_name"))) { 421 if (ic->acc->prpl->handle_cmp(sn, ic->acc->user) != 0) 439 if (ic->acc->prpl->handle_cmp(sn, ic->acc->user) != 0) { 422 440 imcb_log(ic, "Warning: You logged in via OAuth as %s " 423 441 "instead of %s.", sn, ic->acc->user); 442 } 424 443 g_free(td->user); 425 444 td->user = g_strdup(sn); … … 444 463 GMatchInfo *match_info; 445 464 446 if (regex == NULL) 465 if (regex == NULL) { 447 466 regex = g_regex_new("(^|\\s)(http(s)?://[^\\s$]+)", 0, 0, NULL); 448 467 } 468 449 469 g_regex_match(regex, msg, 0, &match_info); 450 470 while (g_match_info_matches(match_info)) { … … 452 472 url_len_diff += target_len - g_utf8_strlen(url, -1); 453 473 /* Add another character for https://t.co/... URLs */ 454 if (g_match_info_fetch(match_info, 3) != NULL) 474 if (g_match_info_fetch(match_info, 3) != NULL) { 455 475 url_len_diff += 1; 476 } 456 477 g_free(url); 457 478 g_match_info_next(match_info, NULL); … … 468 489 int url_len_diff = 0; 469 490 470 if (target_len > 0) 491 if (target_len > 0) { 471 492 url_len_diff = twitter_url_len_diff(msg, target_len); 472 473 if (max == 0 || (len = g_utf8_strlen(msg, -1) + url_len_diff) <= max) 493 } 494 495 if (max == 0 || (len = g_utf8_strlen(msg, -1) + url_len_diff) <= max) { 474 496 return TRUE; 497 } 475 498 476 499 twitter_log(ic, "Maximum message length exceeded: %d > %d", len, max); … … 481 504 static char *set_eval_commands(set_t * set, char *value) 482 505 { 483 if (g_strcasecmp(value, "strict") == 0 )506 if (g_strcasecmp(value, "strict") == 0) { 484 507 return value; 485 else508 } else { 486 509 return set_eval_bool(set, value); 510 } 487 511 } 488 512 … … 490 514 { 491 515 if (g_strcasecmp(value, "one") == 0 || 492 g_strcasecmp(value, "many") == 0 || g_strcasecmp(value, "chat") == 0) 516 g_strcasecmp(value, "many") == 0 || g_strcasecmp(value, "chat") == 0) { 493 517 return value; 494 else518 } else { 495 519 return NULL; 520 } 496 521 } 497 522 … … 507 532 def_tul = "22"; 508 533 def_mentions = "true"; 509 } else { 534 } else { /* if( strcmp( acc->prpl->name, "identica" ) == 0 ) */ 510 535 def_url = IDENTICA_API_URL; 511 536 def_tul = "0"; … … 539 564 540 565 s = set_add(&acc->set, "strip_newlines", "false", set_eval_bool, acc); 541 566 542 567 s = set_add(&acc->set, "_last_tweet", "0", NULL, acc); 543 568 s->flags |= SET_HIDDEN | SET_NOSAVE; … … 560 585 url_t url; 561 586 char *s; 562 587 563 588 if (!url_set(&url, set_getstr(&ic->acc->set, "base_url")) || 564 589 (url.proto != PROTO_HTTP && url.proto != PROTO_HTTPS)) { … … 571 596 set_getbool(&ic->acc->set, "stream")) { 572 597 imcb_error(ic, "Warning: The streaming API is only supported by Twitter, " 573 598 "and you seem to be connecting to a different service."); 574 599 } 575 600 … … 584 609 td->url_port = url.port; 585 610 td->url_host = g_strdup(url.host); 586 if (strcmp(url.file, "/") != 0) 611 if (strcmp(url.file, "/") != 0) { 587 612 td->url_path = g_strdup(url.file); 588 else {613 } else { 589 614 td->url_path = g_strdup(""); 590 if (g_str_has_suffix(url.host, "twitter.com")) 615 if (g_str_has_suffix(url.host, "twitter.com")) { 591 616 /* May fire for people who turned on HTTPS. */ 592 617 imcb_error(ic, "Warning: Twitter requires a version number in API calls " 593 "now. Try resetting the base_url account setting."); 594 } 595 618 "now. Try resetting the base_url account setting."); 619 } 620 } 621 596 622 /* Hacky string mangling: Turn identi.ca into identi.ca and api.twitter.com 597 623 into twitter, and try to be sensible if we get anything else. */ 598 624 td->prefix = g_strdup(url.host); 599 if (g_str_has_suffix(td->prefix, ".com")) 625 if (g_str_has_suffix(td->prefix, ".com")) { 600 626 td->prefix[strlen(url.host) - 4] = '\0'; 627 } 601 628 if ((s = strrchr(td->prefix, '.')) && strlen(s) > 4) { 602 629 /* If we have at least 3 chars after the last dot, cut off the rest. … … 606 633 td->prefix = s; 607 634 } 608 609 if (strstr(acc->pass, "oauth_token=")) 635 636 if (strstr(acc->pass, "oauth_token=")) { 610 637 td->oauth_info = oauth_from_string(acc->pass, get_oauth_service(ic)); 638 } 611 639 612 640 sprintf(name, "%s_%s", td->prefix, acc->user); … … 616 644 td->log = g_new0(struct twitter_log_data, TWITTER_LOG_LENGTH); 617 645 td->log_id = -1; 618 646 619 647 s = set_getstr(&ic->acc->set, "mode"); 620 if (g_strcasecmp(s, "one") == 0) 648 if (g_strcasecmp(s, "one") == 0) { 621 649 td->flags |= TWITTER_MODE_ONE; 622 else if (g_strcasecmp(s, "many") == 0)650 } else if (g_strcasecmp(s, "many") == 0) { 623 651 td->flags |= TWITTER_MODE_MANY; 624 else652 } else { 625 653 td->flags |= TWITTER_MODE_CHAT; 654 } 626 655 627 656 twitter_login_finish(ic); … … 641 670 b_event_remove(td->main_loop_id); 642 671 643 if (td->timeline_gc) 672 if (td->timeline_gc) { 644 673 imcb_chat_free(td->timeline_gc); 674 } 645 675 646 676 if (td) { 647 if (td->filter_update_id > 0) 677 if (td->filter_update_id > 0) { 648 678 b_event_remove(td->filter_update_id); 679 } 649 680 650 681 http_close(td->stream); … … 679 710 680 711 strcpy(pin, message); 681 for (s = pin + sizeof(pin) - 2; s > pin && g_ascii_isspace(*s); s--) 712 for (s = pin + sizeof(pin) - 2; s > pin && g_ascii_isspace(*s); s--) { 682 713 *s = '\0'; 714 } 683 715 for (s = pin; *s && g_ascii_isspace(*s); s++) { 684 716 } … … 686 718 if (!oauth_access_token(s, td->oauth_info)) { 687 719 imcb_error(ic, "OAuth error: %s", 688 720 "Failed to send access token request"); 689 721 imc_logout(ic, TRUE); 690 722 return FALSE; 691 723 } 692 } else 724 } else { 693 725 twitter_handle_command(ic, message); 726 } 694 727 } else { 695 728 twitter_direct_messages_new(ic, who, message); … … 714 747 static void twitter_chat_msg(struct groupchat *c, char *message, int flags) 715 748 { 716 if (c && message) 749 if (c && message) { 717 750 twitter_handle_command(c->ic, message); 751 } 718 752 } 719 753 … … 737 771 tf = l->data; 738 772 739 if (topic->len > 0) 773 if (topic->len > 0) { 740 774 g_string_append(topic, ", "); 741 742 if (tf->type == TWITTER_FILTER_TYPE_FOLLOW) 775 } 776 777 if (tf->type == TWITTER_FILTER_TYPE_FOLLOW) { 743 778 g_string_append_c(topic, '@'); 779 } 744 780 745 781 g_string_append(topic, tf->text); 746 782 } 747 783 748 if (topic->len > 0) 784 if (topic->len > 0) { 749 785 g_string_prepend(topic, "Twitter Filter: "); 786 } 750 787 751 788 imcb_chat_topic(c, NULL, topic->str, 0); … … 820 857 * Returns 0 if the user provides garbage. 821 858 */ 822 static guint64 twitter_message_id_from_command_arg(struct im_connection *ic, char *arg, bee_user_t **bu_) { 859 static guint64 twitter_message_id_from_command_arg(struct im_connection *ic, char *arg, bee_user_t **bu_) 860 { 823 861 struct twitter_data *td = ic->proto_data; 824 862 struct twitter_user_data *tud; 825 863 bee_user_t *bu = NULL; 826 864 guint64 id = 0; 827 828 if (bu_) 865 866 if (bu_) { 829 867 *bu_ = NULL; 830 if (!arg || !arg[0]) 868 } 869 if (!arg || !arg[0]) { 831 870 return 0; 832 871 } 872 833 873 if (arg[0] != '#' && (bu = bee_user_by_handle(ic->bee, ic, arg))) { 834 if ((tud = bu->data)) 874 if ((tud = bu->data)) { 835 875 id = tud->last_id; 876 } 836 877 } else { 837 if (arg[0] == '#') 878 if (arg[0] == '#') { 838 879 arg++; 880 } 839 881 if (sscanf(arg, "%" G_GINT64_MODIFIER "x", &id) == 1 && 840 882 id < TWITTER_LOG_LENGTH) { … … 842 884 id = td->log[id].id; 843 885 /* Beware of dangling pointers! */ 844 if (!g_slist_find(ic->bee->users, bu)) 886 if (!g_slist_find(ic->bee->users, bu)) { 845 887 bu = NULL; 888 } 846 889 } else if (sscanf(arg, "%" G_GINT64_MODIFIER "d", &id) == 1) { 847 890 /* Allow normal tweet IDs as well; not a very useful 848 891 feature but it's always been there. Just ignore 849 892 very low IDs to avoid accidents. */ 850 if (id < 1000000) 893 if (id < 1000000) { 851 894 id = 0; 852 } 853 } 854 if (bu_) 895 } 896 } 897 } 898 if (bu_) { 855 899 *bu_ = bu; 900 } 856 901 return id; 857 902 } … … 863 908 guint64 in_reply_to = 0, id; 864 909 gboolean allow_post = 865 910 g_strcasecmp(set_getstr(&ic->acc->set, "commands"), "strict") != 0; 866 911 bee_user_t *bu = NULL; 867 912 … … 874 919 /* Not supporting commands if "commands" is set to true/strict. */ 875 920 } else if (g_strcasecmp(cmd[0], "undo") == 0) { 876 if (cmd[1] == NULL) 921 if (cmd[1] == NULL) { 877 922 twitter_status_destroy(ic, td->last_status_id); 878 else if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL)))923 } else if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL))) { 879 924 twitter_status_destroy(ic, id); 880 else925 } else { 881 926 twitter_log(ic, "Could not undo last action"); 927 } 882 928 883 929 goto eof; 884 930 } else if ((g_strcasecmp(cmd[0], "favourite") == 0 || 885 886 931 g_strcasecmp(cmd[0], "favorite") == 0 || 932 g_strcasecmp(cmd[0], "fav") == 0) && cmd[1]) { 887 933 if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL))) { 888 934 twitter_favourite_tweet(ic, id); … … 900 946 g_strcasecmp(cmd[0], "spam") == 0) && cmd[1]) { 901 947 char *screen_name; 902 948 903 949 /* Report nominally works on users but look up the user who 904 950 posted the given ID if the user wants to do it that way */ 905 951 twitter_message_id_from_command_arg(ic, cmd[1], &bu); 906 if (bu) 952 if (bu) { 907 953 screen_name = bu->handle; 908 else954 } else { 909 955 screen_name = cmd[1]; 910 956 } 957 911 958 twitter_report_spam(ic, screen_name); 912 959 goto eof; … … 915 962 916 963 td->last_status_id = 0; 917 if (id) 964 if (id) { 918 965 twitter_status_retweet(ic, id); 919 else966 } else { 920 967 twitter_log(ic, "User `%s' does not exist or didn't " 921 "post any statuses recently", cmd[1]); 968 "post any statuses recently", cmd[1]); 969 } 922 970 923 971 goto eof; … … 926 974 if (!id || !bu) { 927 975 twitter_log(ic, "User `%s' does not exist or didn't " 928 976 "post any statuses recently", cmd[1]); 929 977 goto eof; 930 978 } … … 949 997 char *s; 950 998 951 if (!twitter_length_check(ic, message)) 999 if (!twitter_length_check(ic, message)) { 952 1000 goto eof; 1001 } 953 1002 954 1003 s = cmd[0] + strlen(cmd[0]) - 1; … … 960 1009 961 1010 new = g_strdup_printf("@%s %s", bu->handle, 962 1011 message + (s - cmd[0]) + 2); 963 1012 message = new; 964 1013 965 1014 if (time(NULL) < tud->last_time + 966 set_getint(&ic->acc->set, "auto_reply_timeout")) 1015 set_getint(&ic->acc->set, "auto_reply_timeout")) { 967 1016 in_reply_to = tud->last_id; 1017 } 968 1018 } 969 1019 } … … 981 1031 } 982 1032 983 void twitter_log(struct im_connection *ic, char *format, ... 1033 void twitter_log(struct im_connection *ic, char *format, ...) 984 1034 { 985 1035 struct twitter_data *td = ic->proto_data; 986 1036 va_list params; 987 1037 char *text; 988 1038 989 1039 va_start(params, format); 990 1040 text = g_strdup_vprintf(format, params); 991 1041 va_end(params); 992 993 if (td->timeline_gc) 1042 1043 if (td->timeline_gc) { 994 1044 imcb_chat_log(td->timeline_gc, "%s", text); 995 else1045 } else { 996 1046 imcb_log(ic, "%s", text); 997 1047 } 1048 998 1049 g_free(text); 999 1050 }
Note: See TracChangeset
for help on using the changeset viewer.