| ... |
... |
@@ -22,11 +22,11 @@ from typing import Tuple |
|
22
|
22
|
from typing import Union
|
|
23
|
23
|
from typing import Optional
|
|
24
|
24
|
|
|
|
25
|
+import functools
|
|
|
26
|
+
|
|
25
|
27
|
from nbxmpp.namespaces import Namespace
|
|
26
|
28
|
from nbxmpp.protocol import JID
|
|
27
|
|
-from nbxmpp.util import is_error_result
|
|
28
|
29
|
from nbxmpp.structs import BookmarkData
|
|
29
|
|
-from nbxmpp.const import BookmarkStoreType
|
|
30
|
30
|
from gi.repository import GLib
|
|
31
|
31
|
|
|
32
|
32
|
from gajim.common import app
|
| ... |
... |
@@ -36,20 +36,13 @@ from gajim.common.modules.util import event_node |
|
36
|
36
|
|
|
37
|
37
|
|
|
38
|
38
|
class Bookmarks(BaseModule):
|
|
39
|
|
-
|
|
40
|
|
- _nbxmpp_extends = 'Bookmarks'
|
|
41
|
|
- _nbxmpp_methods = [
|
|
42
|
|
- 'request_bookmarks',
|
|
43
|
|
- 'store_bookmarks',
|
|
44
|
|
- 'retract_bookmark',
|
|
45
|
|
- ]
|
|
46
|
|
-
|
|
47
|
39
|
def __init__(self, con):
|
|
48
|
40
|
BaseModule.__init__(self, con)
|
|
49
|
41
|
self._register_pubsub_handler(self._bookmark_event_received)
|
|
50
|
|
- self._register_pubsub_handler(self._bookmark_2_event_received)
|
|
|
42
|
+ self._register_pubsub_handler(self._bookmark_1_event_received)
|
|
51
|
43
|
self._conversion = False
|
|
52
|
|
- self._conversion_2 = False
|
|
|
44
|
+ self._compat = False
|
|
|
45
|
+ self._compat_pep = False
|
|
53
|
46
|
self._bookmarks = {}
|
|
54
|
47
|
self._join_timeouts = []
|
|
55
|
48
|
self._request_in_progress = True
|
| ... |
... |
@@ -59,20 +52,24 @@ class Bookmarks(BaseModule): |
|
59
|
52
|
return self._conversion
|
|
60
|
53
|
|
|
61
|
54
|
@property
|
|
62
|
|
- def conversion_2(self) -> bool:
|
|
63
|
|
- return self._conversion_2
|
|
|
55
|
+ def compat(self) -> bool:
|
|
|
56
|
+ return self._compat
|
|
|
57
|
+
|
|
|
58
|
+ @property
|
|
|
59
|
+ def compat_pep(self) -> bool:
|
|
|
60
|
+ return self._compat_pep
|
|
64
|
61
|
|
|
65
|
62
|
@property
|
|
66
|
63
|
def bookmarks(self) -> List[BookmarkData]:
|
|
67
|
64
|
return self._bookmarks.values()
|
|
68
|
65
|
|
|
69
|
66
|
@property
|
|
70
|
|
- def using_bookmark_1(self) -> bool:
|
|
71
|
|
- return self._pubsub_support() and self.conversion
|
|
|
67
|
+ def pep_bookmarks_used(self) -> bool:
|
|
|
68
|
+ return self._bookmark_module() == 'PEPBookmarks'
|
|
72
|
69
|
|
|
73
|
70
|
@property
|
|
74
|
|
- def using_bookmark_2(self) -> bool:
|
|
75
|
|
- return self._pubsub_support() and self.conversion_2
|
|
|
71
|
+ def nativ_bookmarks_used(self) -> bool:
|
|
|
72
|
+ return self._bookmark_module() == 'NativeBookmarks'
|
|
76
|
73
|
|
|
77
|
74
|
@event_node(Namespace.BOOKMARKS)
|
|
78
|
75
|
def _bookmark_event_received(self, _con, _stanza, properties):
|
| ... |
... |
@@ -84,7 +81,7 @@ class Bookmarks(BaseModule): |
|
84
|
81
|
properties.jid)
|
|
85
|
82
|
return
|
|
86
|
83
|
|
|
87
|
|
- if not self.using_bookmark_1:
|
|
|
84
|
+ if not self.pep_bookmarks_used:
|
|
88
|
85
|
return
|
|
89
|
86
|
|
|
90
|
87
|
if self._request_in_progress:
|
| ... |
... |
@@ -99,14 +96,14 @@ class Bookmarks(BaseModule): |
|
99
|
96
|
app.nec.push_incoming_event(
|
|
100
|
97
|
NetworkEvent('bookmarks-received', account=self._account))
|
|
101
|
98
|
|
|
102
|
|
- @event_node(Namespace.BOOKMARKS_2)
|
|
103
|
|
- def _bookmark_2_event_received(self, _con, _stanza, properties):
|
|
|
99
|
+ @event_node(Namespace.BOOKMARKS_1)
|
|
|
100
|
+ def _bookmark_1_event_received(self, _con, _stanza, properties):
|
|
104
|
101
|
if not properties.is_self_message:
|
|
105
|
102
|
self._log.warning('%s has an open access bookmarks node',
|
|
106
|
103
|
properties.jid)
|
|
107
|
104
|
return
|
|
108
|
105
|
|
|
109
|
|
- if not self.using_bookmark_2:
|
|
|
106
|
+ if not self.nativ_bookmarks_used:
|
|
110
|
107
|
return
|
|
111
|
108
|
|
|
112
|
109
|
if self._request_in_progress:
|
| ... |
... |
@@ -135,18 +132,21 @@ class Bookmarks(BaseModule): |
|
135
|
132
|
NetworkEvent('bookmarks-received', account=self._account))
|
|
136
|
133
|
|
|
137
|
134
|
def pass_disco(self, info):
|
|
138
|
|
- if app.settings.get('dev_force_bookmark_2'):
|
|
139
|
|
- self._log.info('Forcing Bookmark 2 usage, '
|
|
140
|
|
- 'without server conversion support: %s', info.jid)
|
|
141
|
|
- self._conversion_2 = True
|
|
|
135
|
+ self._compat_pep = Namespace.BOOKMARKS_COMPAT_PEP in info.features
|
|
|
136
|
+ self._compat = Namespace.BOOKMARKS_COMPAT in info.features
|
|
|
137
|
+ self._conversion = Namespace.BOOKMARK_CONVERSION in info.features
|
|
|
138
|
+
|
|
|
139
|
+ @functools.lru_cache(maxsize=1)
|
|
|
140
|
+ def _bookmark_module(self):
|
|
|
141
|
+ if not self._con.get_module('PubSub').publish_options:
|
|
|
142
|
+ return 'PrivateBookmarks'
|
|
142
|
143
|
|
|
143
|
|
- elif Namespace.BOOKMARKS_COMPAT in info.features:
|
|
144
|
|
- self._conversion_2 = True
|
|
145
|
|
- self._log.info('Discovered Bookmarks Conversion 2: %s', info.jid)
|
|
|
144
|
+ if app.settings.get('dev_force_bookmark_2') or self._compat_pep:
|
|
|
145
|
+ return 'NativeBookmarks'
|
|
146
|
146
|
|
|
147
|
|
- elif Namespace.BOOKMARK_CONVERSION in info.features:
|
|
148
|
|
- self._conversion = True
|
|
149
|
|
- self._log.info('Discovered Bookmarks Conversion: %s', info.jid)
|
|
|
147
|
+ if self._conversion:
|
|
|
148
|
+ return 'PEPBookmarks'
|
|
|
149
|
+ return 'PrivateBookmarks'
|
|
150
|
150
|
|
|
151
|
151
|
def _act_on_changed_bookmarks(
|
|
152
|
152
|
self, old_bookmarks: Dict[str, BookmarkData]) -> None:
|
| ... |
... |
@@ -194,28 +194,19 @@ class Bookmarks(BaseModule): |
|
194
|
194
|
def get_bookmark(self, jid: Union[str, JID]) -> BookmarkData:
|
|
195
|
195
|
return self._bookmarks.get(jid)
|
|
196
|
196
|
|
|
197
|
|
- def _pubsub_support(self) -> bool:
|
|
198
|
|
- return (self._con.get_module('PEP').supported and
|
|
199
|
|
- self._con.get_module('PubSub').publish_options)
|
|
200
|
|
-
|
|
201
|
197
|
def request_bookmarks(self) -> None:
|
|
202
|
198
|
if not app.account_is_available(self._account):
|
|
203
|
199
|
return
|
|
204
|
200
|
|
|
205
|
201
|
self._request_in_progress = True
|
|
206
|
|
- type_ = BookmarkStoreType.PRIVATE
|
|
207
|
|
- if self._pubsub_support():
|
|
208
|
|
- if self.conversion:
|
|
209
|
|
- type_ = BookmarkStoreType.PUBSUB_BOOKMARK_1
|
|
210
|
|
- if self._conversion_2:
|
|
211
|
|
- type_ = BookmarkStoreType.PUBSUB_BOOKMARK_2
|
|
212
|
|
-
|
|
213
|
|
- self._nbxmpp('Bookmarks').request_bookmarks(
|
|
214
|
|
- type_, callback=self._bookmarks_received)
|
|
215
|
|
-
|
|
216
|
|
- def _bookmarks_received(self, bookmarks: Any) -> None:
|
|
217
|
|
- if is_error_result(bookmarks):
|
|
218
|
|
- self._log.info(bookmarks)
|
|
|
202
|
+ self._nbxmpp(self._bookmark_module()).request_bookmarks(
|
|
|
203
|
+ callback=self._bookmarks_received)
|
|
|
204
|
+
|
|
|
205
|
+ def _bookmarks_received(self, task: Any) -> None:
|
|
|
206
|
+ try:
|
|
|
207
|
+ bookmarks = task.finish()
|
|
|
208
|
+ except Exception as error:
|
|
|
209
|
+ self._log.warning(error)
|
|
219
|
210
|
bookmarks = None
|
|
220
|
211
|
|
|
221
|
212
|
self._request_in_progress = False
|
| ... |
... |
@@ -225,7 +216,7 @@ class Bookmarks(BaseModule): |
|
225
|
216
|
NetworkEvent('bookmarks-received', account=self._account))
|
|
226
|
217
|
|
|
227
|
218
|
def store_difference(self, bookmarks: List) -> None:
|
|
228
|
|
- if self.using_bookmark_2:
|
|
|
219
|
+ if self.nativ_bookmarks_used:
|
|
229
|
220
|
retract, add_or_modify = self._determine_changed_bookmarks(
|
|
230
|
221
|
bookmarks, self._bookmarks)
|
|
231
|
222
|
|
| ... |
... |
@@ -244,30 +235,10 @@ class Bookmarks(BaseModule): |
|
244
|
235
|
if not app.account_is_available(self._account):
|
|
245
|
236
|
return
|
|
246
|
237
|
|
|
247
|
|
- type_ = BookmarkStoreType.PRIVATE
|
|
248
|
|
- if self._pubsub_support():
|
|
249
|
|
- if self.conversion:
|
|
250
|
|
- type_ = BookmarkStoreType.PUBSUB_BOOKMARK_1
|
|
251
|
|
- if self.conversion_2:
|
|
252
|
|
- type_ = BookmarkStoreType.PUBSUB_BOOKMARK_2
|
|
253
|
|
-
|
|
254
|
|
- if bookmarks is None:
|
|
|
238
|
+ if bookmarks is None or not self.nativ_bookmarks_used:
|
|
255
|
239
|
bookmarks = self._bookmarks.values()
|
|
256
|
240
|
|
|
257
|
|
- self._nbxmpp('Bookmarks').store_bookmarks(bookmarks, type_)
|
|
258
|
|
-
|
|
259
|
|
- app.nec.push_incoming_event(
|
|
260
|
|
- NetworkEvent('bookmarks-received', account=self._account))
|
|
261
|
|
-
|
|
262
|
|
- def store_bookmark(self, bookmark: BookmarkData) -> None:
|
|
263
|
|
- if not app.account_is_available(self._account):
|
|
264
|
|
- return
|
|
265
|
|
-
|
|
266
|
|
- if not self.using_bookmark_2:
|
|
267
|
|
- return
|
|
268
|
|
-
|
|
269
|
|
- self._nbxmpp('Bookmarks').store_bookmarks(
|
|
270
|
|
- [bookmark], BookmarkStoreType.PUBSUB_BOOKMARK_2)
|
|
|
241
|
+ self._nbxmpp(self._bookmark_module()).store_bookmarks(bookmarks)
|
|
271
|
242
|
|
|
272
|
243
|
app.nec.push_incoming_event(
|
|
273
|
244
|
NetworkEvent('bookmarks-received', account=self._account))
|
| ... |
... |
@@ -308,10 +279,7 @@ class Bookmarks(BaseModule): |
|
308
|
279
|
self._log.info('Modify bookmark: %s %s', jid, kwargs)
|
|
309
|
280
|
self._bookmarks[jid] = new_bookmark
|
|
310
|
281
|
|
|
311
|
|
- if self.using_bookmark_2:
|
|
312
|
|
- self.store_bookmark(new_bookmark)
|
|
313
|
|
- else:
|
|
314
|
|
- self.store_bookmarks()
|
|
|
282
|
+ self.store_bookmarks([new_bookmark])
|
|
315
|
283
|
|
|
316
|
284
|
def add_or_modify(self, jid: str, **kwargs: Dict[str, str]) -> None:
|
|
317
|
285
|
bookmark = self._bookmarks.get(jid)
|
| ... |
... |
@@ -323,18 +291,15 @@ class Bookmarks(BaseModule): |
|
323
|
291
|
self._bookmarks[jid] = new_bookmark
|
|
324
|
292
|
self._log.info('Add new bookmark: %s', new_bookmark)
|
|
325
|
293
|
|
|
326
|
|
- if self.using_bookmark_2:
|
|
327
|
|
- self.store_bookmark(new_bookmark)
|
|
328
|
|
- else:
|
|
329
|
|
- self.store_bookmarks()
|
|
|
294
|
+ self.store_bookmarks([new_bookmark])
|
|
330
|
295
|
|
|
331
|
296
|
def remove(self, jid: JID, publish: bool = True) -> None:
|
|
332
|
297
|
removed = self._bookmarks.pop(jid, False)
|
|
333
|
298
|
if not removed:
|
|
334
|
299
|
return
|
|
335
|
300
|
if publish:
|
|
336
|
|
- if self.using_bookmark_2:
|
|
337
|
|
- self._nbxmpp('Bookmarks').retract_bookmark(str(jid))
|
|
|
301
|
+ if self.nativ_bookmarks_used:
|
|
|
302
|
+ self._nbxmpp('NativeBookmarks').retract_bookmark(str(jid))
|
|
338
|
303
|
else:
|
|
339
|
304
|
self.store_bookmarks()
|
|
340
|
305
|
|
| ... |
... |
@@ -368,12 +333,6 @@ class Bookmarks(BaseModule): |
|
368
|
333
|
def is_bookmark(self, jid: str) -> bool:
|
|
369
|
334
|
return jid in self._bookmarks
|
|
370
|
335
|
|
|
371
|
|
- def purge_pubsub_bookmarks(self) -> None:
|
|
372
|
|
- self._log.info('Purge/Delete Bookmarks on PubSub, '
|
|
373
|
|
- 'because publish options are not available')
|
|
374
|
|
- self._con.get_module('PubSub').send_pb_purge('', 'storage:bookmarks')
|
|
375
|
|
- self._con.get_module('PubSub').send_pb_delete('', 'storage:bookmarks')
|
|
376
|
|
-
|
|
377
|
336
|
def _remove_timeouts(self):
|
|
378
|
337
|
for _id in self._join_timeouts:
|
|
379
|
338
|
GLib.source_remove(_id)
|