示例#1
0
void flist_remove_chat(FListAccount *fla, const gchar *name) {
    PurpleGroup *g = flist_get_chat_group(fla);
    PurpleChat *b = purple_blist_find_chat(fla->pa, name);
    if(b && purple_chat_get_group(b) == g) {
        purple_blist_remove_chat(b);
    }
}
示例#2
0
PurpleChat *qq_room_find_or_new(PurpleConnection *gc, guint32 id, guint32 qun_id)
{
	qq_data *qd;
	qq_room_data *rmd;
	PurpleChat *chat;
	gchar *num_str;

	g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, NULL);
	qd = (qq_data *) gc->proto_data;

	g_return_val_if_fail(id != 0 && qun_id != 0, NULL);

	purple_debug_info("QQ", "Find or add new room: id %u, qun id %u\n", id, qun_id);

	rmd = qq_room_data_find(gc, id);
	if (rmd == NULL) {
		rmd = room_data_new(id, qun_id, NULL);
		g_return_val_if_fail(rmd != NULL, NULL);
		rmd->my_role = QQ_ROOM_ROLE_YES;
		qd->rooms = g_slist_append(qd->rooms, rmd);
	}

	num_str = g_strdup_printf("%u", qun_id);
	chat = purple_blist_find_chat(purple_connection_get_account(gc), num_str);
	g_free(num_str);
	if (chat) {
		return chat;
	}

	return chat_new(gc, rmd);
}
示例#3
0
void
translate_receiving_chat_msg_cb(const gchar *original_phrase, const gchar *translated_phrase, const gchar *detected_language, gpointer userdata)
{
	struct TranslateConvMessage *convmsg = userdata;
	PurpleChat *chat;
	gchar *html_text;
	const gchar *stored_lang = "";
	const gchar *language_name = NULL;
	gchar *message;
	
	if (detected_language)
	{
		chat = purple_blist_find_chat(convmsg->account, convmsg->conv->name);
		stored_lang = purple_blist_node_get_string((PurpleBlistNode *)chat, DEST_LANG_SETTING);
		purple_blist_node_set_string((PurpleBlistNode *)chat, DEST_LANG_SETTING, detected_language);
		
		language_name = get_language_name(detected_language);
		
		if (language_name != NULL)
		{
			message = g_strdup_printf("Now translating to %s (auto-detected)", language_name);
			purple_conversation_write(convmsg->conv, NULL, message, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL));
			g_free(message);
		}
	}
	
	html_text = purple_strdup_withhtml(translated_phrase);
	
	purple_conversation_write(convmsg->conv, convmsg->sender, html_text, convmsg->flags, time(NULL));
	
	g_free(html_text);
	g_free(convmsg->sender);
	g_free(convmsg);
}
示例#4
0
static void
translate_conversation_created(PurpleConversation *conv)
{
	PurpleBlistNode *node = NULL;
	gchar *message;
	const gchar *language_key;
	const gchar *language_name;
	
	if (conv->type == PURPLE_CONV_TYPE_IM)
		node = (PurpleBlistNode *) purple_find_buddy(conv->account, conv->name);
	else if (conv->type == PURPLE_CONV_TYPE_CHAT)
		node = (PurpleBlistNode *) purple_blist_find_chat(conv->account, conv->name);
	
	if (node != NULL)
	{
		language_key = purple_blist_node_get_string(node, DEST_LANG_SETTING);
		
		if (language_key != NULL)
		{
			language_name = get_language_name(language_key);
		
			message = g_strdup_printf(_("Now translating to %s"), language_name);
			purple_conversation_write(conv, NULL, message, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL));
			g_free(message);
		}
	}
}
示例#5
0
void qq_room_remove(PurpleConnection *gc, guint32 id)
{
	qq_data *qd;
	PurpleChat *chat;
	qq_room_data *rmd;
	gchar *num_str;
	guint32 qun_id;

	g_return_if_fail (gc != NULL && gc->proto_data != NULL);
	qd = (qq_data *) gc->proto_data;

	purple_debug_info("QQ", "Find and remove room data, id %u\n", id);
	rmd = qq_room_data_find(gc, id);
	g_return_if_fail (rmd != NULL);

	qun_id = rmd->qun_id;
	qd->rooms = g_slist_remove(qd->rooms, rmd);
	room_data_free(rmd);

	purple_debug_info("QQ", "Find and remove chat, qun_id %u\n", qun_id);
	num_str = g_strdup_printf("%u", qun_id);
	chat = purple_blist_find_chat(purple_connection_get_account(gc), num_str);
	g_free(num_str);

	g_return_if_fail (chat != NULL);

	purple_blist_remove_chat(chat);
}
示例#6
0
PurpleChat *p2tgl_blist_find_chat(struct tgl_state *TLS, tgl_peer_id_t chat) {
  char *name = peer_strdup_id(chat);
  
  PurpleChat *c = purple_blist_find_chat(tg_get_acc(TLS), name);
  
  g_free (name);
  return c;
}
示例#7
0
gboolean
translate_receiving_chat_msg(PurpleAccount *account, char **sender,
                             char **message, PurpleConversation *conv,
                             PurpleMessageFlags *flags)
{
	struct TranslateConvMessage *convmsg;
	const gchar *stored_lang = "auto";
	gchar *stripped;
	const gchar *to_lang;
	PurpleChat *chat;
	const gchar *service_to_use = "";
	
	chat = purple_blist_find_chat(account, conv->name);
	service_to_use = purple_prefs_get_string(SERVICE_PREF);
	to_lang = purple_prefs_get_string(LOCALE_PREF);
	if (chat)
		stored_lang = purple_blist_node_get_string((PurpleBlistNode *)chat, DEST_LANG_SETTING);
	if (!stored_lang)
		stored_lang = "auto";
	if (!chat || !service_to_use || g_str_equal(stored_lang, "none") || g_str_equal(stored_lang, to_lang))
	{
		//Allow the message to go through as per normal
		return FALSE;
	}
	
	stripped = purple_markup_strip_html(*message);
	
	convmsg = g_new0(struct TranslateConvMessage, 1);
	convmsg->account = account;
	convmsg->sender = *sender;
	convmsg->conv = conv;
	convmsg->flags = *flags;
	
	if (g_str_equal(service_to_use, "google"))
	{
		google_translate(stripped, stored_lang, to_lang, translate_receiving_chat_msg_cb, convmsg);
	} else if (g_str_equal(service_to_use, "bing"))
	{
		bing_translate(stripped, stored_lang, to_lang, translate_receiving_chat_msg_cb, convmsg);
	}
	
	g_free(stripped);
	
	g_free(*message);
	*message = NULL;
	*sender = NULL;
	
	if (conv == NULL)
	{
		// Fake receiving a message to open the conversation window
		*message = g_strdup(" ");
		*flags |= PURPLE_MESSAGE_INVISIBLE | PURPLE_MESSAGE_NO_LOG;
		return FALSE;
	}
	
	//Cancel the message
	return TRUE;
}
示例#8
0
void
fb_got_groups(FacebookAccount *fba, const gchar *data, gsize data_len, gpointer user_data)
{
	// look for  /home.php?sk=group_ ...
	gchar **splits;
	gint i;
	PurpleGroup *group;
	
	splits = g_strsplit(data, "<a href=\\\"\\/home.php?sk=group_", 0);
	
	if (!splits || !splits[0])
	{
		g_strfreev(splits);
		return;
	}
	
	group = purple_find_group(DEFAULT_GROUP_NAME);
	if (!group)
	{
		group = purple_group_new(DEFAULT_GROUP_NAME);
		purple_blist_add_group(group, NULL);
	}
	
	for(i = 1; splits[i]; i++)
	{
		gchar *eos;
		eos = strchr(splits[i], '\\');
		if (eos != NULL)
		{
			*eos = '\0';
			purple_debug_info("facebook", "searching for %s\n", splits[i]);
			if (!purple_blist_find_chat(fba->account, splits[i]))
			{
				gchar *alias = NULL;
				if (eos[1] == '"' && eos[2] == '>')
				{
					purple_debug_info("facebook", "searching for alias\n");
					gchar *eoa = strchr(&eos[3], '<');
					if (eoa)
					{
						*eoa = '\0';
						alias = &eos[3];
						purple_debug_info("facebook", "found chat alias %s\n", alias);
					}
				}

				purple_debug_info("facebook", "adding chat %s to buddy list...\n", splits[i]);
				// Add the group chat to the buddy list
				GHashTable *components = fb_chat_info_defaults(fba->pc, splits[i]);
				PurpleChat *chat = purple_chat_new(fba->account, alias, components);
				purple_blist_add_chat(chat, group, NULL);
				purple_debug_info("facebook", "done\n");
			}
		}
	}
	
	g_strfreev(splits);
}
示例#9
0
PurpleChat* flist_get_chat(FListAccount *fla, const gchar *name) {
    PurpleChat *b = purple_blist_find_chat(fla->pa, name);
    if(!b) {
        GHashTable *components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
        g_hash_table_insert(components, g_strdup("channel"), g_strdup(name));
        b = purple_chat_new(fla->pa, name, components);
        purple_blist_add_chat(b, flist_get_chat_group(fla), NULL);
    }
    return b;
}
示例#10
0
文件: gtklog.c 项目: bf4/pidgin-mac
static void log_delete_log_cb(GtkWidget *menuitem, gpointer *data)
{
	PidginLogViewer *lv = data[0];
	PurpleLog *log = data[1];
	const char *time = log_get_date(log);
	const char *name;
	char *tmp;
	gpointer *data2;

	if (log->type == PURPLE_LOG_IM)
	{
		PurpleBuddy *buddy = purple_find_buddy(log->account, log->name);
		if (buddy != NULL)
			name = purple_buddy_get_contact_alias(buddy);
		else
			name = log->name;

		tmp = g_strdup_printf(_("Are you sure you want to permanently delete the log of the "
		                        "conversation with %s which started at %s?"), name, time);
	}
	else if (log->type == PURPLE_LOG_CHAT)
	{
		PurpleChat *chat = purple_blist_find_chat(log->account, log->name);
		if (chat != NULL)
			name = purple_chat_get_name(chat);
		else
			name = log->name;

		tmp = g_strdup_printf(_("Are you sure you want to permanently delete the log of the "
		                        "conversation in %s which started at %s?"), name, time);
	}
	else if (log->type == PURPLE_LOG_SYSTEM)
	{
		tmp = g_strdup_printf(_("Are you sure you want to permanently delete the system log "
		                        "which started at %s?"), time);
	}
	else
		g_return_if_reached();

	/* The only way to free data in all cases is to tie it to the menuitem with
	 * g_object_set_data_full().  But, since we need to get some data down to
	 * delete_log_cb() to delete the log from the log viewer after the file is
	 * deleted, we have to allocate a new data array and make sure it gets freed
	 * either way. */
	data2 = g_new(gpointer, 3);
	data2[0] = lv->treestore;
	data2[1] = data[3]; /* iter */
	data2[2] = log;
	purple_request_action(lv, NULL, _("Delete Log?"), tmp, 0,
						NULL, NULL, NULL,
						data2, 2,
						_("Delete"), delete_log_cb,
						_("Cancel"), delete_log_cleanup_cb);
	g_free(tmp);
}
示例#11
0
文件: gtklog.c 项目: bf4/pidgin-mac
void pidgin_log_show(PurpleLogType type, const char *screenname, PurpleAccount *account) {
	struct log_viewer_hash_t *ht;
	PidginLogViewer *lv = NULL;
	const char *name = screenname;
	char *title;
	GdkPixbuf *prpl_icon;

	g_return_if_fail(account != NULL);
	g_return_if_fail(screenname != NULL);

	ht = g_new0(struct log_viewer_hash_t, 1);

	ht->type = type;
	ht->screenname = g_strdup(screenname);
	ht->account = account;

	if (log_viewers == NULL) {
		log_viewers = g_hash_table_new(log_viewer_hash, log_viewer_equal);
	} else if ((lv = g_hash_table_lookup(log_viewers, ht))) {
		gtk_window_present(GTK_WINDOW(lv->window));
		g_free(ht->screenname);
		g_free(ht);
		return;
	}

	if (type == PURPLE_LOG_CHAT) {
		PurpleChat *chat;

		chat = purple_blist_find_chat(account, screenname);
		if (chat != NULL)
			name = purple_chat_get_name(chat);

		title = g_strdup_printf(_("Conversations in %s"), name);
	} else {
		PurpleBuddy *buddy;

		buddy = purple_find_buddy(account, screenname);
		if (buddy != NULL)
			name = purple_buddy_get_contact_alias(buddy);

		title = g_strdup_printf(_("Conversations with %s"), name);
	}

	prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);

	display_log_viewer(ht, purple_log_get_logs(type, screenname, account),
			title, gtk_image_new_from_pixbuf(prpl_icon),
			purple_log_get_total_size(type, screenname, account));

	if (prpl_icon)
		g_object_unref(prpl_icon);
	g_free(title);
}
示例#12
0
static void
translate_conv_extended_menu(PurpleConversation *conv, GList **menu)
{
	PurpleBlistNode *node = NULL;
	
	if (conv->type == PURPLE_CONV_TYPE_IM)
		node = (PurpleBlistNode *) purple_find_buddy(conv->account, conv->name);
	else if (conv->type == PURPLE_CONV_TYPE_CHAT)
		node = (PurpleBlistNode *) purple_blist_find_chat(conv->account, conv->name);
	
	if (node != NULL)
		translate_extended_menu(node, menu, (PurpleCallback)translate_action_conv_cb);
}
示例#13
0
void
translate_sending_chat_msg(PurpleAccount *account, char **message, int chat_id)
{
	const gchar *from_lang = "";
	const gchar *service_to_use = "";
	const gchar *to_lang = "";
	PurpleChat *chat = NULL;
	PurpleConversation *conv;
	struct TranslateConvMessage *convmsg;
	gchar *stripped;

	from_lang = purple_prefs_get_string(LOCALE_PREF);
	service_to_use = purple_prefs_get_string(SERVICE_PREF);
	conv = purple_find_chat(purple_account_get_connection(account), chat_id);
	if (conv)
		chat = purple_blist_find_chat(account, conv->name);
	if (chat)
		to_lang = purple_blist_node_get_string((PurpleBlistNode *)chat, DEST_LANG_SETTING);
	
	if (!chat || !service_to_use || !to_lang || g_str_equal(from_lang, to_lang) || g_str_equal(to_lang, "auto"))
	{
		// Don't translate this message
		return;
	}
	
	stripped = purple_markup_strip_html(*message);
	
	convmsg = g_new0(struct TranslateConvMessage, 1);
	convmsg->account = account;
	convmsg->conv = conv;
	convmsg->flags = PURPLE_MESSAGE_SEND;
	
	if (g_str_equal(service_to_use, "google"))
	{
		google_translate(stripped, from_lang, to_lang, translate_sending_chat_message_cb, convmsg);
	} else if (g_str_equal(service_to_use, "bing"))
	{
		bing_translate(stripped, from_lang, to_lang, translate_sending_chat_message_cb, convmsg);
	}
	
	g_free(stripped);
	
	g_free(*message);
	*message = NULL;
}
示例#14
0
/* refresh group local subscription */
void qq_group_refresh(PurpleConnection *gc, qq_group *group)
{
	PurpleChat *chat;
	gchar *external_group_id;
	g_return_if_fail(group != NULL);

	external_group_id = g_strdup_printf("%d", group->external_group_id);
	chat = purple_blist_find_chat(purple_connection_get_account(gc), external_group_id);
	g_free(external_group_id);
	if (chat == NULL && group->my_status != QQ_GROUP_MEMBER_STATUS_NOT_MEMBER) {
		_qq_group_add_to_blist(gc, group);
	} else if (chat != NULL) {	/* we have a local record, update its info */
		/* if there is group_name_utf8, we update the group name */
		if (group->group_name_utf8 != NULL && strlen(group->group_name_utf8) > 0)
			purple_blist_alias_chat(chat, group->group_name_utf8);
		g_hash_table_replace(chat->components,
				     g_strdup(QQ_GROUP_KEY_MEMBER_STATUS), g_strdup_printf("%d", group->my_status));
		group->my_status_desc = _qq_group_set_my_status_desc(group);
		g_hash_table_replace(chat->components,
				     g_strdup(QQ_GROUP_KEY_MEMBER_STATUS_DESC), g_strdup(group->my_status_desc));
		g_hash_table_replace(chat->components,
				     g_strdup(QQ_GROUP_KEY_INTERNAL_ID),
				     g_strdup_printf("%d", group->internal_group_id));
		g_hash_table_replace(chat->components,
				     g_strdup(QQ_GROUP_KEY_EXTERNAL_ID),
				     g_strdup_printf("%d", group->external_group_id));
		g_hash_table_replace(chat->components,
				     g_strdup(QQ_GROUP_KEY_GROUP_TYPE), g_strdup_printf("%d", group->group_type));
		g_hash_table_replace(chat->components,
				     g_strdup(QQ_GROUP_KEY_CREATOR_UID), g_strdup_printf("%d", group->creator_uid));
		g_hash_table_replace(chat->components,
				     g_strdup(QQ_GROUP_KEY_GROUP_CATEGORY),
				     g_strdup_printf("%d", group->group_category));
		g_hash_table_replace(chat->components,
				     g_strdup(QQ_GROUP_KEY_AUTH_TYPE), g_strdup_printf("%d", group->auth_type));
		g_hash_table_replace(chat->components,
				     g_strdup(QQ_GROUP_KEY_GROUP_NAME_UTF8), g_strdup(group->group_name_utf8));
		g_hash_table_replace(chat->components,
				     g_strdup(QQ_GROUP_KEY_GROUP_DESC_UTF8), g_strdup(group->group_desc_utf8));
	}
}
示例#15
0
static int account_join_chat(LuaState *L)
{
    PurpleAccount **account = ms_lua_checkclass(L, "purple.account", 1);
    const char *name         = luaL_checkstring(L, 2);

    g_return_val_if_fail(purple_account_is_connected(*account), 0);

    PurpleConnection *pc = purple_account_get_connection(*account);
    PurpleConversation *conv = purple_find_conversation_with_account(
            PURPLE_CONV_TYPE_CHAT,
            name,
            *account);

    if (conv) {
        purple_conversation_present(conv);
    }
    else {
        conv = purple_conversation_new(
                PURPLE_CONV_TYPE_CHAT,
                *account,
                name);
        purple_conv_chat_left(PURPLE_CONV_CHAT(conv));
    }

    GHashTable *hash;
    PurpleChat *chat = purple_blist_find_chat(*account, name);
    if (chat == NULL) {
        PurplePluginProtocolInfo *info = PURPLE_PLUGIN_PROTOCOL_INFO(
                purple_connection_get_prpl(pc));
        if (info->chat_info_defaults != NULL)
            hash = info->chat_info_defaults(pc, name);
    } else {
        hash = purple_chat_get_components(chat);
    }

    serv_join_chat(pc, hash);
    if (chat == NULL && hash != NULL)
        g_hash_table_destroy(hash);

    return 0;
}
示例#16
0
static void
translate_action_conv_cb(PurpleConversation *conv, PurpleKeyValuePair *pair)
{
	PurpleBlistNode *node = NULL;
	gchar *message;
	
	if (conv->type == PURPLE_CONV_TYPE_IM)
		node = (PurpleBlistNode *) purple_find_buddy(conv->account, conv->name);
	else if (conv->type == PURPLE_CONV_TYPE_CHAT)
		node = (PurpleBlistNode *) purple_blist_find_chat(conv->account, conv->name);
	
	if (node != NULL)
	{
		translate_action_blist_cb(node, pair);
		
		if (pair != NULL)
		{
			message = g_strdup_printf("Now translating to %s", (const gchar *)pair->value);
			purple_conversation_write(conv, NULL, message, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL));
			g_free(message);
		}
	}
}
示例#17
0
static gboolean
close_conv_cb(GtkButton *button, PidginConversation *gtkconv)
{
	/* We are going to destroy the conversations immediately only if the 'close immediately'
	 * preference is selected. Otherwise, close the conversation after a reasonable timeout
	 * (I am going to consider 10 minutes as a 'reasonable timeout' here.
	 * For chats, close immediately if the chat is not in the buddylist, or if the chat is
	 * not marked 'Persistent' */
	PurpleConversation *conv = gtkconv->active_conv;
	PurpleAccount *account = purple_conversation_get_account(conv);
	const char *name = purple_conversation_get_name(conv);

	switch (purple_conversation_get_type(conv)) {
		case PURPLE_CONV_TYPE_IM:
		{
			if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/close_immediately"))
				close_this_sucker(gtkconv);
			else
				hide_conv(gtkconv, TRUE);
			break;
		}
		case PURPLE_CONV_TYPE_CHAT:
		{
			PurpleChat *chat = purple_blist_find_chat(account, name);
			if (!chat ||
					!purple_blist_node_get_bool(&chat->node, "gtk-persistent"))
				close_this_sucker(gtkconv);
			else
				hide_conv(gtkconv, FALSE);
			break;
		}
		default:
			;
	}

	return TRUE;
}
示例#18
0
xmlnode * _h_elim_add_chat( const char *name , 
                            const char *id   ,
                            SEXP_VALUE *args , 
                            gpointer    data )
{
    ASSERT_ALISTP( args, id, name );

    elim_ping();

    const char *aname   = ALIST_VAL_STR  ( args, "account-name" );
    const char *proto   = ALIST_VAL_STR  ( args, "im-protocol"  );
    const char *alias   = ALIST_VAL_STR  ( args, "chat-alias"   );
    gpointer    auid    = ALIST_VAL_PTR  ( args, "account-uid"  );
    GHashTable *opts    = ALIST_VAL_ALIST( args, "chat-options" );
    GHashTable *options = __ghash_str_sexp__str_str( opts );
    PurpleAccount *acct = 
      auid ? find_acct_by_uid( auid ) : purple_accounts_find( aname, proto );

    if( !acct )
    {
        sexp_val_free( args );
        return response_error( ENXIO, id, name, "unknown account" );
    }

    // cook up a chat node. if it's already on our buddy list, uncook it
    // and use the old one instead (name should be unique per account
    // so the operation is reasonable - we cannot supply a name as this
    // parameter can be delegated to the plugin to generate automatically):
    // this will trigger a new_node call, and possibly a remove call 
    PurpleChat *chat = purple_chat_new( acct, alias, options );
    const char *chn  = purple_chat_get_name( chat );
    PurpleChat *ch_2 = purple_blist_find_chat( acct, chn );
    if( ch_2 )
    {
        fprintf( stderr, "(elim-debug chat already exists)\n" );
        purple_blist_remove_chat( chat );
        chat = ch_2;
        chn  = purple_chat_get_name( chat );
        purple_blist_alias_chat( chat, alias );
    }

    fprintf( stderr, "(elim-debug adding chat to blist)\n" );
    purple_blist_add_chat( chat, NULL, NULL );

    // if we have a conversation already, prod the client to show it
    fprintf( stderr, "(elim-debug looking for conversation)\n" );
    PurpleConversation *conv =
      purple_find_conversation_with_account( PURPLE_CONV_TYPE_CHAT, chn, acct );
    if( conv )
        purple_conversation_present( conv );

    xmlnode *rval = xnode_new( "alist" );

    AL_STR( rval, "account-name", purple_account_get_username   (acct) );
    AL_STR( rval, "im-protocol" , purple_account_get_protocol_id(acct) );
    AL_PTR( rval, "account-uid" , acct );
    AL_STR( rval, "chat-name"   , chn  );

    if( conv )
    {
        PurpleConversationType pct = purple_conversation_get_type    ( conv );
        PurpleConnectionFlags  pcf = purple_conversation_get_features( conv );

        AL_PTR ( rval, "conv-uid"     , conv );
        AL_STR ( rval, "conv-name"    , purple_conversation_get_name (conv) );
        AL_STR ( rval, "conv-title"   , purple_conversation_get_title(conv) );
        AL_ENUM( rval, "conv-type"    , pct, ":conversation-type" );
        AL_ENUM( rval, "conv-features", pcf, ":connection-flags"  );
    }

    sexp_val_free( args );
    return response_value( 0, id, name, rval );
}
示例#19
0
static void parse_new_messages(PurpleConnection *pc, FacebookAccount *fba, JsonArray *messages)
{
	int i;
	PurpleBuddy *buddy;

	purple_debug_info("facebook", "parsing new messages\n");

	for (i = 0; i < json_array_get_length(messages); i++) {
		const gchar *type;
		gchar *from, *to;
		

		JsonObject *object = json_node_get_object(json_array_get_element(messages, i));
		type = json_node_get_string(json_object_get_member(object, "type"));

		from = g_strdup_printf("%" G_GINT64_FORMAT, (gint64)json_node_get_int(json_object_get_member(object, "from")));
		to = g_strdup_printf("%" G_GINT64_FORMAT, (gint64)json_node_get_int(json_object_get_member(object, "to")));
		
		/* Use the in-line buddy name if the buddy list hasn't been downloaded yet */
		buddy = purple_find_buddy(pc->account, from);
		if (buddy == NULL || buddy->server_alias == NULL || buddy->alias == NULL)
		{
			if (json_object_has_member(object, "from_name"))
			{
				const gchar *from_name = json_node_get_string(json_object_get_member(
					object, "from_name"));
				fb_blist_set_alias(fba, from, from_name);
			}
		}

		if (from && to && g_str_equal(type, "msg")) {
			JsonObject *messageObj = json_node_get_object(json_object_get_member(object, "msg"));
			parse_message(pc, fba, messageObj, from, to, PURPLE_CONV_TYPE_IM);
		} else if (from && g_str_equal(type, "typ")) {
			purple_debug_info("facebook", "handling typing notification\n");

			gint typing = json_node_get_int(json_object_get_member(object, "st"));
			if (typing == 0) {
				serv_got_typing(pc, from, 10, PURPLE_NOT_TYPING);
			} else {
				serv_got_typing(pc, from, 10, PURPLE_TYPING);
			}
		} else if (g_str_equal(type, "group_msg")) {
			PurpleConversation *conv = fb_find_chat(fba, to);
			
			if (conv != NULL)
			{			
				if (json_object_has_member(object, "to_name"))
				{
					const gchar *to_name = json_node_get_string(json_object_get_member(
						object, "to_name"));
					purple_conversation_set_title(conv, to_name);

					PurpleChat *chat = purple_blist_find_chat(fba->account, to);
					purple_blist_alias_chat(chat, to_name);
				}
				if (!purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), from))
				{
					purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv), from, NULL, PURPLE_CBFLAGS_NONE, FALSE);
				}
				if (!purple_find_buddy(fba->account, from))
				{
					const char *from_name = json_node_get_string(json_object_get_member(
						object, "from_name"));
					buddy = purple_buddy_new(fba->account, from, from_name);
					purple_blist_node_set_flags((PurpleBlistNode *)buddy, PURPLE_BLIST_NODE_FLAG_NO_SAVE);
					purple_blist_add_buddy(buddy, NULL, purple_find_group(DEFAULT_GROUP_NAME), NULL);
				}
			}

			JsonObject *messageObj = json_node_get_object(json_object_get_member(object, "msg"));
			parse_message(pc, fba, messageObj, from, to, PURPLE_CONV_TYPE_CHAT);
		}

		/*
		 * we've received something from a buddy, assume they're online
		 * only if it's not from ourselves
		 */
		if (from && fba->uid != atoll(from)) {
			purple_prpl_got_user_status(
				fba->account, from, 
				purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);

		}
	
		g_free(from);
		g_free(to);

		fba->message_fetch_sequence++;
	}
}