# HG changeset patch # User Paul Aurich # Date 1241380433 0 # Node ID af2b87aa82ee41dc15cb5ea8a0d0bc4d564598fd # Parent ea2306f2f886fda4933613c7d69b24260cebcf90 Add ability to list roles/affiliations in a chat via slash-commands and modify roles/affiliations of multiple users at a time. Closes #5649. Slightly modified patch from Andrei Mozzhuhin. The multiple-user support is inefficient; all the changes can go in one stanza. We should also actually track roles/affiliations of members since ejabberd's MUC won't respond to the list query for a non-admin. diff -r ea2306f2f886 -r af2b87aa82ee ChangeLog --- a/ChangeLog Sun May 03 19:36:36 2009 +0000 +++ b/ChangeLog Sun May 03 19:53:53 2009 +0000 @@ -31,6 +31,8 @@ * Support most recent version of User Avatar. (XEP-0084 v1.1) * Updated Entity Capabilities support. (Tobias Markmann) * Better support for receiving remote users' nicknames. + * /affiliate and /role will now list the room members with the specified + affiliation/role if possible. (Andrei Mozzhuhin) Yahoo: * P2P file transfers. (Sulabh Mahajan) diff -r ea2306f2f886 -r af2b87aa82ee libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Sun May 03 19:36:36 2009 +0000 +++ b/libpurple/protocols/jabber/chat.c Sun May 03 19:53:53 2009 +0000 @@ -916,6 +916,68 @@ return TRUE; } +static void +jabber_chat_affiliation_list_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ + JabberChat *chat; + xmlnode *query, *item; + int chat_id = GPOINTER_TO_INT(data); + GString *buf; + + if(!(chat = jabber_chat_find_by_id(js, chat_id))) + return; + + if (type == JABBER_IQ_ERROR) + return; + + if(!(query = xmlnode_get_child(packet, "query"))) + return; + + buf = g_string_new(_("Affiliations:")); + + item = xmlnode_get_child(query, "item"); + if (item) { + for( ; item; item = xmlnode_get_next_twin(item)) { + const char *jid = xmlnode_get_attrib(item, "jid"); + const char *affiliation = xmlnode_get_attrib(item, "affiliation"); + if (jid && affiliation) + g_string_append_printf(buf, "\n%s %s", jid, affiliation); + } + } else { + buf = g_string_append_c(buf, '\n'); + buf = g_string_append_len(buf, _("No users found"), -1); + } + + purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), "", buf->str, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL)); + + g_string_free(buf, TRUE); +} + +gboolean jabber_chat_affiliation_list(JabberChat *chat, const char *affiliation) +{ + JabberIq *iq; + char *room_jid; + xmlnode *query, *item; + + iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET, + "http://jabber.org/protocol/muc#admin"); + + room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); + xmlnode_set_attrib(iq->node, "to", room_jid); + + query = xmlnode_get_child(iq->node, "query"); + item = xmlnode_new_child(query, "item"); + xmlnode_set_attrib(item, "affiliation", affiliation); + + jabber_iq_set_callback(iq, jabber_chat_affiliation_list_cb, GINT_TO_POINTER(chat->id)); + jabber_iq_send(iq); + + return TRUE; +} + gboolean jabber_chat_role_user(JabberChat *chat, const char *who, const char *role) { char *to; @@ -945,6 +1007,67 @@ return TRUE; } +static void jabber_chat_role_list_cb(JabberStream *js, const char *from, + JabberIqType type, const char *id, + xmlnode *packet, gpointer data) +{ + JabberChat *chat; + xmlnode *query, *item; + int chat_id = GPOINTER_TO_INT(data); + GString *buf; + + if(!(chat = jabber_chat_find_by_id(js, chat_id))) + return; + + if (type == JABBER_IQ_ERROR) + return; + + if(!(query = xmlnode_get_child(packet, "query"))) + return; + + buf = g_string_new(_("Roles:")); + + item = xmlnode_get_child(query, "item"); + if (item) { + for( ; item; item = xmlnode_get_next_twin(item)) { + const char *jid = xmlnode_get_attrib(item, "jid"); + const char *role = xmlnode_get_attrib(item, "role"); + if (jid && role) + g_string_append_printf(buf, "\n%s %s", jid, role); + } + } else { + buf = g_string_append_c(buf, '\n'); + buf = g_string_append_len(buf, _("No users found"), -1); + } + + purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), "", buf->str, + PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL)); + + g_string_free(buf, TRUE); +} + +gboolean jabber_chat_role_list(JabberChat *chat, const char *role) +{ + JabberIq *iq; + char *room_jid; + xmlnode *query, *item; + + iq = jabber_iq_new_query(chat->js, JABBER_IQ_GET, + "http://jabber.org/protocol/muc#admin"); + + room_jid = g_strdup_printf("%s@%s", chat->room, chat->server); + xmlnode_set_attrib(iq->node, "to", room_jid); + + query = xmlnode_get_child(iq->node, "query"); + item = xmlnode_new_child(query, "item"); + xmlnode_set_attrib(item, "role", role); + + jabber_iq_set_callback(iq, jabber_chat_role_list_cb, GINT_TO_POINTER(chat->id)); + jabber_iq_send(iq); + + return TRUE; +} + gboolean jabber_chat_kick_user(JabberChat *chat, const char *who, const char *why) { JabberIq *iq; diff -r ea2306f2f886 -r af2b87aa82ee libpurple/protocols/jabber/chat.h --- a/libpurple/protocols/jabber/chat.h Sun May 03 19:36:36 2009 +0000 +++ b/libpurple/protocols/jabber/chat.h Sun May 03 19:53:53 2009 +0000 @@ -81,8 +81,10 @@ const char *why); gboolean jabber_chat_affiliate_user(JabberChat *chat, const char *who, const char *affiliation); +gboolean jabber_chat_affiliation_list(JabberChat *chat, const char *affiliation); gboolean jabber_chat_role_user(JabberChat *chat, const char *who, const char *role); +gboolean jabber_chat_role_list(JabberChat *chat, const char *role); gboolean jabber_chat_kick_user(JabberChat *chat, const char *who, const char *why); diff -r ea2306f2f886 -r af2b87aa82ee libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Sun May 03 19:36:36 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sun May 03 19:53:53 2009 +0000 @@ -2590,21 +2590,32 @@ { JabberChat *chat = jabber_chat_find_by_conv(conv); - if (!chat || !args || !args[0] || !args[1]) + if (!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; - if (strcmp(args[1], "owner") != 0 && - strcmp(args[1], "admin") != 0 && - strcmp(args[1], "member") != 0 && - strcmp(args[1], "outcast") != 0 && - strcmp(args[1], "none") != 0) { - *error = g_strdup_printf(_("Unknown affiliation: \"%s\""), args[1]); + if (strcmp(args[0], "owner") != 0 && + strcmp(args[0], "admin") != 0 && + strcmp(args[0], "member") != 0 && + strcmp(args[0], "outcast") != 0 && + strcmp(args[0], "none") != 0) { + *error = g_strdup_printf(_("Unknown affiliation: \"%s\""), args[0]); return PURPLE_CMD_RET_FAILED; } - if (!jabber_chat_affiliate_user(chat, args[0], args[1])) { - *error = g_strdup_printf(_("Unable to affiliate user %s as \"%s\""), args[0], args[1]); - return PURPLE_CMD_RET_FAILED; + if (args[1]) { + int i; + char **nicks = g_strsplit(args[1], " ", -1); + + for (i = 0; nicks[i]; ++i) + if (!jabber_chat_affiliate_user(chat, nicks[i], args[0])) { + *error = g_strdup_printf(_("Unable to affiliate user %s as \"%s\""), nicks[i], args[0]); + g_strfreev(nicks); + return PURPLE_CMD_RET_FAILED; + } + + g_strfreev(nicks); + } else { + jabber_chat_affiliation_list(chat, args[0]); } return PURPLE_CMD_RET_OK; @@ -2615,23 +2626,32 @@ { JabberChat *chat = jabber_chat_find_by_conv(conv); - if (!chat || !args || !args[0] || !args[1]) + if (!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; - if (strcmp(args[1], "moderator") != 0 && - strcmp(args[1], "participant") != 0 && - strcmp(args[1], "visitor") != 0 && - strcmp(args[1], "none") != 0) { - *error = g_strdup_printf(_("Unknown role: \"%s\""), args[1]); + if (strcmp(args[0], "moderator") != 0 && + strcmp(args[0], "participant") != 0 && + strcmp(args[0], "visitor") != 0 && + strcmp(args[0], "none") != 0) { + *error = g_strdup_printf(_("Unknown role: \"%s\""), args[0]); return PURPLE_CMD_RET_FAILED; } - if (!jabber_chat_role_user(chat, args[0], args[1])) { - *error = g_strdup_printf(_("Unable to set role \"%s\" for user: %s"), - args[1], args[0]); - return PURPLE_CMD_RET_FAILED; + if (args[1]) { + int i; + char **nicks = g_strsplit(args[1], " ", -1); + + for (i = 0; nicks[i]; i++) + if (!jabber_chat_role_user(chat, nicks[i], args[0])) { + *error = g_strdup_printf(_("Unable to set role \"%s\" for user: %s"), + args[0], nicks[i]); + return PURPLE_CMD_RET_FAILED; + } + + g_strfreev(nicks); + } else { + jabber_chat_role_list(chat, args[0]); } - return PURPLE_CMD_RET_OK; } @@ -3178,13 +3198,13 @@ PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_affiliate, - _("affiliate <user> <owner|admin|member|outcast|none>: Set a user's affiliation with the room."), + _("affiliate <owner|admin|member|outcast|none> [nick1] [nick2] ...: Get the users with an affiliation or set users' affiliation with the room."), NULL); purple_cmd_register("role", "ws", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_role, - _("role <user> <moderator|participant|visitor|none>: Set a user's role in the room."), + _("role <moderator|participant|visitor|none> [nick1] [nick2] ...: Get the users with an role or set users' role with the room."), NULL); purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |