diff --git a/gajim/common/modules/pep.py b/gajim/common/modules/pep.py index 464dd4e32..adc18e084 100644 --- a/gajim/common/modules/pep.py +++ b/gajim/common/modules/pep.py @@ -19,6 +19,7 @@ import logging import nbxmpp from gajim.common import app +from gajim.common.exceptions import StanzaMalformed from gajim.common.nec import NetworkIncomingEvent from gajim.common.const import PEPHandlerType, PEPEventType @@ -46,7 +47,7 @@ class PEP: self._pep_handlers[namespace] = [(notify_handler, retract_handler)] if notify_handler: module_instance = notify_handler.__self__ - if hasattr(module_instance, 'send_stored_publish'): + if module_instance.store_publish: if module_instance not in self._store_publish_modules: self._store_publish_modules.append(module_instance) @@ -98,29 +99,99 @@ class PEP: module.reset_stored_publish() -class PEPEvent: - - name = '' - +class AbstractPEPModule: def __init__(self, con, account): - self.__account = account - self.__con = con + self._account = account + self._con = con + + self._stored_publish = None + + self._con.get_module('PEP').register_pep_handler( + self.namespace, + self._pep_notify_received, + self._pep_retract_received) + + def _pep_notify_received(self, jid, item): + try: + data = self._extract_info(item) + except StanzaMalformed as error: + log.warning('%s, %s: %s', jid, error, item) + return + + self._log.info('Received: %s %s', jid, data) + self._push_event(jid, self.pep_class(data)) + + def _pep_retract_received(self, jid, id_): + self._log.info('Retract: %s %s', jid, id_) + self._push_event(jid, self.pep_class(None)) + + def _extract_info(self, item): + '''To be implemented by subclasses''' + raise NotImplementedError + + def _build_node(self, data): + '''To be implemented by subclasses''' + raise NotImplementedError + + def _push_event(self, jid, user_pep): + self._update_contacts(jid, user_pep) + app.nec.push_incoming_event( + PEPReceivedEvent(None, conn=self._con, + jid=str(jid), + pep_type=self.name, + user_pep=user_pep)) def _update_contacts(self, jid, user_pep): - for contact in app.contacts.get_contacts(self.__account, str(jid)): + for contact in app.contacts.get_contacts(self._account, str(jid)): if user_pep: contact.pep[self.name] = user_pep else: contact.pep.pop(self.name, None) - if jid == self.__con.get_own_jid().getStripped(): + if jid == self._con.get_own_jid().getStripped(): if user_pep: - self.__con.pep[self.name] = user_pep + self._con.pep[self.name] = user_pep else: - self.__con.pep.pop(self.name, None) + self._con.pep.pop(self.name, None) + + def send_stored_publish(self): + if self._stored_publish is not None: + self._log.info('Send stored publish') + self.send(*self._stored_publish) + self._stored_publish = None + + def reset_stored_publish(self): + self._log.info('Reset stored publish') + self._stored_publish = None + + def send(self, data): + if not self._con.pep_supported: + return + + if self._con.connected == 1: + # We are connecting, save activity and send it later + self._stored_publish = data + return + + if data: + self._log.info('Send: %s', data) + else: + self._log.info('Remove') + + item = self._build_node(data) + + self._con.get_module('PubSub').send_pb_publish( + '', self.namespace, item, 'current') + + def retract(self): + if not self._con.pep_supported: + return + self.send(None) + self._con.get_module('PubSub').send_pb_retract( + '', self.namespace, 'current') -class AbstractPEP: +class AbstractPEPData: type_ = PEPEventType diff --git a/gajim/common/modules/user_activity.py b/gajim/common/modules/user_activity.py index 20dae13a0..db46dc41e 100644 --- a/gajim/common/modules/user_activity.py +++ b/gajim/common/modules/user_activity.py @@ -19,121 +19,14 @@ import logging import nbxmpp from gi.repository import GLib -from gajim.common import app from gajim.common.const import PEPEventType, ACTIVITIES from gajim.common.exceptions import StanzaMalformed -from gajim.common.modules.pep import PEPReceivedEvent, PEPEvent, AbstractPEP +from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData log = logging.getLogger('gajim.c.m.user_activity') -class UserActivity(PEPEvent): - - name = 'activity' - - def __init__(self, con): - PEPEvent.__init__(self, con, con.name) - self._con = con - self._account = con.name - - self.handlers = [] - - self._stored_publish = None - - self._con.get_module('PEP').register_pep_handler( - nbxmpp.NS_ACTIVITY, - self._pep_notify_received, - self._pep_retract_received) - - def _pep_notify_received(self, jid, item): - try: - activity = self._extract_info(item) - except StanzaMalformed as error: - log.warning('%s, %s: %s', jid, error, item) - return - - log.info('Received: %s %s', jid, activity) - self._push_event(jid, UserActivityPEP(activity)) - - def _pep_retract_received(self, jid, id_): - log.info('Retract: %s %s', jid, id_) - self._push_event(jid, UserActivityPEP(None)) - - def _push_event(self, jid, user_pep): - self._update_contacts(jid, user_pep) - app.nec.push_incoming_event( - PEPReceivedEvent(None, conn=self._con, - jid=str(jid), - pep_type=self.name)) - - def _extract_info(self, item): - activity_dict = {} - activity_tag = item.getTag('activity', namespace=nbxmpp.NS_ACTIVITY) - if activity_tag is None: - raise StanzaMalformed('No activity node') - - for child in activity_tag.getChildren(): - name = child.getName().strip() - data = child.getData().strip() - if name == 'text': - activity_dict['text'] = data - else: - activity_dict['activity'] = name - for subactivity in child.getChildren(): - subactivity_name = subactivity.getName().strip() - activity_dict['subactivity'] = subactivity_name - - return activity_dict or None - - def send_stored_publish(self): - if self._stored_publish is not None: - log.info('Send stored publish') - self.send_activity(*self._stored_publish) - self._stored_publish = None - - def reset_stored_publish(self): - log.info('Reset stored publish') - self._stored_publish = None - - def send_activity(self, activity=None, subactivity=None, message=None): - if not self._con.pep_supported: - return - - if self._con.connected == 1: - # We are connecting, save activity and send it later - self._stored_publish = (activity, subactivity, message) - return - - if activity: - log.info('Send activity: %s %s %s', activity, subactivity, message) - else: - log.info('Remove activity') - - item = self._build_activity_node(activity, subactivity, message) - - self._con.get_module('PubSub').send_pb_publish( - '', nbxmpp.NS_ACTIVITY, item, 'current') - - def _build_activity_node(self, activity, subactivity=None, message=None): - item = nbxmpp.Node('activity', {'xmlns': nbxmpp.NS_ACTIVITY}) - if activity: - i = item.addChild(activity) - if subactivity: - i.addChild(subactivity) - if message: - i = item.addChild('text') - i.addData(message) - return item - - def retract_activity(self): - if not self._con.pep_supported: - return - self.send_activity() - self._con.get_module('PubSub').send_pb_retract( - '', nbxmpp.NS_ACTIVITY, 'current') - - -class UserActivityPEP(AbstractPEP): +class UserActivityData(AbstractPEPData): type_ = PEPEventType.ACTIVITY @@ -159,3 +52,48 @@ class UserActivityPEP(AbstractPEP): if text: markuptext += ' (%s)' % GLib.markup_escape_text(text) return markuptext + + +class UserActivity(AbstractPEPModule): + + name = 'activity' + namespace = nbxmpp.NS_ACTIVITY + pep_class = UserActivityData + store_publish = True + _log = log + + def __init__(self, con): + AbstractPEPModule.__init__(self, con, con.name) + + self.handlers = [] + + def _extract_info(self, item): + activity_dict = {} + activity_tag = item.getTag('activity', namespace=self.namespace) + if activity_tag is None: + raise StanzaMalformed('No activity node') + + for child in activity_tag.getChildren(): + name = child.getName().strip() + data = child.getData().strip() + if name == 'text': + activity_dict['text'] = data + else: + activity_dict['activity'] = name + for subactivity in child.getChildren(): + subactivity_name = subactivity.getName().strip() + activity_dict['subactivity'] = subactivity_name + + return activity_dict or None + + def _build_node(self, data): + activity, subactivity, message = data + item = nbxmpp.Node('activity', {'xmlns': self.namespace}) + if activity: + i = item.addChild(activity) + if subactivity: + i.addChild(subactivity) + if message: + i = item.addChild('text') + i.addData(message) + return item diff --git a/gajim/roster_window.py b/gajim/roster_window.py index 05216fe5a..285343b94 100644 --- a/gajim/roster_window.py +++ b/gajim/roster_window.py @@ -2099,10 +2099,10 @@ class RosterWindow: activity = pep_dict['activity'] subactivity = pep_dict.get('subactivity', None) activity_text = pep_dict.get('activity_text', None) - connection.get_module('UserActivity').send_activity( - activity, subactivity, activity_text) + connection.get_module('UserActivity').send( + (activity, subactivity, activity_text)) else: - connection.get_module('UserActivity').retract_activity() + connection.get_module('UserActivity').retract() if 'mood' in pep_dict: mood = pep_dict['mood']