| ... |
... |
@@ -16,9 +16,13 @@ |
|
16
|
16
|
|
|
17
|
17
|
from __future__ import annotations
|
|
18
|
18
|
|
|
|
19
|
+from typing import Any
|
|
|
20
|
+from typing import Callable
|
|
19
|
21
|
from typing import Generator
|
|
20
|
22
|
from typing import Optional
|
|
21
|
23
|
|
|
|
24
|
+import weakref
|
|
|
25
|
+
|
|
22
|
26
|
from nbxmpp.const import AvatarState
|
|
23
|
27
|
from nbxmpp.modules.util import is_error
|
|
24
|
28
|
from nbxmpp.modules.vcard_temp import VCard
|
| ... |
... |
@@ -31,8 +35,12 @@ |
|
31
|
35
|
|
|
32
|
36
|
from gajim.common import app
|
|
33
|
37
|
from gajim.common import types
|
|
|
38
|
+from gajim.common.task_manager import Task
|
|
34
|
39
|
from gajim.common.modules.base import BaseModule
|
|
35
|
40
|
from gajim.common.modules.util import as_task
|
|
|
41
|
+from gajim.common.modules.contacts import GroupchatContact
|
|
|
42
|
+from gajim.common.modules.contacts import GroupchatParticipant
|
|
|
43
|
+from gajim.common.modules.contacts import BareContact
|
|
36
|
44
|
|
|
37
|
45
|
|
|
38
|
46
|
class VCardAvatars(BaseModule):
|
| ... |
... |
@@ -62,13 +70,13 @@ def get_avatar_sha(self, jid: JID) -> Optional[str]: |
|
62
|
70
|
|
|
63
|
71
|
@as_task
|
|
64
|
72
|
def _request_vcard(self,
|
|
65
|
|
- jid: JID,
|
|
66
|
|
- expected_sha: str,
|
|
67
|
|
- type_: str
|
|
|
73
|
+ contact: types.ChatContactT,
|
|
|
74
|
+ expected_sha: str
|
|
68
|
75
|
) -> Generator[VCard, None, None]:
|
|
69
|
76
|
_task = yield # noqa: F841
|
|
70
|
77
|
|
|
71
|
|
- vcard = yield self._con.get_module('VCardTemp').request_vcard(jid=jid)
|
|
|
78
|
+ vcard = yield self._con.get_module('VCardTemp').request_vcard(
|
|
|
79
|
+ jid=contact.jid)
|
|
72
|
80
|
|
|
73
|
81
|
if is_error(vcard):
|
|
74
|
82
|
self._log.warning(vcard)
|
| ... |
... |
@@ -76,29 +84,27 @@ def _request_vcard(self, |
|
76
|
84
|
|
|
77
|
85
|
avatar, avatar_sha = vcard.get_avatar()
|
|
78
|
86
|
if avatar is None:
|
|
79
|
|
- self._log.info('Avatar missing: %s %s', jid, expected_sha)
|
|
|
87
|
+ self._log.info('Avatar missing: %s %s', contact.jid, expected_sha)
|
|
80
|
88
|
return
|
|
81
|
89
|
|
|
82
|
90
|
if expected_sha != avatar_sha:
|
|
83
|
91
|
self._log.warning('Avatar mismatch: %s %s != %s',
|
|
84
|
|
- jid,
|
|
|
92
|
+ contact.jid,
|
|
85
|
93
|
expected_sha,
|
|
86
|
94
|
avatar_sha)
|
|
87
|
95
|
return
|
|
88
|
96
|
|
|
89
|
|
- self._log.info('Received: %s %s', jid, avatar_sha)
|
|
|
97
|
+ self._log.info('Received: %s %s', contact.jid, avatar_sha)
|
|
90
|
98
|
app.interface.save_avatar(avatar)
|
|
91
|
99
|
|
|
92
|
|
- contact = self._con.get_module('Contacts').get_contact(jid)
|
|
93
|
|
-
|
|
94
|
|
- if type_ == 'contact':
|
|
95
|
|
- app.storage.cache.set_contact(jid, 'avatar', avatar_sha)
|
|
|
100
|
+ if isinstance(contact, BareContact):
|
|
|
101
|
+ app.storage.cache.set_contact(contact.jid, 'avatar', avatar_sha)
|
|
96
|
102
|
|
|
97
|
|
- elif type_ == 'muc':
|
|
98
|
|
- app.storage.cache.set_muc(jid, 'avatar', avatar_sha)
|
|
|
103
|
+ elif isinstance(contact, GroupchatContact):
|
|
|
104
|
+ app.storage.cache.set_muc(contact.jid, 'avatar', avatar_sha)
|
|
99
|
105
|
|
|
100
|
|
- elif type_ == 'muc-user':
|
|
101
|
|
- self._muc_avatar_cache[jid] = avatar_sha
|
|
|
106
|
+ else:
|
|
|
107
|
+ self._muc_avatar_cache[contact.jid] = avatar_sha
|
|
102
|
108
|
|
|
103
|
109
|
contact.update_avatar(avatar_sha)
|
|
104
|
110
|
|
| ... |
... |
@@ -180,10 +186,11 @@ def _process_update(self, |
|
180
|
186
|
|
|
181
|
187
|
if avatar_sha not in self._requested_shas:
|
|
182
|
188
|
self._requested_shas.append(avatar_sha)
|
|
183
|
|
- if groupchat:
|
|
184
|
|
- self._request_vcard(jid, avatar_sha, 'muc')
|
|
185
|
|
- else:
|
|
186
|
|
- self._request_vcard(jid, avatar_sha, 'contact')
|
|
|
189
|
+
|
|
|
190
|
+ task = VCardAvatarsTask(contact,
|
|
|
191
|
+ avatar_sha,
|
|
|
192
|
+ self._request_vcard)
|
|
|
193
|
+ app.task_manager.add_task(task)
|
|
187
|
194
|
|
|
188
|
195
|
def _muc_update_received(self, properties: PresenceProperties) -> None:
|
|
189
|
196
|
contact = self._con.get_module('Contacts').get_contact(properties.jid,
|
| ... |
... |
@@ -202,9 +209,11 @@ def _muc_update_received(self, properties: PresenceProperties) -> None: |
|
202
|
209
|
if properties.avatar_sha not in self._requested_shas:
|
|
203
|
210
|
app.log('avatar').info('Request: %s', nick)
|
|
204
|
211
|
self._requested_shas.append(properties.avatar_sha)
|
|
205
|
|
- self._request_vcard(properties.jid,
|
|
206
|
|
- properties.avatar_sha,
|
|
207
|
|
- 'muc-user')
|
|
|
212
|
+
|
|
|
213
|
+ task = VCardAvatarsTask(contact,
|
|
|
214
|
+ properties.avatar_sha,
|
|
|
215
|
+ self._request_vcard)
|
|
|
216
|
+ app.task_manager.add_task(task)
|
|
208
|
217
|
return
|
|
209
|
218
|
|
|
210
|
219
|
current_avatar_sha = self._muc_avatar_cache.get(properties.jid)
|
| ... |
... |
@@ -216,3 +225,48 @@ def _muc_update_received(self, properties: PresenceProperties) -> None: |
|
216
|
225
|
|
|
217
|
226
|
else:
|
|
218
|
227
|
self._log.info('Avatar already known: %s', nick)
|
|
|
228
|
+
|
|
|
229
|
+
|
|
|
230
|
+class VCardAvatarsTask(Task):
|
|
|
231
|
+ def __init__(self,
|
|
|
232
|
+ contact: Any,
|
|
|
233
|
+ sha: str,
|
|
|
234
|
+ callback: Callable[..., Any]
|
|
|
235
|
+ ) -> None:
|
|
|
236
|
+
|
|
|
237
|
+ Task.__init__(self)
|
|
|
238
|
+ self._contact = contact
|
|
|
239
|
+ self._sha = sha
|
|
|
240
|
+ self._callback = weakref.WeakMethod(callback)
|
|
|
241
|
+
|
|
|
242
|
+ def execute(self) -> None:
|
|
|
243
|
+ callback = self._callback()
|
|
|
244
|
+ if callback is not None:
|
|
|
245
|
+ callback(self._contact, self._sha)
|
|
|
246
|
+
|
|
|
247
|
+ def preconditions_met(self) -> bool:
|
|
|
248
|
+ try:
|
|
|
249
|
+ client = app.get_client(self._contact.account)
|
|
|
250
|
+ except Exception:
|
|
|
251
|
+ return False
|
|
|
252
|
+
|
|
|
253
|
+ if not client.state.is_available:
|
|
|
254
|
+ return False
|
|
|
255
|
+
|
|
|
256
|
+ if isinstance(self._contact, GroupchatContact):
|
|
|
257
|
+ if not self._contact.is_joined:
|
|
|
258
|
+ self.set_obsolete()
|
|
|
259
|
+ return False
|
|
|
260
|
+
|
|
|
261
|
+ elif isinstance(self._contact, GroupchatParticipant):
|
|
|
262
|
+ if not self._contact.room.is_joined:
|
|
|
263
|
+ self.set_obsolete()
|
|
|
264
|
+ return False
|
|
|
265
|
+
|
|
|
266
|
+ return True
|
|
|
267
|
+
|
|
|
268
|
+ def __repr__(self) -> str:
|
|
|
269
|
+ return f'VCardAvatars ({self._contact.jid} {self._sha})'
|
|
|
270
|
+
|
|
|
271
|
+ def __hash__(self) -> int:
|
|
|
272
|
+ return hash((self._contact, self._sha)) |