diff --git a/cura/PrinterOutput/UploadMaterialsJob.py b/cura/PrinterOutput/UploadMaterialsJob.py index 42254d2475..e675524ec4 100644 --- a/cura/PrinterOutput/UploadMaterialsJob.py +++ b/cura/PrinterOutput/UploadMaterialsJob.py @@ -4,22 +4,80 @@ from PyQt5.QtCore import QUrl import os # To delete the archive when we're done. import tempfile # To create an archive before we upload it. +import enum import cura.CuraApplication # Imported like this to prevent circular imports. +from cura.UltimakerCloud import UltimakerCloudConstants # To know where the API is. +from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope # To know how to communicate with this server. from UM.Job import Job +from UM.Logger import Logger +from UM.TaskManagement.HttpRequestManager import HttpRequestManager # To call the API. +from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope +from typing import Optional, TYPE_CHECKING +if TYPE_CHECKING: + from PyQt5.QtNetwork import QNetworkReply class UploadMaterialsJob(Job): """ Job that uploads a set of materials to the Digital Factory. """ + UPLOAD_REQUEST_URL = f"{UltimakerCloudConstants.CuraDigitalFactoryURL}/materials/profile_upload" + + class Result(enum.IntEnum): + SUCCCESS = 0 + FAILED = 1 + + def __init__(self): + super().__init__() + self._scope = JsonDecoratorScope(UltimakerCloudScope(cura.CuraApplication.CuraApplication.getInstance())) # type: JsonDecoratorScope + def run(self): archive_file = tempfile.NamedTemporaryFile("wb", delete = False) archive_file.close() cura.CuraApplication.CuraApplication.getInstance().getMaterialManagementModel().exportAll(QUrl.fromLocalFile(archive_file.name)) - print("Creating archive completed. Now we need to upload it.") # TODO: Upload that file. + http = HttpRequestManager.getInstance() + http.get( + url = self.UPLOAD_REQUEST_URL, + callback = self.onUploadRequestCompleted, + error_callback = self.onError, + scope = self._scope + ) - os.remove(archive_file.name) # Clean up. \ No newline at end of file + def onUploadRequestCompleted(self, reply: "QNetworkReply", error: Optional["QNetworkReply.NetworkError"]): + if error is not None: + Logger.error(f"Could not request URL to upload material archive to: {error}") + self.setResult(self.Result.FAILED) + return + + response_data = HttpRequestManager.readJSON(reply) + if response_data is None: + Logger.error(f"Invalid response to material upload request. Could not parse JSON data.") + self.setResult(self.Result.FAILED) + return + if "upload_url" not in response_data: + Logger.error(f"Invalid response to material upload request: Missing 'upload_url' field to upload archive to.") + self.setResult(self.Result.Failed) + return + + upload_url = response_data["upload_url"] + http = HttpRequestManager.getInstance() + http.put( + url = upload_url, + callback = self.onUploadCompleted, + error_callback = self.onError, + scope = self._scope + ) + + def onUploadCompleted(self, reply: "QNetworkReply", error: Optional["QNetworkReply.NetworkError"]): + if error is not None: + Logger.error(f"Failed to upload material archive: {error}") + self.setResult(self.Result.FAILED) + return + self.setResult(self.Result.SUCCESS) + + def onError(self, reply: "QNetworkReply", error: Optional["QNetworkReply.NetworkError"]): + pass # TODO: Handle errors. \ No newline at end of file