plugin XEP-0085: use the full JID + fixes bad entity data "type" value

This commit is contained in:
souliane 2014-10-20 12:57:55 +02:00
commit 34d191608d

View file

@ -127,12 +127,13 @@ class XEP_0085(object):
# disable chat state for this or these contact(s)
self.host.bridge.chatStateReceived(unicode(entity_jid), "", profile)
def paramUpdateTrigger(self, name, value, category, type, profile):
def paramUpdateTrigger(self, name, value, category, type_, profile):
"""
Reset all the existing chat state entity data associated with this profile after a parameter modification.
@param name: parameter name
@param value: "true" to activate the notifications, or any other value to delete it
@param category: parameter category
@param type_: parameter type
"""
if (category, name) == (PARAM_KEY, PARAM_NAME):
self.updateEntityData("@ALL@", True if value == "true" else C.PROF_KEY_NONE, profile)
@ -148,19 +149,23 @@ class XEP_0085(object):
return True
from_jid = JID(message.getAttribute("from"))
try:
domish.generateElementsNamed(message.elements(), name="body").next()
if self.__isMUC(from_jid, profile):
from_jid = from_jid.userhostJID()
else: # update entity data for one2one chat
assert(from_jid.resource)
try:
domish.generateElementsNamed(message.elements(), name="active").next()
# contact enabled Chat State Notifications
self.updateEntityData(from_jid, True, profile)
domish.generateElementsNamed(message.elements(), name="body").next()
try:
domish.generateElementsNamed(message.elements(), name="active").next()
# contact enabled Chat State Notifications
self.updateEntityData(from_jid, True, profile)
except StopIteration:
if message.getAttribute('type') == 'chat':
# contact didn't enable Chat State Notifications
self.updateEntityData(from_jid, False, profile)
return True
except StopIteration:
if message.getAttribute('type') == 'chat':
# contact didn't enable Chat State Notifications
self.updateEntityData(from_jid, False, profile)
return True
except StopIteration:
pass
pass
# send our next "composing" states to any MUC and to the contacts who enabled the feature
self.__chatStateInit(from_jid, message.getAttribute("type"), profile)
@ -191,6 +196,8 @@ class XEP_0085(object):
domish.generateElementsNamed(message.elements(), name="body").next()
message.addElement('active', NS_CHAT_STATES)
# launch the chat state machine (init the timer)
if self.__isMUC(to_jid, profile):
to_jid = to_jid.userhostJID()
self.__chatStateActive(to_jid, mess_data["type"], profile)
except StopIteration:
if "chat_state" in mess_data["extra"]:
@ -202,9 +209,24 @@ class XEP_0085(object):
post_xml_treatments.addCallback(treatment)
return True
def __isMUC(self, to_jid, profile):
"""Tell if that JID is a MUC or not
@param to_jid (JID): full or bare JID to check
@param profile (str): %(doc_profile)s
@return: bool
"""
try:
type_ = self.host.memory.getEntityDatum(to_jid.userhostJID(), 'type', profile)
if type_ == 'chatroom':
return True
except (exceptions.UnknownEntityError, KeyError):
pass
return False
def __checkActivation(self, to_jid, forceEntityData, profile):
"""
@param to_joid: the contact's JID
@param to_jid: the contact's full JID (or bare if you know it's a MUC)
@param forceEntityData: if set to True, a non-existing
entity data will be considered to be True (and initialized)
@param: current profile
@ -214,14 +236,11 @@ class XEP_0085(object):
if not self.host.memory.getParamA(PARAM_NAME, PARAM_KEY, profile_key=profile):
return False
# check if notifications should be sent to this contact
if self.__isMUC(to_jid, profile):
return True
assert(to_jid.resource or not self.host.memory.isContactConnected(to_jid, profile))
try:
type_ = self.host.memory.getEntityData(to_jid, ['type'], profile)['type']
if type_ == 'groupchat': # always send to groupchat
return True
except (exceptions.UnknownEntityError, KeyError):
pass # private chat
try:
return self.host.memory.getEntityData(to_jid, [ENTITY_KEY], profile)[ENTITY_KEY]
return self.host.memory.getEntityDatum(to_jid, ENTITY_KEY, profile)
except (exceptions.UnknownEntityError, KeyError):
if forceEntityData:
# enable it for the first time
@ -233,15 +252,17 @@ class XEP_0085(object):
def __chatStateInit(self, to_jid, mess_type, profile):
"""
Data initialization for the chat state machine.
@param to_jid (JID): full JID for one2one, bare JID for MUC
@param mess_type (str): "one2one" or "groupchat"
@param profile (str): %(doc_profile)s
"""
# TODO: use also the resource in map key (not for groupchat)
to_jid = to_jid.userhostJID()
if mess_type is None:
return
if not hasattr(self, "map"):
self.map = {}
profile_map = self.map.setdefault(profile, {})
if not to_jid in profile_map:
if to_jid not in profile_map:
machine = ChatStateMachine(self.host, to_jid,
mess_type, profile)
self.map[profile][to_jid] = machine
@ -249,30 +270,36 @@ class XEP_0085(object):
def __chatStateActive(self, to_jid, mess_type, profile_key):
"""
Launch the chat state machine on "active" state.
@param to_jid (JID): full JID for one2one, bare JID for MUC
@param mess_type (str): "one2one" or "groupchat"
@param profile (str): %(doc_profile)s
"""
# TODO: use also the JID resource in the map key (not for groupchat)
to_jid = to_jid.userhostJID()
profile = self.host.memory.getProfileName(profile_key)
if profile is None:
raise exceptions.ProfileUnknownError
return
self.__chatStateInit(to_jid, mess_type, profile)
self.map[profile][to_jid]._onEvent("active")
def chatStateComposing(self, to_jid_s, profile_key):
"""
Move to the "composing" state. Since this method is called
from the front-end, it needs to check the values of the
parameter "Send chat state notifications" and the entity
"""Move to the "composing" state when required.
Since this method is called from the front-end, it needs to check the
values of the parameter "Send chat state notifications" and the entity
data associated to the target JID.
TODO: try to optimize this method which is called often
@param to_jid_s (str): contact full JID as a string
@param profile_key (str): %(doc_profile_key)s
"""
# TODO: use also the JID resource in the map key (not for groupchat)
to_jid = JID(to_jid_s).userhostJID()
# TODO: try to optimize this method which is called often
profile = self.host.memory.getProfileName(profile_key)
if profile is None:
raise exceptions.ProfileUnknownError
return
to_jid = JID(to_jid_s)
if self.__isMUC(to_jid, profile):
to_jid = to_jid.userhostJID()
elif not to_jid.resource:
to_jid.resource = self.host.memory.getLastResource(to_jid, profile)
if not self.__checkActivation(to_jid, forceEntityData=False, profile=profile):
return
try:
@ -318,14 +345,14 @@ class ChatStateMachine:
extra={"chat_state": state},
profile_key=self.profile)
self.state = state
if not self.timer is None:
if self.timer is not None:
self.timer.cancel()
if not state in TRANSITIONS:
if state not in TRANSITIONS:
return
if not "next_state" in TRANSITIONS[state]:
if "next_state" not in TRANSITIONS[state]:
return
if not "delay" in TRANSITIONS[state]:
if "delay" not in TRANSITIONS[state]:
return
next_state = TRANSITIONS[state]["next_state"]
delay = TRANSITIONS[state]["delay"]