plugin attach: handle large images resizing:

if `C.MESS_KEY_ATTACHMENTS_RESIZE` flag is set for an attachment, it will be checked, and
if it is a large image, a resized copy will be uploaded.
This commit is contained in:
Goffi 2020-03-22 14:04:16 +01:00
commit ddf8cf6ea7

View file

@ -16,15 +16,18 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from functools import partial
from pathlib import Path
from collections import namedtuple
from twisted.internet import defer
import mimetypes
import tempfile
import shutil
from sat.core.i18n import _
from sat.core import exceptions
from sat.core.constants import Const as C
from sat.core.log import getLogger
from sat.tools import utils
from sat.tools import image
log = getLogger(__name__)
@ -86,6 +89,46 @@ class AttachPlugin:
log.debug(f"new attachments handler: {handler}")
async def attachFiles(self, client, data):
"""Main method to attach file
It will do generic pre-treatment, and call the suitable attachments handler
"""
# we check attachment for pre-treatment like large image resizing
# media_type will be added if missing (and if it can be guessed from path)
attachments = data["extra"][C.MESS_KEY_ATTACHMENTS]
tmp_dirs_to_clean = []
for attachment in attachments:
if attachment.get(C.MESS_KEY_ATTACHMENTS_RESIZE, False):
path = Path(attachment["path"])
try:
media_type = attachment[C.MESS_KEY_ATTACHMENTS_MEDIA_TYPE]
except KeyError:
media_type = mimetypes.guess_type(path, strict=False)[0]
if media_type is None:
log.warning(
_("Can't resize attachment of unknown type: {attachment}")
.format(attachment=attachment))
continue
attachment[C.MESS_KEY_ATTACHMENTS_MEDIA_TYPE] = media_type
main_type = media_type.split('/')[0]
if main_type == "image":
report = image.check(self.host, path)
if report['too_large']:
tmp_dir = Path(tempfile.mkdtemp())
tmp_dirs_to_clean.append(tmp_dir)
new_path = tmp_dir / path.name
await image.resize(
path, report["recommended_size"], dest=new_path)
attachment["path"] = new_path
log.info(
_("Attachment {path!r} has been resized at {new_path!r}")
.format(path=str(path), new_path=str(new_path)))
else:
log.warning(
_("Can't resize attachment of type {main_type!r}: {attachment}")
.format(main_type=main_type, attachment=attachment))
if client.encryption.isEncryptionRequested(data):
handlers = self._attachments_handlers['encrypted']
else:
@ -103,6 +146,10 @@ class AttachPlugin:
await utils.asDeferred(handler.attach, client, data)
for dir_path in tmp_dirs_to_clean:
log.debug(f"Cleaning temporary directory at {dir_path}")
shutil.rmtree(dir_path)
return data
async def uploadFiles(self, client, data, upload_cb=None):
@ -186,13 +233,13 @@ class AttachPlugin:
return data
def _attachFiles(self, client, data):
def _attachFiles(self, data, client):
return defer.ensureDeferred(self.attachFiles(client, data))
def _sendMessageTrigger(
self, client, mess_data, pre_xml_treatments, post_xml_treatments):
if mess_data['extra'].get(C.MESS_KEY_ATTACHMENTS):
post_xml_treatments.addCallback(partial(self._attachFiles, client))
post_xml_treatments.addCallback(self._attachFiles, client=client)
return True
async def defaultCanHandle(self, client, data):