From 72fc96ae6374db9e438a439f2d6487403192f2e6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Philipp=20H=C3=B6rist?= <philipp@hoerist.com>
Date: Mon, 18 Feb 2019 22:54:50 +0100
Subject: [PATCH] Refactor Annotations

- Simplify modules because nbxmpp handles more stuff
---
 gajim/common/connection.py          |  4 +-
 gajim/common/modules/annotations.py | 88 ++++++++---------------------
 gajim/vcard.py                      | 18 +++---
 3 files changed, 37 insertions(+), 73 deletions(-)

diff --git a/gajim/common/connection.py b/gajim/common/connection.py
index ac644531cb..6c61013571 100644
--- a/gajim/common/connection.py
+++ b/gajim/common/connection.py
@@ -1488,7 +1488,7 @@ class Connection(CommonConnection, ConnectionHandlers):
             self.get_module('Bookmarks').request_bookmarks()
 
             # Get annotations
-            self.get_module('Annotations').get_annotations()
+            self.get_module('Annotations').request_annotations()
 
             # Blocking
             self.get_module('Blocking').get_blocking_list()
@@ -1614,7 +1614,7 @@ class Connection(CommonConnection, ConnectionHandlers):
             self.get_module('VCardTemp').request_vcard()
 
         self.get_module('Bookmarks').request_bookmarks()
-        self.get_module('Annotations').get_annotations()
+        self.get_module('Annotations').request_annotations()
         self.get_module('Blocking').get_blocking_list()
 
         # Inform GUI we just signed in
diff --git a/gajim/common/modules/annotations.py b/gajim/common/modules/annotations.py
index 4eb8ed7e7b..b9187bc76d 100644
--- a/gajim/common/modules/annotations.py
+++ b/gajim/common/modules/annotations.py
@@ -16,87 +16,49 @@
 
 from typing import Any
 from typing import Dict  # pylint: disable=unused-import
-from typing import List  # pylint: disable=unused-import
 from typing import Tuple
 
 import logging
 
-import nbxmpp
+from nbxmpp.util import is_error_result
 
-from gajim.common import app
-from gajim.common import helpers
 from gajim.common.types import ConnectionT
+from gajim.common.modules.base import BaseModule
 
 log = logging.getLogger('gajim.c.m.annotations')
 
 
-class Annotations:
-    def __init__(self, con: ConnectionT) -> None:
-        self._con = con
-        self._account = con.name
-        self._server = self._con.get_own_jid().getDomain()
+class Annotations(BaseModule):
 
-        self.handlers = []  # type: List[Tuple[Any, ...]]
-        self.annotations = {}  # type: Dict[str, str]
+    _nbxmpp_extends = 'Annotations'
+    _nbxmpp_methods = [
+        'request_annotations',
+        'set_annotations',
+    ]
 
-    def get_annotations(self) -> None:
-        if not app.account_is_connected(self._account):
-            return
-
-        log.info('Request annotations for %s', self._server)
-        iq = nbxmpp.Iq(typ='get')
-        iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
-        iq2.addChild(name='storage', namespace='storage:rosternotes')
+    def __init__(self, con: ConnectionT):
+        BaseModule.__init__(self, con)
 
-        self._con.connection.SendAndCallForResponse(iq, self._result_received)
+        self._register_callback('request_annotations',
+                                self._annotations_received)
+        self._annotations = {}  # type: Dict[str, Any]
 
-    def _result_received(self, stanza: nbxmpp.Iq) -> None:
-        if not nbxmpp.isResultNode(stanza):
-            log.info('Error: %s', stanza.getError())
-            return
+    def set_annotations(self):
+        self._nbxmpp('Annotations').set_annotations(self._annotations.values())
 
-        log.info('Received annotations from %s', self._server)
-        self.annotations = {}
-        query = stanza.getTag('query')
-        storage_node = query.getTag('storage')
-        if storage_node is None:
+    def _annotations_received(self, result):
+        if is_error_result(result):
+            self._annotations = {}
             return
+        for note in result:
+            self._annotations[note.jid] = note
 
-        notes = storage_node.getTags('note')
-        if notes is None:
-            return
+    def get_note(self, jid):
+        return self._annotations.get(jid)
 
-        for note in notes:
-            try:
-                jid = helpers.parse_jid(note.getAttr('jid'))
-            except helpers.InvalidFormat:
-                log.warning('Invalid JID: %s, ignoring it',
-                            note.getAttr('jid'))
-                continue
-            self.annotations[jid] = note.getData()
-
-    def store_annotations(self) -> None:
-        if not app.account_is_connected(self._account):
-            return
-
-        iq = nbxmpp.Iq(typ='set')
-        iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
-        iq3 = iq2.addChild(name='storage', namespace='storage:rosternotes')
-        for jid in self.annotations:
-            if self.annotations[jid]:
-                iq4 = iq3.addChild(name='note')
-                iq4.setAttr('jid', jid)
-                iq4.setData(self.annotations[jid])
-
-        self._con.connection.SendAndCallForResponse(
-            iq, self._store_result_received)
-
-    @staticmethod
-    def _store_result_received(stanza: nbxmpp.Iq) -> None:
-        if not nbxmpp.isResultNode(stanza):
-            log.warning('Storing rosternotes failed: %s', stanza.getError())
-            return
-        log.info('Storing rosternotes successful')
+    def set_note(self, note):
+        self._annotations[note.jid] = note
+        self.set_annotations()
 
 
 def get_instance(*args: Any, **kwargs: Any) -> Tuple[Annotations, str]:
diff --git a/gajim/vcard.py b/gajim/vcard.py
index cbed78e4a9..9dae488e6c 100644
--- a/gajim/vcard.py
+++ b/gajim/vcard.py
@@ -32,6 +32,7 @@ import binascii
 from gi.repository import Gtk
 from gi.repository import GLib
 from gi.repository import Gdk
+from nbxmpp.structs import AnnotationNote
 
 from gajim import gtkgui_helpers
 from gajim.gui_menu_builder import show_save_as_menu
@@ -108,10 +109,10 @@ class VcardWindow:
 
         self.fill_jabber_page()
         con = app.connections[self.account]
-        annotations = con.get_module('Annotations').annotations
-        if self.contact.jid in annotations:
+        note = con.get_module('Annotations').get_note(self.contact.jid)
+        if note is not None:
             buffer_ = self.xml.get_object('textview_annotation').get_buffer()
-            buffer_.set_text(annotations[self.contact.jid])
+            buffer_.set_text(note.data)
 
         for widget_name in ('URL_label',
                             'EMAIL_WORK_USERID_label',
@@ -140,12 +141,13 @@ class VcardWindow:
         del app.interface.instances[self.account]['infos'][self.contact.jid]
         buffer_ = self.xml.get_object('textview_annotation').get_buffer()
         new_annotation = buffer_.get_text(buffer_.get_start_iter(),
-                buffer_.get_end_iter(), True)
+                                          buffer_.get_end_iter(),
+                                          True)
         con = app.connections[self.account]
-        annotations = con.get_module('Annotations').annotations
-        if new_annotation != annotations.get(self.contact.jid, ''):
-            annotations[self.contact.jid] = new_annotation
-            con.get_module('Annotations').store_annotations()
+        note = con.get_module('Annotations').get_note(self.contact.jid)
+        if note is None or new_annotation != note.data:
+            new_note = AnnotationNote(jid=self.contact.jid, data=new_annotation)
+            con.get_module('Annotations').set_note(new_note)
         app.ged.remove_event_handler('version-result-received', ged.GUI1,
             self.set_os_info)
         app.ged.remove_event_handler('time-result-received', ged.GUI1,
-- 
GitLab