Fix SVG uploads, fix entire Upload model deleted
This commit is contained in:
parent
ace79a169c
commit
4c15b7dc62
1
TODO.md
1
TODO.md
@ -1,5 +1,4 @@
|
|||||||
- Media
|
- Media
|
||||||
- SVG uploads
|
|
||||||
- Uploading progress bar (+local echo)
|
- Uploading progress bar (+local echo)
|
||||||
- Text bubbles theming
|
- Text bubbles theming
|
||||||
- Directly create cache files for our uploads before actually uploading
|
- Directly create cache files for our uploads before actually uploading
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
hsluv == 0.0.2
|
hsluv == 0.0.2
|
||||||
Pillow >= 5.4.1, < 6
|
Pillow >= 5.4.1, < 6
|
||||||
pymediainfo >= 4.1, < 5
|
pymediainfo >= 4.1, < 5
|
||||||
|
cairosvg >= 2.4.2, < 3
|
||||||
aiofiles >= 0.4.0, < 0.5
|
aiofiles >= 0.4.0, < 0.5
|
||||||
appdirs >= 1.4.3, < 2
|
appdirs >= 1.4.3, < 2
|
||||||
filetype >= 1.0.5, < 2
|
filetype >= 1.0.5, < 2
|
||||||
|
@ -18,6 +18,7 @@ from typing import (
|
|||||||
)
|
)
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
|
import cairosvg
|
||||||
from PIL import Image as PILImage
|
from PIL import Image as PILImage
|
||||||
from pymediainfo import MediaInfo
|
from pymediainfo import MediaInfo
|
||||||
|
|
||||||
@ -252,18 +253,22 @@ class MatrixClient(nio.AsyncClient):
|
|||||||
content["url"] = url
|
content["url"] = url
|
||||||
|
|
||||||
if kind == "image":
|
if kind == "image":
|
||||||
|
is_svg = mime == "image/svg+xml"
|
||||||
|
|
||||||
event_type = \
|
event_type = \
|
||||||
nio.RoomEncryptedImage if encrypt else nio.RoomMessageImage
|
nio.RoomEncryptedImage if encrypt else nio.RoomMessageImage
|
||||||
|
|
||||||
content["msgtype"] = "m.image"
|
content["msgtype"] = "m.image"
|
||||||
|
|
||||||
content["info"]["w"], content["info"]["h"] = \
|
content["info"]["w"], content["info"]["h"] = (
|
||||||
|
utils.svg_dimensions(str(path)) if is_svg else
|
||||||
PILImage.open(path).size
|
PILImage.open(path).size
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
thumb_url, thumb_info, thumb_crypt_dict = \
|
thumb_url, thumb_info, thumb_crypt_dict = \
|
||||||
await self.upload_thumbnail(
|
await self.upload_thumbnail(
|
||||||
path, upload_item, encrypt=encrypt,
|
path, upload_item, is_svg=is_svg, encrypt=encrypt,
|
||||||
)
|
)
|
||||||
except (UneededThumbnail, UnthumbnailableError):
|
except (UneededThumbnail, UnthumbnailableError):
|
||||||
pass
|
pass
|
||||||
@ -313,7 +318,7 @@ class MatrixClient(nio.AsyncClient):
|
|||||||
content["filename"] = path.name
|
content["filename"] = path.name
|
||||||
|
|
||||||
upload_item.status = UploadStatus.Success
|
upload_item.status = UploadStatus.Success
|
||||||
del self.models[Upload, room_id]
|
del self.models[Upload, room_id][upload_item.uuid]
|
||||||
|
|
||||||
uuid = str(uuid4())
|
uuid = str(uuid4())
|
||||||
|
|
||||||
@ -451,19 +456,31 @@ class MatrixClient(nio.AsyncClient):
|
|||||||
self,
|
self,
|
||||||
path: Union[Path, str],
|
path: Union[Path, str],
|
||||||
item: Optional[Upload] = None,
|
item: Optional[Upload] = None,
|
||||||
|
is_svg: bool = False,
|
||||||
encrypt: bool = False,
|
encrypt: bool = False,
|
||||||
) -> Tuple[str, Dict[str, Any], CryptDict]:
|
) -> Tuple[str, Dict[str, Any], CryptDict]:
|
||||||
|
|
||||||
png_modes = ("1", "L", "P", "RGBA")
|
png_modes = ("1", "L", "P", "RGBA")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
thumb = PILImage.open(path)
|
if is_svg:
|
||||||
|
svg_width, svg_height = utils.svg_dimensions(str(path))
|
||||||
|
|
||||||
|
thumb = PILImage.open(io.BytesIO(
|
||||||
|
cairosvg.svg2png(
|
||||||
|
url = str(path),
|
||||||
|
parent_width = svg_width,
|
||||||
|
parent_height = svg_height,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
thumb = PILImage.open(path)
|
||||||
|
|
||||||
small = thumb.width <= 800 and thumb.height <= 600
|
small = thumb.width <= 800 and thumb.height <= 600
|
||||||
is_jpg_png = thumb.format in ("JPEG", "PNG")
|
is_jpg_png = thumb.format in ("JPEG", "PNG")
|
||||||
jpgable_png = thumb.format == "PNG" and thumb.mode not in png_modes
|
jpgable_png = thumb.format == "PNG" and thumb.mode not in png_modes
|
||||||
|
|
||||||
if small and is_jpg_png and not jpgable_png:
|
if small and is_jpg_png and not jpgable_png and not is_svg:
|
||||||
raise UneededThumbnail()
|
raise UneededThumbnail()
|
||||||
|
|
||||||
if item:
|
if item:
|
||||||
|
@ -3,7 +3,7 @@ import html
|
|||||||
import xml.etree.cElementTree as xml_etree # FIXME: bandit warning
|
import xml.etree.cElementTree as xml_etree # FIXME: bandit warning
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from enum import auto as autostr
|
from enum import auto as autostr
|
||||||
from typing import IO, Optional
|
from typing import IO, Tuple, Union
|
||||||
|
|
||||||
import filetype
|
import filetype
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ def dict_update_recursive(dict1, dict2):
|
|||||||
dict1[k] = dict2[k]
|
dict1[k] = dict2[k]
|
||||||
|
|
||||||
|
|
||||||
def is_svg(file: IO) -> bool:
|
def is_svg(file: Union[IO, bytes, str]) -> bool:
|
||||||
try:
|
try:
|
||||||
_, element = next(xml_etree.iterparse(file, ("start",)))
|
_, element = next(xml_etree.iterparse(file, ("start",)))
|
||||||
return element.tag == "{http://www.w3.org/2000/svg}svg"
|
return element.tag == "{http://www.w3.org/2000/svg}svg"
|
||||||
@ -34,6 +34,22 @@ def is_svg(file: IO) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def svg_dimensions(file: Union[IO, bytes, str]) -> Tuple[int, int]:
|
||||||
|
attrs = xml_etree.parse(file).getroot().attrib
|
||||||
|
|
||||||
|
try:
|
||||||
|
width = round(float(attrs.get("width", attrs["viewBox"].split()[3])))
|
||||||
|
except (KeyError, IndexError, ValueError, TypeError):
|
||||||
|
width = 256
|
||||||
|
|
||||||
|
try:
|
||||||
|
height = round(float(attrs.get("height", attrs["viewBox"].split()[4])))
|
||||||
|
except (KeyError, IndexError, ValueError, TypeError):
|
||||||
|
height = 256
|
||||||
|
|
||||||
|
return (width, height)
|
||||||
|
|
||||||
|
|
||||||
def guess_mime(file: IO) -> str:
|
def guess_mime(file: IO) -> str:
|
||||||
if is_svg(file):
|
if is_svg(file):
|
||||||
return "image/svg+xml"
|
return "image/svg+xml"
|
||||||
|
Loading…
Reference in New Issue
Block a user