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:
parent
cdf468a7c1
commit
ddf8cf6ea7
3 changed files with 52 additions and 4 deletions
|
|
@ -136,6 +136,7 @@ class Const(object):
|
|||
MESS_KEY_ATTACHMENTS = "attachments"
|
||||
MESS_KEY_ATTACHMENTS_MEDIA_TYPE = "media_type"
|
||||
MESS_KEY_ATTACHMENTS_PREVIEW = "preview"
|
||||
MESS_KEY_ATTACHMENTS_RESIZE = "resize"
|
||||
|
||||
# File encryption algorithms
|
||||
ENC_AES_GCM = "AES-GCM"
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ class XEP_0363(object):
|
|||
should be closed, but it is needed to send the progressFinished signal
|
||||
@param slot(Slot): put/get urls
|
||||
"""
|
||||
log.info("HTTP upload finished")
|
||||
log.info(f"HTTP upload finished ({slot.get})")
|
||||
sat_file.progressFinished({"url": slot.get})
|
||||
return slot.get
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue