仕組みなんですが、Google App EngineにGoogleTalkのオンライン状況を拾えるAPIがあるので、それを使ってます。ところがこのAPI、ちょっと不便なことに、オンラインかオフラインの2択でしか拾えないんです。
API自体も非常にシンプルで、(1)フレンドが接続してるか調べる (2)フレンドにメッセージを送る (3)メッセージを受け取る。この3つのみ。
これだけじゃどう工夫しても細かい状況を拾うことは無理なので、別のアプローチ。GoogleTalkのクライアント側で「離席になったよ!」と状況がかわるたびに、AppEngineにメッセージを送るようにしてみました。
ちなみにクライアントはPidginをつかってるので、こういう処理はプラグインで書いちゃえばいいですね。
こういう感じに書けました
#include "internal.h" #include "signals.h" #include "version.h" #include "prpl.h" #include "xmlnode.h" #define PLUGIN_ID "core-himika_presence" #define GAE_ACCOUNT_NAME "himika-xmpp@appspot.com" static void send_message_presence(const PurpleAccount *account, const PurpleStatus *status) { PurpleConnection *gc; PurplePluginProtocolInfo *prpl_info = NULL; PurpleBuddy *buddy; GSList *list, *l; xmlnode *message, *child; int len; char *text, *status_id; char buffer[128]; if ( strcmp(purple_account_get_protocol_id(account), "prpl-jabber") ) return; if ( !purple_status_is_online(status) ) return; gc = purple_account_get_connection(account); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); if ( !prpl_info || !prpl_info->send_raw ) return; list = purple_find_buddies(account, GAE_ACCOUNT_NAME); if (list) { for (l = list; l != NULL; l = l->next) { buddy = l->data; message = xmlnode_new("message"); xmlnode_set_attrib(message, "type", "chat"); sprintf(buffer, "himika_presence_%x", g_random_int()); xmlnode_set_attrib(message, "id", buffer); xmlnode_set_attrib(message, "to", buddy->name); child = xmlnode_new_child(message, "body"); status_id = purple_status_get_id(status); sprintf(buffer, "himika_presence: %s", status_id); xmlnode_insert_data(child, buffer, -1); text = xmlnode_to_str(message, &len); prpl_info->send_raw(gc, text, len); g_free(text); xmlnode_free(message); } g_slist_free(list); } } static void account_status_changed_cb(PurpleAccount *account, PurpleStatus *old, PurpleStatus *newstatus) { if ( strcmp(purple_account_get_protocol_id(account), "prpl-jabber") ) return; if ( !purple_status_is_online(newstatus) ) return; send_message_presence(account, newstatus); } static void signed_on_cb(PurpleConnection *gc) { PurpleAccount *account; PurpleStatus *status; account = purple_connection_get_account(gc); if (!account || strcmp(purple_account_get_protocol_id(account), "prpl-jabber") ) return; status = purple_account_get_active_status(account); send_message_presence(account, status); } static gboolean plugin_load(PurplePlugin *plugin) { PurplePlugin *jabber; if ( !purple_find_prpl("prpl-jabber") ) return FALSE; purple_signal_connect(purple_accounts_get_handle(), "account-status-changed", plugin, PURPLE_CALLBACK(account_status_changed_cb), NULL); purple_signal_connect(purple_connections_get_handle(), "signed-on", plugin, PURPLE_CALLBACK(signed_on_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 */ /**< name */ N_("Presence Notifier for GAE.XMPP"), DISPLAY_VERSION, /**< version */ N_("test."), /** summary */ N_("test."), /** description */ /**< author */ "himika", /**< author */ "http://www.himika.com/", /**< homepage */ plugin_load, /**< load */ NULL, /**< unload */ NULL, /**< destroy */ NULL, /**< ui_info */ NULL, /**< extra_info */ NULL, NULL, /* padding */ NULL, NULL, NULL, NULL }; static gboolean init_plugin(PurplePlugin *plugin) { return TRUE; } PURPLE_INIT_PLUGIN(himika_presence, init_plugin, info)こういう力技をつかわなくても、そのうちAPIで拾えるようになってくれるといいな~。今後に期待。
0 件のコメント:
コメントを投稿