view pidgin-twitter.c @ 34:44ffbd056f33

added patch to strip excessive hyper link on @username when it copied and pasted from message window. patch by mikanbako (maoutwo@gmail.com).
author Yoshiki Yazawa <yaz@cc.rim.or.jp>
date Sat, 10 May 2008 20:18:20 +0900
parents 92715b489de6
children 7d07fcb9c616
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 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 twitter_debug(fmt, ...)	purple_debug(PURPLE_DEBUG_INFO, PLUGIN_NAME, \
                                             fmt, ## __VA_ARGS__);
#define twitter_error(fmt, ...)	purple_debug(PURPLE_DEBUG_ERROR, PLUGIN_NAME, \

/* globals */
static GRegex *regp[5];

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;
}

/* 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
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);
        }
        delete_sender_with_link(buffer);
    }
    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 call 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
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);

    /* 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("@<a href=.+?>([A-Za-z0-9_]+?)</a>", 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));

    /* 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 shoud 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();

    /* frame title */
    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);





    /* frame title */
    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);

    /* comaescape pseudo command setting */
    pref = purple_plugin_pref_new_with_name_and_label(
        OPT_COUNTER,
        "Show text counter");
    purple_plugin_pref_frame_add(frame, pref);

    /* xxx */
	purple_prefs_connect_callback(plugin, OPT_COUNTER,
								counter_prefs_cb, NULL);





    /* frame title */
    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_INIT_PLUGIN(pidgin_twitter, init_plugin, info)