comparison pidgin-twitter.c @ 82:c9600d64781a

work in progress adaptation to wassr service. cleanups required: - sender/recipient translation have been added. - added work around for "parrot problem" in sending to a channel.
author Yoshiki Yazawa <yaz@honeyplnaet.jp>
date Sat, 05 Jul 2008 16:26:39 +0900
parents f1163f2e4920
children 15f4886720e4
comparison
equal deleted inserted replaced
81:f1163f2e4920 82:c9600d64781a
23 /* globals */ 23 /* globals */
24 static GRegex *regp[7]; 24 static GRegex *regp[7];
25 static gboolean suppress_oops = FALSE; 25 static gboolean suppress_oops = FALSE;
26 static GHashTable *icon_data_by_user = NULL; 26 static GHashTable *icon_data_by_user = NULL;
27 27
28 #define WASSR_POST_LEN (255 * 4)
29 static gchar wassr_post[WASSR_POST_LEN + 1];
30
28 typedef struct icon_data { 31 typedef struct icon_data {
29 gint icon_id; // image id 32 gint icon_id; // image id
30 gboolean requested; // TRUE if download icon has been requested 33 gboolean requested; // TRUE if download icon has been requested
31 GList *request_list; // marker list 34 GList *request_list; // marker list
32 PurpleUtilFetchUrlData *fetch_data; // icon fetch data 35 PurpleUtilFetchUrlData *fetch_data; // icon fetch data
33 } icon_data; 36 } icon_data;
34 37
38 enum {
39 TWITTER_SERVICE,
40 WASSR_SERVICE
41 }
42
43 typedef struct _eval_data {
44 int which;
45 int service;
46 } eval_data;
35 47
36 /* this function is a modified clone of purple_markup_strip_html() */ 48 /* this function is a modified clone of purple_markup_strip_html() */
37 static char * 49 static char *
38 strip_html_markup(const char *str) 50 strip_html_markup(const char *str)
39 { 51 {
444 { 456 {
445 int utflen, bytes; 457 int utflen, bytes;
446 458
447 twitter_debug("called\n"); 459 twitter_debug("called\n");
448 460
461 if(is_wassr_account(account, recipient)) {
462 /* store sending message to address parrot problem */
463 g_strlcpy(wassr_post, *buffer, WASSR_POST_LEN);
464 twitter_debug("parrot pushed:%s\n", *buffer);
465 }
466
449 /* check if the message is from twitter */ 467 /* check if the message is from twitter */
450 if(!is_twitter_account(account, recipient)) 468 if(!is_twitter_account(account, recipient))
451 return FALSE; 469 return FALSE;
452 470
453 /* strip all markups */ 471 /* strip all markups */
454 strip_markup(buffer); 472 strip_markup(buffer);
455 473
456 /* escape pseudo command */ 474 /* escape pseudo command */
457 if(purple_prefs_get_bool(OPT_ESCAPE_PSEUDO)) { 475 if(is_twitter_account(account, recipient) &&
476 purple_prefs_get_bool(OPT_ESCAPE_PSEUDO)) {
458 escape(buffer); 477 escape(buffer);
459 } 478 }
460 479
461 /* update status with Twitter API instead of IM protocol */ 480 /* update status with Twitter API instead of IM protocol */
462 if (purple_prefs_get_bool(OPT_API_BASE_POST)) { 481 if (purple_prefs_get_bool(OPT_API_BASE_POST)) {
478 } 497 }
479 498
480 static gboolean 499 static gboolean
481 eval(const GMatchInfo *match_info, GString *result, gpointer user_data) 500 eval(const GMatchInfo *match_info, GString *result, gpointer user_data)
482 { 501 {
483 int which = *(int *)user_data; 502 eval_data *data = (eval_data *)user_data;
503 int which = data->which;
504 int service = data->service;
484 gchar sub[128]; 505 gchar sub[128];
506
507 twitter_debug("which = %d service = %d\n", which, service);
485 508
486 if(which == RECIPIENT) { 509 if(which == RECIPIENT) {
487 gchar *match = g_match_info_fetch(match_info, 1); 510 gchar *match = g_match_info_fetch(match_info, 1);
488 511
489 snprintf(sub, 128, RECIPIENT_FORMAT, match, match); 512 if(service == TWITTER_SERVICE)
513 snprintf(sub, 128, RECIPIENT_FORMAT, match, match);
514 else if(service == WASSR_SERVICE)
515 snprintf(sub, 128, RECIPIENT_FORMAT_WASSR, match, match);
516
490 g_free(match); 517 g_free(match);
491 } 518 }
492 else if(which == SENDER) { 519 else if(which == SENDER) {
493 gchar *match1 = g_match_info_fetch(match_info, 1); //preceding CR|LF 520 gchar *match1 = g_match_info_fetch(match_info, 1); //preceding CR|LF
494 gchar *match2 = g_match_info_fetch(match_info, 2); //sender 521 gchar *match2 = g_match_info_fetch(match_info, 2); //sender
495 522
496 snprintf(sub, 128, SENDER_FORMAT, match1 ? match1: "", 523 if(service == TWITTER_SERVICE) {
497 match2, match2); 524 snprintf(sub, 128, SENDER_FORMAT, match1 ? match1: "",
525 match2, match2);
526 }
527 else if(service == WASSR_SERVICE) {
528 snprintf(sub, 128, SENDER_FORMAT_WASSR, match1 ? match1: "",
529 match2, match2);
530 }
498 g_free(match1); 531 g_free(match1);
499 g_free(match2); 532 g_free(match2);
500 } 533 }
501 534
502 g_string_append(result, sub); 535 g_string_append(result, sub);
504 537
505 return FALSE; 538 return FALSE;
506 } 539 }
507 540
508 static void 541 static void
509 translate(gchar **str, int which) 542 translate(gchar **str, int which, int service)
510 { 543 {
511 gchar *newstr; 544 gchar *newstr;
545
546 eval_data *data = g_new0(eval_data, 1);
547
548 data->which = which;
549 data->service = service;
512 550
513 newstr = g_regex_replace_eval(regp[which], // compiled regex 551 newstr = g_regex_replace_eval(regp[which], // compiled regex
514 *str, // subject string 552 *str, // subject string
515 -1, // length of the subject string 553 -1, // length of the subject string
516 0, // start position 554 0, // start position
517 0, // match options 555 0, // match options
518 eval, // function to be called for each match 556 eval, // function to be called for each match
519 &which, // user data 557 data, // user data
520 NULL); // error handler 558 NULL); // error handler
559
560 g_free(data); data = NULL;
521 561
522 twitter_debug("which = %d *str = %s newstr = %s\n", which, *str, newstr); 562 twitter_debug("which = %d *str = %s newstr = %s\n", which, *str, newstr);
523 563
524 g_free(*str); 564 g_free(*str);
525 *str = newstr; 565 *str = newstr;
573 writing_im_cb(PurpleAccount *account, char *sender, char **buffer, 613 writing_im_cb(PurpleAccount *account, char *sender, char **buffer,
574 PurpleConversation *conv, int *flags, void *data) 614 PurpleConversation *conv, int *flags, void *data)
575 { 615 {
576 twitter_debug("called\n"); 616 twitter_debug("called\n");
577 617
578 /* check if the message is from twitter */ 618 /* check if the conversation is between twitter */
579 if(!is_twitter_conv(conv)) 619 if(!is_twitter_conv(conv) && !is_wassr_conv(conv))
580 /* if(!is_twitter_account(account, sender)) */
581 return FALSE; 620 return FALSE;
582 621
583 /* strip all markups */ 622 /* strip all markups */
584 strip_markup(buffer); 623 strip_markup(buffer);
585 624
589 } 628 }
590 if(purple_prefs_get_bool(OPT_PLAYSOUND_RECIPIENT)) { 629 if(purple_prefs_get_bool(OPT_PLAYSOUND_RECIPIENT)) {
591 playsound(buffer, RECIPIENT); 630 playsound(buffer, RECIPIENT);
592 } 631 }
593 632
633 /* XXX should cleanup */
634 int service = 0;
635 if(is_twitter_conv(conv))
636 service = TWITTER_SERVICE;
637 else if(is_wassr_conv(conv))
638 service = WASSR_SERVICE;
639
594 /* translate */ 640 /* translate */
595 if(purple_prefs_get_bool(OPT_TRANSLATE_SENDER)) { 641 if(purple_prefs_get_bool(OPT_TRANSLATE_SENDER)) {
596 translate(buffer, SENDER); 642 translate(buffer, SENDER, service);
597 } 643 }
598 if(purple_prefs_get_bool(OPT_TRANSLATE_RECIPIENT)) { 644 if(purple_prefs_get_bool(OPT_TRANSLATE_RECIPIENT)) {
599 translate(buffer, RECIPIENT); 645 translate(buffer, RECIPIENT, service);
600 } 646 }
601 647
602 /* escape pseudo command (to show same result to sending message) */ 648 /* escape pseudo command (to show same result to sending message) */
603 if(purple_prefs_get_bool(OPT_ESCAPE_PSEUDO)) { 649 if(is_twitter_conv(conv) && purple_prefs_get_bool(OPT_ESCAPE_PSEUDO)) {
604 escape(buffer); 650 escape(buffer);
605 } 651 }
606 652
607 return FALSE; 653 return FALSE;
608 } 654 }
609 655
610 static void 656 static void
611 insert_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *position, 657 insert_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *position,
612 gchar *new_text, gint new_text_length, gpointer user_data) 658 gchar *new_text, gint new_text_length, gpointer user_data)
613 { 659 {
614 PidginConversation *gtkconv = (PidginConversation *)user_data; 660 PurpleConversation *conv = (PurpleConversation *)user_data;
661 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
662
615 GtkWidget *box, *counter = NULL; 663 GtkWidget *box, *counter = NULL;
616 gchar *markup = NULL; 664 gchar *markup = NULL;
617 guint count; 665 guint count;
618 666
619 g_return_if_fail(gtkconv != NULL); 667 g_return_if_fail(gtkconv != NULL);
620 668
621 count = gtk_text_buffer_get_char_count(textbuffer) + 669 count = gtk_text_buffer_get_char_count(textbuffer) +
622 (unsigned int)g_utf8_strlen(new_text, -1); 670 (unsigned int)g_utf8_strlen(new_text, -1);
623 671
624 markup = g_markup_printf_escaped("<span color=\"%s\">%u</span>", 672 if(is_twitter_conv(conv)) {
625 count <= 140 ? "black" : "red", count); 673 markup = g_markup_printf_escaped("<span color=\"%s\">%u</span>",
674 count <= 140 ? "black" : "red", count);
675 }
676 else if(is_wassr_conv(conv)) {
677 markup = g_markup_printf_escaped("<span color=\"%s\">%u</span>",
678 count <= 255 ? "black" : "red", count);
679 }
626 680
627 box = gtkconv->toolbar; 681 box = gtkconv->toolbar;
628 counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter"); 682 counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter");
629 if(counter) 683 if(counter)
630 gtk_label_set_markup(GTK_LABEL(counter), markup); 684 gtk_label_set_markup(GTK_LABEL(counter), markup);
634 688
635 static void 689 static void
636 delete_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *start_pos, 690 delete_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *start_pos,
637 GtkTextIter *end_pos, gpointer user_data) 691 GtkTextIter *end_pos, gpointer user_data)
638 { 692 {
639 PidginConversation *gtkconv = (PidginConversation *)user_data; 693 PurpleConversation *conv = (PurpleConversation *)user_data;
694 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
640 GtkWidget *box, *counter = NULL; 695 GtkWidget *box, *counter = NULL;
641 gchar *markup = NULL; 696 gchar *markup = NULL;
642 697
643 g_return_if_fail(gtkconv != NULL); 698 g_return_if_fail(gtkconv != NULL);
644 699
645 guint count = gtk_text_buffer_get_char_count(textbuffer) - 700 guint count = gtk_text_buffer_get_char_count(textbuffer) -
646 (gtk_text_iter_get_offset(end_pos) - 701 (gtk_text_iter_get_offset(end_pos) -
647 gtk_text_iter_get_offset(start_pos)); 702 gtk_text_iter_get_offset(start_pos));
648 703
649 markup = g_markup_printf_escaped("<span color=\"%s\">%u</span>", 704 if(is_twitter_conv(conv)) {
650 count <= 140 ? "black" : "red", count); 705 markup = g_markup_printf_escaped("<span color=\"%s\">%u</span>",
706 count <= 140 ? "black" : "red", count);
707 }
708 else if(is_wassr_conv(conv)) {
709 markup = g_markup_printf_escaped("<span color=\"%s\">%u</span>",
710 count <= 255 ? "black" : "red", count);
711 }
651 712
652 box = gtkconv->toolbar; 713 box = gtkconv->toolbar;
653 counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter"); 714 counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter");
654 if(counter) 715 if(counter)
655 gtk_label_set_markup(GTK_LABEL(counter), markup); 716 gtk_label_set_markup(GTK_LABEL(counter), markup);
666 for(list = pidgin_conv_windows_get_list(); list; list = list->next) { 727 for(list = pidgin_conv_windows_get_list(); list; list = list->next) {
667 PidginWindow *win = list->data; 728 PidginWindow *win = list->data;
668 PurpleConversation *conv = 729 PurpleConversation *conv =
669 pidgin_conv_window_get_active_conversation(win); 730 pidgin_conv_window_get_active_conversation(win);
670 if(is_twitter_conv(conv)) 731 if(is_twitter_conv(conv))
671 detach_from_gtkconv(PIDGIN_CONVERSATION(conv), NULL); 732 detach_from_conv(conv, NULL);
672 } 733 if(is_wassr_conv(conv))
673 } 734 detach_from_conv(conv, NULL);
674 735 }
675 static void 736 }
676 detach_from_gtkconv(PidginConversation *gtkconv, gpointer null) 737
677 { 738 static void
739 detach_from_conv(PurpleConversation *conv, gpointer null)
740 {
741 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
678 GtkWidget *box, *counter = NULL, *sep = NULL; 742 GtkWidget *box, *counter = NULL, *sep = NULL;
679 743
680 g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry_buffer), 744 g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry_buffer),
681 (GFunc) insert_text_cb, gtkconv); 745 (GFunc) insert_text_cb, conv);
682 g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry_buffer), 746 g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry_buffer),
683 (GFunc) delete_text_cb, gtkconv); 747 (GFunc) delete_text_cb, conv);
684 748
685 box = gtkconv->toolbar; 749 box = gtkconv->toolbar;
686 750
687 /* remove counter */ 751 /* remove counter */
688 counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter"); 752 counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter");
763 PidginWindow *win = list->data; 827 PidginWindow *win = list->data;
764 PurpleConversation *conv = 828 PurpleConversation *conv =
765 pidgin_conv_window_get_active_conversation(win); 829 pidgin_conv_window_get_active_conversation(win);
766 /* only attach to twitter conversation window */ 830 /* only attach to twitter conversation window */
767 if(is_twitter_conv(conv)) 831 if(is_twitter_conv(conv))
768 attach_to_gtkconv(PIDGIN_CONVERSATION(conv), NULL); 832 attach_to_conv(conv, NULL);
769 } 833 if(is_wassr_conv(conv))
770 } 834 attach_to_conv(conv, NULL);
771 835 }
772 static void 836 }
773 attach_to_gtkconv(PidginConversation *gtkconv, gpointer null) 837
774 { 838 static void
839 attach_to_conv(PurpleConversation *conv, gpointer null)
840 {
841 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
775 GtkWidget *box, *sep, *counter, *menus; 842 GtkWidget *box, *sep, *counter, *menus;
776 GtkIMHtml *imhtml; 843 GtkIMHtml *imhtml;
777 844
778 box = gtkconv->toolbar; 845 box = gtkconv->toolbar;
779 imhtml = GTK_IMHTML(gtkconv->imhtml); 846 imhtml = GTK_IMHTML(gtkconv->imhtml);
818 gtk_widget_show_all(sep); 885 gtk_widget_show_all(sep);
819 g_object_set_data(G_OBJECT(box), PLUGIN_ID "-sep", sep); 886 g_object_set_data(G_OBJECT(box), PLUGIN_ID "-sep", sep);
820 887
821 /* connect to signals */ 888 /* connect to signals */
822 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text", 889 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text",
823 G_CALLBACK(insert_text_cb), gtkconv); 890 G_CALLBACK(insert_text_cb), conv);
824 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range", 891 g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range",
825 G_CALLBACK(delete_text_cb), gtkconv); 892 G_CALLBACK(delete_text_cb), conv);
826 893
827 /* redraw window */ 894 /* redraw window */
828 gtk_widget_queue_draw(pidgin_conv_get_window(gtkconv)->window); 895 gtk_widget_queue_draw(pidgin_conv_get_window(gtkconv)->window);
829 } 896 }
830 897
857 { 924 {
858 const gchar *proto = purple_account_get_protocol_id(account); 925 const gchar *proto = purple_account_get_protocol_id(account);
859 926
860 twitter_debug("name = %s proto = %s\n", name, proto); 927 twitter_debug("name = %s proto = %s\n", name, proto);
861 928
862 if(!strcmp(name, "wassr-bot@wassr.jp/bot") && 929 if(strstr(name, "wassr-bot@wassr.jp") &&
863 !strcmp(proto, "prpl-jabber")) { 930 !strcmp(proto, "prpl-jabber")) {
864 return TRUE; 931 return TRUE;
865 } 932 }
866 933
867 return FALSE; 934 return FALSE;
882 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); 949 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
883 g_return_if_fail(gtkconv != NULL); 950 g_return_if_fail(gtkconv != NULL);
884 951
885 /* only attach to twitter conversation window */ 952 /* only attach to twitter conversation window */
886 if(is_twitter_conv(conv)) 953 if(is_twitter_conv(conv))
887 attach_to_gtkconv(gtkconv, NULL); 954 attach_to_conv(conv, NULL);
955 if(is_wassr_conv(conv))
956 attach_to_conv(conv, NULL);
888 } 957 }
889 958
890 static void 959 static void
891 deleting_conv_cb(PurpleConversation *conv) 960 deleting_conv_cb(PurpleConversation *conv)
892 { 961 {
894 g_return_if_fail(gtkconv != NULL); 963 g_return_if_fail(gtkconv != NULL);
895 964
896 /* only attach to twitter conversation window */ 965 /* only attach to twitter conversation window */
897 if(is_twitter_conv(conv)) 966 if(is_twitter_conv(conv))
898 delete_requested_icon_marks(gtkconv); 967 delete_requested_icon_marks(gtkconv);
968 #if 0
969 if(is_wassr_conv(conv))
970 delete_requested_icon_marks(gtkconv);
971 #endif
899 } 972 }
900 973
901 static gboolean 974 static gboolean
902 receiving_im_cb(PurpleAccount *account, char **sender, char **buffer, 975 receiving_im_cb(PurpleAccount *account, char **sender, char **buffer,
903 PurpleConversation *conv, PurpleMessageFlags *flags, void *data) 976 PurpleConversation *conv, PurpleMessageFlags *flags, void *data)
910 * And if check is a twitter conv. */ 983 * And if check is a twitter conv. */
911 984
912 /* quick hack to suppress annoying completion message from wassr */ 985 /* quick hack to suppress annoying completion message from wassr */
913 if(conv && is_wassr_conv(conv)) { 986 if(conv && is_wassr_conv(conv)) {
914 if(strstr(*buffer, "<body>投稿完了:") || 987 if(strstr(*buffer, "<body>投稿完了:") ||
915 strstr(*buffer, "<body>チャンネル投稿完了:")) { 988 strstr(*buffer, "<body>チャンネル投稿完了:")) {
916 twitter_debug("clearing sender and buffer\n"); 989 twitter_debug("clearing sender and buffer\n");
990 g_free(*sender); *sender = NULL;
991 g_free(*buffer); *buffer = NULL;
992 }
993 /* fix for parrot problem during post to a channel */
994 else if(strstr(*buffer, wassr_post)) {
995 twitter_debug("parrot clearing: %s\n", *buffer);
917 g_free(*sender); *sender = NULL; 996 g_free(*sender); *sender = NULL;
918 g_free(*buffer); *buffer = NULL; 997 g_free(*buffer); *buffer = NULL;
919 } 998 }
920 } 999 }
921 1000