File indexing completed on 2025-01-19 04:28:13
0001 /** 0002 * SPDX-FileCopyrightText: 2021 Bart De Vries <bart@mogwai.be> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "episodeactionrequest.h" 0008 0009 #include <QJsonArray> 0010 #include <QJsonDocument> 0011 #include <QJsonObject> 0012 #include <QNetworkReply> 0013 #include <QSqlQuery> 0014 #include <QString> 0015 #include <QVector> 0016 0017 #include "database.h" 0018 #include "synclogging.h" 0019 0020 EpisodeActionRequest::EpisodeActionRequest(SyncUtils::Provider provider, QNetworkReply *reply, QObject *parent) 0021 : GenericRequest(provider, reply, parent) 0022 { 0023 } 0024 0025 QVector<SyncUtils::EpisodeAction> EpisodeActionRequest::episodeActions() const 0026 { 0027 return m_episodeActions; 0028 } 0029 0030 qulonglong EpisodeActionRequest::timestamp() const 0031 { 0032 return m_timestamp; 0033 } 0034 0035 void EpisodeActionRequest::processResults() 0036 { 0037 if (m_reply->error()) { 0038 m_error = m_reply->error(); 0039 m_errorString = m_reply->errorString(); 0040 qCDebug(kastsSync) << "m_reply error" << m_reply->errorString(); 0041 } else { 0042 QJsonParseError *error = nullptr; 0043 QJsonDocument data = QJsonDocument::fromJson(m_reply->readAll(), error); 0044 if (error) { 0045 qCDebug(kastsSync) << "parse error" << error->errorString(); 0046 m_error = 1; 0047 m_errorString = error->errorString(); 0048 } else if (!m_abort) { 0049 for (const auto &jsonAction : data.object().value(QStringLiteral("actions")).toArray()) { 0050 SyncUtils::EpisodeAction episodeAction; 0051 episodeAction.id = jsonAction.toObject().value(QStringLiteral("guid")).toString(); 0052 episodeAction.url = jsonAction.toObject().value(QStringLiteral("episode")).toString(); 0053 episodeAction.podcast = cleanupUrl(jsonAction.toObject().value(QStringLiteral("podcast")).toString()); 0054 episodeAction.device = jsonAction.toObject().value(QStringLiteral("device")).toString(); 0055 episodeAction.action = jsonAction.toObject().value(QStringLiteral("action")).toString().toLower(); 0056 if (episodeAction.action == QStringLiteral("play")) { 0057 episodeAction.started = jsonAction.toObject().value(QStringLiteral("started")).toInt(); 0058 episodeAction.position = jsonAction.toObject().value(QStringLiteral("position")).toInt(); 0059 episodeAction.total = jsonAction.toObject().value(QStringLiteral("total")).toInt(); 0060 } else { 0061 episodeAction.started = 0; 0062 episodeAction.position = 0; 0063 episodeAction.total = 0; 0064 } 0065 QString actionTimestamp = jsonAction.toObject().value(QStringLiteral("timestamp")).toString(); 0066 episodeAction.timestamp = static_cast<qulonglong>( 0067 QDateTime::fromString(actionTimestamp.section(QStringLiteral("."), 0, 0), QStringLiteral("yyyy-MM-dd'T'hh:mm:ss")).toMSecsSinceEpoch() 0068 / 1000); 0069 0070 // Now we try to find the id for the entry based on either the GUID 0071 // or the episode download URL. We also try to match with a percent- 0072 // decoded version of the URL. 0073 // There can be several hits (e.g. different entries pointing to the 0074 // same download URL; we add all of them to make sure everything's 0075 // consistent. 0076 // We also retrieve the feedUrl from the database to avoid problems with 0077 // different URLs pointing to the same feed (e.g. http vs https) 0078 QSqlQuery query; 0079 query.prepare(QStringLiteral("SELECT id, feed, url FROM Enclosures WHERE url=:url OR url=:decodeurl OR id=:id;")); 0080 query.bindValue(QStringLiteral(":url"), episodeAction.url); 0081 query.bindValue(QStringLiteral(":decodeurl"), cleanupUrl(episodeAction.url)); 0082 query.bindValue(QStringLiteral(":id"), episodeAction.id); 0083 Database::instance().execute(query); 0084 if (!query.next()) { 0085 qCDebug(kastsSync) << "cannot find episode with url:" << episodeAction.url; 0086 continue; 0087 } 0088 do { 0089 SyncUtils::EpisodeAction action = episodeAction; 0090 action.id = query.value(QStringLiteral("id")).toString(); 0091 action.podcast = query.value(QStringLiteral("feed")).toString(); 0092 action.url = query.value(QStringLiteral("url")).toString(); 0093 m_episodeActions += action; 0094 } while (query.next()); 0095 } 0096 m_timestamp = data.object().value(QStringLiteral("timestamp")).toInt(); 0097 } 0098 } 0099 Q_EMIT finished(); 0100 m_reply->deleteLater(); 0101 deleteLater(); 0102 }