[Git][gajim/python-nbxmpp][master] 3 commits: Add UserMood (XEP-0107) module

Philipp Hörist gitlab at dev.gajim.org
Thu Jan 31 22:58:58 CET 2019


Philipp Hörist pushed to branch master at gajim / python-nbxmpp


Commits:
bcf7fd1f by Philipp Hörist at 2019-01-28T22:59:22Z
Add UserMood (XEP-0107) module

- - - - -
1cbd94ea by Philipp Hörist at 2019-01-30T23:03:23Z
Add UserActivity (XEP-0107) module

- - - - -
a1f0d26a by Philipp Hörist at 2019-01-31T21:55:09Z
Pubsub: Handle only new item notifications

- - - - -


6 changed files:

- nbxmpp/const.py
- nbxmpp/dispatcher_nb.py
- + nbxmpp/modules/activity.py
- + nbxmpp/modules/mood.py
- nbxmpp/modules/pubsub.py
- nbxmpp/structs.py


Changes:

=====================================
nbxmpp/const.py
=====================================
@@ -283,3 +283,172 @@ class Error(Enum):
 
     def __str__(self):
         return self.value
+
+
+MOODS = [
+    'afraid',
+    'amazed',
+    'amorous',
+    'angry',
+    'annoyed',
+    'anxious',
+    'aroused',
+    'ashamed',
+    'bored',
+    'brave',
+    'calm',
+    'cautious',
+    'cold',
+    'confident',
+    'confused',
+    'contemplative',
+    'contented',
+    'cranky',
+    'crazy',
+    'creative',
+    'curious',
+    'dejected',
+    'depressed',
+    'disappointed',
+    'disgusted',
+    'dismayed',
+    'distracted',
+    'embarrassed',
+    'envious',
+    'excited',
+    'flirtatious',
+    'frustrated',
+    'grateful',
+    'grieving',
+    'grumpy',
+    'guilty',
+    'happy',
+    'hopeful',
+    'hot',
+    'humbled',
+    'humiliated',
+    'hungry',
+    'hurt',
+    'impressed',
+    'in_awe',
+    'in_love',
+    'indignant',
+    'interested',
+    'intoxicated',
+    'invincible',
+    'jealous',
+    'lonely',
+    'lost',
+    'lucky',
+    'mean',
+    'moody',
+    'nervous',
+    'neutral',
+    'offended',
+    'outraged',
+    'playful',
+    'proud',
+    'relaxed',
+    'relieved',
+    'remorseful',
+    'restless',
+    'sad',
+    'sarcastic',
+    'satisfied',
+    'serious',
+    'shocked',
+    'shy',
+    'sick',
+    'sleepy',
+    'spontaneous',
+    'stressed',
+    'strong',
+    'surprised',
+    'thankful',
+    'thirsty',
+    'tired',
+    'undefined',
+    'weak',
+    'worried']
+
+
+ACTIVITIES = {
+    'doing_chores': [
+        'buying_groceries',
+        'cleaning',
+        'cooking',
+        'doing_maintenance',
+        'doing_the_dishes',
+        'doing_the_laundry',
+        'gardening',
+        'running_an_errand',
+        'walking_the_dog'],
+    'drinking': [
+        'having_a_beer',
+        'having_coffee',
+        'having_tea'],
+    'eating': [
+        'having_a_snack',
+        'having_breakfast',
+        'having_dinner',
+        'having_lunch'],
+    'exercising': [
+        'cycling',
+        'dancing',
+        'hiking',
+        'jogging',
+        'playing_sports',
+        'running',
+        'skiing',
+        'swimming',
+        'working_out'],
+    'grooming': [
+        'at_the_spa',
+        'brushing_teeth',
+        'getting_a_haircut',
+        'shaving',
+        'taking_a_bath',
+        'taking_a_shower'],
+    'having_appointment': [],
+    'inactive': [
+        'day_off',
+        'hanging_out',
+        'hiding',
+        'on_vacation',
+        'praying',
+        'scheduled_holiday',
+        'sleeping',
+        'thinking'],
+    'relaxing': [
+        'fishing',
+        'gaming',
+        'going_out',
+        'partying',
+        'reading',
+        'rehearsing',
+        'shopping',
+        'smoking',
+        'socializing',
+        'sunbathing',
+        'watching_tv',
+        'watching_a_movie'],
+    'talking': [
+        'in_real_life',
+        'on_the_phone',
+        'on_video_phone'],
+    'traveling': [
+        'commuting',
+        'cycling',
+        'driving',
+        'in_a_car',
+        'on_a_bus',
+        'on_a_plane',
+        'on_a_train',
+        'on_a_trip',
+        'walking'],
+    'working': [
+        'coding',
+        'in_a_meeting',
+        'studying',
+        'writing']
+}
\ No newline at end of file


=====================================
nbxmpp/dispatcher_nb.py
=====================================
@@ -57,6 +57,8 @@ from nbxmpp.modules.captcha import Captcha
 from nbxmpp.modules.entity_caps import EntityCaps
 from nbxmpp.modules.blocking import Blocking
 from nbxmpp.modules.pubsub import PubSub
+from nbxmpp.modules.activity import Activity
+from nbxmpp.modules.mood import Mood
 from nbxmpp.modules.misc import unwrap_carbon
 from nbxmpp.modules.misc import unwrap_mam
 from nbxmpp.util import get_properties_struct
@@ -181,6 +183,8 @@ class XMPPDispatcher(PlugIn):
         self._modules['EntityCaps'] = EntityCaps(self._owner)
         self._modules['Blocking'] = Blocking(self._owner)
         self._modules['PubSub'] = PubSub(self._owner)
+        self._modules['Mood'] = Mood(self._owner)
+        self._modules['Activity'] = Activity(self._owner)
 
         for instance in self._modules.values():
             for handler in instance.handlers:


=====================================
nbxmpp/modules/activity.py
=====================================
@@ -0,0 +1,87 @@
+# Copyright (C) 2018 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_ACTIVITY
+from nbxmpp.protocol import NS_PUBSUB_EVENT
+from nbxmpp.protocol import Node
+from nbxmpp.structs import StanzaHandler
+from nbxmpp.structs import ActivityData
+from nbxmpp.const import ACTIVITIES
+
+log = logging.getLogger('nbxmpp.m.activity')
+
+
+class Activity:
+    def __init__(self, client):
+        self._client = client
+        self.handlers = [
+            StanzaHandler(name='message',
+                          callback=self._process_pubsub_activity,
+                          ns=NS_PUBSUB_EVENT,
+                          priority=16),
+        ]
+
+    def _process_pubsub_activity(self, _con, stanza, properties):
+        if not properties.is_pubsub_event:
+            return
+
+        if properties.pubsub_event.node != NS_ACTIVITY:
+            return
+
+        item = properties.pubsub_event.item
+
+        activity_node = item.getTag('activity', namespace=NS_ACTIVITY)
+
+        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)
+            return
+
+        data = ActivityData(activity, subactivity, text)
+        log.info('Received activity: %s - %s', properties.jid, data)
+        properties.pubsub_event = properties.pubsub_event._replace(data=data)
+
+    @staticmethod
+    def _parse_sub_activity(activity):
+        sub_activities = ACTIVITIES[activity.getName()]
+        for sub in activity.getChildren():
+            if sub.getName() in sub_activities:
+                return sub.getName()
+
+    def set_activity(self, data):
+        item = Node('activity', {'xmlns': NS_ACTIVITY})
+        if data is not None and data.activity:
+            activity_node = item.addChild(data.activity)
+            if data.subactivity:
+                activity_node.addChild(data.subactivity)
+            if data.text:
+                item.addChild('text', payload=data.text)
+
+        jid = self._client.get_bound_jid().getBare()
+        self._client.get_module('PubSub').publish(
+            jid, NS_ACTIVITY, item, id_='current')


=====================================
nbxmpp/modules/mood.py
=====================================
@@ -0,0 +1,78 @@
+# Copyright (C) 2018 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_MOOD
+from nbxmpp.protocol import NS_PUBSUB_EVENT
+from nbxmpp.protocol import Node
+from nbxmpp.structs import StanzaHandler
+from nbxmpp.structs import MoodData
+from nbxmpp.const import MOODS
+
+log = logging.getLogger('nbxmpp.m.mood')
+
+
+class Mood:
+    def __init__(self, client):
+        self._client = client
+        self.handlers = [
+            StanzaHandler(name='message',
+                          callback=self._process_pubsub_mood,
+                          ns=NS_PUBSUB_EVENT,
+                          priority=16),
+        ]
+
+    def _process_pubsub_mood(self, _con, stanza, properties):
+        if not properties.is_pubsub_event:
+            return
+
+        if properties.pubsub_event.node != NS_MOOD:
+            return
+
+        item = properties.pubsub_event.item
+
+        mood_node = item.getTag('mood', namespace=NS_MOOD)
+
+        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)
+            return
+
+        data = MoodData(mood, text)
+        log.info('Received mood: %s - %s', properties.jid, data)
+        properties.pubsub_event = properties.pubsub_event._replace(data=data)
+
+    def set_mood(self, data):
+        item = Node('mood', {'xmlns': NS_MOOD})
+        if data is not None and data.mood:
+            item.addChild(data.mood)
+
+            if data.text:
+                item.addChild('text', payload=data.text)
+
+        jid = self._client.get_bound_jid().getBare()
+        self._client.get_module('PubSub').publish(
+            jid, NS_MOOD, item, id_='current')


=====================================
nbxmpp/modules/pubsub.py
=====================================
@@ -42,6 +42,7 @@ class PubSub:
         ]
 
     def _process_pubsub_base(self, _con, stanza, properties):
+        properties.pubsub = True
         event = stanza.getTag('event', namespace=NS_PUBSUB_EVENT)
         items = event.getTag('items')
         if len(items.getChildren()) != 1:
@@ -49,6 +50,8 @@ class PubSub:
             log.warning(stanza)
         node = items.getAttr('node')
         item = items.getTag('item')
+        if item is None:
+            return
         id_ = item.getAttr('id')
         properties.pubsub_event = PubSubEventData(node, id_, item, None)
 


=====================================
nbxmpp/structs.py
=====================================
@@ -60,6 +60,10 @@ StanzaIDData.__new__.__defaults__ = (None, None)
 
 PubSubEventData = namedtuple('PubSubEventData', 'node id item data')
 
+MoodData = namedtuple('MoodData', 'mood text')
+
+ActivityData = namedtuple('ActivityData', 'activity subactivity text')
+
 
 class MAMData(namedtuple('MAMData', 'id query_id archive namespace timestamp')):
 
@@ -105,8 +109,13 @@ class MessageProperties:
         self.voice_request = None
         self.self_message = False
         self.mam = None
+        self.pubsub = False
         self.pubsub_event = None
 
+    @property
+    def is_pubsub(self):
+        return self.pubsub
+
     @property
     def is_pubsub_event(self):
         return self.pubsub_event is not None



View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/compare/18edd864e367a26b702965496c15444e9e3582be...a1f0d26a1a7357c7db66ea88cf86bd9d7c1a1eb8

-- 
View it on GitLab: https://dev.gajim.org/gajim/python-nbxmpp/compare/18edd864e367a26b702965496c15444e9e3582be...a1f0d26a1a7357c7db66ea88cf86bd9d7c1a1eb8
You're receiving this email because of your account on dev.gajim.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.gajim.org/pipermail/commits/attachments/20190131/b8c7ebd8/attachment-0001.html>


More information about the Commits mailing list