Mercurial > grim > purple-plugin-pack
view awaynotify/awaynotify.c @ 1028:314cfd774bc4
s/purple.guifications.org/plugins.guifications.org/
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Thu, 06 Aug 2009 12:30:12 -0700 |
parents | 6dabeef0718f |
children |
line wrap: on
line source
/* * awaynotify - show notices when status changes * Copyright (C) 2005-2008 Matt Perry <guy@somewhere.fscked.org> * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA. */ /* If you can't figure out what this line is for, DON'T TOUCH IT. */ #include "../common/pp_internal.h" #include <blist.h> #include <conversation.h> #include <debug.h> #include <signals.h> #include <plugin.h> #include <pluginpref.h> #include <prefs.h> #include <string.h> #define PLUGIN_ID "core-plugin_pack-awaynotify" #define CHECK_AWAY_MESSAGE_TIME_MS 1000 typedef struct _Infochecker Infochecker; struct _Infochecker { PurpleAccount *account; char *buddy; guint timeout_id; }; GList* infochecker_list = NULL; static gint infocheck_timeout(gpointer data); static Infochecker* infocheck_new(PurpleAccount* account, char* buddy) { Infochecker* checker = g_new0(Infochecker, 1); checker->account = account; checker->buddy = g_strdup(buddy); return checker; } static void infocheck_delete(Infochecker* checker) { g_free(checker->buddy); g_free(checker); } static void infocheck_remove(GList* node) { Infochecker* checker = (Infochecker*)node->data; g_source_remove(checker->timeout_id); infochecker_list = g_list_remove_link(infochecker_list, node); infocheck_delete(checker); } static gint infocheck_compare(gconstpointer pa, gconstpointer pb) { Infochecker* a = (Infochecker*)pa; Infochecker* b = (Infochecker*)pb; return (a->account == b->account) ? strcmp(a->buddy, b->buddy) : 1; } static void write_status(PurpleBuddy *buddy, const char *message, const char* status) { PurpleConversation *conv; const char *who; char buf[256]; char *escaped; conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); if (conv == NULL) return; who = purple_buddy_get_alias(buddy); escaped = g_markup_escape_text(who, -1); g_snprintf(buf, sizeof(buf), message, escaped, status); g_free(escaped); purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); } static char* parse_away_message(char* statustext) { char* away_ptr = strstr(statustext, "Away Message:"); if (away_ptr == NULL) return g_strdup(""); away_ptr += 4 + 1 + 7 + 1; if (*away_ptr == '<') { char* tmp = strchr(away_ptr, '>'); if (tmp) away_ptr = tmp + 1; } while (*away_ptr == ' ') away_ptr++; return g_strdup(away_ptr); } static char* get_away_message(PurpleBuddy* buddy) { PurplePlugin *prpl; PurplePluginProtocolInfo *prpl_info = NULL; char* statustext = NULL; if (buddy == NULL) return NULL; prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account)); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); if (prpl_info && prpl_info->tooltip_text) { const char *end; char *statustext = NULL; PurpleNotifyUserInfo *info = purple_notify_user_info_new(); prpl_info->tooltip_text(buddy, info, TRUE); statustext = purple_notify_user_info_get_text_with_newline(info, "\n"); purple_notify_user_info_destroy(info); if (statustext && !g_utf8_validate(statustext, -1, &end)) { char *new = g_strndup(statustext, g_utf8_pointer_to_offset(statustext, end)); g_free(statustext); statustext = new; } } if (statustext) { char* away_message = parse_away_message(statustext); g_free(statustext); return away_message; } else return NULL; } static gint infocheck_timeout(gpointer data) { GList* node = (GList*)data; Infochecker* checker = node ? (Infochecker*)node->data : NULL; PurpleBuddy* buddy; char* away_message; if (node == NULL || checker == NULL) { purple_debug_warning("awaynotify", "checker called without being active!\n"); return FALSE; } buddy = purple_find_buddy(checker->account, checker->buddy); away_message = get_away_message(buddy); if (away_message == NULL) { /* He must have signed off or there was some other error. Give up. */ infocheck_remove(node); return FALSE; } if (away_message[0] == 0) { /* Not away yet. Return true to try again. */ g_free(away_message); return TRUE; } write_status(buddy, _("%s is away: %s"), away_message); g_free(away_message); infocheck_remove(node); return FALSE; } static void infocheck_add(Infochecker* checker) { infochecker_list = g_list_prepend(infochecker_list, checker); checker->timeout_id = g_timeout_add(CHECK_AWAY_MESSAGE_TIME_MS, infocheck_timeout, g_list_first(infochecker_list)); } static void buddy_away_cb(PurpleBuddy *buddy, void *data) { if (purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account) == NULL) return; /* Ignore if there's no conv open. */ infocheck_add(infocheck_new(buddy->account, buddy->name)); } static void buddy_unaway_cb(PurpleBuddy *buddy, void *data) { GList* node = g_list_find_custom(infochecker_list, buddy->name, infocheck_compare); if (node) infocheck_remove(node); write_status(buddy, _("%s is no longer away."), NULL); } static gboolean plugin_load(PurplePlugin *plugin) { void *blist_handle = purple_blist_get_handle(); purple_signal_connect(blist_handle, "buddy-away", plugin, PURPLE_CALLBACK(buddy_away_cb), NULL); purple_signal_connect(blist_handle, "buddy-back", plugin, PURPLE_CALLBACK(buddy_unaway_cb), NULL); return TRUE; } static PurplePluginInfo info = { PURPLE_PLUGIN_MAGIC, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_PLUGIN_STANDARD, /**< type */ NULL, /**< ui_requirement */ 0, /**< flags */ NULL, /**< dependencies */ PURPLE_PRIORITY_DEFAULT, /**< priority */ PLUGIN_ID, /**< id */ NULL, /**< name */ PP_VERSION, /**< version */ NULL, /** summary */ NULL, /** description */ "Matt Perry <guy@somewhere.fscked.org>", /**< author */ PP_WEBSITE, /**< homepage */ plugin_load, /**< load */ NULL, /**< unload */ NULL, /**< destroy */ NULL, /**< ui_info */ NULL, /**< extra_info */ NULL, /**< prefs_info */ NULL }; static void init_plugin(PurplePlugin *plugin) { info.name = _("Away State Notification"); info.summary = _("Notifies in a conversation window when a buddy goes or returns from away"); info.description = info.summary; } PURPLE_INIT_PLUGIN(statenotify, init_plugin, info)