comparison sat/core/xmpp.py @ 3254:6cf4bd6972c2

core, frontends: avatar refactoring: /!\ huge commit Avatar logic has been reworked around the IDENTITY plugin: plugins able to handle avatar or other identity related metadata (like nicknames) register to IDENTITY plugin in the same way as for other features like download/upload. Once registered, IDENTITY plugin will call them when suitable in order of priority, and handle caching. Methods to manage those metadata from frontend now use serialised data. For now `avatar` and `nicknames` are handled: - `avatar` is now a dict with `path` + metadata like `media_type`, instead of just a string path - `nicknames` is now a list of nicknames in order of priority. This list is never empty, and `nicknames[0]` should be the preferred nickname to use by frontends in most cases. In addition to contact specified nicknames, user set nickname (the one set in roster) is used in priority when available. Among the side changes done with this commit, there are: - a new `contactGet` bridge method to get roster metadata for a single contact - SatPresenceProtocol.send returns a Deferred to check when it has actually been sent - memory's methods to handle entities data now use `client` as first argument - metadata filter can be specified with `getIdentity` - `getAvatar` and `setAvatar` are now part of the IDENTITY plugin instead of XEP-0054 (and there signature has changed) - `isRoom` and `getBareOrFull` are now part of XEP-0045 plugin - jp avatar/get command uses `xdg-open` first when available for `--show` flag - `--no-cache` has been added to jp avatar/get and identity/get - jp identity/set has been simplified, explicit options (`--nickname` only for now) are used instead of `--field`. `--field` may come back in the future if necessary for extra data. - QuickContactList `SetContact` now handle None as a value, and doesn't use it to delete the metadata anymore - improved cache handling for `metadata` and `nicknames` in quick frontend - new `default` argument in QuickContactList `getCache`
author Goffi <goffi@goffi.org>
date Tue, 14 Apr 2020 21:00:33 +0200
parents f16c96c7a91a
children 5369ce5bcecf
comparison
equal deleted inserted replaced
3253:1af840e84af7 3254:6cf4bd6972c2
648 elif not data["to"].resource: # if to JID has a resource, 648 elif not data["to"].resource: # if to JID has a resource,
649 # the type is not 'groupchat' 649 # the type is not 'groupchat'
650 # we may have a groupchat message, we check if the we know this jid 650 # we may have a groupchat message, we check if the we know this jid
651 try: 651 try:
652 entity_type = self.host_app.memory.getEntityDatum( 652 entity_type = self.host_app.memory.getEntityDatum(
653 data["to"], C.ENTITY_TYPE, self.profile 653 self, data["to"], C.ENTITY_TYPE
654 ) 654 )
655 # FIXME: should entity_type manage resources ? 655 # FIXME: should entity_type manage resources ?
656 except (exceptions.UnknownEntityError, KeyError): 656 except (exceptions.UnknownEntityError, KeyError):
657 entity_type = "contact" 657 entity_type = "contact"
658 658
1549 else: 1549 else:
1550 return item.name or entity_jid.user 1550 return item.name or entity_jid.user
1551 1551
1552 1552
1553 class SatPresenceProtocol(xmppim.PresenceClientProtocol): 1553 class SatPresenceProtocol(xmppim.PresenceClientProtocol):
1554
1554 def __init__(self, host): 1555 def __init__(self, host):
1555 xmppim.PresenceClientProtocol.__init__(self) 1556 xmppim.PresenceClientProtocol.__init__(self)
1556 self.host = host 1557 self.host = host
1558
1559 @property
1560 def client(self):
1561 return self.parent
1557 1562
1558 def send(self, obj): 1563 def send(self, obj):
1559 presence_d = defer.succeed(None) 1564 presence_d = defer.succeed(None)
1560 if not self.host.trigger.point("Presence send", self.parent, obj, presence_d): 1565 if not self.host.trigger.point("Presence send", self.parent, obj, presence_d):
1561 return 1566 return
1562 presence_d.addCallback(lambda __: super(SatPresenceProtocol, self).send(obj)) 1567 presence_d.addCallback(lambda __: super(SatPresenceProtocol, self).send(obj))
1568 return presence_d
1563 1569
1564 def availableReceived(self, entity, show=None, statuses=None, priority=0): 1570 def availableReceived(self, entity, show=None, statuses=None, priority=0):
1565 if not statuses: 1571 if not statuses:
1566 statuses = {} 1572 statuses = {}
1567 1573
1602 # now it's time to notify frontends 1608 # now it's time to notify frontends
1603 # if the entity is not known yet in this session or is already unavailable, 1609 # if the entity is not known yet in this session or is already unavailable,
1604 # there is no need to send an unavailable signal 1610 # there is no need to send an unavailable signal
1605 try: 1611 try:
1606 presence = self.host.memory.getEntityDatum( 1612 presence = self.host.memory.getEntityDatum(
1607 entity, "presence", self.parent.profile 1613 self.client, entity, "presence"
1608 ) 1614 )
1609 except (KeyError, exceptions.UnknownEntityError): 1615 except (KeyError, exceptions.UnknownEntityError):
1610 # the entity has not been seen yet in this session 1616 # the entity has not been seen yet in this session
1611 pass 1617 pass
1612 else: 1618 else:
1655 if None in statuses: 1661 if None in statuses:
1656 statuses["default"] = statuses.pop(None) 1662 statuses["default"] = statuses.pop(None)
1657 1663
1658 if not self.host.trigger.point("presence_available", presence_elt, self.parent): 1664 if not self.host.trigger.point("presence_available", presence_elt, self.parent):
1659 return 1665 return
1660 self.send(presence_elt) 1666 return self.send(presence_elt)
1661 1667
1662 @defer.inlineCallbacks 1668 @defer.inlineCallbacks
1663 def subscribed(self, entity): 1669 def subscribed(self, entity):
1664 yield self.parent.roster.got_roster 1670 yield self.parent.roster.got_roster
1665 xmppim.PresenceClientProtocol.subscribed(self, entity) 1671 xmppim.PresenceClientProtocol.subscribed(self, entity)