Mercurial > pidgin-twitter
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 |