annotate libervia/backend/plugins/plugin_misc_attach.py @ 4118:07370d2a9bde

plugin XEP-0167: keep media order when starting a call: media content order is relevant when building Jingle contents/SDP notably for bundling. This patch fixes the previous behaviour of always using the same order by keeping the order of the data (i.e. order of original SDP offer). Previous behaviour could lead to call failure. rel 424
author Goffi <goffi@goffi.org>
date Tue, 03 Oct 2023 15:15:24 +0200
parents 4b842c1fb686
children 0d7bb4df2343
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python3
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
2
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
3 # SàT plugin for attaching files
3479
be6d91572633 date update
Goffi <goffi@goffi.org>
parents: 3223
diff changeset
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
5
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
6 # This program is free software: you can redistribute it and/or modify
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # it under the terms of the GNU Affero General Public License as published by
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # the Free Software Foundation, either version 3 of the License, or
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # (at your option) any later version.
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
10
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
11 # This program is distributed in the hope that it will be useful,
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # GNU Affero General Public License for more details.
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
15
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
16 # You should have received a copy of the GNU Affero General Public License
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
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
4071
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
28 from libervia.backend.core import exceptions
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
29 from libervia.backend.core.constants import Const as C
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
30 from libervia.backend.core.core_types import SatXMPPEntity
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
31 from libervia.backend.core.i18n import _
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
32 from libervia.backend.core.log import getLogger
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
33 from libervia.backend.tools import utils
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
34 from libervia.backend.tools import image
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
35
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
36
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 log = getLogger(__name__)
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
38
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
39
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 PLUGIN_INFO = {
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
41 C.PI_NAME: "File Attach",
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
42 C.PI_IMPORT_NAME: "ATTACH",
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
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
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
45 C.PI_DEPENDENCIES: ["UPLOAD"],
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 C.PI_MAIN: "AttachPlugin",
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 C.PI_HANDLER: "no",
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
48 C.PI_DESCRIPTION: _("""Attachments handler"""),
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 }
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
50
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
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
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
55 class AttachPlugin:
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
56
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 def __init__(self, host):
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 log.info(_("plugin Attach initialization"))
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 self.host = host
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 self._u = host.plugins["UPLOAD"]
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
61 host.trigger.add("sendMessage", self._send_message_trigger)
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
62 host.trigger.add("sendMessageComponent", self._send_message_trigger)
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
63 self._attachments_handlers = {'clear': [], 'encrypted': []}
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
64 self.register(self.default_can_handle, self.default_attach, False, -1000)
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
65
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
66 def register(self, can_handle, attach, encrypted=False, priority=0):
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
67 """Register an attachments handler
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
68
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
69 @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
70 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
71 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
72 generated
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
73 @param attach(callable, coroutine, Deferred): attach the file
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
74 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
75 generated. Upload operation must be handled
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
76 hint: "UPLOAD" plugin can be used
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
77 @param encrypted(bool): True if the handler manages encrypted files
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
78 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
79 attachments
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
80 @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
81 be tried first
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
82 """
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
83 handler = AttachmentHandler(can_handle, attach, priority)
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
84 handlers = (
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
85 self._attachments_handlers['encrypted']
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
86 if encrypted else self._attachments_handlers['clear']
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
87 )
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
88 if handler in handlers:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
89 raise exceptions.InternalError(
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
90 'Attachment handler has been registered twice, this should never happen'
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
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
93 handlers.append(handler)
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
94 handlers.sort(key=lambda h: h.priority, reverse=True)
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
95 log.debug(f"new attachments handler: {handler}")
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
96
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
97 async def attach_files(self, client, data):
3223
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
98 """Main method to attach file
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
99
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
100 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
101 """
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
102 # 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
103 # media_type will be added if missing (and if it can be guessed from path)
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
104 attachments = data["extra"][C.KEY_ATTACHMENTS]
3223
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
105 tmp_dirs_to_clean = []
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
106 for attachment in attachments:
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
107 if attachment.get(C.KEY_ATTACHMENTS_RESIZE, False):
3223
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
108 path = Path(attachment["path"])
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
109 try:
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
110 media_type = attachment[C.KEY_ATTACHMENTS_MEDIA_TYPE]
3223
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
111 except KeyError:
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
112 media_type = mimetypes.guess_type(path, strict=False)[0]
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
113 if media_type is None:
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
114 log.warning(
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
115 _("Can't resize attachment of unknown type: {attachment}")
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
116 .format(attachment=attachment))
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
117 continue
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
118 attachment[C.KEY_ATTACHMENTS_MEDIA_TYPE] = media_type
3223
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
119
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
120 main_type = media_type.split('/')[0]
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
121 if main_type == "image":
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
122 report = image.check(self.host, path)
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
123 if report['too_large']:
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
124 tmp_dir = Path(tempfile.mkdtemp())
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
125 tmp_dirs_to_clean.append(tmp_dir)
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
126 new_path = tmp_dir / path.name
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
127 await image.resize(
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
128 path, report["recommended_size"], dest=new_path)
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
129 attachment["path"] = new_path
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
130 log.info(
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
131 _("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
132 .format(path=str(path), new_path=str(new_path)))
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
133 else:
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
134 log.warning(
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
135 _("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
136 .format(main_type=main_type, attachment=attachment))
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
137
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
138 if client.encryption.is_encryption_requested(data):
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
139 handlers = self._attachments_handlers['encrypted']
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
140 else:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
141 handlers = self._attachments_handlers['clear']
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
142
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
143 for handler in handlers:
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
144 can_handle = await utils.as_deferred(handler.can_handle, client, data)
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
145 if can_handle:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
146 break
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
147 else:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
148 raise exceptions.NotFound(
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
149 _("No plugin can handle attachment with {destinee}").format(
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
150 destinee = data['to']
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
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
153 await utils.as_deferred(handler.attach, client, data)
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
154
3223
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
155 for dir_path in tmp_dirs_to_clean:
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
156 log.debug(f"Cleaning temporary directory at {dir_path}")
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
157 shutil.rmtree(dir_path)
163014f09bf4 plugin attach: handle large images resizing:
Goffi <goffi@goffi.org>
parents: 3219
diff changeset
158
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
159 return data
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
160
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
161 async def upload_files(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
162 self,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
163 client: SatXMPPEntity,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
164 data: dict,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
165 upload_cb: Optional[Callable] = None
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
166 ):
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
167 """Upload file, and update attachments
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
168
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
169 invalid attachments will be removed
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
170 @param client:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
171 @param data(dict): message data
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
172 @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
173 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
174 Otherwise, following kwargs will be used with the cb:
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
175 - client
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
176 - filepath
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
177 - filename
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
178 - options
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
179 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
180 it must contain:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
181 - progress_id
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
182 - a deferred which fire download URL
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
183 """
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
184 if upload_cb is None:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
185 upload_cb = self._u.upload
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
186
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
187 uploads_d = []
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 to_delete = []
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
189 attachments = data["extra"]["attachments"]
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
190
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 for attachment in attachments:
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
192 if "url" in attachment and not "path" in attachment:
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
193 log.debug(f"attachment is external, we don't upload it: {attachment}")
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
194 continue
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
195 try:
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
196 # 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
197 # only in a temporary location
2e892f9f54f6 plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents: 3192
diff changeset
198 path = Path(attachment.pop("path"))
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
199 except KeyError:
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
200 log.warning("no path in attachment: {attachment}")
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
201 to_delete.append(attachment)
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 continue
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
203
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
204 if "url" in attachment:
3202
2e892f9f54f6 plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents: 3192
diff changeset
205 url = attachment.pop('url')
2e892f9f54f6 plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents: 3192
diff changeset
206 log.warning(
2e892f9f54f6 plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents: 3192
diff changeset
207 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
208 )
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
209
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
210 try:
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
211 name = attachment["name"]
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
212 except KeyError:
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
213 name = attachment["name"] = path.name
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
214
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
215 attachment["size"] = path.stat().st_size
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
216
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
217 extra = {
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
218 "attachment": attachment
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
219 }
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
220 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
221 if progress_id:
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
222 extra["progress_id"] = progress_id
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
223 check_certificate = self.host.memory.param_get_a(
3192
883fb4981958 plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents: 3182
diff changeset
224 "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
225 if not check_certificate:
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
226 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
227 log.warning(
883fb4981958 plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents: 3182
diff changeset
228 _("certificate check disabled for upload, this is dangerous!"))
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
229
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
230 __, upload_d = await upload_cb(
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
231 client=client,
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
232 filepath=path,
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
233 filename=name,
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
234 extra=extra,
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
235 )
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
236 uploads_d.append(upload_d)
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
237
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
238 for attachment in to_delete:
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
239 attachments.remove(attachment)
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
240
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
241 upload_results = await defer.DeferredList(uploads_d)
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
242 for idx, (success, ret) in enumerate(upload_results):
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
243 attachment = attachments[idx]
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
244
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
245 if not success:
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
246 # ret is a failure here
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
247 log.warning(f"error while uploading {attachment}: {ret}")
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
248 continue
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
249
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
250 attachment["url"] = ret
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
251
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
252 return data
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
253
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
254 def _attach_files(self, data, client):
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
255 return defer.ensureDeferred(self.attach_files(client, data))
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
256
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
257 def _send_message_trigger(
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
258 self, client, mess_data, pre_xml_treatments, post_xml_treatments):
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
259 if mess_data['extra'].get(C.KEY_ATTACHMENTS):
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
260 post_xml_treatments.addCallback(self._attach_files, client=client)
3181
5ff2cf7f0aba plugin attach: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
261 return True
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
262
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
263 async def default_can_handle(self, client, data):
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
264 return True
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
265
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 4023
diff changeset
266 async def default_attach(self, client, data):
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
267 await self.upload_files(client, data)
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
268 # TODO: handle xhtml-im
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
269 body_elt = data["xml"].body
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
270 if body_elt is None:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3859
diff changeset
271 body_elt = data["xml"].addElement("body")
4023
78b5f356900c component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents: 3922
diff changeset
272 attachments = data["extra"][C.KEY_ATTACHMENTS]
3219
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
273 if attachments:
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
274 body_links = '\n'.join(a['url'] for a in attachments)
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
275 if str(body_elt).strip():
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
276 # 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
277 body_elt.addContent('\n')
2ba602aef90e plugin attach, aesgcm: attachments refactoring:
Goffi <goffi@goffi.org>
parents: 3202
diff changeset
278 body_elt.addContent(body_links)