Mercurial > pidgin-twitter
view pidgin-twitter.c @ 38:625e385036c3
applied indent to fix indentations
author | Yoshiki Yazawa <yaz@cc.rim.or.jp> |
---|---|
date | Mon, 12 May 2008 19:46:10 +0900 |
parents | bafe2abf2d3b |
children | 2ac81c0afb53 |
line wrap: on
line source
/* * Pidgin-Twitter plugin. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #define PURPLE_PLUGINS 1 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <glib.h> #include "gtkplugin.h" #include "util.h" #include "debug.h" #include "connection.h" #include "version.h" #include "sound.h" #include "gtkconv.h" #define RECIPIENT 0 #define SENDER 1 #define COMMAND 2 #define PSEUDO 3 #define SENDER_WITH_LINK 4 #define PLUGIN_ID "gtk-honeyplanet-pidgin_twitter" #define PLUGIN_NAME "pidgin-twitter" #define OPT_PIDGINTWITTER "/plugins/pidgin_twitter" #define OPT_TRANSLATE_RECIPIENT OPT_PIDGINTWITTER "/translate_recipient" #define OPT_TRANSLATE_SENDER OPT_PIDGINTWITTER "/translate_sender" #define OPT_PLAYSOUND_RECIPIENT OPT_PIDGINTWITTER "/playsound_recipient" #define OPT_PLAYSOUND_SENDER OPT_PIDGINTWITTER "/playsound_sender" #define OPT_SOUNDID_RECIPIENT OPT_PIDGINTWITTER "/soundid_recipient" #define OPT_SOUNDID_SENDER OPT_PIDGINTWITTER "/soundid_sender" #define OPT_ESCAPE_PSEUDO OPT_PIDGINTWITTER "/escape_pseudo" #define OPT_USERLIST_RECIPIENT OPT_PIDGINTWITTER "/userlist_recipient" #define OPT_USERLIST_SENDER OPT_PIDGINTWITTER "/userlist_sender" #define OPT_COUNTER OPT_PIDGINTWITTER "/counter" #define OPT_SUPPRESS_OOPS OPT_PIDGINTWITTER "/suppress_oops" #define RECIPIENT_FORMAT "@<a href='http://twitter.com/%s'>%s</a>" #define SENDER_FORMAT "<a href='http://twitter.com/%s'>%s</a>: " #define DEFAULT_LIST "(list of users: separated with ' ,:;')" #define OOPS_MESSAGE "<body>Oops! Your update was over 140 characters. We sent the short version to your friends (they can view the entire update on the web).<BR></body>" #define twitter_debug(fmt, ...) purple_debug(PURPLE_DEBUG_INFO, PLUGIN_NAME, fmt, ## __VA_ARGS__); #define twitter_error(fmt, ...) purple_debug(PURPLE_DEBUG_ERROR, PLUGIN_NAME, fmt, ## __VA_ARGS__); /* globals */ static GRegex *regp[5]; static gboolean suppress_oops = FALSE; /* prototypes */ static gboolean is_twitter_conv(PurpleConversation *conv); static void attach_to_gtkconv(PidginConversation *gtkconv, gpointer null); static void detach_from_gtkconv(PidginConversation *gtkconv, gpointer null); static void escape(gchar **str); static void delete_sender_with_link(gchar **str) { gchar *newstr = NULL; /* replace senders with link */ newstr = g_regex_replace(regp[SENDER_WITH_LINK], *str, -1, 0, "@\\1", 0, NULL); twitter_debug("*str = %s\n", *str); twitter_debug("rnewstr = %s\n", newstr); g_free(*str); *str = newstr; } static void escape(gchar **str) { GMatchInfo *match_info = NULL; gchar *newstr = NULL, *match = NULL; gboolean flag = FALSE; /* search genuine command */ g_regex_match(regp[COMMAND], *str, 0, &match_info); while(g_match_info_matches(match_info)) { match = g_match_info_fetch(match_info, 1); twitter_debug("command = %s\n", match); g_free(match); g_match_info_next(match_info, NULL); flag = TRUE; } g_match_info_free(match_info); match_info = NULL; if(flag) { return; } /* if not found, check pseudo command */ g_regex_match(regp[PSEUDO], *str, 0, &match_info); while(g_match_info_matches(match_info)) { match = g_match_info_fetch(match_info, 1); twitter_debug("pseudo = %s\n", match); g_free(match); g_match_info_next(match_info, NULL); flag = TRUE; } g_match_info_free(match_info); match_info = NULL; /* if there is pseudo one, escape it */ if(flag) { /* put ". " to the beginning of buffer */ newstr = g_strdup_printf(". %s", *str); twitter_debug("*str = %s\n", *str); twitter_debug("newstr = %s\n", newstr); g_free(*str); *str = newstr; } } static gboolean sending_im_cb(PurpleAccount *account, char *recipient, char **buffer, void *data) { const gchar *proto; /* check if the message is from twitter */ proto = purple_account_get_protocol_id(account); twitter_debug("sending_im_cb\n"); twitter_debug("proto = %s\n", proto); twitter_debug("recipient = %s\n", recipient); if(!strcmp(proto, "prpl-jabber") && !strcmp(recipient, "twitter@twitter.com")) { /* escape */ if(purple_prefs_get_bool(OPT_ESCAPE_PSEUDO)) { escape(buffer); } /* strip excessive link from @username */ delete_sender_with_link(buffer); /* try to suppress Oops message */ gint utflen = g_utf8_strlen(*buffer, -1); gint bytes = strlen(*buffer); twitter_debug("utflen = %d bytes = %d\n", utflen, bytes); if(bytes > 140 && utflen <= 140) suppress_oops = TRUE; } return FALSE; } static gboolean eval(const GMatchInfo *match_info, GString *result, gpointer user_data) { gchar sub[128]; gchar *match = g_match_info_fetch(match_info, 1); int which = *(int *)user_data; snprintf(sub, 128, which ? SENDER_FORMAT : RECIPIENT_FORMAT, match, match); twitter_debug("sub = %s\n", sub); g_string_append(result, sub); g_free(match); return FALSE; } static void translate(gchar **str, int which) { gchar *newstr; twitter_debug("*str = %s\n", *str); newstr = g_regex_replace_eval(regp[which], // compiled regex *str, // subject string -1, // length of the subject string 0, // start position 0, // match options eval, // function to be called for each match &which, // user data NULL); // error handler twitter_debug("newstr = %s\n", newstr); g_free(*str); *str = newstr; } static void playsound(gchar **str, int which) { GMatchInfo *match_info; const gchar *list; gchar **candidates = NULL, **candidate = NULL; list = purple_prefs_get_string(which ? OPT_USERLIST_SENDER : OPT_USERLIST_RECIPIENT); g_return_if_fail(list != NULL); if(!strcmp(list, DEFAULT_LIST)) return; candidates = g_strsplit_set(list, " ,:;", 0); g_return_if_fail(candidates != NULL); g_regex_match(regp[which], *str, 0, &match_info); while(g_match_info_matches(match_info)) { gchar *user = g_match_info_fetch(match_info, 1); twitter_debug("user = %s\n", user); for(candidate = candidates; *candidate; candidate++) { if(!strcmp(*candidate, "")) continue; twitter_debug("candidate = %s\n", *candidate); if(!strcmp(user, *candidate)) { twitter_debug("match. play sound\n"); purple_sound_play_event(purple_prefs_get_int (which ? OPT_SOUNDID_SENDER : OPT_SOUNDID_RECIPIENT), NULL); break; } } g_free(user); g_match_info_next(match_info, NULL); } g_strfreev(candidates); g_match_info_free(match_info); } static gboolean writing_im_cb(PurpleAccount *account, char *sender, char **buffer, PurpleConversation *conv, int *flags, void *data) { const gchar *proto; /* check if the message is from twitter */ proto = purple_account_get_protocol_id(account); twitter_debug("writing_im_cb\n"); twitter_debug("proto = %s\n", proto); twitter_debug("sender = %s\n", sender); if(!strcmp(sender, "twitter@twitter.com") && !strcmp(proto, "prpl-jabber")) { /* playsound */ if(purple_prefs_get_bool(OPT_PLAYSOUND_SENDER)) { playsound(buffer, SENDER); } if(purple_prefs_get_bool(OPT_PLAYSOUND_RECIPIENT)) { playsound(buffer, RECIPIENT); } /* translate */ if(purple_prefs_get_bool(OPT_TRANSLATE_SENDER)) { translate(buffer, SENDER); } if(purple_prefs_get_bool(OPT_TRANSLATE_RECIPIENT)) { translate(buffer, RECIPIENT); } /* escape */ if(purple_prefs_get_bool(OPT_ESCAPE_PSEUDO)) { escape(buffer); } } return FALSE; } static void insert_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *position, gchar *new_text, gint new_text_length, gpointer user_data) { PidginConversation *gtkconv = (PidginConversation *)user_data; GtkWidget *box, *counter = NULL; gchar *markup = NULL; g_return_if_fail(gtkconv != NULL); guint count = gtk_text_buffer_get_char_count(textbuffer) + (unsigned int)g_utf8_strlen(new_text, -1); // twitter_debug("new_text = %s utf8_strlen = %ld new_text_length = %d\n", // new_text, g_utf8_strlen(new_text, -1), new_text_length); markup = g_markup_printf_escaped("<span color=\"%s\">%u</span>", count <= 140 ? "black" : "red", count); box = gtkconv->toolbar; counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter"); if(counter) gtk_label_set_markup(GTK_LABEL(counter), markup); g_free(markup); } static void delete_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *start_pos, GtkTextIter *end_pos, gpointer user_data) { PidginConversation *gtkconv = (PidginConversation *)user_data; GtkWidget *box, *counter = NULL; gchar *markup = NULL; g_return_if_fail(gtkconv != NULL); guint count = gtk_text_buffer_get_char_count(textbuffer) - (gtk_text_iter_get_offset(end_pos) - gtk_text_iter_get_offset(start_pos)); markup = g_markup_printf_escaped("<span color=\"%s\">%u</span>", count <= 140 ? "black" : "red", count); box = gtkconv->toolbar; counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter"); if(counter) gtk_label_set_markup(GTK_LABEL(counter), markup); g_free(markup); } static void detach_from_window(void) { GList *list; for(list = pidgin_conv_windows_get_list(); list; list = list->next) { PidginWindow *win = list->data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); if(is_twitter_conv(conv)) detach_from_gtkconv(PIDGIN_CONVERSATION(conv), NULL); } } static void detach_from_gtkconv(PidginConversation *gtkconv, gpointer null) { GtkWidget *box, *counter = NULL, *sep = NULL; g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry_buffer), (GFunc) insert_text_cb, gtkconv); g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->entry_buffer), (GFunc) delete_text_cb, gtkconv); box = gtkconv->toolbar; /* remove counter */ counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter"); if(counter) { gtk_container_remove(GTK_CONTAINER(box), counter); g_object_unref(counter); g_object_set_data(G_OBJECT(box), PLUGIN_ID "-counter", NULL); } /* remove separator */ sep = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-sep"); if(sep) { gtk_container_remove(GTK_CONTAINER(box), sep); g_object_unref(sep); g_object_set_data(G_OBJECT(box), PLUGIN_ID "-sep", NULL); } gtk_widget_queue_draw(pidgin_conv_get_window(gtkconv)->window); } static void attach_to_window(void) { GList *list; for(list = pidgin_conv_windows_get_list(); list; list = list->next) { PidginWindow *win = list->data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); if(is_twitter_conv(conv)) attach_to_gtkconv(PIDGIN_CONVERSATION(conv), NULL); } } static void attach_to_gtkconv(PidginConversation *gtkconv, gpointer null) { GtkWidget *box, *sep, *counter; box = gtkconv->toolbar; counter = g_object_get_data(G_OBJECT(box), PLUGIN_ID "-counter"); g_return_if_fail(counter == NULL); /* make counter object */ counter = gtk_label_new(NULL); gtk_widget_set_name(counter, "counter_label"); gtk_label_set_text(GTK_LABEL(counter), "0"); gtk_box_pack_end(GTK_BOX(box), counter, FALSE, FALSE, 0); gtk_widget_show_all(counter); g_object_set_data(G_OBJECT(box), PLUGIN_ID "-counter", counter); /* make separator object */ sep = gtk_vseparator_new(); gtk_box_pack_end(GTK_BOX(box), sep, FALSE, FALSE, 0); gtk_widget_show_all(sep); g_object_set_data(G_OBJECT(box), PLUGIN_ID "-sep", sep); /* connect signals, etc. */ g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "insert_text", G_CALLBACK(insert_text_cb), gtkconv); g_signal_connect(G_OBJECT(gtkconv->entry_buffer), "delete_range", G_CALLBACK(delete_text_cb), gtkconv); /* redraw window */ gtk_widget_queue_draw(pidgin_conv_get_window(gtkconv)->window); } static gboolean is_twitter_conv(PurpleConversation *conv) { const char *name = purple_conversation_get_name(conv); PurpleAccount *account = purple_conversation_get_account(conv); const gchar *proto = purple_account_get_protocol_id(account); twitter_debug("is_twitter_conv\n"); twitter_debug("name = %s\n", name); twitter_debug("proto = %s\n", proto); if(!strcmp(name, "twitter@twitter.com") && !strcmp(proto, "prpl-jabber")) { return TRUE; } return FALSE; } static void conv_created_cb(PurpleConversation *conv, gpointer null) { PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); g_return_if_fail(gtkconv != NULL); /* only attach to twitter conversation window */ if(is_twitter_conv(conv)) { gboolean enabled = purple_prefs_get_bool(OPT_COUNTER); if(enabled) { attach_to_gtkconv(gtkconv, NULL); } } } static gboolean receiving_im_cb(PurpleAccount *account, char **sender, char **buffer, PurpleConversation *conv, PurpleMessageFlags *flags, void *data) { twitter_debug("receiving_im_cb: buffer = %s\n", *buffer); twitter_debug("receiving_im_cb: suppress_oops = %d\n", suppress_oops); if(!suppress_oops || !purple_prefs_get_bool(OPT_SUPPRESS_OOPS)) return FALSE; if(strstr(*buffer, OOPS_MESSAGE)) { twitter_debug("receiving_im_cb: clearing sender and buffer\n"); g_free(*sender); *sender = NULL; g_free(*buffer); *buffer = NULL; suppress_oops = FALSE; } return FALSE; } static gboolean load_plugin(PurplePlugin *plugin) { /* connect to signal */ purple_signal_connect(purple_conversations_get_handle(), "writing-im-msg", plugin, PURPLE_CALLBACK(writing_im_cb), NULL); purple_signal_connect(purple_conversations_get_handle(), "sending-im-msg", plugin, PURPLE_CALLBACK(sending_im_cb), NULL); purple_signal_connect(purple_conversations_get_handle(), "conversation-created", plugin, PURPLE_CALLBACK(conv_created_cb), NULL); purple_signal_connect(purple_conversations_get_handle(), "receiving-im-msg", plugin, PURPLE_CALLBACK(receiving_im_cb), NULL); /* compile regex */ regp[RECIPIENT] = g_regex_new("@([A-Za-z0-9_]+)", 0, 0, NULL); regp[SENDER] = g_regex_new("<body>([A-Za-z0-9_]+): ", 0, 0, NULL); regp[COMMAND] = g_regex_new("^(?:\\s*)([dDfFgGlLmMnNtTwW]{1}\\s+[A-Za-z0-9_]+\\Z)", G_REGEX_RAW, 0, NULL); regp[PSEUDO] = g_regex_new ("^\\s*(?:[\"#$%&'()*+,\\-./:;<=>?\\[\\\\\\]_`{|}~]|[^\\s\\x21-\\x7E])*([dDfFgGlLmMnNtTwW]{1})(?:\\Z|\\s+|[^\\x21-\\x7E]+\\Z)", G_REGEX_RAW, 0, NULL); regp[SENDER_WITH_LINK] = g_regex_new ("@(?:<font .+?>)?<a href=.+?>([A-Za-z0-9_]+?)</a>(?:</font>)?", 0, 0, NULL); /* attach counter to the existing twitter window */ gboolean enabled = purple_prefs_get_bool(OPT_COUNTER); if(enabled) { attach_to_window(); } return TRUE; } static gboolean unload_plugin(PurplePlugin *plugin) { twitter_debug("pidgin-twitter unload called\n"); /* disconnect from signal */ purple_signal_disconnect(purple_conversations_get_handle(), "writing-im-msg", plugin, PURPLE_CALLBACK(writing_im_cb)); purple_signal_disconnect(purple_conversations_get_handle(), "sending-im-msg", plugin, PURPLE_CALLBACK(sending_im_cb)); purple_signal_disconnect(purple_conversations_get_handle(), "conversation-created", plugin, PURPLE_CALLBACK(conv_created_cb)); purple_signal_disconnect(purple_conversations_get_handle(), "receiving-im-msg", plugin, PURPLE_CALLBACK(receiving_im_cb)); /* unreference regp */ g_regex_unref(regp[RECIPIENT]); g_regex_unref(regp[SENDER]); g_regex_unref(regp[COMMAND]); g_regex_unref(regp[PSEUDO]); g_regex_unref(regp[SENDER_WITH_LINK]); /* detach from twitter window */ detach_from_window(); return TRUE; } static void counter_prefs_cb(const char *name, PurplePrefType type, gconstpointer val, gpointer data) { gboolean enabled = purple_prefs_get_bool(OPT_COUNTER); if(enabled) { attach_to_window(); //xxx should check whether already attached or not? } else { detach_from_window(); } } static PurplePluginPrefFrame * get_plugin_pref_frame(PurplePlugin *plugin) { /* create gtk elements for the plugin preferences */ PurplePluginPref *pref; PurplePluginPrefFrame *frame = purple_plugin_pref_frame_new(); /************************/ /* translatione heading */ /************************/ pref = purple_plugin_pref_new_with_label("Translation Configurations"); purple_plugin_pref_frame_add(frame, pref); /* translation settings */ pref = purple_plugin_pref_new_with_name_and_label(OPT_TRANSLATE_RECIPIENT, "Translate @username to link"); purple_plugin_pref_frame_add(frame, pref); pref = purple_plugin_pref_new_with_name_and_label(OPT_TRANSLATE_SENDER, "Translate sender name to link"); purple_plugin_pref_frame_add(frame, pref); /*************************/ /* miscellaneous heading */ /*************************/ pref = purple_plugin_pref_new_with_label("Miscellaneous Configurations"); purple_plugin_pref_frame_add(frame, pref); /* escape pseudo command setting */ pref = purple_plugin_pref_new_with_name_and_label(OPT_ESCAPE_PSEUDO, "Escape pseudo command string"); purple_plugin_pref_frame_add(frame, pref); /* show text counter */ pref = purple_plugin_pref_new_with_name_and_label(OPT_COUNTER, "Show text counter"); purple_plugin_pref_frame_add(frame, pref); purple_prefs_connect_callback(plugin, OPT_COUNTER, counter_prefs_cb, NULL); /* suppress oops message */ pref = purple_plugin_pref_new_with_name_and_label(OPT_SUPPRESS_OOPS, "Suppress oops message"); purple_plugin_pref_frame_add(frame, pref); /*****************/ /* sound heading */ /*****************/ pref = purple_plugin_pref_new_with_label("Sound Configurations"); purple_plugin_pref_frame_add(frame, pref); /* sound settings for recipient */ pref = purple_plugin_pref_new_with_name_and_label(OPT_PLAYSOUND_RECIPIENT, "Play sound on a reply to the user in the recipient list"); purple_plugin_pref_frame_add(frame, pref); /* recipient list */ pref = purple_plugin_pref_new_with_name_and_label(OPT_USERLIST_RECIPIENT, "Recipient List"); purple_plugin_pref_frame_add(frame, pref); /* sound id selector */ pref = purple_plugin_pref_new_with_name_and_label(OPT_SOUNDID_RECIPIENT, "Recipient Sound"); purple_plugin_pref_set_type(pref, PURPLE_PLUGIN_PREF_CHOICE); purple_plugin_pref_add_choice(pref, "Arrive", GINT_TO_POINTER(0)); purple_plugin_pref_add_choice(pref, "Leave", GINT_TO_POINTER(1)); purple_plugin_pref_add_choice(pref, "Receive", GINT_TO_POINTER(2)); purple_plugin_pref_add_choice(pref, "Fist Receive", GINT_TO_POINTER(3)); purple_plugin_pref_add_choice(pref, "Send", GINT_TO_POINTER(4)); purple_plugin_pref_add_choice(pref, "Chat Join", GINT_TO_POINTER(5)); purple_plugin_pref_add_choice(pref, "Chat Leave", GINT_TO_POINTER(6)); purple_plugin_pref_add_choice(pref, "Chat You Say", GINT_TO_POINTER(7)); purple_plugin_pref_add_choice(pref, "Chat Someone Say", GINT_TO_POINTER(8)); purple_plugin_pref_add_choice(pref, "Pounce Default", GINT_TO_POINTER(9)); purple_plugin_pref_add_choice(pref, "Chat Nick Said", GINT_TO_POINTER(10)); purple_plugin_pref_frame_add(frame, pref); /* sound setting for sender */ pref = purple_plugin_pref_new_with_name_and_label(OPT_PLAYSOUND_SENDER, "Play sound if sender of a message is in the sender list"); purple_plugin_pref_frame_add(frame, pref); /* sender list */ pref = purple_plugin_pref_new_with_name_and_label(OPT_USERLIST_SENDER, "Sender List"); purple_plugin_pref_frame_add(frame, pref); /* sound id selector */ pref = purple_plugin_pref_new_with_name_and_label(OPT_SOUNDID_SENDER, "Sender Sound"); purple_plugin_pref_set_type(pref, PURPLE_PLUGIN_PREF_CHOICE); purple_plugin_pref_add_choice(pref, "Arrive", GINT_TO_POINTER(0)); purple_plugin_pref_add_choice(pref, "Leave", GINT_TO_POINTER(1)); purple_plugin_pref_add_choice(pref, "Receive", GINT_TO_POINTER(2)); purple_plugin_pref_add_choice(pref, "Fist Receive", GINT_TO_POINTER(3)); purple_plugin_pref_add_choice(pref, "Send", GINT_TO_POINTER(4)); purple_plugin_pref_add_choice(pref, "Chat Join", GINT_TO_POINTER(5)); purple_plugin_pref_add_choice(pref, "Chat Leave", GINT_TO_POINTER(6)); purple_plugin_pref_add_choice(pref, "Chat You Say", GINT_TO_POINTER(7)); purple_plugin_pref_add_choice(pref, "Chat Someone Say", GINT_TO_POINTER(8)); purple_plugin_pref_add_choice(pref, "Pounce Default", GINT_TO_POINTER(9)); purple_plugin_pref_add_choice(pref, "Chat Nick Said", GINT_TO_POINTER(10)); purple_plugin_pref_frame_add(frame, pref); return frame; } static PurplePluginUiInfo pref_info = { get_plugin_pref_frame }; static PurplePluginInfo info = { PURPLE_PLUGIN_MAGIC, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_PLUGIN_STANDARD, /**< type */ NULL, /**< ui_req */ 0, /**< flags */ NULL, /**< deps */ PURPLE_PRIORITY_DEFAULT, /**< priority */ PLUGIN_ID, /**< id */ "Pidgin-Twitter", /**< name */ "0.6.0", /**< version */ "replaces usernames with links and play sounds", /** summary */ "replaces usernames with links and play sounds", /** desc */ "Yoshiki Yazawa (yaz@honeyplanet.jp)", /**< author */ "http://www.honeyplanet.jp/", /**< homepage */ load_plugin, /**< load */ unload_plugin, /**< unload */ NULL, /**< destroy */ NULL, /**< ui_info */ NULL, /**< extra_info */ &pref_info, /**< pref info */ NULL }; static void init_plugin(PurplePlugin *plugin) { g_type_init(); /* add plugin preferences */ purple_prefs_add_none(OPT_PIDGINTWITTER); purple_prefs_add_bool(OPT_TRANSLATE_RECIPIENT, TRUE); purple_prefs_add_bool(OPT_TRANSLATE_SENDER, TRUE); purple_prefs_add_bool(OPT_ESCAPE_PSEUDO, TRUE); purple_prefs_add_bool(OPT_PLAYSOUND_RECIPIENT, TRUE); purple_prefs_add_bool(OPT_PLAYSOUND_SENDER, TRUE); purple_prefs_add_int(OPT_SOUNDID_RECIPIENT, PURPLE_SOUND_POUNCE_DEFAULT); purple_prefs_add_string(OPT_USERLIST_RECIPIENT, DEFAULT_LIST); purple_prefs_add_int(OPT_SOUNDID_SENDER, PURPLE_SOUND_POUNCE_DEFAULT); purple_prefs_add_string(OPT_USERLIST_SENDER, DEFAULT_LIST); purple_prefs_add_bool(OPT_COUNTER, TRUE); purple_prefs_add_bool(OPT_SUPPRESS_OOPS, TRUE); } PURPLE_INIT_PLUGIN(pidgin_twitter, init_plugin, info)