From 029303cbf2a88ebff52299622a84ad690a70786b Mon Sep 17 00:00:00 2001 From: bdvllrs Date: Tue, 7 Feb 2023 20:19:48 +0100 Subject: [PATCH] Add option to convert webp images to gifs --- mautrix_facebook/config.py | 2 ++ mautrix_facebook/example-config.yaml | 4 ++++ mautrix_facebook/portal.py | 21 ++++++++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/mautrix_facebook/config.py b/mautrix_facebook/config.py index c803e197..ea6c1734 100644 --- a/mautrix_facebook/config.py +++ b/mautrix_facebook/config.py @@ -142,6 +142,8 @@ def do_update(self, helper: ConfigUpdateHelper) -> None: if isinstance(value, list) and len(value) != 2: raise ValueError(f"{key} must only be a list of two items") + copy("bridge.convert_animated_webp_attachments") + copy("facebook.device_seed") if base["facebook.device_seed"] == "generate": base["facebook.device_seed"] = self._new_token() diff --git a/mautrix_facebook/example-config.yaml b/mautrix_facebook/example-config.yaml index 256be8a9..da8fbfc6 100644 --- a/mautrix_facebook/example-config.yaml +++ b/mautrix_facebook/example-config.yaml @@ -365,6 +365,10 @@ bridge: m.video: '$sender_displayname sent a video' m.location: '$sender_displayname sent a location' + # Whether to convert animated webp to gifs. Element for Android does not support + # Animated WebP (https://github.com/vector-im/element-android/issues/2695). + convert_animated_webp_attachments: false + facebook: device_seed: generate default_region_hint: ODN diff --git a/mautrix_facebook/portal.py b/mautrix_facebook/portal.py index 6e3d8516..6b5ee669 100644 --- a/mautrix_facebook/portal.py +++ b/mautrix_facebook/portal.py @@ -340,6 +340,7 @@ async def _reupload_fb_file( referer: str = "messenger_thread_photo", find_size: bool = False, convert_audio: bool = False, + convert_animated_webp_to_gif: bool = False, ) -> tuple[ContentURI, FileInfo | VideoInfo | AudioInfo | ImageInfo, EncryptedFile | None]: if not url: raise ValueError("URL not provided") @@ -357,6 +358,22 @@ async def _reupload_fb_file( data, ".ogg", output_args=("-c:a", "libopus"), input_mime=mime ) mime = "audio/ogg" + if convert_animated_webp_to_gif and mime == "image/webp": + with Image.open(BytesIO(data)) as img: + with BytesIO() as data_bytes: + loop = img.info.get("loop", 0) + duration = img.info.get("duration", 70) + img.save( + data_bytes, + "gif", + save_all=True, + duration=duration, + loop=loop, + background=0, + ) + data = data_bytes.getvalue() + mime = "image/gif" + info = FileInfo(mimetype=mime, size=len(data)) if Image and mime.startswith("image/") and find_size: with Image.open(BytesIO(data)) as img: @@ -1930,6 +1947,7 @@ async def _convert_mqtt_attachment( return TextMessageEventContent( msgtype=MessageType.NOTICE, body="Unsupported attachment" ) + convert_animated_webp_to_gif = self.config["bridge.convert_animated_webp_attachments"] mxc, additional_info, decryption_info = await self._reupload_fb_file( url, source, @@ -1939,9 +1957,10 @@ async def _convert_mqtt_attachment( find_size=False, referer=referer, convert_audio=voice_message, + convert_animated_webp_to_gif=convert_animated_webp_to_gif, ) info.size = additional_info.size - info.mimetype = attachment.mime_type or additional_info.mimetype + info.mimetype = additional_info.mimetype or attachment.mime_type content = MediaMessageEventContent( url=mxc, file=decryption_info, msgtype=msgtype, body=filename, info=info )