From 1c13fcd6481a71bebec7b7e043b912e0cec2b3c0 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Fri, 3 Mar 2006 14:41:55 +0000 Subject: [PATCH] [Geobert] Don't send bot JEP85 and JEP22 when only JEP22 is supported by contact. Fixes #1317 --- src/chat_control.py | 41 ++++++++++++++++++++++++---------------- src/common/connection.py | 32 ++++++++++++++++++++----------- src/common/contacts.py | 13 +++++++++---- src/gajim.py | 6 ++++-- src/message_control.py | 6 ++++-- 5 files changed, 63 insertions(+), 35 deletions(-) diff --git a/src/chat_control.py b/src/chat_control.py index 64dc56d41..3e65efb96 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -337,14 +337,15 @@ class ChatControlBase(MessageControl): return True return False - def send_message(self, message, keyID = '', type = 'chat', chatstate = None, msg_id = None): + def send_message(self, message, keyID = '', type = 'chat', chatstate = None, msg_id = None, + composing_jep = None): '''Send the given message to the active tab''' if not message or message == '\n': return if not self._process_command(message): MessageControl.send_message(self, message, keyID, type = type, - chatstate = chatstate, msg_id = msg_id) + chatstate = chatstate, msg_id = msg_id, composing_jep = composing_jep) # Record message history self.save_sent_message(message) @@ -954,7 +955,7 @@ class ChatControl(ChatControlBase): chatstates_on = gajim.config.get('chat_state_notifications') != 'disabled' chatstate_to_send = None if chatstates_on and contact is not None: - if contact.our_chatstate is None: + if contact.composing_jep is None: # no info about peer # send active to discover chat state capabilities # this is here (and not in send_chatstate) @@ -964,7 +965,7 @@ class ChatControl(ChatControlBase): contact.our_chatstate = 'ask' # pseudo state # if peer supports jep85 and we are not 'ask', send 'active' # NOTE: first active and 'ask' is set in gajim.py - elif contact.our_chatstate not in (False, 'ask'): + elif contact.composing_jep is not False: #send active chatstate on every message (as JEP says) chatstate_to_send = 'active' contact.our_chatstate = 'active' @@ -974,7 +975,8 @@ class ChatControl(ChatControlBase): self._schedule_activity_timers() ChatControlBase.send_message(self, message, keyID, type = 'chat', - chatstate = chatstate_to_send, msg_id = contact.msg_id) + chatstate = chatstate_to_send, + composing_jep = contact.composing_jep) self.print_conversation(message, self.contact.jid, encrypted = encrypted) def check_for_possible_paused_chatstate(self, arg): @@ -1183,20 +1185,17 @@ class ChatControl(ChatControlBase): if contact is None: contact = self.parent_win.get_active_contact() - jid = contact.jid - else: - jid = contact.jid - - if contact is None: - # contact was from pm in MUC, and left the room so contact is None - # so we cannot send chatstate anymore - return + if contact is None: + # contact was from pm in MUC, and left the room so contact is None + # so we cannot send chatstate anymore + return + jid = contact.jid # Don't send chatstates to offline contacts if contact.show == 'offline': return - if contact.our_chatstate is False: # jid cannot do jep85 + if contact.composing_jep is False: # jid cannot do jep85 nor jep22 return # if the new state we wanna send (state) equals @@ -1204,7 +1203,7 @@ class ChatControl(ChatControlBase): if contact.our_chatstate == state: return - if contact.our_chatstate is None: + if contact.composing_jep is None: # we don't know anything about jid, so return # NOTE: # send 'active', set current state to 'ask' and return is done @@ -1216,6 +1215,15 @@ class ChatControl(ChatControlBase): if contact.our_chatstate == 'ask': return + # in JEP22, when we already sent stop composing + # notification on paused, don't resend it + if contact.composing_jep == 'JEP-0022' and \ + contact.our_chatstate in ('paused', 'active', 'inactive') and \ + state is not 'composing': # not composing == in (active, inactive, gone) + contact.our_chatstate = 'active' + self.reset_kbd_mouse_timeout_vars() + return + # prevent going paused if we we were not composing (JEP violation) if state == 'paused' and not contact.our_chatstate == 'composing': MessageControl.send_message(self, None, chatstate = 'active') # go active before @@ -1228,7 +1236,8 @@ class ChatControl(ChatControlBase): contact.our_chatstate = 'active' self.reset_kbd_mouse_timeout_vars() - MessageControl.send_message(self, None, chatstate = state) + MessageControl.send_message(self, None, chatstate = state, msg_id = contact.msg_id, + composing_jep = contact.composing_jep) contact.our_chatstate = state if contact.our_chatstate == 'active': self.reset_kbd_mouse_timeout_vars() diff --git a/src/common/connection.py b/src/common/connection.py index 0a643c2c2..c901317b4 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -398,6 +398,7 @@ class Connection: invite = None delayed = msg.getTag('x', namespace = common.xmpp.NS_DELAY) != None msg_id = None + composing_jep = None # FIXME: Msn transport (CMSN1.2.1 and PyMSN0.10) do NOT RECOMMENDED # invitation # stanza (MUC JEP) remove in 2007, as we do not do NOT RECOMMENDED @@ -409,16 +410,19 @@ class Connection: return # chatstates - look for chatstate tags in a message if not delayed if not delayed: + composing_jep = False children = msg.getChildren() for child in children: if child.getNamespace() == 'http://jabber.org/protocol/chatstates': chatstate = child.getName() + composing_jep = 'JEP-0085' break # No JEP-0085 support, fallback to JEP-0022 if not chatstate: chatstate_child = msg.getTag('x', namespace = common.xmpp.NS_EVENT) if chatstate_child: chatstate = 'active' + composing_jep = 'JEP-0022' if not msgtxt and chatstate_child.getTag('composing'): chatstate = 'composing' @@ -456,7 +460,7 @@ class Connection: no_log_for: gajim.logger.write('chat_msg_recv', frm, msgtxt, tim = tim, subject = subject) self.dispatch('MSG', (frm, msgtxt, tim, encrypted, mtype, subject, - chatstate, msg_id)) + chatstate, msg_id, composing_jep)) else: # it's single message if self.name not in no_log_for and jid not in no_log_for: gajim.logger.write('single_msg_recv', frm, msgtxt, tim = tim, subject = subject) @@ -469,7 +473,7 @@ class Connection: self.dispatch('GC_INVITATION',(frm, jid_from, reason, password)) else: self.dispatch('MSG', (frm, msgtxt, tim, encrypted, 'normal', - subject, chatstate, msg_id)) + subject, chatstate, msg_id, composing_jep)) # END messageCB def _presenceCB(self, con, prs): @@ -2112,7 +2116,8 @@ class Connection: msg_iq = common.xmpp.Message(to = jid, body = msg, subject = subject) self.connection.send(msg_iq) - def send_message(self, jid, msg, keyID, type = 'chat', subject='', chatstate = None, msg_id = None): + def send_message(self, jid, msg, keyID, type = 'chat', subject='', + chatstate = None, msg_id = None, composing_jep = None): if not self.connection: return if not msg and chatstate is None: @@ -2144,14 +2149,19 @@ class Connection: # please note that the only valid tag inside a message containing a # tag is the active event if chatstate is not None: - # JEP-0085 - msg_iq.setTag(chatstate, namespace = common.xmpp.NS_CHATSTATES) - # JEP-0022 - chatstate_node = msg_iq.setTag('x', namespace = common.xmpp.NS_EVENT) - if msg_id: - chatstate_node.setTagData('id', msg_id) - if chatstate is 'composing' or msgtxt: - chatstate_node.addChild(name = 'composing') # we request JEP-0022 composing notification + if composing_jep == 'JEP-0085' or not composing_jep: + # JEP-0085 + msg_iq.setTag(chatstate, namespace = common.xmpp.NS_CHATSTATES) + if composing_jep == 'JEP-0022' or not composing_jep: + # JEP-0022 + chatstate_node = msg_iq.setTag('x', namespace = common.xmpp.NS_EVENT) + if not msgtxt: # when no , add + if not msg_id: # avoid putting 'None' in tag + msg_id = '' + chatstate_node.setTagData('id', msg_id) + # when msgtxt, requests JEP-0022 composing notification + if chatstate is 'composing' or msgtxt: + chatstate_node.addChild(name = 'composing') self.connection.send(msg_iq) no_log_for = gajim.config.get_per('accounts', self.name, 'no_log_for') diff --git a/src/common/contacts.py b/src/common/contacts.py index b0628d0df..fa05a030a 100644 --- a/src/common/contacts.py +++ b/src/common/contacts.py @@ -28,7 +28,7 @@ class Contact: '''Information concerning each contact''' def __init__(self, jid='', name='', groups=[], show='', status='', sub='', ask='', resource='', priority=5, keyID='', our_chatstate=None, - chatstate=None, last_status_time=None): + chatstate=None, last_status_time=None, msg_id = None, composing_jep = None): self.jid = jid self.name = name self.groups = groups @@ -48,7 +48,11 @@ class Contact: # 'ask' if we sent the first 'active' chatstate and are waiting for reply # this holds what WE SEND to contact (our current chatstate) self.our_chatstate = our_chatstate - self.msg_id = None + self.msg_id = msg_id + # tell which JEP we're using for composing state + # None = have to ask, JEP-0022 = use this jep, + # JEP-0085 = use this jep, False = no composing support + self.composing_jep = composing_jep # this is contact's chatstate self.chatstate = chatstate self.last_status_time = last_status_time @@ -120,9 +124,10 @@ class Contacts: def create_contact(self, jid='', name='', groups=[], show='', status='', sub='', ask='', resource='', priority=5, keyID='', our_chatstate=None, - chatstate=None, last_status_time=None): + chatstate=None, last_status_time=None, composing_jep=None): return Contact(jid, name, groups, show, status, sub, ask, resource, - priority, keyID, our_chatstate, chatstate, last_status_time) + priority, keyID, our_chatstate, chatstate, last_status_time, + composing_jep) def copy_contact(self, contact): return self.create_contact(jid = contact.jid, name = contact.name, diff --git a/src/gajim.py b/src/gajim.py index 5a7bae0d7..0b0f493db 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -388,7 +388,7 @@ class Interface: # reset chatstate if needed: # (when contact signs out or has errors) if array[1] in ('offline', 'error'): - contact1.our_chatstate = contact1.chatstate = None + contact1.our_chatstate = contact1.chatstate = contact1.composing_jep = None self.roster.chg_contact_status(contact1, array[1], array[2], account) # play sound if old_show < 2 and new_show > 1: @@ -474,6 +474,7 @@ class Interface: msg_type = array[4] chatstate = array[6] msg_id = array[7] + composing_jep = array[8] if jid.find('@') <= 0: jid = jid.replace('@', '') @@ -512,6 +513,7 @@ class Interface: # Handle chat states contact = gajim.contacts.get_first_contact_from_jid(account, jid) + contact.composing_jep = composing_jep if chat_control and chat_control.type_id == message_control.TYPE_CHAT: if chatstate is not None: # he or she sent us reply, so he supports jep85 or jep22 contact.chatstate = chatstate @@ -520,7 +522,7 @@ class Interface: chat_control.handle_incoming_chatstate() elif contact.chatstate != 'active': - # got no valid jep85 no jep22 answer, peer does not support it + # got no valid jep85 answer, peer does not support it contact.chatstate = False elif contact and chatstate == 'active': # Brand new message, incoming. diff --git a/src/message_control.py b/src/message_control.py index 40f1e894d..de717bbe8 100644 --- a/src/message_control.py +++ b/src/message_control.py @@ -133,12 +133,14 @@ class MessageControl: n = len(gajim.awaiting_events[self.account][self.contact.jid]) return n - def send_message(self, message, keyID = '', type = 'chat', chatstate = None, msg_id = None): + def send_message(self, message, keyID = '', type = 'chat', + chatstate = None, msg_id = None, composing_jep = None): '''Send the given message to the active tab''' jid = self.contact.jid # Send and update history gajim.connections[self.account].send_message(jid, message, keyID, - type = type, chatstate = chatstate, msg_id = msg_id) + type = type, chatstate = chatstate, msg_id = msg_id, + composing_jep = composing_jep) def position_menu_under_button(self, menu): #FIXME: BUG http://bugs.gnome.org/show_bug.cgi?id=316786