仕組みなんですが、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 件のコメント:
コメントを投稿