aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjgeboski <jgeboski@gmail.com>2016-06-22 14:54:52 -0400
committerMarius Halden <marius.h@lden.org>2016-06-29 22:22:38 +0200
commitc64689e78f2a8c733608edba11c08e2e16be3091 (patch)
treed7756796a4765606da4d9bc3195146f2d91733f2
parentb26fb4788bdfdb1c1765b54f03b1b09538c4b135 (diff)
Added an interface for the listing of existing chatrooms
Several protocols can provide a list of existing chatrooms that a user is able join. This is crucial for the usage of several protocols, most notably Purple and Facebook. Plugins wishing to support this extended functionality must implement the new prpl->chat_list() function. This implemented function will in most cases send a remote request for the list of chatrooms. Once the list of chatrooms is obtained, a bee_chat_info_t GSList must be created and assigned to the im_connection->chatlist field. Then a call to the bee_chat_list_finish() is needed to display the list to the user. The chat list is maintained entirely by the plugin, so it is important to ensure all pointers related to the chat list remain valid until the chat list is set to NULL. This list is used internally by bitlbee to calculate indexes, which then allows the user to join a chat with an index, rather than some random identifier. It also important to ensure the list is properly freed whenever it is updated, or when the account is disconnect via the prpl->logout() function. On the user interface side of things, the 'chat list' subcommand was recommissioned. For a user to list the existing chat rooms: chat list <account id> Afterwards a user can join a chatroom in the list with its index. This extends the functionality of the 'chat add' subcommand by adding in support for the exclamation point operator to denote an index. chat add <account id> !<index> [channel]
-rw-r--r--bitlbee.h1
-rw-r--r--doc/user-guide/commands.xml12
-rw-r--r--protocols/bee.h10
-rw-r--r--protocols/bee_chat.c5
-rw-r--r--protocols/nogaim.h8
-rw-r--r--root_commands.c80
6 files changed, 110 insertions, 6 deletions
diff --git a/bitlbee.h b/bitlbee.h
index cbc44af1..cad06f1e 100644
--- a/bitlbee.h
+++ b/bitlbee.h
@@ -174,6 +174,7 @@ void root_command_string(irc_t *irc, char *command);
void root_command(irc_t *irc, char *command[]);
gboolean root_command_add(const char *command, int params, void (*func)(irc_t *, char **args), int flags);
gboolean cmd_identify_finish(gpointer data, gint fd, b_input_condition cond);
+void cmd_chat_list_finish(struct im_connection *ic);
gboolean bitlbee_shutdown(gpointer data, gint fd, b_input_condition cond);
char *set_eval_root_nick(set_t *set, char *new_nick);
diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml
index 56beba54..53979b13 100644
--- a/doc/user-guide/commands.xml
+++ b/doc/user-guide/commands.xml
@@ -263,7 +263,7 @@
</description>
<bitlbee-command name="add">
- <syntax>chat add &lt;account id&gt; &lt;room&gt; [&lt;channel&gt;]</syntax>
+ <syntax>chat add &lt;account id&gt; &lt;room|!index&gt; [&lt;channel&gt;]</syntax>
<description>
<para>
@@ -281,6 +281,16 @@
</bitlbee-command>
+ <bitlbee-command name="list">
+ <syntax>chat list &lt;account id&gt; [&lt;server&gt;]</syntax>
+
+ <description>
+ <para>
+ List existing chatrooms provided by an account. BitlBee needs this to propogate an internal list of chats. The existing chat can then be added with <emphasis>chat add</emphasis>.
+ </para>
+ </description>
+ </bitlbee-command>
+
<bitlbee-command name="with">
<syntax>chat with &lt;nickname&gt;</syntax>
diff --git a/protocols/bee.h b/protocols/bee.h
index d22e4d85..8e665ac8 100644
--- a/protocols/bee.h
+++ b/protocols/bee.h
@@ -83,6 +83,14 @@ typedef struct bee_user {
void *data; /* Can be used by the IM module. */
} bee_user_t;
+typedef struct bee_chat_info {
+ char *title;
+ char *topic;
+
+ /* If less than zero, the user count is ignored when displaying */
+ int userc;
+} bee_chat_info_t;
+
/* This one's mostly used so save space and make it easier (cheaper) to
compare groups of contacts, etc. */
typedef struct bee_group {
@@ -184,4 +192,6 @@ G_MODULE_EXPORT int bee_chat_msg(bee_t *bee, struct groupchat *c, const char *ms
G_MODULE_EXPORT struct groupchat *bee_chat_by_title(bee_t *bee, struct im_connection *ic, const char *title);
G_MODULE_EXPORT void imcb_chat_invite(struct im_connection *ic, const char *name, const char *who, const char *msg);
+G_MODULE_EXPORT void bee_chat_list_finish(struct im_connection *ic);
+
#endif /* __BEE_H__ */
diff --git a/protocols/bee_chat.c b/protocols/bee_chat.c
index 2fcb0396..76ed7f85 100644
--- a/protocols/bee_chat.c
+++ b/protocols/bee_chat.c
@@ -273,3 +273,8 @@ void imcb_chat_invite(struct im_connection *ic, const char *name, const char *wh
ic->bee->ui->chat_invite(ic->bee, bu, name, msg);
}
}
+
+void bee_chat_list_finish(struct im_connection *ic)
+{
+ cmd_chat_list_finish(ic);
+}
diff --git a/protocols/nogaim.h b/protocols/nogaim.h
index e5569313..b2ae2cae 100644
--- a/protocols/nogaim.h
+++ b/protocols/nogaim.h
@@ -95,6 +95,7 @@ struct im_connection {
bee_t *bee;
GSList *groupchats;
+ GSList *chatlist;
};
struct groupchat {
@@ -262,6 +263,13 @@ struct prpl {
/* If null, equivalent to handle_cmp( ic->acc->user, who ) */
gboolean (* handle_is_self) (struct im_connection *, const char *who);
+ /* This sets/updates the im_connection->chatlist field with a
+ * bee_chat_info_t GSList. This function should ensure the
+ * bee_chat_list_finish() function gets called at some point
+ * after the chat list is completely updated.
+ */
+ void (*chat_list) (struct im_connection *, const char *server);
+
/* Some placeholders so eventually older plugins may cooperate with newer BitlBees. */
void *resv1;
void *resv2;
diff --git a/root_commands.c b/root_commands.c
index add9bceb..59974026 100644
--- a/root_commands.c
+++ b/root_commands.c
@@ -1234,8 +1234,10 @@ static void cmd_chat(irc_t *irc, char **cmd)
account_t *acc;
if (g_strcasecmp(cmd[1], "add") == 0) {
- char *channel, *s;
+ bee_chat_info_t *ci;
+ char *channel, *room, *s;
struct irc_channel *ic;
+ guint i;
MIN_ARGS(3);
@@ -1247,8 +1249,22 @@ static void cmd_chat(irc_t *irc, char **cmd)
return;
}
+ if (cmd[3][0] == '!') {
+ i = g_ascii_strtoull(cmd[3] + 1, NULL, 10);
+ ci = g_slist_nth_data(acc->ic->chatlist, i - 1);
+
+ if (ci == NULL) {
+ irc_rootmsg(irc, "Invalid chatroom index");
+ return;
+ }
+
+ room = ci->title;
+ } else {
+ room = cmd[3];
+ }
+
if (cmd[4] == NULL) {
- channel = g_strdup(cmd[3]);
+ channel = g_strdup(room);
if ((s = strchr(channel, '@'))) {
*s = 0;
}
@@ -1268,7 +1284,7 @@ static void cmd_chat(irc_t *irc, char **cmd)
set_setstr(&ic->set, "type", "chat") &&
set_setstr(&ic->set, "chat_type", "room") &&
set_setstr(&ic->set, "account", cmd[2]) &&
- set_setstr(&ic->set, "room", cmd[3])) {
+ set_setstr(&ic->set, "room", room)) {
irc_rootmsg(irc, "Chatroom successfully added.");
} else {
if (ic) {
@@ -1278,6 +1294,18 @@ static void cmd_chat(irc_t *irc, char **cmd)
irc_rootmsg(irc, "Could not add chatroom.");
}
g_free(channel);
+ } else if (g_strcasecmp(cmd[1], "list") == 0) {
+ MIN_ARGS(2);
+
+ if (!(acc = account_get(irc->b, cmd[2]))) {
+ irc_rootmsg(irc, "Invalid account");
+ return;
+ } else if (!acc->prpl->chat_list) {
+ irc_rootmsg(irc, "Existing chatrooms not supported on that account.");
+ return;
+ }
+
+ acc->prpl->chat_list(acc->ic, cmd[3]);
} else if (g_strcasecmp(cmd[1], "with") == 0) {
irc_user_t *iu;
@@ -1292,8 +1320,7 @@ static void cmd_chat(irc_t *irc, char **cmd)
} else {
irc_rootmsg(irc, "Can't open a groupchat with %s.", cmd[2]);
}
- } else if (g_strcasecmp(cmd[1], "list") == 0 ||
- g_strcasecmp(cmd[1], "set") == 0 ||
+ } else if (g_strcasecmp(cmd[1], "set") == 0 ||
g_strcasecmp(cmd[1], "del") == 0) {
irc_rootmsg(irc,
"Warning: The \002chat\002 command was mostly replaced with the \002channel\002 command.");
@@ -1305,6 +1332,49 @@ static void cmd_chat(irc_t *irc, char **cmd)
}
}
+void cmd_chat_list_finish(struct im_connection *ic)
+{
+ account_t *acc = ic->acc;
+ bee_chat_info_t *ci;
+ char *hformat, *iformat, *topic;
+ GSList *l;
+ GString *userc;
+ guint i = 0;
+ irc_t *irc = ic->bee->ui_data;
+
+ if (ic->chatlist == NULL) {
+ irc_rootmsg(irc, "No existing chatrooms");
+ return;
+ }
+
+ if (strchr(irc->umode, 'b') != NULL) {
+ hformat = "%s\t%s\t%s\t%s";
+ iformat = "%u\t%s\t%s\t%s";
+ } else {
+ hformat = "%s %-20s %s %s";
+ iformat = "%5u %-20.20s %5s %s";
+ }
+
+ irc_rootmsg(irc, hformat, "Index", "Title", "Users", "Topic");
+ userc = g_string_new(NULL);
+
+ for (l = ic->chatlist; l; l = l->next) {
+ ci = l->data;
+ topic = ci->topic ? ci->topic : "";
+
+ if (ci->userc >= 0) {
+ g_string_printf(userc, "%d", ci->userc);
+ } else {
+ g_string_assign(userc, "-");
+ }
+
+ irc_rootmsg(irc, iformat, ++i, ci->title, userc->str, topic);
+ }
+
+ irc_rootmsg(irc, "%u %s chatrooms", i, acc->tag);
+ g_string_free(userc, TRUE);
+}
+
static void cmd_group(irc_t *irc, char **cmd)
{
GSList *l;