Mercurial > libervia-backend
comparison sat/plugins/plugin_misc_attach.py @ 3223:163014f09bf4
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.
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 22 Mar 2020 14:04:16 +0100 |
parents | 2ba602aef90e |
children | be6d91572633 |
comparison
equal
deleted
inserted
replaced
3222:653fa213d2f8 | 3223:163014f09bf4 |
---|---|
14 # GNU Affero General Public License for more details. | 14 # GNU Affero General Public License for more details. |
15 | 15 |
16 # You should have received a copy of the GNU Affero General Public License | 16 # You should have received a copy of the GNU Affero General Public License |
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 | 18 |
19 from functools import partial | |
20 from pathlib import Path | 19 from pathlib import Path |
21 from collections import namedtuple | 20 from collections import namedtuple |
22 from twisted.internet import defer | 21 from twisted.internet import defer |
22 import mimetypes | |
23 import tempfile | |
24 import shutil | |
23 from sat.core.i18n import _ | 25 from sat.core.i18n import _ |
24 from sat.core import exceptions | 26 from sat.core import exceptions |
25 from sat.core.constants import Const as C | 27 from sat.core.constants import Const as C |
26 from sat.core.log import getLogger | 28 from sat.core.log import getLogger |
27 from sat.tools import utils | 29 from sat.tools import utils |
30 from sat.tools import image | |
28 | 31 |
29 | 32 |
30 log = getLogger(__name__) | 33 log = getLogger(__name__) |
31 | 34 |
32 | 35 |
84 handlers.append(handler) | 87 handlers.append(handler) |
85 handlers.sort(key=lambda h: h.priority, reverse=True) | 88 handlers.sort(key=lambda h: h.priority, reverse=True) |
86 log.debug(f"new attachments handler: {handler}") | 89 log.debug(f"new attachments handler: {handler}") |
87 | 90 |
88 async def attachFiles(self, client, data): | 91 async def attachFiles(self, client, data): |
92 """Main method to attach file | |
93 | |
94 It will do generic pre-treatment, and call the suitable attachments handler | |
95 """ | |
96 # we check attachment for pre-treatment like large image resizing | |
97 # media_type will be added if missing (and if it can be guessed from path) | |
98 attachments = data["extra"][C.MESS_KEY_ATTACHMENTS] | |
99 tmp_dirs_to_clean = [] | |
100 for attachment in attachments: | |
101 if attachment.get(C.MESS_KEY_ATTACHMENTS_RESIZE, False): | |
102 path = Path(attachment["path"]) | |
103 try: | |
104 media_type = attachment[C.MESS_KEY_ATTACHMENTS_MEDIA_TYPE] | |
105 except KeyError: | |
106 media_type = mimetypes.guess_type(path, strict=False)[0] | |
107 if media_type is None: | |
108 log.warning( | |
109 _("Can't resize attachment of unknown type: {attachment}") | |
110 .format(attachment=attachment)) | |
111 continue | |
112 attachment[C.MESS_KEY_ATTACHMENTS_MEDIA_TYPE] = media_type | |
113 | |
114 main_type = media_type.split('/')[0] | |
115 if main_type == "image": | |
116 report = image.check(self.host, path) | |
117 if report['too_large']: | |
118 tmp_dir = Path(tempfile.mkdtemp()) | |
119 tmp_dirs_to_clean.append(tmp_dir) | |
120 new_path = tmp_dir / path.name | |
121 await image.resize( | |
122 path, report["recommended_size"], dest=new_path) | |
123 attachment["path"] = new_path | |
124 log.info( | |
125 _("Attachment {path!r} has been resized at {new_path!r}") | |
126 .format(path=str(path), new_path=str(new_path))) | |
127 else: | |
128 log.warning( | |
129 _("Can't resize attachment of type {main_type!r}: {attachment}") | |
130 .format(main_type=main_type, attachment=attachment)) | |
131 | |
89 if client.encryption.isEncryptionRequested(data): | 132 if client.encryption.isEncryptionRequested(data): |
90 handlers = self._attachments_handlers['encrypted'] | 133 handlers = self._attachments_handlers['encrypted'] |
91 else: | 134 else: |
92 handlers = self._attachments_handlers['clear'] | 135 handlers = self._attachments_handlers['clear'] |
93 | 136 |
100 _("No plugin can handle attachment with {destinee}").format( | 143 _("No plugin can handle attachment with {destinee}").format( |
101 destinee = data['to'] | 144 destinee = data['to'] |
102 )) | 145 )) |
103 | 146 |
104 await utils.asDeferred(handler.attach, client, data) | 147 await utils.asDeferred(handler.attach, client, data) |
148 | |
149 for dir_path in tmp_dirs_to_clean: | |
150 log.debug(f"Cleaning temporary directory at {dir_path}") | |
151 shutil.rmtree(dir_path) | |
105 | 152 |
106 return data | 153 return data |
107 | 154 |
108 async def uploadFiles(self, client, data, upload_cb=None): | 155 async def uploadFiles(self, client, data, upload_cb=None): |
109 """Upload file, and update attachments | 156 """Upload file, and update attachments |
184 | 231 |
185 attachment["url"] = ret | 232 attachment["url"] = ret |
186 | 233 |
187 return data | 234 return data |
188 | 235 |
189 def _attachFiles(self, client, data): | 236 def _attachFiles(self, data, client): |
190 return defer.ensureDeferred(self.attachFiles(client, data)) | 237 return defer.ensureDeferred(self.attachFiles(client, data)) |
191 | 238 |
192 def _sendMessageTrigger( | 239 def _sendMessageTrigger( |
193 self, client, mess_data, pre_xml_treatments, post_xml_treatments): | 240 self, client, mess_data, pre_xml_treatments, post_xml_treatments): |
194 if mess_data['extra'].get(C.MESS_KEY_ATTACHMENTS): | 241 if mess_data['extra'].get(C.MESS_KEY_ATTACHMENTS): |
195 post_xml_treatments.addCallback(partial(self._attachFiles, client)) | 242 post_xml_treatments.addCallback(self._attachFiles, client=client) |
196 return True | 243 return True |
197 | 244 |
198 async def defaultCanHandle(self, client, data): | 245 async def defaultCanHandle(self, client, data): |
199 return True | 246 return True |
200 | 247 |