core, frontends: refactoring to base Libervia on QuickFrontend (big mixed commit):
/!\ not finished, everything is still instable !
- bridge: DBus bridge has been modified to allow blocking call to be called in the same way as asynchronous calls
- bridge: calls with a callback and no errback are now possible, default errback log the error
- constants: removed hack to manage presence without OrderedDict, as an OrderedDict like class has been implemented in Libervia
- core: getLastResource has been removed and replaced by getMainResource (there is a global better management of resources)
- various style improvments: use of constants when possible, fixed variable overlaps, import of module instead of direct class import
- frontends: printInfo and printMessage methods in (Quick)Chat are more generic (use of extra instead of timestamp)
- frontends: bridge creation and option parsing (command line arguments) are now specified by the frontend in QuickApp __init__
- frontends: ProfileManager manage a more complete plug sequence (some stuff formerly manage in contact_list have moved to ProfileManager)
- quick_frontend (quick_widgets): QuickWidgetsManager is now iterable (all widgets are then returned), or can return an iterator on a specific class (return all widgets of this class) with getWidgets
- frontends: tools.jid can now be used in Pyjamas, with some care
- frontends (XMLUI): profile is now managed
- core (memory): big improvment on entities cache management (and specially resource management)
- core (params/exceptions): added PermissionError
- various fixes and improvments, check diff for more details
This commit is contained in:
parent
f45e55388f
commit
8ce5c1862b
1 changed files with 1125 additions and 452 deletions
|
|
@ -39,6 +39,7 @@ MESSAGE_TYPES = ["chat", "groupchat"]
|
|||
PARAM_KEY = "Notifications"
|
||||
PARAM_NAME = "Enable chat state notifications"
|
||||
ENTITY_KEY = PARAM_KEY + "_" + PARAM_NAME
|
||||
DELETE_VALUE = "DELETE"
|
||||
|
||||
PLUGIN_INFO = {
|
||||
"name": "Chat State Notifications Protocol Plugin",
|
||||
|
|
@ -126,28 +127,31 @@ class XEP_0085(object):
|
|||
del self.map[profile]
|
||||
|
||||
def updateEntityData(self, entity_jid, value, profile):
|
||||
"""
|
||||
Update the entity data of the given profile for one or all contacts.
|
||||
"""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 C.PROF_KEY_NONE to delete the entity data
|
||||
@param entity_jid: contact's JID, or C.ENTITY_ALL to update all contacts.
|
||||
@param value: True, False or DELETE_VALUE to delete the entity data
|
||||
@param profile: current profile
|
||||
"""
|
||||
self.host.memory.updateEntityData(entity_jid, ENTITY_KEY, value, profile)
|
||||
if not value or value == C.PROF_KEY_NONE:
|
||||
# disable chat state for this or these contact(s)
|
||||
self.host.bridge.chatStateReceived(unicode(entity_jid), "", profile)
|
||||
if value == DELETE_VALUE:
|
||||
self.host.memory.delEntityData(entity_jid, ENTITY_KEY, profile)
|
||||
else:
|
||||
self.host.memory.updateEntityData(entity_jid, ENTITY_KEY, value, profile)
|
||||
if not value or value == DELETE_VALUE:
|
||||
# reinit chat state UI for this or these contact(s)
|
||||
self.host.bridge.chatStateReceived(entity_jid.full(), "", 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.
|
||||
"""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)
|
||||
self.updateEntityData(C.ENTITY_ALL, True if bool("true") else DELETE_VALUE, profile)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
|
@ -160,7 +164,7 @@ class XEP_0085(object):
|
|||
return True
|
||||
|
||||
from_jid = JID(message.getAttribute("from"))
|
||||
if self.__isMUC(from_jid, profile):
|
||||
if self._isMUC(from_jid, profile):
|
||||
from_jid = from_jid.userhostJID()
|
||||
else: # update entity data for one2one chat
|
||||
# assert from_jid.resource # FIXME: assert doesn't work on normal message from server (e.g. server announce), because there is no resource
|
||||
|
|
@ -200,27 +204,27 @@ class XEP_0085(object):
|
|||
def treatment(mess_data):
|
||||
message = mess_data['xml']
|
||||
to_jid = JID(message.getAttribute("to"))
|
||||
if not self.__checkActivation(to_jid, forceEntityData=True, profile=profile):
|
||||
if not self._checkActivation(to_jid, forceEntityData=True, profile=profile):
|
||||
return mess_data
|
||||
try:
|
||||
# message with a body always mean active state
|
||||
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):
|
||||
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"]:
|
||||
state = mess_data["extra"].pop("chat_state")
|
||||
assert(state in CHAT_STATES)
|
||||
assert state in CHAT_STATES
|
||||
message.addElement(state, NS_CHAT_STATES)
|
||||
return mess_data
|
||||
|
||||
post_xml_treatments.addCallback(treatment)
|
||||
return True
|
||||
|
||||
def __isMUC(self, to_jid, profile):
|
||||
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
|
||||
|
|
@ -229,13 +233,13 @@ class XEP_0085(object):
|
|||
"""
|
||||
try:
|
||||
type_ = self.host.memory.getEntityDatum(to_jid.userhostJID(), 'type', profile)
|
||||
if type_ == 'chatroom':
|
||||
if type_ == 'chatroom': # FIXME: should not use disco instead ?
|
||||
return True
|
||||
except (exceptions.UnknownEntityError, KeyError):
|
||||
pass
|
||||
return False
|
||||
|
||||
def __checkActivation(self, to_jid, forceEntityData, profile):
|
||||
def _checkActivation(self, to_jid, forceEntityData, profile):
|
||||
"""
|
||||
@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
|
||||
|
|
@ -247,9 +251,10 @@ 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):
|
||||
if self._isMUC(to_jid, profile):
|
||||
return True
|
||||
assert to_jid.resource or not self.host.memory.isContactConnected(to_jid, profile)
|
||||
# FIXME: this assertion crash when we want to send a message to an online bare jid
|
||||
# assert to_jid.resource or not self.host.memory.isEntityAvailable(to_jid, profile) # must either have a resource, or talk to an offline contact
|
||||
try:
|
||||
return self.host.memory.getEntityDatum(to_jid, ENTITY_KEY, profile)
|
||||
except (exceptions.UnknownEntityError, KeyError):
|
||||
|
|
@ -305,11 +310,11 @@ class XEP_0085(object):
|
|||
if profile is None:
|
||||
raise exceptions.ProfileUnknownError
|
||||
to_jid = JID(to_jid_s)
|
||||
if self.__isMUC(to_jid, profile):
|
||||
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):
|
||||
to_jid.resource = self.host.memory.getMainResource(to_jid, profile)
|
||||
if not self._checkActivation(to_jid, forceEntityData=False, profile=profile):
|
||||
return
|
||||
try:
|
||||
self.map[profile][to_jid]._onEvent("composing")
|
||||
|
|
@ -347,9 +352,9 @@ class ChatStateMachine:
|
|||
notification to the contact (the "active" state is
|
||||
automatically sent with each message) and set the timer.
|
||||
"""
|
||||
assert(state in TRANSITIONS)
|
||||
assert state in TRANSITIONS
|
||||
transition = TRANSITIONS[state]
|
||||
assert("next_state" in transition and "delay" in transition)
|
||||
assert "next_state" in transition and "delay" in transition
|
||||
|
||||
if state != self.state and state != "active":
|
||||
if state != 'gone' or self.mess_type != 'groupchat':
|
||||
|
|
|
|||
Loading…
Reference in a new issue