Changeset 2322a9f for protocols/twitter
- Timestamp:
- 2011-08-25T18:08:07Z (13 years ago)
- Branches:
- master
- Children:
- 429a9b1
- Parents:
- 4804b2f
- Location:
- protocols/twitter
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/twitter/twitter.c
r4804b2f r2322a9f 30 30 31 31 #define twitter_msg( ic, fmt... ) \ 32 do { 33 struct twitter_data *td = ic->proto_data; 34 if( td-> home_timeline_gc )\35 imcb_chat_log( td-> home_timeline_gc, fmt );\36 else 37 imcb_log( ic, fmt ); 32 do { \ 33 struct twitter_data *td = ic->proto_data; \ 34 if( td->timeline_gc ) \ 35 imcb_chat_log( td->timeline_gc, fmt ); \ 36 else \ 37 imcb_log( ic, fmt ); \ 38 38 } while( 0 ); 39 39 … … 52 52 53 53 // Do stuff.. 54 twitter_get_ home_timeline(ic, -1);54 twitter_get_timeline(ic, -1); 55 55 56 56 // If we are still logged in run this function again after timeout. … … 69 69 // Queue the main_loop 70 70 // Save the return value, so we can remove the timeout on logout. 71 td->main_loop_id = b_timeout_add(60000, twitter_main_loop, ic); 71 td->main_loop_id = 72 b_timeout_add(set_getint(&ic->acc->set, "fetch_interval") * 1000, twitter_main_loop, ic); 72 73 } 73 74 … … 77 78 { 78 79 struct twitter_data *td = ic->proto_data; 80 81 td->flags &= ~TWITTER_DOING_TIMELINE; 79 82 80 83 if (set_getbool(&ic->acc->set, "oauth") && !td->oauth_info) … … 216 219 def_oauth = "true"; 217 220 } else { /* if( strcmp( acc->prpl->name, "identica" ) == 0 ) */ 218 219 221 def_url = IDENTICA_API_URL; 220 222 def_oauth = "false"; … … 228 230 s = set_add(&acc->set, "commands", "true", set_eval_bool, acc); 229 231 232 s = set_add(&acc->set, "fetch_interval", "60", set_eval_int, acc); 233 s->flags |= ACC_SET_OFFLINE_ONLY; 234 235 s = set_add(&acc->set, "fetch_mentions", "true", set_eval_bool, acc); 236 230 237 s = set_add(&acc->set, "message_length", "140", set_eval_int, acc); 231 238 … … 235 242 s = set_add(&acc->set, "show_ids", "false", set_eval_bool, acc); 236 243 s->flags |= ACC_SET_OFFLINE_ONLY; 244 245 s = set_add(&acc->set, "show_old_mentions", "true", set_eval_bool, acc); 237 246 238 247 s = set_add(&acc->set, "oauth", def_oauth, set_eval_bool, acc); … … 317 326 b_event_remove(td->main_loop_id); 318 327 319 if (td-> home_timeline_gc)320 imcb_chat_free(td-> home_timeline_gc);328 if (td->timeline_gc) 329 imcb_chat_free(td->timeline_gc); 321 330 322 331 if (td) { … … 404 413 struct twitter_data *td = c->ic->proto_data; 405 414 406 if (c != td-> home_timeline_gc)415 if (c != td->timeline_gc) 407 416 return; /* WTF? */ 408 417 409 418 /* If the user leaves the channel: Fine. Rejoin him/her once new 410 419 tweets come in. */ 411 imcb_chat_free(td-> home_timeline_gc);412 td-> home_timeline_gc = NULL;420 imcb_chat_free(td->timeline_gc); 421 td->timeline_gc = NULL; 413 422 } 414 423 -
protocols/twitter/twitter.h
r4804b2f r2322a9f 36 36 { 37 37 TWITTER_HAVE_FRIENDS = 1, 38 TWITTER_DOING_TIMELINE = 0x10000, 39 TWITTER_GOT_TIMELINE = 0x20000, 40 TWITTER_GOT_MENTIONS = 0x40000, 38 41 } twitter_flags_t; 39 42 … … 44 47 char* user; 45 48 struct oauth_info *oauth_info; 49 50 gpointer home_timeline_obj; 51 gpointer mentions_obj; 52 53 guint64 timeline_id; 54 46 55 GSList *follow_ids; 47 56 48 guint64 home_timeline_id;49 57 guint64 last_status_id; /* For undo */ 50 58 gint main_loop_id; 51 struct groupchat * home_timeline_gc;59 struct groupchat *timeline_gc; 52 60 gint http_fails; 53 61 twitter_flags_t flags; -
protocols/twitter/twitter_lib.c
r4804b2f r2322a9f 78 78 if (txu == NULL) 79 79 return; 80 80 81 g_free(txu->name); 81 82 g_free(txu->screen_name); … … 83 84 } 84 85 85 86 86 /** 87 87 * Frees a twitter_xml_status struct. … … 89 89 static void txs_free(struct twitter_xml_status *txs) 90 90 { 91 if (txs == NULL) 92 return; 93 91 94 g_free(txs->text); 92 95 txu_free(txs->user); … … 103 106 if (txl == NULL) 104 107 return; 105 for (l = txl->list; l; l = g_slist_next(l)) 106 if (txl->type == TXL_STATUS) 108 109 for (l = txl->list; l; l = g_slist_next(l)) { 110 if (txl->type == TXL_STATUS) { 107 111 txs_free((struct twitter_xml_status *) l->data); 108 else if (txl->type == TXL_ID)112 } else if (txl->type == TXL_ID) { 109 113 g_free(l->data); 110 else if (txl->type == TXL_USER)114 } else if (txl->type == TXL_USER) { 111 115 txu_free(l->data); 116 } 117 } 118 112 119 g_slist_free(txl->list); 113 120 g_free(txl); … … 115 122 116 123 /** 117 * Add a buddy if it is not allready added, set the status to logged in. 124 * Compare status elements 125 */ 126 static gint twitter_compare_elements(gconstpointer a, gconstpointer b) 127 { 128 struct twitter_xml_status *a_status = (struct twitter_xml_status *) a; 129 struct twitter_xml_status *b_status = (struct twitter_xml_status *) b; 130 131 if (a_status->created_at < b_status->created_at) { 132 return -1; 133 } else if (a_status->created_at > b_status->created_at) { 134 return 1; 135 } else { 136 return 0; 137 } 138 } 139 140 /** 141 * Add a buddy if it is not already added, set the status to logged in. 118 142 */ 119 143 static void twitter_add_buddy(struct im_connection *ic, char *name, const char *fullname) … … 132 156 exact Twitter username. */ 133 157 imcb_buddy_nick_hint(ic, name, name); 134 imcb_chat_add_buddy(td-> home_timeline_gc, name);158 imcb_chat_add_buddy(td->timeline_gc, name); 135 159 } else if (g_strcasecmp(mode, "many") == 0) 136 160 imcb_buddy_status(ic, name, OPT_LOGGED_IN, NULL, NULL); … … 260 284 261 285 /* Create the room now that we "logged in". */ 262 if (!td-> home_timeline_gc && g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0)286 if (!td->timeline_gc && g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0) 263 287 twitter_groupchat_init(ic); 264 288 … … 522 546 } 523 547 524 static void twitter_http_get_home_timeline(struct http_request *req);525 526 /**527 * Get the timeline.528 */529 void twitter_get_home_timeline(struct im_connection *ic, gint64 next_cursor)530 {531 struct twitter_data *td = ic->proto_data;532 533 char *args[4];534 args[0] = "cursor";535 args[1] = g_strdup_printf("%lld", (long long) next_cursor);536 if (td->home_timeline_id) {537 args[2] = "since_id";538 args[3] = g_strdup_printf("%llu", (long long unsigned int) td->home_timeline_id);539 }540 541 twitter_http(ic, TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, args,542 td->home_timeline_id ? 4 : 2);543 544 g_free(args[1]);545 if (td->home_timeline_id) {546 g_free(args[3]);547 }548 }549 550 548 static char *twitter_msg_add_id(struct im_connection *ic, 551 549 struct twitter_xml_status *txs, const char *prefix) … … 586 584 GSList *l; 587 585 588 td-> home_timeline_gc = gc = imcb_chat_new(ic, "home/timeline");586 td->timeline_gc = gc = imcb_chat_new(ic, "twitter/timeline"); 589 587 590 588 name_hint = g_strdup_printf("%s_%s", td->prefix, ic->acc->user); … … 595 593 bee_user_t *bu = l->data; 596 594 if (bu->ic == ic) 597 imcb_chat_add_buddy(td-> home_timeline_gc, bu->handle);595 imcb_chat_add_buddy(td->timeline_gc, bu->handle); 598 596 } 599 597 } … … 608 606 struct twitter_xml_status *status; 609 607 struct groupchat *gc; 608 guint64 last_id = 0; 610 609 611 610 // Create a new groupchat if it does not exsist. 612 if (!td-> home_timeline_gc)611 if (!td->timeline_gc) 613 612 twitter_groupchat_init(ic); 614 613 615 gc = td-> home_timeline_gc;614 gc = td->timeline_gc; 616 615 if (!gc->joined) 617 616 imcb_chat_add_buddy(gc, ic->acc->user); … … 621 620 622 621 status = l->data; 623 if (status->user == NULL || status->text == NULL )622 if (status->user == NULL || status->text == NULL || last_id == status->id) 624 623 continue; 625 624 626 twitter_add_buddy(ic, status->user->screen_name, status->user->name);625 last_id = status->id; 627 626 628 627 strip_html(status->text); 628 629 629 msg = twitter_msg_add_id(ic, status, ""); 630 630 631 631 // Say it! 632 if (g_strcasecmp(td->user, status->user->screen_name) == 0) 632 if (g_strcasecmp(td->user, status->user->screen_name) == 0) { 633 633 imcb_chat_log(gc, "You: %s", msg ? msg : status->text); 634 else 634 } else { 635 twitter_add_buddy(ic, status->user->screen_name, status->user->name); 636 635 637 imcb_chat_msg(gc, status->user->screen_name, 636 638 msg ? msg : status->text, 0, status->created_at); 639 } 637 640 638 641 g_free(msg); 639 642 640 // Update the home_timeline_id to hold the highest id, so that by the next request643 // Update the timeline_id to hold the highest id, so that by the next request 641 644 // we won't pick up the updates already in the list. 642 td-> home_timeline_id = MAX(td->home_timeline_id, status->id);645 td->timeline_id = MAX(td->timeline_id, status->id); 643 646 } 644 647 } … … 654 657 char from[MAX_STRING]; 655 658 gboolean mode_one; 659 guint64 last_id = 0; 656 660 657 661 mode_one = g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "one") == 0; … … 666 670 667 671 status = l->data; 672 if (status->user == NULL || status->text == NULL || last_id == status->id) 673 continue; 674 675 last_id = status->id; 668 676 669 677 strip_html(status->text); … … 680 688 text ? text : status->text, 0, status->created_at); 681 689 682 // Update the home_timeline_id to hold the highest id, so that by the next request690 // Update the timeline_id to hold the highest id, so that by the next request 683 691 // we won't pick up the updates already in the list. 684 td-> home_timeline_id = MAX(td->home_timeline_id, status->id);692 td->timeline_id = MAX(td->timeline_id, status->id); 685 693 686 694 g_free(text); 687 695 g_free(prefix); 696 } 697 } 698 699 static void twitter_http_get_home_timeline(struct http_request *req); 700 static void twitter_http_get_mentions(struct http_request *req); 701 702 /** 703 * Get the timeline with optionally mentions 704 */ 705 void twitter_get_timeline(struct im_connection *ic, gint64 next_cursor) 706 { 707 struct twitter_data *td = ic->proto_data; 708 gboolean include_mentions = set_getbool(&ic->acc->set, "fetch_mentions"); 709 710 if (td->flags & TWITTER_DOING_TIMELINE) { 711 return; 712 } 713 714 td->flags |= TWITTER_DOING_TIMELINE; 715 716 twitter_get_home_timeline(ic, next_cursor); 717 718 if (include_mentions) { 719 twitter_get_mentions(ic, next_cursor); 720 } 721 } 722 723 /** 724 * Call this one after receiving timeline/mentions. Show to user once we have 725 * both. 726 */ 727 void twitter_flush_timeline(struct im_connection *ic) 728 { 729 struct twitter_data *td = ic->proto_data; 730 gboolean include_mentions = set_getbool(&ic->acc->set, "fetch_mentions"); 731 gboolean show_old_mentions = set_getbool(&ic->acc->set, "show_old_mentions"); 732 struct twitter_xml_list *home_timeline = td->home_timeline_obj; 733 struct twitter_xml_list *mentions = td->mentions_obj; 734 GSList *output = NULL; 735 GSList *l; 736 737 if (!(td->flags & TWITTER_GOT_TIMELINE)) { 738 return; 739 } 740 741 if (include_mentions && !(td->flags & TWITTER_GOT_MENTIONS)) { 742 return; 743 } 744 745 if (home_timeline && home_timeline->list) { 746 for (l = home_timeline->list; l; l = g_slist_next(l)) { 747 output = g_slist_insert_sorted(output, l->data, twitter_compare_elements); 748 } 749 } 750 751 if (include_mentions && mentions && mentions->list) { 752 for (l = mentions->list; l; l = g_slist_next(l)) { 753 if (!show_old_mentions && output && twitter_compare_elements(l->data, output->data) < 0) { 754 continue; 755 } 756 757 output = g_slist_insert_sorted(output, l->data, twitter_compare_elements); 758 } 759 } 760 761 // See if the user wants to see the messages in a groupchat window or as private messages. 762 if (g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0) 763 twitter_groupchat(ic, output); 764 else 765 twitter_private_message_chat(ic, output); 766 767 g_slist_free(output); 768 769 if (home_timeline && home_timeline->list) { 770 txl_free(home_timeline); 771 } 772 773 if (mentions && mentions->list) { 774 txl_free(mentions); 775 } 776 777 td->flags &= ~(TWITTER_DOING_TIMELINE | TWITTER_GOT_TIMELINE | TWITTER_GOT_MENTIONS); 778 } 779 780 /** 781 * Get the timeline. 782 */ 783 void twitter_get_home_timeline(struct im_connection *ic, gint64 next_cursor) 784 { 785 struct twitter_data *td = ic->proto_data; 786 787 td->home_timeline_obj = NULL; 788 td->flags &= ~TWITTER_GOT_TIMELINE; 789 790 char *args[4]; 791 args[0] = "cursor"; 792 args[1] = g_strdup_printf("%lld", (long long) next_cursor); 793 if (td->timeline_id) { 794 args[2] = "since_id"; 795 args[3] = g_strdup_printf("%llu", (long long unsigned int) td->timeline_id); 796 } 797 798 twitter_http(ic, TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, args, 799 td->timeline_id ? 4 : 2); 800 801 g_free(args[1]); 802 if (td->timeline_id) { 803 g_free(args[3]); 804 } 805 } 806 807 /** 808 * Get mentions. 809 */ 810 void twitter_get_mentions(struct im_connection *ic, gint64 next_cursor) 811 { 812 struct twitter_data *td = ic->proto_data; 813 814 td->mentions_obj = NULL; 815 td->flags &= ~TWITTER_GOT_MENTIONS; 816 817 char *args[4]; 818 args[0] = "cursor"; 819 args[1] = g_strdup_printf("%lld", (long long) next_cursor); 820 if (td->timeline_id) { 821 args[2] = "since_id"; 822 args[3] = g_strdup_printf("%llu", (long long unsigned int) td->timeline_id); 823 } 824 825 twitter_http(ic, TWITTER_MENTIONS_URL, twitter_http_get_mentions, ic, 0, args, 826 td->timeline_id ? 4 : 2); 827 828 g_free(args[1]); 829 if (td->timeline_id) { 830 g_free(args[3]); 688 831 } 689 832 } … … 713 856 imcb_error(ic, "Authentication failure"); 714 857 imc_logout(ic, FALSE); 715 return;858 goto end; 716 859 } else { 717 860 // It didn't go well, output the error and return. … … 720 863 TWITTER_HOME_TIMELINE_URL, twitter_parse_error(req)); 721 864 722 return;865 goto end; 723 866 } 724 867 … … 733 876 xt_free(parser); 734 877 735 // See if the user wants to see the messages in a groupchat window or as private messages. 736 if (txl->list == NULL); 737 else if (g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0) 738 twitter_groupchat(ic, txl->list); 739 else 740 twitter_private_message_chat(ic, txl->list); 741 742 // Free the structure. 743 txl_free(txl); 878 td->home_timeline_obj = txl; 879 880 end: 881 td->flags |= TWITTER_GOT_TIMELINE; 882 883 twitter_flush_timeline(ic); 884 } 885 886 /** 887 * Callback for getting mentions. 888 */ 889 static void twitter_http_get_mentions(struct http_request *req) 890 { 891 struct im_connection *ic = req->data; 892 struct twitter_data *td; 893 struct xt_parser *parser; 894 struct twitter_xml_list *txl; 895 896 // Check if the connection is still active. 897 if (!g_slist_find(twitter_connections, ic)) 898 return; 899 900 td = ic->proto_data; 901 902 // Check if the HTTP request went well. 903 if (req->status_code == 200) { 904 td->http_fails = 0; 905 if (!(ic->flags & OPT_LOGGED_IN)) 906 imcb_connected(ic); 907 } else if (req->status_code == 401) { 908 imcb_error(ic, "Authentication failure"); 909 imc_logout(ic, FALSE); 910 goto end; 911 } else { 912 // It didn't go well, output the error and return. 913 if (++td->http_fails >= 5) 914 imcb_error(ic, "Could not retrieve " TWITTER_MENTIONS_URL ": %s", 915 twitter_parse_error(req)); 916 917 goto end; 918 } 919 920 txl = g_new0(struct twitter_xml_list, 1); 921 txl->list = NULL; 922 923 // Parse the data. 924 parser = xt_new(NULL, txl); 925 xt_feed(parser, req->reply_body, req->body_size); 926 // The root <statuses> node should hold the list of statuses <status> 927 twitter_xt_get_status_list(ic, parser->root, txl); 928 xt_free(parser); 929 930 td->mentions_obj = txl; 931 932 end: 933 td->flags |= TWITTER_GOT_MENTIONS; 934 935 twitter_flush_timeline(ic); 744 936 } 745 937 -
protocols/twitter/twitter_lib.h
r4804b2f r2322a9f 76 76 #define TWITTER_BLOCKS_DESTROY_URL "/blocks/destroy/" 77 77 78 void twitter_get_timeline(struct im_connection *ic, gint64 next_cursor); 78 79 void twitter_get_friends_ids(struct im_connection *ic, gint64 next_cursor); 79 80 void twitter_get_home_timeline(struct im_connection *ic, gint64 next_cursor); 81 void twitter_get_mentions(struct im_connection *ic, gint64 next_cursor); 80 82 void twitter_get_statuses_friends(struct im_connection *ic, gint64 next_cursor); 81 83
Note: See TracChangeset
for help on using the changeset viewer.