diff 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
line wrap: on
line diff
--- a/sat/plugins/plugin_misc_attach.py	Thu Oct 06 16:02:05 2022 +0200
+++ b/sat/plugins/plugin_misc_attach.py	Thu Oct 06 16:02:05 2022 +0200
@@ -16,15 +16,19 @@
 # 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 pathlib import Path
 from collections import namedtuple
-from twisted.internet import defer
 import mimetypes
-import tempfile
+from pathlib import Path
 import shutil
-from sat.core.i18n import _
+import tempfile
+from typing import Callable, Optional
+
+from twisted.internet import defer
+
 from sat.core import exceptions
 from sat.core.constants import Const as C
+from sat.core.core_types import SatXMPPEntity
+from sat.core.i18n import _
 from sat.core.log import getLogger
 from sat.tools import utils
 from sat.tools import image
@@ -37,6 +41,7 @@
     C.PI_NAME: "File Attach",
     C.PI_IMPORT_NAME: "ATTACH",
     C.PI_TYPE: C.PLUG_TYPE_MISC,
+    C.PI_MODES: C.PLUG_MODE_BOTH,
     C.PI_DEPENDENCIES: ["UPLOAD"],
     C.PI_MAIN: "AttachPlugin",
     C.PI_HANDLER: "no",
@@ -152,7 +157,12 @@
 
         return data
 
-    async def uploadFiles(self, client, data, upload_cb=None):
+    async def upload_files(
+        self,
+        client: SatXMPPEntity,
+        data: dict,
+        upload_cb: Optional[Callable] = None
+    ):
         """Upload file, and update attachments
 
         invalid attachments will be removed
@@ -160,7 +170,7 @@
         @param data(dict): message data
         @param upload_cb(coroutine, Deferred, None): method to use for upload
             if None, upload method from UPLOAD plugin will be used.
-            Otherwise, following kwargs will be use with the cb:
+            Otherwise, following kwargs will be used with the cb:
                 - client
                 - filepath
                 - filename
@@ -179,7 +189,7 @@
 
         for attachment in attachments:
             try:
-                # we pop path because we don't want it to be stored, as the image can be
+                # we pop path because we don't want it to be stored, as the file can be
                 # only in a temporary location
                 path = Path(attachment.pop("path"))
             except KeyError:
@@ -198,14 +208,18 @@
             except KeyError:
                 name = attachment["name"] = path.name
 
-            options = {}
+            attachment["size"] = path.stat().st_size
+
+            extra = {
+                "attachment": attachment
+            }
             progress_id = attachment.pop("progress_id", None)
             if progress_id:
-                options["progress_id"] = progress_id
+                extra["progress_id"] = progress_id
             check_certificate = self.host.memory.getParamA(
                 "check_certificate", "Connection", profile_key=client.profile)
             if not check_certificate:
-                options['ignore_tls_errors'] = True
+                extra['ignore_tls_errors'] = True
                 log.warning(
                     _("certificate check disabled for upload, this is dangerous!"))
 
@@ -213,7 +227,7 @@
                 client=client,
                 filepath=path,
                 filename=name,
-                options=options,
+                extra=extra,
             )
             uploads_d.append(upload_d)
 
@@ -246,9 +260,11 @@
         return True
 
     async def defaultAttach(self, client, data):
-        await self.uploadFiles(client, data)
+        await self.upload_files(client, data)
         # TODO: handle xhtml-im
-        body_elt = next(data["xml"].elements(C.NS_CLIENT, "body"))
+        body_elt = data["xml"].body
+        if body_elt is None:
+            body_elt = data["xml"].addElement("body")
         attachments = data["extra"][C.MESS_KEY_ATTACHMENTS]
         if attachments:
             body_links = '\n'.join(a['url'] for a in attachments)