Mercurial > pidgin-twitter
changeset 64:da37857f3033
- separated header things into pidgin-twitter.h
- preliminary save icon feature
author | Yoshiki Yazawa <yaz@cc.rim.or.jp> |
---|---|
date | Sun, 22 Jun 2008 16:02:44 +0900 |
parents | 760006015519 |
children | 4949d4eb34ec |
files | pidgin-twitter.c pidgin-twitter.h |
diffstat | 2 files changed, 168 insertions(+), 98 deletions(-) [+] |
line wrap: on
line diff
--- a/pidgin-twitter.c Sun Jun 22 01:44:48 2008 +0900 +++ b/pidgin-twitter.c Sun Jun 22 16:02:44 2008 +0900 @@ -18,67 +18,7 @@ */ #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" -#include "gtkimhtml.h" - -#define RECIPIENT 0 -#define SENDER 1 -#define COMMAND 2 -#define PSEUDO 3 -#define MESSAGE 4 -#define USER 5 -#define USER_FIRST_LINE 6 -#define USER_FORMATTED 7 - -#define PLUGIN_ID "gtk-honeyplanet-pidgin_twitter" -#define PLUGIN_NAME "pidgin-twitter" - -/* options */ -#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 OPT_PREVENT_NOTIFICATION OPT_PIDGINTWITTER "/prevent_notification" - -/* formats and templates */ -#define RECIPIENT_FORMAT "@<a href='http://twitter.com/%s'>%s</a>" -#define SENDER_FORMAT "%s<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>" - -/* patterns */ -#define P_RECIPIENT "@([A-Za-z0-9_]+)" -#define P_SENDER "^(\\r?\\n?)([A-Za-z0-9_]+): " -#define P_COMMAND "^(?:\\s*)([dDfFgGlLmMnNtTwW]{1}\\s+[A-Za-z0-9_]+)(?:\\s*\\Z)" -#define P_PSEUDO "^\\s*(?:[\"#$%&'()*+,\\-./:;<=>?\\[\\\\\\]_`{|}~]|[^\\s\\x21-\\x7E])*([dDfFgGlLmMnNtTwW]{1})(?:\\Z|\\s+|[^\\x21-\\x7E]+\\Z)" -#define P_MESSAGE "^<body>(.*)</body>" -#define P_USER "^\\(.+?\\)\\s*([A-Za-z0-9_]+):" -#define P_USER_FIRST_LINE "^\\(.+?\\)\\s*.+:\\s*([A-Za-z0-9_]+):" -#define P_USER_FORMATTED "^.*?<a .+?>([A-Za-z0-9_]+)</a>:" - -/* debug macros */ -#define twitter_debug(fmt, ...) purple_debug(PURPLE_DEBUG_INFO, PLUGIN_NAME, "%s():%4d: " fmt, __FUNCTION__, (int)__LINE__, ## __VA_ARGS__); -#define twitter_error(fmt, ...) purple_debug(PURPLE_DEBUG_ERROR, PLUGIN_NAME, "%s():%4d: " fmt, __FUNCTION__, (int)__LINE__, ## __VA_ARGS__); - +#include "pidgin-twitter.h" /* globals */ static GRegex *regp[8]; @@ -88,36 +28,6 @@ static GList *requestings = NULL; static GList *requested_icon_marks = NULL; -/* prototypes */ -static void escape(gchar **str); -static gboolean sending_im_cb(PurpleAccount *account, char *recipient, char **buffer, void *data); -static gboolean eval(const GMatchInfo *match_info, GString *result, gpointer user_data); -static void translate(gchar **str, int which); -static void playsound(gchar **str, int which); -static gboolean writing_im_cb(PurpleAccount *account, char *sender, char **buffer, PurpleConversation *conv, int *flags, void *data); -static void insert_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *position, gchar *new_text, gint new_text_length, gpointer user_data); -static void delete_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *start_pos, GtkTextIter *end_pos, gpointer user_data); -static void detach_from_window(void); -static void detach_from_gtkconv(PidginConversation *gtkconv, gpointer null); -static void delete_requested_icon_marks(PidginConversation *gtkconv); -static void attach_to_window(void); -static void attach_to_gtkconv(PidginConversation *gtkconv, gpointer null); -static gboolean is_twitter_account(PurpleAccount *account, const char *name); -static gboolean is_twitter_conv(PurpleConversation *conv); -static void conv_created_cb(PurpleConversation *conv, gpointer null); -static void deleting_conv_cb(PurpleConversation *conv); -static gboolean receiving_im_cb(PurpleAccount *account, char **sender, char **buffer, PurpleConversation *conv, PurpleMessageFlags *flags, void *data); -static void insert_requested_icon(gpointer data, gpointer user_data); -static void downloaded_icon_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message); -static void request_icon(const char *buffer); -static void displayed_im_cb(PurpleAccount *account, const char *who, char *message, PurpleConversation *conv, PurpleMessageFlags flags); -static gboolean load_plugin(PurplePlugin *plugin); -static gboolean unload_plugin(PurplePlugin *plugin); -static void counter_prefs_cb(const char *name, PurplePrefType type, gconstpointer val, gpointer data); -static PurplePluginPrefFrame *get_plugin_pref_frame(PurplePlugin *plugin); -static void init_plugin(PurplePlugin *plugin); - - /* this function is a modified clone of purple_markup_strip_html() */ static char * strip_html_markup(const char *str) @@ -275,9 +185,22 @@ return str2; } +/* this function has been taken from autoaccept plugin */ +static gboolean +ensure_path_exists(const char *dir) +{ + if (!g_file_test(dir, G_FILE_TEST_IS_DIR)) { + if (purple_build_dir(dir, S_IRUSR | S_IWUSR | S_IXUSR)) + return FALSE; + } + return TRUE; +} + + +/**********************/ /* our implementation */ - +/**********************/ static void escape(gchar **str) { @@ -592,7 +515,7 @@ GtkTextBuffer *text_buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(conv->imhtml)); GList *mark_list = g_list_first(requested_icon_marks); - + /* delete the marks in the buffer that will be closed. */ while(mark_list) { GtkTextMark *mark = mark_list->data; @@ -650,7 +573,7 @@ purple_conversation_set_features( gtkconv->active_conv, purple_conversation_get_features(gtkconv->active_conv) & - ~PURPLE_CONNECTION_HTML); + ~PURPLE_CONNECTION_HTML); /* check if the counter is enabled */ if(!purple_prefs_get_bool(OPT_COUNTER)) @@ -795,7 +718,7 @@ GtkIMHtml *current_imhtml = GTK_IMHTML(conv->imhtml); GtkTextBuffer *current_buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(current_imhtml)); - + if(current_buffer == gtk_text_mark_get_buffer(requested_mark)) { target_imhtml = current_imhtml; target_buffer = current_buffer; @@ -846,6 +769,9 @@ return; } + /* xxx scale stored icon to adequate size here. --yaz */ + + /* insert icon actually */ gtk_imhtml_insert_image_at_iter(target_imhtml, icon_id, &inserting_point); /* mark the entry contains the deleted mark with NULL */ @@ -884,6 +810,25 @@ user_name); g_hash_table_insert(icon_id_by_user, user_name, GINT_TO_POINTER(icon_id)); + const gchar *dirname = purple_prefs_get_string(OPT_ICON_DIR); + + /* store retrieved image to a file in icon dir */ + if(ensure_path_exists(dirname)) { + gchar *filename = NULL; + FILE *fp = NULL; + + filename = g_build_filename(dirname, user_name, ".gif", NULL); + + fp = fopen(filename, "w"); + g_free(filename); filename = NULL; + + if(fp) { + int len; + len = fwrite(url_text, len, 1, fp); + } + fclose(fp); fp = NULL; + } + twitter_debug("Downloading %s's icon has been complete.(icon_id = %d)\n", user_name, icon_id); @@ -903,7 +848,6 @@ PurpleUtilFetchUrlData *fetch_data = NULL; /* get user's name */ - g_regex_match(regp[MESSAGE], buffer, 0, &match_info); if(!g_match_info_matches(match_info)) { twitter_debug("Message was not matched : %s\n", buffer); @@ -927,9 +871,33 @@ g_match_info_free(match_info); g_free(message); + /***********************/ /* request user's icon */ + /***********************/ + + /* first of all, look local icon cache for the requested icon */ + gchar *filename = NULL; + filename = g_build_filename( + purple_prefs_get_string(OPT_ICON_DIR), user_name, ".gif", NULL); - /* Return if user's icon had already been requested. */ + if(!g_file_test(filename, G_FILE_TEST_EXISTS)) { + g_free(filename); + filename = g_build_filename( + purple_prefs_get_string(OPT_ICON_DIR), user_name, ".png", NULL); + } + + if(g_file_test(filename, G_FILE_TEST_EXISTS)) { + purple_imgstore_new_from_file(filename); + icon_id = purple_imgstore_add_from_file_with_id(); + g_hash_table_insert(icon_id_by_user, user_name, GINT_TO_POINTER(icon_id)); + g_free(user_name); + g_free(filename); + + return; + } + + + /* Return if user's icon has been requested already. */ if(g_list_find_custom(requested_users, user_name, (GCompareFunc)strcmp)) { g_free(user_name); return; @@ -1035,7 +1003,7 @@ regp[USER_FIRST_LINE] = g_regex_new(P_USER_FIRST_LINE, 0, 0, NULL); regp[USER_FORMATTED] = g_regex_new(P_USER_FORMATTED, G_REGEX_RAW, 0, NULL); - /* hash table for user's icons + /* hash table for user's icons * the key is owned by requested_user */ icon_id_by_user = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); @@ -1281,7 +1249,13 @@ static void init_plugin(PurplePlugin *plugin) { + char *dirname = NULL; + g_type_init(); + dirname = g_build_filename(purple_user_dir(), "pidgin-twitter/icons", NULL); + if(dirname) + purple_prefs_add_string(OPT_ICON_DIR, dirname); + g_free(dirname); /* add plugin preferences */ purple_prefs_add_none(OPT_PIDGINTWITTER);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin-twitter.h Sun Jun 22 16:02:44 2008 +0900 @@ -0,0 +1,96 @@ +#ifndef _PIDGIN_TWITTER_H_ +#define _PIDGIN_TWITTER_H_ + +#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" +#include "gtkimhtml.h" + +/* regp id */ +#define RECIPIENT 0 +#define SENDER 1 +#define COMMAND 2 +#define PSEUDO 3 +#define MESSAGE 4 +#define USER 5 +#define USER_FIRST_LINE 6 +#define USER_FORMATTED 7 + +#define PLUGIN_ID "gtk-honeyplanet-pidgin_twitter" +#define PLUGIN_NAME "pidgin-twitter" + +/* options */ +#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 OPT_PREVENT_NOTIFICATION OPT_PIDGINTWITTER "/prevent_notification" +#define OPT_ICON_DIR OPT_PIDGINTWITTER "/icon_dir" + +/* formats and templates */ +#define RECIPIENT_FORMAT "@<a href='http://twitter.com/%s'>%s</a>" +#define SENDER_FORMAT "%s<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>" + +/* patterns */ +#define P_RECIPIENT "@([A-Za-z0-9_]+)" +#define P_SENDER "^(\\r?\\n?)([A-Za-z0-9_]+): " +#define P_COMMAND "^(?:\\s*)([dDfFgGlLmMnNtTwW]{1}\\s+[A-Za-z0-9_]+)(?:\\s*\\Z)" +#define P_PSEUDO "^\\s*(?:[\"#$%&'()*+,\\-./:;<=>?\\[\\\\\\]_`{|}~]|[^\\s\\x21-\\x7E])*([dDfFgGlLmMnNtTwW]{1})(?:\\Z|\\s+|[^\\x21-\\x7E]+\\Z)" +#define P_MESSAGE "^<body>(.*)</body>" +#define P_USER "^\\(.+?\\)\\s*([A-Za-z0-9_]+):" +#define P_USER_FIRST_LINE "^\\(.+?\\)\\s*.+:\\s*([A-Za-z0-9_]+):" +#define P_USER_FORMATTED "^.*?<a .+?>([A-Za-z0-9_]+)</a>:" + +/* debug macros */ +#define twitter_debug(fmt, ...) purple_debug(PURPLE_DEBUG_INFO, PLUGIN_NAME, "%s():%4d: " fmt, __FUNCTION__, (int)__LINE__, ## __VA_ARGS__); +#define twitter_error(fmt, ...) purple_debug(PURPLE_DEBUG_ERROR, PLUGIN_NAME, "%s():%4d: " fmt, __FUNCTION__, (int)__LINE__, ## __VA_ARGS__); + +/* prototypes */ +static void escape(gchar **str); +static gboolean sending_im_cb(PurpleAccount *account, char *recipient, char **buffer, void *data); +static gboolean eval(const GMatchInfo *match_info, GString *result, gpointer user_data); +static void translate(gchar **str, int which); +static void playsound(gchar **str, int which); +static gboolean writing_im_cb(PurpleAccount *account, char *sender, char **buffer, PurpleConversation *conv, int *flags, void *data); +static void insert_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *position, gchar *new_text, gint new_text_length, gpointer user_data); +static void delete_text_cb(GtkTextBuffer *textbuffer, GtkTextIter *start_pos, GtkTextIter *end_pos, gpointer user_data); +static void detach_from_window(void); +static void detach_from_gtkconv(PidginConversation *gtkconv, gpointer null); +static void delete_requested_icon_marks(PidginConversation *gtkconv); +static void attach_to_window(void); +static void attach_to_gtkconv(PidginConversation *gtkconv, gpointer null); +static gboolean is_twitter_account(PurpleAccount *account, const char *name); +static gboolean is_twitter_conv(PurpleConversation *conv); +static void conv_created_cb(PurpleConversation *conv, gpointer null); +static void deleting_conv_cb(PurpleConversation *conv); +static gboolean receiving_im_cb(PurpleAccount *account, char **sender, char **buffer, PurpleConversation *conv, PurpleMessageFlags *flags, void *data); +static void insert_requested_icon(gpointer data, gpointer user_data); +static void downloaded_icon_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message); +static void request_icon(const char *buffer); +static void displayed_im_cb(PurpleAccount *account, const char *who, char *message, PurpleConversation *conv, PurpleMessageFlags flags); +static gboolean load_plugin(PurplePlugin *plugin); +static gboolean unload_plugin(PurplePlugin *plugin); +static void counter_prefs_cb(const char *name, PurplePrefType type, gconstpointer val, gpointer data); +static PurplePluginPrefFrame *get_plugin_pref_frame(PurplePlugin *plugin); +static void init_plugin(PurplePlugin *plugin); + +#endif