diff options
author | dequis <dx@dxzone.com.ar> | 2015-09-13 01:45:43 -0300 |
---|---|---|
committer | dequis <dx@dxzone.com.ar> | 2015-10-30 07:28:32 -0300 |
commit | fb2338df133ff82ce06dbeae4737a50f26861fdb (patch) | |
tree | 80b05983f315603ab0a3233ffca350a7959e936e | |
parent | 345577bc90da1d1fffa0df013426eab54fa2b1b2 (diff) |
jabber: Self message handling (echo removal) in MUCs
XMPP MUCs always echo own messages, and send messages from other
clients. So, we must display everything except the messages we just
sent.
This implementation uses the jabber stanza cache to add an ID to the
message and attach it to a callback which always returns XT_ABORT.
This way, if we do get the echo, the message packet handler can call
jabber_cache_handle_packet(), and if it returns XT_ABORT, it can skip
that particular message.
Every other message that looks like it comes from our own JID and wasn't
handled by the cache will be displayed, with the OPT_SELFMESSAGE flag
Stanza cache entries expire after some time, so it's not a problem if
the server doesn't echo messages for some reason.
I actually wrote this forever ago, for hipchat, but it works the same
way for standard XMPP MUCs.
-rw-r--r-- | protocols/jabber/conference.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index bf0d5e2f..9c32bb01 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -25,6 +25,7 @@ #include "sha1.h" static xt_status jabber_chat_join_failed(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); +static xt_status jabber_chat_self_message(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); struct groupchat *jabber_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password) { @@ -126,6 +127,12 @@ static xt_status jabber_chat_join_failed(struct im_connection *ic, struct xt_nod return XT_HANDLED; } +static xt_status jabber_chat_self_message(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) +{ + /* This is a self message sent by this bitlbee - just drop it */ + return XT_ABORT; +} + struct groupchat *jabber_chat_by_jid(struct im_connection *ic, const char *name) { char *normalized = jabber_normalize(name); @@ -170,13 +177,9 @@ int jabber_chat_msg(struct groupchat *c, char *message, int flags) node = xt_new_node("body", message, NULL); node = jabber_make_packet("message", "groupchat", jc->name, node); - if (!jabber_write_packet(ic, node)) { - xt_free_node(node); - return 0; - } - xt_free_node(node); + jabber_cache_add(ic, node, jabber_chat_self_message); - return 1; + return !jabber_write_packet(ic, node); } int jabber_chat_topic(struct groupchat *c, char *topic) @@ -402,6 +405,7 @@ void jabber_chat_pkt_message(struct im_connection *ic, struct jabber_buddy *bud, char *nick = NULL; char *final_from = NULL; char *bare_jid = NULL; + guint32 flags = 0; from = (bud) ? bud->full_jid : xt_find_attr(node, "from"); @@ -465,20 +469,21 @@ void jabber_chat_pkt_message(struct im_connection *ic, struct jabber_buddy *bud, } else if (chat != NULL && bud == NULL && nick == NULL) { imcb_chat_log(chat, "From conference server: %s", body->text); return; - } else if (jc && jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me) { - /* exclude self-messages since they would get filtered out - * but not the ones in the backlog */ + } else if (jc && jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me && + (jabber_cache_handle_packet(ic, node) == XT_ABORT)) { + /* Self message marked by this bitlbee, don't show it */ return; } - if (bud && jc && bud != jc->me) { + if (bud) { bare_jid = jabber_get_bare_jid(bud->ext_jid ? bud->ext_jid : bud->full_jid); final_from = bare_jid; + flags = (bud == jc->me) ? OPT_SELFMESSAGE : 0; } else { final_from = nick; } - imcb_chat_msg(chat, final_from, body->text, 0, jabber_get_timestamp(node)); + imcb_chat_msg(chat, final_from, body->text, flags, jabber_get_timestamp(node)); g_free(bare_jid); } |