Philipp Hörist pushed to branch master at gajim / python-nbxmpp
Commits: 96593877 by Philipp Hörist at 2019-02-02T15:50:13Z Add UserLocation (XEP-0080) module
- - - - - 5fdfcbb7 by Philipp Hörist at 2019-02-02T15:57:07Z Set empty attr for activity and mood
- - - - - 45b02fd2 by Philipp Hörist at 2019-02-02T15:57:24Z Simplify Tune module
- - - - - 40ff2a82 by Philipp Hörist at 2019-02-02T16:31:12Z Improve pubsub event logging
- - - - -
9 changed files:
- nbxmpp/const.py - nbxmpp/dispatcher_nb.py - nbxmpp/modules/activity.py - + nbxmpp/modules/location.py - nbxmpp/modules/mood.py - nbxmpp/modules/nickname.py - nbxmpp/modules/pubsub.py - nbxmpp/modules/tune.py - nbxmpp/structs.py
Changes:
===================================== nbxmpp/const.py ===================================== @@ -451,4 +451,41 @@ ACTIVITIES = { 'in_a_meeting', 'studying', 'writing'] -} \ No newline at end of file +} + + +LOCATION_DATA = [ + 'accuracy', + 'alt', + 'altaccuracy', + 'area', + 'bearing', + 'building', + 'country', + 'countrycode', + 'datum', + 'description', + 'error', + 'floor', + 'lat', + 'locality', + 'lon', + 'postalcode', + 'region', + 'room', + 'speed', + 'street', + 'text', + 'timestamp', + 'tzo', + 'uri'] + + +TUNE_DATA = [ + 'artist', + 'length', + 'rating', + 'source', + 'title', + 'track', + 'uri']
===================================== nbxmpp/dispatcher_nb.py ===================================== @@ -60,6 +60,7 @@ from nbxmpp.modules.pubsub import PubSub from nbxmpp.modules.activity import Activity from nbxmpp.modules.tune import Tune from nbxmpp.modules.mood import Mood +from nbxmpp.modules.location import Location from nbxmpp.modules.misc import unwrap_carbon from nbxmpp.modules.misc import unwrap_mam from nbxmpp.util import get_properties_struct @@ -187,6 +188,7 @@ class XMPPDispatcher(PlugIn): self._modules['Mood'] = Mood(self._owner) self._modules['Activity'] = Activity(self._owner) self._modules['Tune'] = Tune(self._owner) + self._modules['Location'] = Location(self._owner)
for instance in self._modules.values(): for handler in instance.handlers:
===================================== nbxmpp/modules/activity.py ===================================== @@ -20,6 +20,7 @@ import logging from nbxmpp.protocol import NS_ACTIVITY from nbxmpp.protocol import NS_PUBSUB_EVENT from nbxmpp.protocol import Node +from nbxmpp.protocol import NodeProcessed from nbxmpp.structs import StanzaHandler from nbxmpp.structs import ActivityData from nbxmpp.const import ACTIVITIES @@ -47,24 +48,29 @@ class Activity: item = properties.pubsub_event.item
activity_node = item.getTag('activity', namespace=NS_ACTIVITY) + if not activity_node.getChildren(): + pubsub_event = properties.pubsub_event._replace(empty=True) + log.info('Received activity: %s - no activity set', properties.jid) + else: + activity, subactivity, text = None, None, None + for child in activity_node.getChildren(): + name = child.getName() + if name == 'text': + text = child.getData() + elif name in ACTIVITIES: + activity = name + subactivity = self._parse_sub_activity(child)
- activity, subactivity, text = None, None, None - for child in activity_node.getChildren(): - name = child.getName() - if name == 'text': - text = child.getData() - elif name in ACTIVITIES: - activity = name - subactivity = self._parse_sub_activity(child) + if activity is None and activity_node.getPayload(): + log.warning('No valid activity value found') + log.warning(stanza) + raise NodeProcessed
- if activity is None and activity_node.getPayload(): - log.warning('No valid activity value found') - log.warning(stanza) - return + data = ActivityData(activity, subactivity, text) + pubsub_event = properties.pubsub_event._replace(data=data) + log.info('Received activity: %s - %s', properties.jid, data)
- data = ActivityData(activity, subactivity, text) - log.info('Received activity: %s - %s', properties.jid, data) - properties.pubsub_event = properties.pubsub_event._replace(data=data) + properties.pubsub_event = pubsub_event
@staticmethod def _parse_sub_activity(activity):
===================================== nbxmpp/modules/location.py ===================================== @@ -0,0 +1,75 @@ +# Copyright (C) 2019 Philipp Hörist <philipp AT hoerist.com> +# +# This file is part of nbxmpp. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; If not, see http://www.gnu.org/licenses/. + +import logging + +from nbxmpp.protocol import NS_LOCATION +from nbxmpp.protocol import NS_PUBSUB_EVENT +from nbxmpp.protocol import Node +from nbxmpp.structs import StanzaHandler +from nbxmpp.structs import LocationData +from nbxmpp.const import LOCATION_DATA + +log = logging.getLogger('nbxmpp.m.location') + + +class Location: + def __init__(self, client): + self._client = client + self.handlers = [ + StanzaHandler(name='message', + callback=self._process_pubsub_location, + ns=NS_PUBSUB_EVENT, + priority=16), + ] + + def _process_pubsub_location(self, _con, _stanza, properties): + if not properties.is_pubsub_event: + return + + if properties.pubsub_event.node != NS_LOCATION: + return + + item = properties.pubsub_event.item + + location_node = item.getTag('geoloc', namespace=NS_LOCATION) + if not location_node.getChildren(): + pubsub_event = properties.pubsub_event._replace(empty=True) + log.info('Received location: %s - no location set', properties.jid) + else: + location_dict = {} + for node in LOCATION_DATA: + location_dict[node] = location_node.getTagData(node) + data = LocationData(**location_dict) + pubsub_event = properties.pubsub_event._replace(data=data) + log.info('Received location: %s - %s', properties.jid, data) + + properties.pubsub_event = pubsub_event + + def set_location(self, data): + item = Node('geoloc', {'xmlns': NS_LOCATION}) + if data is None: + return item + + data = data._asdict() + for tag, value in data: + if value is not None: + item.addChild(tag, payload=value) + + jid = self._client.get_bound_jid().getBare() + self._client.get_module('PubSub').publish( + jid, NS_LOCATION, item, id_='current')
===================================== nbxmpp/modules/mood.py ===================================== @@ -20,6 +20,7 @@ import logging from nbxmpp.protocol import NS_MOOD from nbxmpp.protocol import NS_PUBSUB_EVENT from nbxmpp.protocol import Node +from nbxmpp.protocol import NodeProcessed from nbxmpp.structs import StanzaHandler from nbxmpp.structs import MoodData from nbxmpp.const import MOODS @@ -47,23 +48,28 @@ class Mood: item = properties.pubsub_event.item
mood_node = item.getTag('mood', namespace=NS_MOOD) + if not mood_node.getChildren(): + pubsub_event = properties.pubsub_event._replace(empty=True) + log.info('Received mood: %s - no mood set', properties.jid) + else: + mood, text = None, None + for child in mood_node.getChildren(): + name = child.getName().strip() + if name == 'text': + text = child.getData() + elif name in MOODS: + mood = name
- mood, text = None, None - for child in mood_node.getChildren(): - name = child.getName().strip() - if name == 'text': - text = child.getData() - elif name in MOODS: - mood = name + if mood is None and mood_node.getPayload(): + log.warning('No valid mood value found') + log.warning(stanza) + raise NodeProcessed
- if mood is None and mood_node.getPayload(): - log.warning('No valid mood value found') - log.warning(stanza) - return + data = MoodData(mood, text) + pubsub_event = properties.pubsub_event._replace(data=data) + log.info('Received mood: %s - %s', properties.jid, data)
- data = MoodData(mood, text) - log.info('Received mood: %s - %s', properties.jid, data) - properties.pubsub_event = properties.pubsub_event._replace(data=data) + properties.pubsub_event = pubsub_event
def set_mood(self, data): item = Node('mood', {'xmlns': NS_MOOD})
===================================== nbxmpp/modules/nickname.py ===================================== @@ -65,7 +65,10 @@ class Nickname: return
nick = self._parse_nickname(properties.pubsub_event.item) - log.info('Received nickname: %s - %s', properties.jid, nick) + if nick is None: + log.info('Received nickname: %s - no nickname set', properties.jid) + else: + log.info('Received nickname: %s - %s', properties.jid, nick)
properties.pubsub_event = properties.pubsub_event._replace(data=nick)
===================================== nbxmpp/modules/pubsub.py ===================================== @@ -53,7 +53,7 @@ class PubSub: if item is None: return id_ = item.getAttr('id') - properties.pubsub_event = PubSubEventData(node, id_, item, None) + properties.pubsub_event = PubSubEventData(node, id_, item, None, False)
@call_on_response('_default_response') def publish(self, jid, node, item, id_=None, options=None):
===================================== nbxmpp/modules/tune.py ===================================== @@ -22,6 +22,7 @@ from nbxmpp.protocol import NS_PUBSUB_EVENT from nbxmpp.protocol import Node from nbxmpp.structs import StanzaHandler from nbxmpp.structs import TuneData +from nbxmpp.const import TUNE_DATA
log = logging.getLogger('nbxmpp.m.tune')
@@ -47,40 +48,28 @@ class Tune:
tune_node = item.getTag('tune', namespace=NS_TUNE) if not tune_node.getChildren(): - data = TuneData() + pubsub_event = properties.pubsub_event._replace(empty=True) + log.info('Received tune: %s - no tune set', properties.jid) else: - artist = tune_node.getTagData('artist') - length = tune_node.getTagData('length') - rating = tune_node.getTagData('rating') - source = tune_node.getTagData('source') - title = tune_node.getTagData('title') - track = tune_node.getTagData('track') - uri = tune_node.getTagData('uri') + tune_dict = {} + for attr in TUNE_DATA: + tune_dict[attr] = tune_node.getTagData(attr)
- data = TuneData(artist, length, rating, source, title, track, uri) + data = TuneData(**tune_dict) + pubsub_event = properties.pubsub_event._replace(data=data) + log.info('Received tune: %s - %s', properties.jid, data)
- log.info('Received tune: %s - %s', properties.jid, data) - properties.pubsub_event = properties.pubsub_event._replace(data=data) + properties.pubsub_event = pubsub_event
def set_tune(self, data): item = Node('tune', {'xmlns': NS_TUNE}) if data is None: return item
- if data.artist: - item.addChild('artist', payload=data.artist) - if data.length: - item.addChild('length', payload=data.length) - if data.rating: - item.addChild('length', payload=data.rating) - if data.source: - item.addChild('source', payload=data.source) - if data.title: - item.addChild('title', payload=data.title) - if data.track: - item.addChild('track', payload=data.track) - if data.uri: - item.addChild('track', payload=data.uri) + data = data._asdict() + for tag, value in data: + if value is not None: + item.addChild(tag, payload=value)
jid = self._client.get_bound_jid().getBare() self._client.get_module('PubSub').publish(
===================================== nbxmpp/structs.py ===================================== @@ -27,6 +27,7 @@ from nbxmpp.const import AvatarState from nbxmpp.const import StatusCode from nbxmpp.const import PresenceType from nbxmpp.const import Error +from nbxmpp.const import LOCATION_DATA
StanzaHandler = namedtuple('StanzaHandler', 'name callback typ ns xmlns system priority') @@ -58,12 +59,15 @@ HTTPAuthData.__new__.__defaults__ = (None, None, None, None) StanzaIDData = namedtuple('StanzaIDData', 'id by') StanzaIDData.__new__.__defaults__ = (None, None)
-PubSubEventData = namedtuple('PubSubEventData', 'node id item data') +PubSubEventData = namedtuple('PubSubEventData', 'node id item data empty')
MoodData = namedtuple('MoodData', 'mood text')
ActivityData = namedtuple('ActivityData', 'activity subactivity text')
+LocationData = namedtuple('LocationData', LOCATION_DATA) +LocationData.__new__.__defaults__ = (None,) * len(LocationData._fields) +
class TuneData(namedtuple('TuneData', 'artist length rating source title track uri')):
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/compare/b1cb29c0f415234f42971e722d...