plugin xep-0085: bug fix + improvement
This commit is contained in:
parent
bbd2b75ef8
commit
58561b8732
1 changed files with 45 additions and 36 deletions
|
|
@ -18,7 +18,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from sat.core import exceptions
|
||||
from logging import debug, info, error
|
||||
from logging import info
|
||||
from wokkel import disco, iwokkel
|
||||
from zope.interface import implements
|
||||
from twisted.words.protocols.jabber.jid import JID
|
||||
|
|
@ -89,7 +89,7 @@ class XEP_0085(object):
|
|||
}
|
||||
|
||||
def __init__(self, host):
|
||||
info(_("CSN plugin initialization"))
|
||||
info(_("Chat State Notifications plugin initialization"))
|
||||
self.host = host
|
||||
|
||||
# parameter value is retrieved before each use
|
||||
|
|
@ -99,7 +99,7 @@ class XEP_0085(object):
|
|||
host.trigger.add("MessageReceived", self.messageReceivedTrigger)
|
||||
host.trigger.add("sendMessageXml", self.sendMessageXmlTrigger)
|
||||
host.trigger.add("paramUpdateTrigger", self.paramUpdateTrigger)
|
||||
# TODO: handle profile disconnexion (free memory in entity data)
|
||||
# TODO: handle profile disconnection (free memory in entity data)
|
||||
|
||||
# args: to_s (jid as string), profile
|
||||
host.bridge.addMethod("chatStateComposing", ".plugin", in_sign='ss',
|
||||
|
|
@ -113,9 +113,11 @@ class XEP_0085(object):
|
|||
|
||||
def updateEntityData(self, entity_jid, value, profile):
|
||||
"""
|
||||
Update the entity data and reset the chat state display
|
||||
if the notification has been disabled. Parameter "entity_jid"
|
||||
could be @ALL@ to update all entities.
|
||||
Update the entity data of the given profile for one or all contacts.
|
||||
Reset the chat state(s) display if the notification has been disabled.
|
||||
@param entity_jid: contact's JID, or '@ALL@' to update all contacts.
|
||||
@param value: True, False or '@NONE@' to delete the entity data
|
||||
@param profile: current profile
|
||||
"""
|
||||
self.host.memory.updateEntityData(entity_jid, ENTITY_KEY, value, profile)
|
||||
if not value or value == "@NONE@":
|
||||
|
|
@ -124,9 +126,10 @@ class XEP_0085(object):
|
|||
|
||||
def paramUpdateTrigger(self, name, value, category, type, profile):
|
||||
"""
|
||||
Reset all the existing chat state entity data associated
|
||||
with this profile after a parameter modification (value
|
||||
different then "true" would delete the entity data).
|
||||
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
|
||||
"""
|
||||
if (category, name) == (PARAM_KEY, PARAM_NAME):
|
||||
self.updateEntityData("@ALL@", True if value == "true" else "@NONE@", profile)
|
||||
|
|
@ -151,6 +154,7 @@ class XEP_0085(object):
|
|||
except StopIteration:
|
||||
# contact didn't enable Chat State Notifications
|
||||
self.updateEntityData(from_jid, False, profile)
|
||||
return True
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
|
|
@ -160,8 +164,7 @@ class XEP_0085(object):
|
|||
and child.defaultUri == NS_CHAT_STATES]
|
||||
for state in state_list:
|
||||
# there must be only one state according to the XEP
|
||||
self.host.bridge.chatStateReceived(message.getAttribute("from"),
|
||||
state, profile)
|
||||
self.host.bridge.chatStateReceived(message.getAttribute("from"), state, profile)
|
||||
break
|
||||
return True
|
||||
|
||||
|
|
@ -170,19 +173,8 @@ class XEP_0085(object):
|
|||
Eventually add the chat state to the message and initiate
|
||||
the state machine when sending an "active" state.
|
||||
"""
|
||||
if not self.host.memory.getParamA(PARAM_NAME, PARAM_KEY, profile_key=profile):
|
||||
return True
|
||||
|
||||
# check if notifications should be sent to this contact
|
||||
contact_enabled = True
|
||||
to_jid = JID(message.getAttribute("to"))
|
||||
try:
|
||||
contact_enabled = self.host.memory.getEntityData(
|
||||
to_jid, [ENTITY_KEY], profile)[ENTITY_KEY]
|
||||
except (exceptions.UnknownEntityError, KeyError):
|
||||
# enable it for the first time
|
||||
self.updateEntityData(to_jid, True, profile)
|
||||
if not contact_enabled:
|
||||
if not self.__checkActivation(to_jid, forceEntityData=True, profile=profile):
|
||||
return True
|
||||
try:
|
||||
# message with a body always mean active state
|
||||
|
|
@ -197,6 +189,28 @@ class XEP_0085(object):
|
|||
message.addElement(state, NS_CHAT_STATES)
|
||||
return True
|
||||
|
||||
def __checkActivation(self, to_jid, forceEntityData, profile):
|
||||
"""
|
||||
@param to_joid: the contact's JID
|
||||
@param forceEntityData: if set to True, a non-existing
|
||||
entity data will be considered to be True (and initialized)
|
||||
@param: current profile
|
||||
@return: True if the notifications should be sent to this JID.
|
||||
"""
|
||||
# check if the parameter is active
|
||||
if not self.host.memory.getParamA(PARAM_NAME, PARAM_KEY, profile_key=profile):
|
||||
return False
|
||||
# check if notifications should be sent to this contact
|
||||
try:
|
||||
return self.host.memory.getEntityData(to_jid, [ENTITY_KEY], profile)[ENTITY_KEY]
|
||||
except (exceptions.UnknownEntityError, KeyError):
|
||||
if forceEntityData:
|
||||
# enable it for the first time
|
||||
self.updateEntityData(to_jid, True, profile)
|
||||
return True
|
||||
# wait for the first message before sending states
|
||||
return False
|
||||
|
||||
def __chatStateInit(self, to_jid, mess_type, profile):
|
||||
"""
|
||||
Data initialization for the chat state machine.
|
||||
|
|
@ -222,6 +236,7 @@ class XEP_0085(object):
|
|||
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")
|
||||
|
||||
|
|
@ -233,26 +248,20 @@ class XEP_0085(object):
|
|||
data associated to the target JID.
|
||||
TODO: try to optimize this method which is called often
|
||||
"""
|
||||
# check if the parameter is active
|
||||
if not self.host.memory.getParamA(PARAM_NAME, PARAM_KEY, profile_key=profile_key):
|
||||
return
|
||||
# TODO: use also the JID resource in the map key
|
||||
to_jid = JID(to_jid_s).userhostJID()
|
||||
profile = self.host.memory.getProfileName(profile_key)
|
||||
if profile is None:
|
||||
raise exceptions.ProfileUnknownError
|
||||
# check if notifications should be sent to this contact
|
||||
contact_enabled = True
|
||||
return
|
||||
if not self.__checkActivation(to_jid, forceEntityData=False, profile=profile):
|
||||
return
|
||||
try:
|
||||
contact_enabled = self.host.memory.getEntityData(
|
||||
to_jid, [ENTITY_KEY], profile)[ENTITY_KEY]
|
||||
except (exceptions.UnknownEntityError, KeyError):
|
||||
# wait for the first message before sending states
|
||||
self.map[profile][to_jid]._onEvent("composing")
|
||||
except AttributeError:
|
||||
# no message has been sent/received since the notifications
|
||||
# have been enabled, it's better to wait for a first one
|
||||
pass
|
||||
if not contact_enabled:
|
||||
return True
|
||||
# now we are sure that the state should be sent
|
||||
self.map[profile][to_jid]._onEvent("composing")
|
||||
|
||||
|
||||
class ChatStateMachine:
|
||||
|
|
|
|||
Loading…
Reference in a new issue