XEP-0446: complete support and tests

This commit is contained in:
mathieui 2025-02-02 12:16:07 +01:00
parent 8c8bb5da8b
commit 04244ecf82
No known key found for this signature in database
GPG Key ID: C59F84CEEFD616E3
5 changed files with 160 additions and 7 deletions

View File

@ -916,6 +916,14 @@
<xmpp:since>1.6.0</xmpp:since> <xmpp:since>1.6.0</xmpp:since>
</xmpp:SupportedXep> </xmpp:SupportedXep>
</implements> </implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0446.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:version>0.2.0</xmpp:version>
<xmpp:since>1.8.7</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements> <implements>
<xmpp:SupportedXep> <xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0454.html"/> <xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0454.html"/>

View File

@ -118,6 +118,7 @@ PLUGINS = [
'xep_0439', # Quick Response 'xep_0439', # Quick Response
'xep_0441', # Message Archive Management Preferences 'xep_0441', # Message Archive Management Preferences
'xep_0444', # Message Reactions 'xep_0444', # Message Reactions
'xep_0446', # File metadata element
'xep_0447', # Stateless file sharing 'xep_0447', # Stateless file sharing
'xep_0461', # Message Replies 'xep_0461', # Message Replies
'xep_0469', # Bookmarks Pinning 'xep_0469', # Bookmarks Pinning

View File

@ -18,3 +18,7 @@ class XEP_0446(BasePlugin):
name = "xep_0446" name = "xep_0446"
description = "XEP-0446: File metadata element" description = "XEP-0446: File metadata element"
stanza = stanza stanza = stanza
dependencies = {'xep_0300', 'xep_0264'}
def plugin_init(self):
stanza.register_plugins()

View File

@ -1,7 +1,10 @@
from datetime import datetime from datetime import datetime
from typing import Optional
from slixmpp.plugins.xep_0082 import format_datetime, parse from slixmpp.plugins.xep_0082 import format_datetime, parse
from slixmpp.xmlstream import ElementBase from slixmpp.plugins.xep_0300 import Hash
from slixmpp.plugins.xep_0264.stanza import Thumbnail
from slixmpp.xmlstream import ElementBase, register_stanza_plugin
NS = "urn:xmpp:file:metadata:0" NS = "urn:xmpp:file:metadata:0"
@ -10,15 +13,42 @@ class File(ElementBase):
name = "file" name = "file"
namespace = NS namespace = NS
plugin_attrib = "file" plugin_attrib = "file"
interfaces = sub_interfaces = {"media-type", "name", "date", "size", "hash", "desc"} interfaces = sub_interfaces = {
"media-type",
"name",
"date",
"size",
"desc",
"width",
"height",
"length"
}
def set_width(self, width: int):
self.__set_if_positive("width", width)
def get_width(self) -> Optional[int]:
return _positive_int_or_none(self._get_sub_text("width"))
def set_height(self, height: int):
self.__set_if_positive("height", height)
def get_height(self) -> Optional[int]:
return _positive_int_or_none(self._get_sub_text("height"))
def set_length(self, length: int):
self.__set_if_positive("length", length)
def get_length(self) -> Optional[int]:
return _positive_int_or_none(self._get_sub_text("length"))
def set_size(self, size: int): def set_size(self, size: int):
self._set_sub_text("size", str(size)) self.__set_if_positive("size", size)
def get_size(self): def get_size(self) -> Optional[int]:
return _int_or_none(self._get_sub_text("size")) return _positive_int_or_none(self._get_sub_text("size"))
def get_date(self): def get_date(self) -> Optional[datetime]:
try: try:
return parse(self._get_sub_text("date")) return parse(self._get_sub_text("date"))
except ValueError: except ValueError:
@ -30,9 +60,18 @@ class File(ElementBase):
except ValueError: except ValueError:
pass pass
def __set_if_positive(self, key: str, value: int):
if value <= 0:
raise ValueError(f"Invalid value for element {key}: {value}")
self._set_sub_text(key, str(value))
def _int_or_none(v):
def _positive_int_or_none(v: str) -> Optional[int]:
try: try:
return int(v) return int(v)
except ValueError: except ValueError:
return None return None
def register_plugins():
register_stanza_plugin(File, Hash)
register_stanza_plugin(File, Thumbnail)

View File

@ -0,0 +1,101 @@
import unittest
from slixmpp.test import SlixTest
from slixmpp.plugins.xep_0446 import stanza
class TestFileMeta(SlixTest):
def setUp(self):
stanza.register_plugins()
def test_simple(self):
file = stanza.File()
file["desc"] = "a description"
file["name"] = "toto.jpg"
file["media-type"] = "image/jpeg"
file["height"] = 1024
file["width"] = 768
file["size"] = 2048
self.check(
file,
"""
<file xmlns='urn:xmpp:file:metadata:0'>
<desc>a description</desc>
<name>toto.jpg</name>
<media-type>image/jpeg</media-type>
<height>1024</height>
<width>768</width>
<size>2048</size>
</file>
""",
)
def test_bad_value(self):
file = stanza.File()
file["desc"] = "My great video"
file["name"] = "toto.mp4"
file["media-type"] = "video/3gpp"
file["height"] = 1024
file["width"] = 768
with self.assertRaises(ValueError):
file["length"] = -100
def test_hash_element(self):
file = stanza.File()
file["desc"] = "My great video"
file["name"] = "toto.3gp"
file["media-type"] = "video/3gpp"
file["height"] = 1024
file["width"] = 768
file["length"] = 2000
file["hash"]["algo"] = "sha3-256"
file["hash"]["value"] = "abcdef="
self.check(
file,
"""
<file xmlns='urn:xmpp:file:metadata:0'>
<desc>My great video</desc>
<name>toto.3gp</name>
<media-type>video/3gpp</media-type>
<height>1024</height>
<width>768</width>
<length>2000</length>
<hash xmlns='urn:xmpp:hashes:2' algo="sha3-256">abcdef=</hash>
</file>
""",
)
def test_thumbnail_element(self):
file = stanza.File()
file["desc"] = "a description"
file["name"] = "toto.jpg"
file["media-type"] = "image/jpeg"
file["height"] = 1024
file["width"] = 768
file["size"] = 2048
file["thumbnail"]["media-type"] = "image/png"
file["thumbnail"]["uri"] = "cid:sha1+deadbeef@bob.xmpp.org"
file["thumbnail"]["width"] = 128
file["thumbnail"]["height"] = 96
self.check(
file,
"""
<file xmlns='urn:xmpp:file:metadata:0'>
<desc>a description</desc>
<name>toto.jpg</name>
<media-type>image/jpeg</media-type>
<height>1024</height>
<width>768</width>
<size>2048</size>
<thumbnail xmlns='urn:xmpp:thumbs:1'
uri='cid:sha1+deadbeef@bob.xmpp.org'
media-type='image/png'
width='128'
height='96'/>
</file>
""",
)
suite = unittest.TestLoader().loadTestsFromTestCase(TestFileMeta)