about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/command/command.c60
-rw-r--r--src/contact.c14
-rw-r--r--src/contact.h1
-rw-r--r--src/ui/console.c60
-rw-r--r--src/ui/ui.h1
-rw-r--r--src/xmpp/roster.c81
-rw-r--r--src/xmpp/xmpp.h4
7 files changed, 220 insertions, 1 deletions
diff --git a/src/command/command.c b/src/command/command.c
index fff81351..41413320 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -276,7 +276,7 @@ static struct cmd_t main_commands[] =
           NULL } } },
 
     { "/roster",
-        _cmd_roster, parse_args_with_freetext, 0, 3,
+        _cmd_roster, parse_args_with_freetext, 0, 4,
         { "/roster [add|remove|nick] [jid] [handle]", "Manage your roster.",
         { "/roster [add|remove|nick] [jid] [handle]",
           "----------------------------------------",
@@ -927,6 +927,7 @@ cmd_init(void)
     roster_ac = autocomplete_new();
     autocomplete_add(roster_ac, strdup("add"));
     autocomplete_add(roster_ac, strdup("nick"));
+    autocomplete_add(roster_ac, strdup("group"));
     autocomplete_add(roster_ac, strdup("remove"));
 
     theme_load_ac = NULL;
@@ -2091,6 +2092,63 @@ _cmd_roster(gchar **args, struct cmd_help_t help)
         return TRUE;
     }
 
+    // group command
+    if (strcmp(args[0], "group") == 0) {
+        char *command = args[1];
+        char *group = args[2];
+        char *jid = args[3];
+
+        if (command == NULL) {
+            cons_show("Usage: %s", help.usage);
+            return TRUE;
+        }
+
+        if (strcmp(command, "show") == 0) {
+            if (group == NULL) {
+                cons_show("Usage: %s", help.usage);
+                return TRUE;
+            }
+
+            GSList *list = roster_get_group(group);
+            cons_show_roster_group(group, list);
+            return TRUE;
+        }
+
+        if (strcmp(command, "add") == 0) {
+            if ((group == NULL) || (jid == NULL)) {
+                cons_show("Usage: %s", help.usage);
+                return TRUE;
+            }
+
+            PContact contact = roster_get_contact(jid);
+            if (contact == NULL) {
+                cons_show("Contact not found in roster: %s", jid);
+                return TRUE;
+            }
+
+            roster_add_to_group(group, jid);
+
+            return TRUE;
+        }
+
+        if (strcmp(command, "remove") == 0) {
+            if ((group == NULL) || (jid == NULL)) {
+                cons_show("Usage: %s", help.usage);
+                return TRUE;
+            }
+
+            PContact contact = roster_get_contact(jid);
+            if (contact == NULL) {
+                cons_show("Contact not found in roster: %s", jid);
+                return TRUE;
+            }
+
+            roster_remove_from_group(group, jid);
+
+            return TRUE;
+        }
+    }
+
     cons_show("Usage: %s", help.usage);
     return TRUE;
 }
diff --git a/src/contact.c b/src/contact.c
index 009478a0..bab3d89c 100644
--- a/src/contact.c
+++ b/src/contact.c
@@ -101,6 +101,20 @@ p_contact_set_groups(const PContact contact, GSList *groups)
     contact->groups = groups;
 }
 
+gboolean
+p_contact_in_group(const PContact contact, const char * const group)
+{
+    GSList *groups = contact->groups;
+    while (groups != NULL) {
+        if (strcmp(groups->data, group) == 0) {
+            return TRUE;
+        }
+        groups = g_slist_next(groups);
+    }
+
+    return FALSE;
+}
+
 GSList *
 p_contact_groups(const PContact contact)
 {
diff --git a/src/contact.h b/src/contact.h
index 3aa8e6a3..cfd8b4d4 100644
--- a/src/contact.h
+++ b/src/contact.h
@@ -52,5 +52,6 @@ gboolean p_contact_has_available_resource(const PContact contact);
 Resource * p_contact_get_resource(const PContact contact, const char * const resource);
 void p_contact_set_groups(const PContact contact, GSList *groups);
 GSList * p_contact_groups(const PContact contact);
+gboolean p_contact_in_group(const PContact contact, const char * const group);
 
 #endif
diff --git a/src/ui/console.c b/src/ui/console.c
index 95c7d9b0..992ac9b5 100644
--- a/src/ui/console.c
+++ b/src/ui/console.c
@@ -1240,6 +1240,49 @@ cons_navigation_help(void)
 }
 
 void
+cons_show_roster_group(const char * const group, GSList *list)
+{
+    GSList *curr = list;
+    cons_show("");
+
+    if (curr != NULL) {
+        cons_show("%s:", group);
+    } else {
+        cons_show("No group named %s exists.", group);
+    }
+
+    while(curr) {
+
+        PContact contact = curr->data;
+        GString *title = g_string_new("  ");
+        title = g_string_append(title, p_contact_barejid(contact));
+        if (p_contact_name(contact) != NULL) {
+            title = g_string_append(title, " (");
+            title = g_string_append(title, strdup(p_contact_name(contact)));
+            title = g_string_append(title, ")");
+        }
+        cons_show(title->str);
+        g_string_free(title, TRUE);
+
+        GString *sub = g_string_new("    Subscription : ");
+        sub = g_string_append(sub, p_contact_subscription(contact));
+        if (p_contact_pending_out(contact)) {
+            sub = g_string_append(sub, ", request sent");
+        }
+        if (presence_sub_request_exists(p_contact_barejid(contact))) {
+            sub = g_string_append(sub, ", request received");
+        }
+        cons_show(sub->str);
+        g_string_free(sub, TRUE);
+
+        curr = g_slist_next(curr);
+    }
+
+    ui_console_dirty();
+    cons_alert();
+}
+
+void
 cons_show_roster(GSList *list)
 {
     GSList *curr = list;
@@ -1247,6 +1290,7 @@ cons_show_roster(GSList *list)
     cons_show("Roster:");
 
     while(curr) {
+
         PContact contact = curr->data;
         GString *title = g_string_new("  ");
         title = g_string_append(title, p_contact_barejid(contact));
@@ -1268,6 +1312,22 @@ cons_show_roster(GSList *list)
         }
         cons_show(sub->str);
         g_string_free(sub, TRUE);
+
+        GSList *groups = p_contact_groups(contact);
+        if (groups != NULL) {
+            GString *groups_str = g_string_new("    Groups : ");
+            while (groups != NULL) {
+                g_string_append(groups_str, strdup(groups->data));
+                if (g_slist_next(groups) != NULL) {
+                    g_string_append(groups_str, ", ");
+                }
+                groups = g_slist_next(groups);
+            }
+
+            cons_show(groups_str->str);
+            g_string_free(groups_str, TRUE);
+        }
+
         curr = g_slist_next(curr);
     }
 
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 6eb0d814..a41a8cff 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -168,6 +168,7 @@ void cons_show_error(const char * const cmd, ...);
 void cons_highlight_show(const char * const cmd);
 void cons_show_contacts(GSList * list);
 void cons_show_roster(GSList * list);
+void cons_show_roster_group(const char * const group, GSList * list);
 void cons_show_wins(void);
 void cons_show_status(const char * const barejid);
 void cons_show_info(PContact pcontact);
diff --git a/src/xmpp/roster.c b/src/xmpp/roster.c
index 234bfad2..2126efd8 100644
--- a/src/xmpp/roster.c
+++ b/src/xmpp/roster.c
@@ -286,6 +286,63 @@ roster_change_name(const char * const barejid, const char * const new_name)
     }
 }
 
+void
+roster_add_to_group(const char * const group, const char * const barejid)
+{
+    PContact contact = g_hash_table_lookup(contacts, barejid);
+
+    if (contact != NULL) {
+        if (p_contact_in_group(contact, group)) {
+            return;
+        }
+
+        GSList *groups = p_contact_groups(contact);
+        GSList *new_groups = NULL;
+        while (groups != NULL) {
+            new_groups = g_slist_append(new_groups, strdup(groups->data));
+            groups = g_slist_next(groups);
+        }
+
+        new_groups = g_slist_append(new_groups, strdup(group));
+
+        xmpp_conn_t * const conn = connection_get_conn();
+        xmpp_ctx_t * const ctx = connection_get_ctx();
+        xmpp_stanza_t *iq = stanza_create_roster_set(ctx, barejid,
+            p_contact_name(contact), new_groups);
+        xmpp_send(conn, iq);
+        xmpp_stanza_release(iq);
+    }
+}
+
+void
+roster_remove_from_group(const char * const group, const char * const barejid)
+{
+    PContact contact = g_hash_table_lookup(contacts, barejid);
+
+    if (contact != NULL) {
+        if (!p_contact_in_group(contact, group)) {
+            return;
+        }
+
+        GSList *groups = p_contact_groups(contact);
+        GSList *new_groups = NULL;
+        while (groups != NULL) {
+            if (strcmp(groups->data, group) != 0) {
+                new_groups = g_slist_append(new_groups, strdup(groups->data));
+            }
+            groups = g_slist_next(groups);
+        }
+
+        xmpp_conn_t * const conn = connection_get_conn();
+        xmpp_ctx_t * const ctx = connection_get_ctx();
+        xmpp_stanza_t *iq = stanza_create_roster_set(ctx, barejid,
+            p_contact_name(contact), new_groups);
+        xmpp_send(conn, iq);
+        xmpp_stanza_release(iq);
+    }
+
+}
+
 gboolean
 roster_has_pending_subscriptions(void)
 {
@@ -321,6 +378,30 @@ roster_get_contacts(void)
     return result;
 }
 
+GSList *
+roster_get_group(const char * const group)
+{
+    GSList *result = NULL;
+    GHashTableIter iter;
+    gpointer key;
+    gpointer value;
+
+    g_hash_table_iter_init(&iter, contacts);
+    while (g_hash_table_iter_next(&iter, &key, &value)) {
+        GSList *groups = p_contact_groups(value);
+        while (groups != NULL) {
+            if (strcmp(groups->data, group) == 0) {
+                result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts);
+                break;
+            }
+            groups = g_slist_next(groups);
+        }
+    }
+
+    // resturn all contact structs
+    return result;
+}
+
 char *
 roster_find_contact(char *search_str)
 {
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index 345fa8f1..7d077237 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -146,5 +146,9 @@ void roster_change_name(const char * const barejid, const char * const new_name)
 char * roster_barejid_from_name(const char * const name);
 void roster_add_new(const char * const barejid, const char * const name);
 void roster_remove(const char * const barejid);
+GSList * roster_get_group(const char * const group);
+void roster_add_to_group(const char * const group, const char * const barejid);
+void roster_remove_from_group(const char * const group,
+    const char * const barejid);
 
 #endif