summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordefanor <defanor@uberspace.net>2020-07-04 11:48:43 +0300
committerdefanor <defanor@uberspace.net>2020-07-04 11:48:43 +0300
commitc09bb4e4434667debc0e28d25b5a358ef4ffb498 (patch)
tree03fd85ad0986b68288417e7e0a94c4b9193e4238
parentf9c2810adb8e19a228535ea7c8b131a5e8b6928e (diff)
Fill weechat nicklists
The server buffer's nicklist is filled with roster items, and MUC buffers' nicklists are filled with active MUC participants. No MUC role indications, groups, or contact presence tracking yet.
-rw-r--r--examples/weechat.c58
-rw-r--r--src/rexmpp.c1
-rw-r--r--src/rexmpp.h2
-rw-r--r--src/rexmpp_roster.c12
4 files changed, 73 insertions, 0 deletions
diff --git a/examples/weechat.c b/examples/weechat.c
index d247eb3..0c26f6e 100644
--- a/examples/weechat.c
+++ b/examples/weechat.c
@@ -140,6 +140,7 @@ int my_xml_in_cb (struct weechat_rexmpp *wr, xmlNodePtr node) {
buf = weechat_buffer_new (from,
&query_input_cb, wr, NULL,
&query_close_cb, wr, NULL);
+ weechat_buffer_set(buf, "nicklist", "1");
}
if (resource_removed) {
from[i] = '/'; /* restore */
@@ -157,6 +158,39 @@ int my_xml_in_cb (struct weechat_rexmpp *wr, xmlNodePtr node) {
xmlFree(from);
}
}
+ if (rexmpp_xml_match(node, "jabber:client", "presence")) {
+ char *presence_type = xmlGetProp(node, "type");
+ char *jid = xmlGetProp(node, "from");
+ int i;
+ char *resource = "";
+ for (i = 0; i < strlen(jid); i++) {
+ if (jid[i] == '/') {
+ jid[i] = 0;
+ resource = jid + i + 1;
+ break;
+ }
+ }
+ if (rexmpp_xml_find_child(node, "http://jabber.org/protocol/muc#user", "x")) {
+ /* Update MUC nicklist */
+ struct t_gui_buffer *buf = weechat_buffer_search("rexmpp", jid);
+ if (buf != NULL) {
+ if (presence_type != NULL && strcmp(presence_type, "unavailable") == 0) {
+ struct t_gui_nick *nick =
+ weechat_nicklist_search_nick(buf, NULL, resource);
+ if (nick != NULL) {
+ weechat_nicklist_remove_nick(buf, nick);
+ }
+ } else {
+ weechat_nicklist_add_nick(buf, NULL, resource,
+ "bar_fg", "", "lightgreen", 1);
+ }
+ }
+ }
+ free(jid);
+ if (presence_type != NULL) {
+ free(presence_type);
+ }
+ }
free(xml_buf);
return 0;
}
@@ -194,6 +228,7 @@ my_input_cb (const struct weechat_rexmpp *wr, void *data,
buf = weechat_buffer_new (jid,
&query_input_cb, wr, NULL,
&query_close_cb, wr, NULL);
+ weechat_buffer_set(buf, "nicklist", "1");
}
} else if (input_data[0] == 'j' && input_data[1] == ' ') {
char *jid = input_data + 2;
@@ -219,14 +254,35 @@ my_input_cb (const struct weechat_rexmpp *wr, void *data,
buf = weechat_buffer_new (jid,
&muc_input_cb, wrm, NULL,
&muc_close_cb, wrm, NULL);
+ weechat_buffer_set(buf, "nicklist", "1");
}
}
return WEECHAT_RC_OK;
}
+void my_roster_modify_cb (struct weechat_rexmpp *wr, xmlNodePtr item) {
+ char *subscription = xmlGetProp(item, "subscription");
+ char *jid = xmlGetProp(item, "jid");
+ if (subscription != NULL && strcmp(subscription, "remove") == 0) {
+ /* delete */
+ weechat_nicklist_remove_nick(wr->server_buffer, jid);
+ } else {
+ /* add or modify */
+ weechat_nicklist_add_nick(wr->server_buffer, NULL, jid,
+ "bar_fg", "", "lightgreen", 1);
+ }
+ free(jid);
+ if (subscription != NULL) {
+ free(subscription);
+ }
+}
+
int
my_close_cb (struct weechat_rexmpp *wr, void *data, struct t_gui_buffer *buffer)
{
+ /* todo: close MUC buffers first? or at least mark them somehow, so
+ that they won't attempt to send "unavailable" presence on
+ closing. */
wr->server_buffer = NULL;
rexmpp_stop(&wr->rexmpp_state);
return WEECHAT_RC_OK;
@@ -331,6 +387,7 @@ command_xmpp_cb (const void *pointer, void *data,
wr->server_buffer = weechat_buffer_new (argv[1],
&my_input_cb, wr, NULL,
&my_close_cb, wr, NULL);
+ weechat_buffer_set(wr->server_buffer, "nicklist", "1");
wr->password = strdup(argv[2]);
wr->hooks = weechat_arraylist_new(42, 0, 0, NULL, NULL, hook_free_cb, NULL);
rexmpp_t *s = &wr->rexmpp_state;
@@ -339,6 +396,7 @@ command_xmpp_cb (const void *pointer, void *data,
s->sasl_property_cb = my_sasl_property_cb;
s->xml_in_cb = my_xml_in_cb;
s->xml_out_cb = my_xml_out_cb;
+ s->roster_modify_cb = my_roster_modify_cb;
fd_set read_fds, write_fds;
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
diff --git a/src/rexmpp.c b/src/rexmpp.c
index 02dcf5b..c4c1e1c 100644
--- a/src/rexmpp.c
+++ b/src/rexmpp.c
@@ -268,6 +268,7 @@ rexmpp_err_t rexmpp_init (rexmpp_t *s, const char *jid)
s->sasl_property_cb = NULL;
s->xml_in_cb = NULL;
s->xml_out_cb = NULL;
+ s->roster_modify_cb = NULL;
s->ping_delay = 600;
s->ping_requested = 0;
s->last_network_activity = 0;
diff --git a/src/rexmpp.h b/src/rexmpp.h
index 9f748cf..6157f86 100644
--- a/src/rexmpp.h
+++ b/src/rexmpp.h
@@ -202,6 +202,7 @@ typedef void (*log_function_t) (rexmpp_t *s, int priority, const char *format, v
typedef int (*sasl_property_cb_t) (rexmpp_t *s, Gsasl_property prop);
typedef int (*xml_in_cb_t) (rexmpp_t *s, xmlNodePtr node);
typedef int (*xml_out_cb_t) (rexmpp_t *s, xmlNodePtr node);
+typedef void (*roster_modify_cb_t) (rexmpp_t *s, xmlNodePtr item);
/** @brief Complete connection state */
struct rexmpp
@@ -248,6 +249,7 @@ struct rexmpp
sasl_property_cb_t sasl_property_cb;
xml_in_cb_t xml_in_cb;
xml_out_cb_t xml_out_cb;
+ roster_modify_cb_t roster_modify_cb;
/* Stream-related state. */
char *assigned_jid;
diff --git a/src/rexmpp_roster.c b/src/rexmpp_roster.c
index 8479c14..3d62613 100644
--- a/src/rexmpp_roster.c
+++ b/src/rexmpp_roster.c
@@ -81,6 +81,9 @@ rexmpp_err_t rexmpp_modify_roster (rexmpp_t *s, xmlNodePtr item) {
if (subscription != NULL) {
free(subscription);
}
+ if (s->roster_modify_cb != NULL) {
+ s->roster_modify_cb(s, item);
+ }
return ret;
}
@@ -93,6 +96,15 @@ void rexmpp_roster_set (rexmpp_t *s, xmlNodePtr query) {
}
s->roster_ver = xmlGetProp(query, "ver");
s->roster_items = xmlCopyNodeList(xmlFirstElementChild(query));
+ if (s->roster_modify_cb != NULL) {
+ xmlNodePtr item;
+ for (item = xmlFirstElementChild(query);
+ item != NULL;
+ item = xmlNextElementSibling(item))
+ {
+ s->roster_modify_cb(s, item);
+ }
+ }
}
void rexmpp_roster_cache_read (rexmpp_t *s) {