#include "./youtubeplaylist.h" #include "../httpdownload.h" #include "../youtubedownload.h" #include "../../application/utils.h" #include using namespace CppUtilities; using namespace Application; namespace Network { /*! * \class YoutubePlaylist * \brief The YoutubePlaylist class retrieves videos from a YouTube playlist. */ /*! * \brief Constructs a new YouTube playlist with the specified \a url. */ YoutubePlaylist::YoutubePlaylist(const QUrl &url, QObject *parent) : DownloadFinder(parent) { if (url.hasQuery()) { QUrlQuery query(url.query()); m_playlistId = query.queryItemValue(QStringLiteral("list")); } } /*! * \brief Constructs a new YouTube playlist with the specified \a id. */ YoutubePlaylist::YoutubePlaylist(const QString &id, QObject *parent) : DownloadFinder(parent) , m_playlistId(id) { } Download *YoutubePlaylist::createRequest(QString &reasonForFail) { if (!m_playlistId.isEmpty()) { return new HttpDownload(QUrl(QStringLiteral("https://www.youtube.com/playlist?list=%1").arg(m_playlistId)), this); } reasonForFail = tr("The playlist ID couldn't be found."); return nullptr; } YoutubePlaylist::ParsingResult YoutubePlaylist::parseResults(const QByteArray &data, QString &reasonForFail) { QString playlistInfo(data); QString collectionTitle; if (substring(playlistInfo, collectionTitle, 0, QStringLiteral("\"title\" content=\""), QStringLiteral("\"")) > 0) { replaceHtmlEntities(collectionTitle); } reportCollectionTitle(collectionTitle); YoutubeDownload *res = nullptr; int indexIndex = 0; int hrefIndex = 0; int nextAmpIndex = 0; int videoOwnerIndex = 0; QString id, title, uploader, durationStr; for (int index = 1;; ++index) { id.clear(); title.clear(); uploader.clear(); durationStr.clear(); indexIndex = playlistInfo.indexOf(QLatin1String(" -1) { indexIndex = playlistInfo.indexOf(QLatin1String("&index="), indexIndex, Qt::CaseInsensitive); if (indexIndex > -1) { hrefIndex = playlistInfo.lastIndexOf(QLatin1String("href=\"/watch?v="), indexIndex, Qt::CaseInsensitive); if (hrefIndex > -1) { hrefIndex += 15; // get video id nextAmpIndex = playlistInfo.indexOf(QLatin1String("&list="), hrefIndex, Qt::CaseInsensitive); if (nextAmpIndex > hrefIndex) { id = playlistInfo.mid(hrefIndex, nextAmpIndex - hrefIndex); } else { continue; } // get title if (substring(playlistInfo, title, indexIndex, QStringLiteral("title=\""), QStringLiteral("\"")) > indexIndex) { replaceHtmlEntities(title); } else { continue; } // get uploader videoOwnerIndex = playlistInfo.indexOf(QLatin1String(""), indexIndex); substring(playlistInfo, uploader, videoOwnerIndex, QStringLiteral(" dir=\"ltr\">"), QStringLiteral("")); // get duration substring(playlistInfo, durationStr, videoOwnerIndex, QStringLiteral(""), QStringLiteral("")); // construct download, provide obtained meta data, and report it as result res = new YoutubeDownload(id); res->provideMetaData(title, uploader, durationStr.isEmpty() ? TimeSpan() : TimeSpan::fromString(durationStr.toStdString()), collectionTitle, index); reportResult(res); } else { continue; } } else { break; } } else { break; } } if (res) { return ParsingResult::Success; } else { reasonForFail = tr("No videos could be found (maybe the playlist ID is invalid)."); return ParsingResult::Error; } } } // namespace Network