plugin XEP-0085: use the full JID + fixes bad entity data "type" value
This commit is contained in:
parent
92cb3c0503
commit
34d191608d
1 changed files with 65 additions and 38 deletions
|
|
@ -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"]
|
||||
|
|
|
|||
Loading…
Reference in a new issue