Mercurial > libervia-backend
diff sat/plugins/plugin_xep_0363.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 | e84ffb48acd4 |
children | 412b99c29d83 |
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0363.py Thu Oct 06 16:02:05 2022 +0200 +++ b/sat/plugins/plugin_xep_0363.py Thu Oct 06 16:02:05 2022 +0200 @@ -16,25 +16,29 @@ # 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/>. -import os.path +from dataclasses import dataclass import mimetypes -from typing import NamedTuple, Callable, Optional -from dataclasses import dataclass +import os.path +from pathlib import Path +from typing import Callable, NamedTuple, Optional, Tuple from urllib import parse -from wokkel import disco, iwokkel -from zope.interface import implementer -from twisted.words.protocols.jabber import jid, xmlstream, error -from twisted.words.xish import domish + from twisted.internet import reactor from twisted.internet import defer from twisted.web import client as http_client from twisted.web import http_headers -from sat.core.i18n import _ -from sat.core.xmpp import SatXMPPComponent +from twisted.words.protocols.jabber import error, jid, xmlstream +from twisted.words.xish import domish +from wokkel import disco, iwokkel +from zope.interface import implementer + +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.core import exceptions -from sat.tools import web as sat_web, utils +from sat.core.xmpp import SatXMPPComponent +from sat.tools import utils, web as sat_web log = getLogger(__name__) @@ -87,7 +91,7 @@ ".plugin", in_sign="sssbs", out_sign="", - method=self._fileHTTPUpload, + method=self._file_http_upload, ) host.bridge.addMethod( "fileHTTPUploadGetSlot", @@ -98,7 +102,7 @@ async_=True, ) host.plugins["UPLOAD"].register( - "HTTP Upload", self.getHTTPUploadEntity, self.fileHTTPUpload + "HTTP Upload", self.getHTTPUploadEntity, self.file_http_upload ) # list of callbacks used when a request is done to a component self.handlers = [] @@ -151,58 +155,67 @@ return entity - def _fileHTTPUpload(self, filepath, filename="", upload_jid="", + def _file_http_upload(self, filepath, filename="", upload_jid="", ignore_tls_errors=False, profile=C.PROF_KEY_NONE): assert os.path.isabs(filepath) and os.path.isfile(filepath) client = self.host.getClient(profile) - progress_id_d, __ = defer.ensureDeferred(self.fileHTTPUpload( + return defer.ensureDeferred(self.file_http_upload( client, filepath, filename or None, jid.JID(upload_jid) if upload_jid else None, {"ignore_tls_errors": ignore_tls_errors}, )) - return progress_id_d - async def fileHTTPUpload( - self, client, filepath, filename=None, upload_jid=None, options=None): + async def file_http_upload( + self, + client: SatXMPPEntity, + filepath: Path, + filename: Optional[str] = None, + upload_jid: Optional[jid.JID] = None, + extra: Optional[dict] = None + ) -> Tuple[str, defer.Deferred]: """Upload a file through HTTP - @param filepath(str): absolute path of the file - @param filename(None, unicode): name to use for the upload + @param filepath: absolute path of the file + @param filename: name to use for the upload None to use basename of the path - @param upload_jid(jid.JID, None): upload capable entity jid, + @param upload_jid: upload capable entity jid, or None to use autodetected, if possible - @param options(dict): options where key can be: + @param extra: options where key can be: - ignore_tls_errors(bool): if True, SSL certificate will not be checked + - attachment(dict): file attachment data @param profile: %(doc_profile)s - @return (D(tuple[D(unicode), D(unicode)])): progress id and Deferred which fire - download URL + @return: progress id and Deferred which fire download URL """ - if options is None: - options = {} - ignore_tls_errors = options.get("ignore_tls_errors", False) - filename = filename or os.path.basename(filepath) - size = os.path.getsize(filepath) + if extra is None: + extra = {} + ignore_tls_errors = extra.get("ignore_tls_errors", False) + file_metadata = { + "filename": filename or os.path.basename(filepath), + "filepath": filepath, + "size": os.path.getsize(filepath), + } - size_adjust = [] - #: this trigger can be used to modify the requested size, it is notably useful - #: with encryption. The size_adjust is a list which can be filled by int to add - #: to the initial size + #: this trigger can be used to modify the filename or size requested when geting + #: the slot, it is notably useful with encryption. self.host.trigger.point( - "XEP-0363_upload_size", client, options, filepath, size, size_adjust, - triggers_no_cancel=True) - if size_adjust: - size = sum([size, *size_adjust]) + "XEP-0363_upload_pre_slot", client, extra, file_metadata, + triggers_no_cancel=True + ) try: - slot = await self.getSlot(client, filename, size, upload_jid=upload_jid) + slot = await self.getSlot( + client, file_metadata["filename"], file_metadata["size"], + upload_jid=upload_jid + ) except Exception as e: log.warning(_("Can't get upload slot: {reason}").format(reason=e)) raise e else: log.debug(f"Got upload slot: {slot}") sat_file = self.host.plugins["FILE"].File( - self.host, client, filepath, uid=options.get("progress_id"), size=size, + self.host, client, filepath, uid=extra.get("progress_id"), + size=file_metadata["size"], auto_end_signals=False ) progress_id = sat_file.uid @@ -223,7 +236,7 @@ await self.host.trigger.asyncPoint( - "XEP-0363_upload", client, options, sat_file, file_producer, slot, + "XEP-0363_upload", client, extra, sat_file, file_producer, slot, triggers_no_cancel=True) download_d = agent.request( @@ -233,8 +246,8 @@ file_producer, ) download_d.addCallbacks( - self._uploadCb, - self._uploadEb, + self._upload_cb, + self._upload_eb, (sat_file, slot), None, (sat_file,), @@ -242,7 +255,7 @@ return progress_id, download_d - def _uploadCb(self, __, sat_file, slot): + def _upload_cb(self, __, sat_file, slot): """Called once file is successfully uploaded @param sat_file(SatFile): file used for the upload @@ -253,7 +266,7 @@ sat_file.progressFinished({"url": slot.get}) return slot.get - def _uploadEb(self, failure_, sat_file): + def _upload_eb(self, failure_, sat_file): """Called on unsuccessful upload @param sat_file(SatFile): file used for the upload