File indexing completed on 2024-05-19 04:03:04
0001 /* 0002 SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "youtubejob.h" 0008 #include <KPasswordDialog> 0009 0010 #include <KIO/StoredTransferJob> 0011 #include <QDebug> 0012 #include <QJsonDocument> 0013 #include <QJsonObject> 0014 #include <QNetworkReply> 0015 0016 static const QUrl apiUrl(QStringLiteral("https://www.googleapis.com/upload/youtube/v3/videos?part=snippet%2Cstatus&uploadType=resumable")); 0017 static const QString watchUrl = QStringLiteral("https://www.youtube.com/watch?v="); 0018 0019 YoutubeJob::YoutubeJob(const QUrl &url, 0020 const QByteArray &accessToken, 0021 const QString &title, 0022 const QStringList &tags, 0023 const QString &description, 0024 QObject *parent) 0025 : KJob(parent) 0026 , m_url(url) 0027 , m_token(accessToken) 0028 { 0029 m_metadata = QByteArray("{ " 0030 "\"snippet\": {" 0031 "\"title\": \"" + title.toUtf8() + "\", " 0032 "\"categoryId\": \"22\", " 0033 "\"description\": \"" + description.toUtf8() + "\", " 0034 "\"tags\": [ \"" + tags.join(QStringLiteral("\", \"")).toUtf8() + "\" ] " 0035 "}, " 0036 "\"status\": { " 0037 "\"privacyStatus\": \"public\" " 0038 "} " 0039 "}"); 0040 } 0041 0042 void YoutubeJob::start() 0043 { 0044 createLocation(); 0045 } 0046 0047 void YoutubeJob::fileFetched(KJob *j) 0048 { 0049 if (j->error()) { 0050 setError(j->error()); 0051 setErrorText(j->errorText()); 0052 emitResult(); 0053 } 0054 KIO::StoredTransferJob *job = qobject_cast<KIO::StoredTransferJob *>(j); 0055 0056 uploadVideo(job->data()); 0057 } 0058 0059 void YoutubeJob::createLocation() 0060 { 0061 QNetworkRequest req(apiUrl); 0062 req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/json; charset=UTF-8")); 0063 req.setRawHeader("Authorization", "Bearer " + m_token); 0064 req.setRawHeader("X-Upload-Content-Type", "video/*"); 0065 0066 auto reply = m_manager.post(req, m_metadata); 0067 connect(reply, &QNetworkReply::finished, this, &YoutubeJob::locationCreated); 0068 connect(reply, &QNetworkReply::errorOccurred, this, [](QNetworkReply::NetworkError e) { 0069 qDebug() << "creation error" << e; 0070 }); 0071 } 0072 0073 void YoutubeJob::locationCreated() 0074 { 0075 QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender()); 0076 if (reply->error()) { 0077 setError(reply->error()); 0078 setErrorText(reply->errorString()); 0079 qWarning() << "couldn't upload file" << reply->readAll(); 0080 emitResult(); 0081 return; 0082 } 0083 Q_ASSERT(reply->atEnd()); 0084 Q_ASSERT(reply->hasRawHeader("Location")); 0085 0086 m_uploadUrl = QUrl::fromEncoded(reply->rawHeader("Location")); 0087 0088 KIO::StoredTransferJob *job = KIO::storedGet(m_url); 0089 connect(job, &KJob::finished, this, &YoutubeJob::fileFetched); 0090 } 0091 0092 void YoutubeJob::uploadVideo(const QByteArray &data) 0093 { 0094 QNetworkRequest req(m_uploadUrl); 0095 req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("video/*")); 0096 req.setRawHeader("X-Upload-Content-Length", QByteArray::number(data.size())); 0097 req.setRawHeader("Authorization", "Bearer " + m_token); 0098 0099 setTotalAmount(Bytes, data.size()); 0100 auto reply = m_manager.post(req, data); 0101 connect(reply, &QNetworkReply::finished, this, &YoutubeJob::videoUploaded); 0102 connect(reply, &QNetworkReply::uploadProgress, this, [this](quint64 bytesSent, quint64 bytesTotal) { 0103 setProcessedAmount(Bytes, bytesSent); 0104 setPercent(bytesTotal == 0 ? 0 : (bytesSent * 100) / bytesTotal); 0105 }); 0106 connect(reply, &QNetworkReply::errorOccurred, this, [](QNetworkReply::NetworkError e) { 0107 qDebug() << "upload error" << e; 0108 }); 0109 } 0110 0111 void YoutubeJob::videoUploaded() 0112 { 0113 QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender()); 0114 if (reply->error()) { 0115 setError(reply->error()); 0116 setErrorText(reply->errorString()); 0117 qWarning() << "couldn't finish upload" << reply->readAll(); 0118 emitResult(); 0119 return; 0120 } 0121 0122 auto doc = QJsonDocument::fromJson(reply->readAll()).object(); 0123 m_output = watchUrl + doc.value(QLatin1String("id")).toString(); 0124 emitResult(); 0125 } 0126 0127 #include "moc_youtubejob.cpp"