summaryrefslogtreecommitdiff
path: root/transferengine-plugins/fediversetransferplugin/fediverseuploader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'transferengine-plugins/fediversetransferplugin/fediverseuploader.cpp')
-rw-r--r--transferengine-plugins/fediversetransferplugin/fediverseuploader.cpp252
1 files changed, 252 insertions, 0 deletions
diff --git a/transferengine-plugins/fediversetransferplugin/fediverseuploader.cpp b/transferengine-plugins/fediversetransferplugin/fediverseuploader.cpp
new file mode 100644
index 0000000..7c8766b
--- /dev/null
+++ b/transferengine-plugins/fediversetransferplugin/fediverseuploader.cpp
@@ -0,0 +1,252 @@
+/*
+ * SPDX-FileCopyrightText: 2013 - 2026 Jolla Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fediverseuploader.h"
+#include "fediverseapi.h"
+
+#include <imageoperation.h>
+#include <mediaitem.h>
+
+#include <QtCore/QFile>
+#include <QtCore/QMimeDatabase>
+#include <QtCore/QMimeType>
+
+#include <QtDebug>
+
+FediverseUploader::FediverseUploader(QNetworkAccessManager *qnam, QObject *parent)
+ : MediaTransferInterface(parent)
+ , m_api(0)
+ , m_fediverseShareServiceStatus(0)
+ , m_qnam(qnam)
+ , m_useTmpFile(false)
+{
+}
+
+FediverseUploader::~FediverseUploader()
+{
+}
+
+QString FediverseUploader::displayName() const
+{
+ return tr("Fediverse");
+}
+
+QUrl FediverseUploader::serviceIcon() const
+{
+ return QUrl(QStringLiteral("image://theme/icon-l-fediverse"));
+}
+
+bool FediverseUploader::cancelEnabled() const
+{
+ return true;
+}
+
+bool FediverseUploader::restartEnabled() const
+{
+ return true;
+}
+
+void FediverseUploader::start()
+{
+ if (!mediaItem()) {
+ qWarning() << Q_FUNC_INFO << "NULL MediaItem. Can't continue";
+ setStatus(MediaTransferInterface::TransferInterrupted);
+ return;
+ }
+
+ if (!m_fediverseShareServiceStatus) {
+ m_fediverseShareServiceStatus = new FediverseShareServiceStatus(this);
+ connect(m_fediverseShareServiceStatus, &FediverseShareServiceStatus::serviceReady,
+ this, &FediverseUploader::startUploading);
+ connect(m_fediverseShareServiceStatus, &FediverseShareServiceStatus::serviceError,
+ this, [this] (const QString &) {
+ transferError();
+ });
+ }
+
+ m_fediverseShareServiceStatus->queryStatus();
+}
+
+void FediverseUploader::cancel()
+{
+ if (m_api) {
+ m_api->cancelUpload();
+ } else {
+ qWarning() << Q_FUNC_INFO << "Can't cancel. NULL FediverseApi object!";
+ }
+}
+
+void FediverseUploader::startUploading()
+{
+ if (!m_fediverseShareServiceStatus) {
+ qWarning() << Q_FUNC_INFO << "NULL FediverseShareServiceStatus object!";
+ return;
+ }
+
+ const quint32 accountId = mediaItem()->value(MediaItem::AccountId).toInt();
+ m_accountDetails = m_fediverseShareServiceStatus->detailsByIdentifier(accountId);
+ if (m_accountDetails.accountId <= 0 || m_accountDetails.accessToken.isEmpty()) {
+ qWarning() << Q_FUNC_INFO << "Fediverse account details missing for id" << accountId;
+ transferError();
+ return;
+ }
+
+ const QString mimeType = mediaItem()->value(MediaItem::MimeType).toString();
+ if (mimeType.startsWith(QLatin1String("image/"))
+ || mimeType.startsWith(QLatin1String("video/"))) {
+ postImage();
+ } else if (mimeType.contains(QLatin1String("text/plain"))
+ || mimeType.contains(QLatin1String("text/x-url"))) {
+ postStatus();
+ } else {
+ qWarning() << Q_FUNC_INFO << "Unsupported mime type:" << mimeType;
+ setStatus(MediaTransferInterface::TransferInterrupted);
+ }
+}
+
+void FediverseUploader::transferFinished()
+{
+ setStatus(MediaTransferInterface::TransferFinished);
+}
+
+void FediverseUploader::transferProgress(qreal progress)
+{
+ setProgress(progress);
+}
+
+void FediverseUploader::transferError()
+{
+ setStatus(MediaTransferInterface::TransferInterrupted);
+ qWarning() << Q_FUNC_INFO << "Transfer interrupted";
+}
+
+void FediverseUploader::transferCanceled()
+{
+ setStatus(MediaTransferInterface::TransferCanceled);
+}
+
+void FediverseUploader::credentialsExpired()
+{
+ const quint32 accountId = mediaItem()->value(MediaItem::AccountId).toInt();
+ m_fediverseShareServiceStatus->setCredentialsNeedUpdate(accountId, QStringLiteral("fediverse-sharing"));
+}
+
+void FediverseUploader::setStatus(MediaTransferInterface::TransferStatus status)
+{
+ const bool finished = (status == TransferCanceled
+ || status == TransferInterrupted
+ || status == TransferFinished);
+ if (m_useTmpFile && finished) {
+ QFile::remove(m_filePath);
+ m_useTmpFile = false;
+ m_filePath.clear();
+ }
+
+ MediaTransferInterface::setStatus(status);
+}
+
+void FediverseUploader::postImage()
+{
+ m_useTmpFile = false;
+ m_filePath.clear();
+ const QString sourceFile = mediaItem()->value(MediaItem::Url).toUrl().toLocalFile();
+ if (sourceFile.isEmpty()) {
+ qWarning() << Q_FUNC_INFO << "Empty source file";
+ setStatus(MediaTransferInterface::TransferInterrupted);
+ return;
+ }
+
+ QMimeDatabase db;
+ const QMimeType mime = db.mimeTypeForFile(sourceFile);
+ const bool isImage = mediaItem()->value(MediaItem::MimeType).toString().startsWith(QLatin1String("image/"));
+ const bool isJpeg = isImage && mime.name() == QLatin1String("image/jpeg");
+
+ if (isJpeg && mediaItem()->value(MediaItem::MetadataStripped).toBool()) {
+ m_useTmpFile = true;
+ m_filePath = ImageOperation::removeImageMetadata(sourceFile);
+ if (m_filePath.isEmpty()) {
+ qWarning() << Q_FUNC_INFO << "Failed to remove metadata";
+ MediaTransferInterface::setStatus(MediaTransferInterface::TransferInterrupted);
+ return;
+ }
+ }
+
+ const qreal scale = mediaItem()->value(MediaItem::ScalePercent).toReal();
+ if (isImage && 0 < scale && scale < 1) {
+ m_useTmpFile = true;
+ m_filePath = ImageOperation::scaleImage(sourceFile, scale, m_filePath);
+ if (m_filePath.isEmpty()) {
+ qWarning() << Q_FUNC_INFO << "Failed to scale image";
+ MediaTransferInterface::setStatus(MediaTransferInterface::TransferInterrupted);
+ return;
+ }
+ }
+
+ if (!m_useTmpFile) {
+ m_filePath = sourceFile;
+ }
+
+ ensureApi();
+
+ const bool ok = m_api->uploadImage(m_filePath,
+ mediaItem()->value(MediaItem::Description).toString(),
+ mediaItem()->value(MediaItem::MimeType).toString(),
+ m_accountDetails.apiHost,
+ m_accountDetails.accessToken);
+ if (ok) {
+ setStatus(MediaTransferInterface::TransferStarted);
+ } else {
+ setStatus(MediaTransferInterface::TransferInterrupted);
+ qWarning() << Q_FUNC_INFO << "Failed to upload media";
+ }
+}
+
+void FediverseUploader::postStatus()
+{
+ ensureApi();
+
+ const QVariantMap userData = mediaItem()->value(MediaItem::UserData).toMap();
+ QString statusText = userData.value(QStringLiteral("status")).toString().trimmed();
+ if (statusText.isEmpty()) {
+ statusText = mediaItem()->value(MediaItem::Description).toString().trimmed();
+ }
+ if (statusText.isEmpty()) {
+ statusText = mediaItem()->value(MediaItem::ContentData).toString().trimmed();
+ }
+
+ if (statusText.isEmpty()) {
+ qWarning() << Q_FUNC_INFO << "Failed to resolve status text";
+ setStatus(MediaTransferInterface::TransferInterrupted);
+ return;
+ }
+
+ const bool ok = m_api->postStatus(statusText,
+ m_accountDetails.apiHost,
+ m_accountDetails.accessToken);
+ if (ok) {
+ setStatus(MediaTransferInterface::TransferStarted);
+ } else {
+ setStatus(MediaTransferInterface::TransferInterrupted);
+ qWarning() << Q_FUNC_INFO << "Failed to post status";
+ }
+}
+
+void FediverseUploader::ensureApi()
+{
+ if (!m_api) {
+ m_api = new FediverseApi(m_qnam, this);
+ connect(m_api, &FediverseApi::transferProgressUpdated,
+ this, &FediverseUploader::transferProgress);
+ connect(m_api, &FediverseApi::transferFinished,
+ this, &FediverseUploader::transferFinished);
+ connect(m_api, &FediverseApi::transferError,
+ this, &FediverseUploader::transferError);
+ connect(m_api, &FediverseApi::transferCanceled,
+ this, &FediverseUploader::transferCanceled);
+ connect(m_api, &FediverseApi::credentialsExpired,
+ this, &FediverseUploader::credentialsExpired);
+ }
+}