aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordequis <dx@dxzone.com.ar>2015-09-13 01:45:43 -0300
committerdequis <dx@dxzone.com.ar>2015-10-30 07:28:32 -0300
commitfb2338df133ff82ce06dbeae4737a50f26861fdb (patch)
tree80b05983f315603ab0a3233ffca350a7959e936e
parent345577bc90da1d1fffa0df013426eab54fa2b1b2 (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.c27
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);
}