plugin XEP-0084: Support multiple images format:
XEP-0084 implementation was only supporting PNG, but some client (notably Conversations) don't publish PNG, so we have to handle a few other formats.
This commit is contained in:
parent
e241075a34
commit
b65325c1d6
1 changed files with 37 additions and 10 deletions
|
|
@ -35,6 +35,9 @@ from tx_xmpp import disco, itx_xmpp, pubsub
|
|||
|
||||
log = getLogger(__name__)
|
||||
|
||||
# Supported image formats, in priority order
|
||||
FORMATS = ("png", "jpeg", "webp", "gif", "svg+xml")
|
||||
|
||||
IMPORT_NAME = "XEP-0084"
|
||||
|
||||
PLUGIN_INFO = {
|
||||
|
|
@ -79,6 +82,9 @@ class XEP_0084:
|
|||
client = self.host.get_client(profile)
|
||||
defer.ensureDeferred(self.on_metadata_update(client, itemsEvent))
|
||||
|
||||
class UnsupportedFormat(Exception):
|
||||
"""Avatar metadata exists but no supported format is found."""
|
||||
|
||||
@staticmethod
|
||||
def _parse_metadata_info(
|
||||
item_elt: domish.Element,
|
||||
|
|
@ -86,8 +92,8 @@ class XEP_0084:
|
|||
"""Parse avatar metadata item and extract ID, media type, and size.
|
||||
|
||||
@param item_elt: pubsub item element containing metadata.
|
||||
@return: (avatar_id, media_type, size) if a valid info element is found,
|
||||
None if avatar is disabled or metadata is invalid.
|
||||
@return: (avatar_id, media_type, size) if a supported format is found,
|
||||
None if avatar is disabled or no supported format is found.
|
||||
"""
|
||||
try:
|
||||
metadata_elt = next(item_elt.elements(NS_AVATAR_METADATA, "metadata"))
|
||||
|
|
@ -95,6 +101,8 @@ class XEP_0084:
|
|||
log.warning(f"missing metadata element: {item_elt.toXml()}")
|
||||
return None
|
||||
|
||||
# (priority, id, type, size)
|
||||
candidates: list[tuple[int, str, str, int]] = []
|
||||
for info_elt in metadata_elt.elements(NS_AVATAR_METADATA, "info"):
|
||||
try:
|
||||
avatar_id = str(info_elt["id"])
|
||||
|
|
@ -104,14 +112,26 @@ class XEP_0084:
|
|||
log.warning(f"invalid <info> element: {item_elt.toXml()}")
|
||||
continue
|
||||
if not avatar_id:
|
||||
# Avatar is explicitly disabled
|
||||
# (https://xmpp.org/extensions/xep-0084.html#pub-disable)
|
||||
return None
|
||||
if not media_type.startswith("image/"):
|
||||
continue
|
||||
# FIXME: to simplify, we only handle image/png for now
|
||||
if media_type == "image/png":
|
||||
return (avatar_id, media_type, size)
|
||||
subtype = media_type.split("/", 1)[1].lower()
|
||||
try:
|
||||
priority = FORMATS.index(subtype)
|
||||
except ValueError:
|
||||
continue
|
||||
candidates.append((priority, avatar_id, media_type, size))
|
||||
|
||||
# mandatory image/png is missing, or avatar is disabled
|
||||
# (https://xmpp.org/extensions/xep-0084.html#pub-disable)
|
||||
return None
|
||||
if not candidates:
|
||||
raise XEP_0084.UnsupportedFormat(
|
||||
f"no supported format found in avatar metadata"
|
||||
)
|
||||
|
||||
candidates.sort(key=lambda c: c[0])
|
||||
_, avatar_id, media_type, size = candidates[0]
|
||||
return (avatar_id, media_type, size)
|
||||
|
||||
async def on_metadata_update(
|
||||
self, client: SatXMPPEntity, itemsEvent: pubsub.ItemsEvent
|
||||
|
|
@ -130,7 +150,11 @@ class XEP_0084:
|
|||
await self._i.update(client, IMPORT_NAME, "avatar", None, entity)
|
||||
return
|
||||
|
||||
parsed = self._parse_metadata_info(items[0])
|
||||
try:
|
||||
parsed = self._parse_metadata_info(items[0])
|
||||
except XEP_0084.UnsupportedFormat:
|
||||
log.warning(f"Avatar for {entity.full()} is in unsupported format.")
|
||||
parsed = None
|
||||
if parsed is None:
|
||||
log.debug(f"Avatar disabled for {entity.full()}")
|
||||
await self._i.update(client, IMPORT_NAME, "avatar", None, entity)
|
||||
|
|
@ -223,7 +247,10 @@ class XEP_0084:
|
|||
if not data_items:
|
||||
return None
|
||||
|
||||
parsed = self._parse_metadata_info(data_items[0])
|
||||
try:
|
||||
parsed = self._parse_metadata_info(data_items[0])
|
||||
except XEP_0084.UnsupportedFormat:
|
||||
return None
|
||||
if parsed is None:
|
||||
return None
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue