Mercurial > libervia-backend
annotate sat/plugins/plugin_misc_attach.py @ 3922:0ff265725489
plugin XEP-0447: handle attachment and download:
- plugin XEP-0447 can now be used in message attachments and to retrieve an attachment
- plugin attach: `attachment` being processed is added to `extra` so the handler can inspect it
- plugin attach: `size` is added to attachment
- plugin download: a whole attachment dict is now used in `download` and
`file_download`/`file_download_complete`. `download_uri` can be used as a shortcut when
just a URI is used. In addition to URI scheme handler, whole attachment handlers can now
be registered with `register_download_handler`
- plugin XEP-0363: `file_http_upload` `XEP-0363_upload_size` triggers have been renamed to
`XEP-0363_upload_pre_slot` and is now using a dict with arguments, allowing for the size
but also the filename to be modified, which is necessary for encryption (filename may
be hidden from URL this way).
- plugin XEP-0446: fix wrong element name
- plugin XEP-0447: source handler can now be registered (`url-data` is registered by
default)
- plugin XEP-0447: source parsing has been put in a separated `parse_sources_elt` method,
as it may be useful to do it independently (notably with XEP-0448)
- plugin XEP-0447: parse received message and complete attachments when suitable
- plugin XEP-0447: can now be used with message attachments
- plugin XEP-0447: can now be used with attachments download
- renamed `options` arguments to `extra` for consistency
- some style change (progressive move from legacy camelCase to PEP8 snake_case)
- some typing
rel 379
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 06 Oct 2022 16:02:05 +0200 |
parents | 3ef988734869 |
children | 78b5f356900c |
rev | line source |
---|---|
3181 | 1 #!/usr/bin/env python3 |
2 | |
3 # SàT plugin for attaching files | |
3479 | 4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) |
3181 | 5 |
6 # This program is free software: you can redistribute it and/or modify | |
7 # it under the terms of the GNU Affero General Public License as published by | |
8 # the Free Software Foundation, either version 3 of the License, or | |
9 # (at your option) any later version. | |
10 | |
11 # This program is distributed in the hope that it will be useful, | |
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 # GNU Affero General Public License for more details. | |
15 | |
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/>. | |
18 | |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
19 from collections import namedtuple |
3223
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
20 import mimetypes |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
21 from pathlib import Path |
3223
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
22 import shutil |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
23 import tempfile |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
24 from typing import Callable, Optional |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
25 |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
26 from twisted.internet import defer |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
27 |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
28 from sat.core import exceptions |
3181 | 29 from sat.core.constants import Const as C |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
30 from sat.core.core_types import SatXMPPEntity |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
31 from sat.core.i18n import _ |
3181 | 32 from sat.core.log import getLogger |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
33 from sat.tools import utils |
3223
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
34 from sat.tools import image |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
35 |
3181 | 36 |
37 log = getLogger(__name__) | |
38 | |
39 | |
40 PLUGIN_INFO = { | |
41 C.PI_NAME: "File Attach", | |
42 C.PI_IMPORT_NAME: "ATTACH", | |
43 C.PI_TYPE: C.PLUG_TYPE_MISC, | |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
44 C.PI_MODES: C.PLUG_MODE_BOTH, |
3181 | 45 C.PI_DEPENDENCIES: ["UPLOAD"], |
46 C.PI_MAIN: "AttachPlugin", | |
47 C.PI_HANDLER: "no", | |
48 C.PI_DESCRIPTION: _("""Attachments handler"""), | |
49 } | |
50 | |
51 | |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
52 AttachmentHandler = namedtuple('AttachmentHandler', ['can_handle', 'attach', 'priority']) |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
53 |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
54 |
3181 | 55 class AttachPlugin: |
56 | |
57 def __init__(self, host): | |
58 log.info(_("plugin Attach initialization")) | |
59 self.host = host | |
60 self._u = host.plugins["UPLOAD"] | |
61 host.trigger.add("sendMessage", self._sendMessageTrigger) | |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
62 self._attachments_handlers = {'clear': [], 'encrypted': []} |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
63 self.register(self.defaultCanHandle, self.defaultAttach, False, -1000) |
3181 | 64 |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
65 def register(self, can_handle, attach, encrypted=False, priority=0): |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
66 """Register an attachments handler |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
67 |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
68 @param can_handle(callable, coroutine, Deferred): a method which must return True |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
69 if this plugin can handle the upload, otherwise next ones will be tried. |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
70 This method will get client and mess_data as arguments, before the XML is |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
71 generated |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
72 @param attach(callable, coroutine, Deferred): attach the file |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
73 this method will get client and mess_data as arguments, after XML is |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
74 generated. Upload operation must be handled |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
75 hint: "UPLOAD" plugin can be used |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
76 @param encrypted(bool): True if the handler manages encrypted files |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
77 A handler can be registered twice if it handle both encrypted and clear |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
78 attachments |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
79 @param priority(int): priority of this handler, handler with higher priority will |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
80 be tried first |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
81 """ |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
82 handler = AttachmentHandler(can_handle, attach, priority) |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
83 handlers = ( |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
84 self._attachments_handlers['encrypted'] |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
85 if encrypted else self._attachments_handlers['clear'] |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
86 ) |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
87 if handler in handlers: |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
88 raise exceptions.InternalError( |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
89 'Attachment handler has been registered twice, this should never happen' |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
90 ) |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
91 |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
92 handlers.append(handler) |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
93 handlers.sort(key=lambda h: h.priority, reverse=True) |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
94 log.debug(f"new attachments handler: {handler}") |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
95 |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
96 async def attachFiles(self, client, data): |
3223
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
97 """Main method to attach file |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
98 |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
99 It will do generic pre-treatment, and call the suitable attachments handler |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
100 """ |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
101 # we check attachment for pre-treatment like large image resizing |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
102 # media_type will be added if missing (and if it can be guessed from path) |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
103 attachments = data["extra"][C.MESS_KEY_ATTACHMENTS] |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
104 tmp_dirs_to_clean = [] |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
105 for attachment in attachments: |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
106 if attachment.get(C.MESS_KEY_ATTACHMENTS_RESIZE, False): |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
107 path = Path(attachment["path"]) |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
108 try: |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
109 media_type = attachment[C.MESS_KEY_ATTACHMENTS_MEDIA_TYPE] |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
110 except KeyError: |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
111 media_type = mimetypes.guess_type(path, strict=False)[0] |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
112 if media_type is None: |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
113 log.warning( |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
114 _("Can't resize attachment of unknown type: {attachment}") |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
115 .format(attachment=attachment)) |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
116 continue |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
117 attachment[C.MESS_KEY_ATTACHMENTS_MEDIA_TYPE] = media_type |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
118 |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
119 main_type = media_type.split('/')[0] |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
120 if main_type == "image": |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
121 report = image.check(self.host, path) |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
122 if report['too_large']: |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
123 tmp_dir = Path(tempfile.mkdtemp()) |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
124 tmp_dirs_to_clean.append(tmp_dir) |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
125 new_path = tmp_dir / path.name |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
126 await image.resize( |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
127 path, report["recommended_size"], dest=new_path) |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
128 attachment["path"] = new_path |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
129 log.info( |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
130 _("Attachment {path!r} has been resized at {new_path!r}") |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
131 .format(path=str(path), new_path=str(new_path))) |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
132 else: |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
133 log.warning( |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
134 _("Can't resize attachment of type {main_type!r}: {attachment}") |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
135 .format(main_type=main_type, attachment=attachment)) |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
136 |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
137 if client.encryption.isEncryptionRequested(data): |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
138 handlers = self._attachments_handlers['encrypted'] |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
139 else: |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
140 handlers = self._attachments_handlers['clear'] |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
141 |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
142 for handler in handlers: |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
143 can_handle = await utils.asDeferred(handler.can_handle, client, data) |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
144 if can_handle: |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
145 break |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
146 else: |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
147 raise exceptions.NotFound( |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
148 _("No plugin can handle attachment with {destinee}").format( |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
149 destinee = data['to'] |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
150 )) |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
151 |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
152 await utils.asDeferred(handler.attach, client, data) |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
153 |
3223
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
154 for dir_path in tmp_dirs_to_clean: |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
155 log.debug(f"Cleaning temporary directory at {dir_path}") |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
156 shutil.rmtree(dir_path) |
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
157 |
3181 | 158 return data |
159 | |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
160 async def upload_files( |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
161 self, |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
162 client: SatXMPPEntity, |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
163 data: dict, |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
164 upload_cb: Optional[Callable] = None |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
165 ): |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
166 """Upload file, and update attachments |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
167 |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
168 invalid attachments will be removed |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
169 @param client: |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
170 @param data(dict): message data |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
171 @param upload_cb(coroutine, Deferred, None): method to use for upload |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
172 if None, upload method from UPLOAD plugin will be used. |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
173 Otherwise, following kwargs will be used with the cb: |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
174 - client |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
175 - filepath |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
176 - filename |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
177 - options |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
178 the method must return a tuple similar to UPLOAD plugin's upload method, |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
179 it must contain: |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
180 - progress_id |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
181 - a deferred which fire download URL |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
182 """ |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
183 if upload_cb is None: |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
184 upload_cb = self._u.upload |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
185 |
3181 | 186 uploads_d = [] |
187 to_delete = [] | |
188 attachments = data["extra"]["attachments"] | |
189 | |
190 for attachment in attachments: | |
191 try: | |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
192 # we pop path because we don't want it to be stored, as the file can be |
3202
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
193 # only in a temporary location |
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
194 path = Path(attachment.pop("path")) |
3181 | 195 except KeyError: |
196 log.warning("no path in attachment: {attachment}") | |
197 to_delete.append(attachment) | |
198 continue | |
199 | |
200 if "url" in attachment: | |
3202
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
201 url = attachment.pop('url') |
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
202 log.warning( |
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
203 f"unexpected URL in attachment: {url!r}\nattachment: {attachment}" |
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
204 ) |
3181 | 205 |
206 try: | |
207 name = attachment["name"] | |
208 except KeyError: | |
209 name = attachment["name"] = path.name | |
210 | |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
211 attachment["size"] = path.stat().st_size |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
212 |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
213 extra = { |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
214 "attachment": attachment |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
215 } |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
216 progress_id = attachment.pop("progress_id", None) |
3182
f2bb57348587
plugin attach, XEP-0363: progress id can now be specified:
Goffi <goffi@goffi.org>
parents:
3181
diff
changeset
|
217 if progress_id: |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
218 extra["progress_id"] = progress_id |
3192
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
219 check_certificate = self.host.memory.getParamA( |
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
220 "check_certificate", "Connection", profile_key=client.profile) |
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
221 if not check_certificate: |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
222 extra['ignore_tls_errors'] = True |
3192
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
223 log.warning( |
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
224 _("certificate check disabled for upload, this is dangerous!")) |
3181 | 225 |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
226 __, upload_d = await upload_cb( |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
227 client=client, |
3181 | 228 filepath=path, |
229 filename=name, | |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
230 extra=extra, |
3181 | 231 ) |
232 uploads_d.append(upload_d) | |
233 | |
234 for attachment in to_delete: | |
235 attachments.remove(attachment) | |
236 | |
237 upload_results = await defer.DeferredList(uploads_d) | |
238 for idx, (success, ret) in enumerate(upload_results): | |
239 attachment = attachments[idx] | |
240 | |
241 if not success: | |
242 # ret is a failure here | |
243 log.warning(f"error while uploading {attachment}: {ret}") | |
244 continue | |
245 | |
246 attachment["url"] = ret | |
247 | |
248 return data | |
249 | |
3223
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
250 def _attachFiles(self, data, client): |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
251 return defer.ensureDeferred(self.attachFiles(client, data)) |
3181 | 252 |
253 def _sendMessageTrigger( | |
254 self, client, mess_data, pre_xml_treatments, post_xml_treatments): | |
255 if mess_data['extra'].get(C.MESS_KEY_ATTACHMENTS): | |
3223
163014f09bf4
plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents:
3219
diff
changeset
|
256 post_xml_treatments.addCallback(self._attachFiles, client=client) |
3181 | 257 return True |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
258 |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
259 async def defaultCanHandle(self, client, data): |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
260 return True |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
261 |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
262 async def defaultAttach(self, client, data): |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
263 await self.upload_files(client, data) |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
264 # TODO: handle xhtml-im |
3922
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
265 body_elt = data["xml"].body |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
266 if body_elt is None: |
0ff265725489
plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents:
3859
diff
changeset
|
267 body_elt = data["xml"].addElement("body") |
3219
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
268 attachments = data["extra"][C.MESS_KEY_ATTACHMENTS] |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
269 if attachments: |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
270 body_links = '\n'.join(a['url'] for a in attachments) |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
271 if str(body_elt).strip(): |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
272 # if there is already a body, we add a line feed before the first link |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
273 body_elt.addContent('\n') |
2ba602aef90e
plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents:
3202
diff
changeset
|
274 body_elt.addContent(body_links) |