Fix SVG uploads, fix entire Upload model deleted

This commit is contained in:
miruka 2019-11-06 07:50:31 -04:00
parent ace79a169c
commit 4c15b7dc62
4 changed files with 41 additions and 8 deletions

View File

@ -1,5 +1,4 @@
- Media
- SVG uploads
- Uploading progress bar (+local echo)
- Text bubbles theming
- Directly create cache files for our uploads before actually uploading

View File

@ -1,6 +1,7 @@
hsluv == 0.0.2
Pillow >= 5.4.1, < 6
pymediainfo >= 4.1, < 5
cairosvg >= 2.4.2, < 3
aiofiles >= 0.4.0, < 0.5
appdirs >= 1.4.3, < 2
filetype >= 1.0.5, < 2

View File

@ -18,6 +18,7 @@ from typing import (
)
from uuid import uuid4
import cairosvg
from PIL import Image as PILImage
from pymediainfo import MediaInfo
@ -252,18 +253,22 @@ class MatrixClient(nio.AsyncClient):
content["url"] = url
if kind == "image":
is_svg = mime == "image/svg+xml"
event_type = \
nio.RoomEncryptedImage if encrypt else nio.RoomMessageImage
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
)
try:
thumb_url, thumb_info, thumb_crypt_dict = \
await self.upload_thumbnail(
path, upload_item, encrypt=encrypt,
path, upload_item, is_svg=is_svg, encrypt=encrypt,
)
except (UneededThumbnail, UnthumbnailableError):
pass
@ -313,7 +318,7 @@ class MatrixClient(nio.AsyncClient):
content["filename"] = path.name
upload_item.status = UploadStatus.Success
del self.models[Upload, room_id]
del self.models[Upload, room_id][upload_item.uuid]
uuid = str(uuid4())
@ -451,19 +456,31 @@ class MatrixClient(nio.AsyncClient):
self,
path: Union[Path, str],
item: Optional[Upload] = None,
is_svg: bool = False,
encrypt: bool = False,
) -> Tuple[str, Dict[str, Any], CryptDict]:
png_modes = ("1", "L", "P", "RGBA")
try:
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
is_jpg_png = thumb.format in ("JPEG", "PNG")
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()
if item:

View File

@ -3,7 +3,7 @@ import html
import xml.etree.cElementTree as xml_etree # FIXME: bandit warning
from enum import Enum
from enum import auto as autostr
from typing import IO, Optional
from typing import IO, Tuple, Union
import filetype
@ -26,7 +26,7 @@ def dict_update_recursive(dict1, dict2):
dict1[k] = dict2[k]
def is_svg(file: IO) -> bool:
def is_svg(file: Union[IO, bytes, str]) -> bool:
try:
_, element = next(xml_etree.iterparse(file, ("start",)))
return element.tag == "{http://www.w3.org/2000/svg}svg"
@ -34,6 +34,22 @@ def is_svg(file: IO) -> bool:
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:
if is_svg(file):
return "image/svg+xml"