diff mcabber/src/jabglue.c @ 990:35e7913affb7

Send events/chatstates notifications (JEP-22/JEP-85)
author Mikael Berthe <mikael@lilotux.net>
date Wed, 01 Nov 2006 00:57:56 +0100
parents 859ab76e5093
children ef10906691bb
line wrap: on
line diff
--- a/mcabber/src/jabglue.c	Tue Oct 31 20:30:29 2006 +0100
+++ b/mcabber/src/jabglue.c	Wed Nov 01 00:57:56 2006 +0100
@@ -481,6 +481,7 @@
       jep85->support = CHATSTATES_SUPPORT_PROBED;
     else
       which_jep = 1;
+    jep85->last_state_sent = ROSTER_EVENT_ACTIVE;
   }
 #endif
 #ifdef JEP0022
@@ -489,19 +490,22 @@
    * If not, we try to fall back to JEP-0022.
    */
   if (!which_jep) {
+    struct jep0022 *jep22 = NULL;
     event = xmlnode_insert_tag(x, "x");
     xmlnode_put_attrib(event, "xmlns", NS_EVENT);
     xmlnode_insert_tag(event, "composing");
 
+    if (sl_buddy)
+      jep22 = buddy_resource_jep22(sl_buddy->data, rname);
+    if (jep22)
+      jep22->last_state_sent = ROSTER_EVENT_ACTIVE;
+
     // An id is mandatory when using JEP-0022.
     if (!msgid && (text || subject)) {
-      struct jep0022 *jep22;
       msgid = new_msgid();
       // Let's update last_msgid_sent
       // (We do not update it when the msgid is provided by the caller,
       // because this is probably a special message...)
-      if (sl_buddy)
-        jep22 = buddy_resource_jep22(sl_buddy->data, rname);
       if (jep22) {
         g_free(jep22->last_msgid_sent);
         jep22->last_msgid_sent = g_strdup(msgid);
@@ -518,10 +522,68 @@
   jb_reset_keepalive();
 }
 
+
+#ifdef JEP0085
+//  jb_send_jep85_chatstate()
+// Send a JEP-85 chatstate.
+static void jb_send_jep85_chatstate(const char *jid, guint state)
+{
+  xmlnode x;
+  xmlnode event;
+  char *rname, *barejid;
+  GSList *sl_buddy;
+  const char *chattag;
+  struct jep0085 *jep85 = NULL;
+
+  if (!online) return;
+
+  rname = strchr(jid, JID_RESOURCE_SEPARATOR);
+  barejid = jidtodisp(jid);
+  sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER);
+  g_free(barejid);
+
+  // If we can get a resource name, we use it.  Else we use NULL,
+  // which hopefully will give us the most likely resource.
+  if (rname)
+    rname++;
+  if (sl_buddy)
+    jep85 = buddy_resource_jep85(sl_buddy->data, rname);
+
+  if (!jep85 || (jep85->support != CHATSTATES_SUPPORT_OK))
+    return;
+
+  if (state == jep85->last_state_sent)
+    return;
+
+  if (state == ROSTER_EVENT_ACTIVE)
+    chattag = "active";
+  else if (state == ROSTER_EVENT_COMPOSING)
+    chattag = "composing";
+  else if (state == ROSTER_EVENT_PAUSED)
+    chattag = "paused";
+  else {
+    scr_LogPrint(LPRINT_LOGNORM, "Error: unsupported JEP-85 state (%d)", state);
+    return;
+  }
+
+  jep85->last_state_sent = state;
+
+  x = jutil_msgnew(TMSG_CHAT, (char*)jid, NULL, NULL);
+
+  event = xmlnode_insert_tag(x, chattag);
+  xmlnode_put_attrib(event, "xmlns", NS_CHATSTATES);
+
+  jab_send(jc, x);
+  xmlnode_free(x);
+
+  jb_reset_keepalive();
+}
+#endif
+
 #ifdef JEP0022
 //  jb_send_jep22_event()
 // Send a JEP-22 message event (delivered, composing...).
-void jb_send_jep22_event(const char *jid, guint type)
+static void jb_send_jep22_event(const char *jid, guint type)
 {
   xmlnode x;
   xmlnode event;
@@ -529,6 +591,7 @@
   char *rname, *barejid;
   GSList *sl_buddy;
   struct jep0022 *jep22 = NULL;
+  guint jep22_state;
 
   if (!online) return;
 
@@ -544,8 +607,27 @@
   if (sl_buddy)
     jep22 = buddy_resource_jep22(sl_buddy->data, rname);
 
-  if (jep22)
-    msgid = jep22->last_msgid_rcvd;
+  if (!jep22)
+    return; // XXX Maybe we could try harder (other resources?)
+
+  msgid = jep22->last_msgid_rcvd;
+
+  // For composing events (composing, active, inactive, paused...),
+  // JEP22 only has 2 states; we'll use composing and active.
+  if (type == ROSTER_EVENT_COMPOSING)
+    jep22_state = ROSTER_EVENT_COMPOSING;
+  else if (type == ROSTER_EVENT_ACTIVE ||
+           type == ROSTER_EVENT_PAUSED)
+    jep22_state = ROSTER_EVENT_ACTIVE;
+  else
+    jep22_state = 0; // ROSTER_EVENT_NONE
+
+  if (jep22_state) {
+    // Do not re-send a same event
+    if (jep22_state == jep22->last_state_sent)
+      return;
+    jep22->last_state_sent = jep22_state;
+  }
 
   x = jutil_msgnew(TMSG_CHAT, (char*)jid, NULL, NULL);
 
@@ -555,7 +637,7 @@
     xmlnode_insert_tag(event, "delivered");
   else if (type == ROSTER_EVENT_COMPOSING)
     xmlnode_insert_tag(event, "composing");
-  xmlnode_put_attrib(event, "id", (msgid ? msgid : ""));
+  xmlnode_put_attrib(event, "id", msgid);
 
   jab_send(jc, x);
   xmlnode_free(x);
@@ -564,6 +646,34 @@
 }
 #endif
 
+#if defined JEP0022 || defined JEP0085
+void jb_send_chatstate(gpointer buddy, guint chatstate)
+{
+  const char *jid;
+  struct jep0085 *jep85 = NULL;
+  struct jep0022 *jep22 = NULL;
+
+  jid = buddy_getjid(buddy);
+  if (!jid) return;
+
+#ifdef JEP0085
+  jep85 = buddy_resource_jep85(buddy, NULL);
+  if (jep85 && jep85->support == CHATSTATES_SUPPORT_OK) {
+    // FIXME: compare w/ last state sent...
+    jb_send_jep85_chatstate(jid, chatstate);
+    return;
+  }
+#endif
+#ifdef JEP0022
+  jep22 = buddy_resource_jep22(buddy, NULL);
+  if (jep22 && jep22->support == CHATSTATES_SUPPORT_OK) {
+    // FIXME: compare w/ last state sent...
+    jb_send_jep22_event(jid, chatstate);
+  }
+#endif
+}
+#endif
+
 //  jb_subscr_send_auth(jid)
 // Allow jid to receive our presence updates
 void jb_subscr_send_auth(const char *jid)
@@ -1572,14 +1682,14 @@
 void handle_state_events(char *from, xmlnode xmldata)
 {
 #if defined JEP0022 || defined JEP0085
-  xmlnode state_ns;
+  xmlnode state_ns = NULL;
   const char *body;
   char *rname, *jid;
   GSList *sl_buddy;
   guint events;
   guint which_jep = 0; /* 0: none, 1: 85, 2: 22 */
-  struct jep0022 *jep22;
-  struct jep0085 *jep85;
+  struct jep0022 *jep22 = NULL;
+  struct jep0085 *jep85 = NULL;
 
   rname = strchr(from, JID_RESOURCE_SEPARATOR);
   jid   = jidtodisp(from);