X-Git-Url: https://git.sur5r.net/?p=minitube;a=blobdiff_plain;f=src%2Fvideo.cpp;h=e7c90da4464d06b3bbaf85be11e6f8b20d1ad952;hp=64cbf6dcfd174dbd49774f79ddd1dbd360202382;hb=4250cf62c1410d5c4e16720128264aeb59c8dc17;hpb=5ecc9c04fb173c5693bcded5191d29816304d12c diff --git a/src/video.cpp b/src/video.cpp index 64cbf6d..e7c90da 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -35,10 +35,10 @@ static const QString jsNameChars = "a-zA-Z0-9\\$_"; Video::Video() : m_duration(0), m_viewCount(-1), + m_license(LicenseYouTube), definitionCode(0), elIndex(0), ageGate(false), - m_license(LicenseYouTube), loadingStreamUrl(false), loadingThumbnail(false) { } @@ -67,11 +67,8 @@ void Video::setWebpage(QUrl webpage) { m_webpage = webpage; // Get Video ID - // youtube-dl line 428 - // QRegExp re("^((?:http://)?(?:\\w+\\.)?youtube\\.com/(?:(?:v/)|(?:(?:watch(?:\\.php)?)?\\?(?:.+&)?v=)))?([0-9A-Za-z_-]+)(?(1).+)?$"); - QRegExp re("^https?://www\\.youtube\\.com/watch\\?v=([0-9A-Za-z_-]+).*"); - bool match = re.exactMatch(m_webpage.toString()); - if (!match) { + QRegExp re(JsFunctions::instance()->videoIdRE()); + if (re.indexIn(m_webpage.toString()) == -1) { qWarning() << QString("Cannot get video id for %1").arg(m_webpage.toString()); // emit errorStreamUrl(QString("Cannot get video id for %1").arg(m_webpage.toString())); // loadingStreamUrl = false; @@ -163,29 +160,26 @@ void Video::gotVideoInfo(QByteArray data) { // qDebug() << "videoInfo" << videoInfo; // get video token - QRegExp re = QRegExp("^.*&token=([^&]+).*$"); - bool match = re.exactMatch(videoInfo); - // handle regexp failure - if (!match) { - // qDebug() << "Cannot get token. Trying next el param"; + QRegExp videoTokeRE(JsFunctions::instance()->videoTokenRE()); + if (videoTokeRE.indexIn(videoInfo) == -1) { + // qWarning() << "Cannot get token. Trying next el param" << videoInfo << videoTokeRE.pattern(); // Don't panic! We're gonna try another magic "el" param elIndex++; getVideoInfo(); return; } - QString videoToken = re.cap(1); + QString videoToken = videoTokeRE.cap(1); + // qWarning() << "got token" << videoToken; while (videoToken.contains('%')) videoToken = QByteArray::fromPercentEncoding(videoToken.toLatin1()); // qDebug() << "videoToken" << videoToken; this->videoToken = videoToken; // get fmt_url_map - re = QRegExp("^.*&url_encoded_fmt_stream_map=([^&]+).*$"); - match = re.exactMatch(videoInfo); - // handle regexp failure - if (!match) { - // qDebug() << "Cannot get urlMap. Trying next el param"; + QRegExp fmtMapRE(JsFunctions::instance()->videoInfoFmtMapRE()); + if (fmtMapRE.indexIn(videoInfo) == -1) { + // qWarning() << "Cannot get urlMap. Trying next el param"; // Don't panic! We're gonna try another magic "el" param elIndex++; getVideoInfo(); @@ -194,7 +188,8 @@ void Video::gotVideoInfo(QByteArray data) { // qDebug() << "Got token and urlMap" << elIndex; - QString fmtUrlMap = re.cap(1); + QString fmtUrlMap = fmtMapRE.cap(1); + // qWarning() << "got fmtUrlMap" << fmtUrlMap; fmtUrlMap = QByteArray::fromPercentEncoding(fmtUrlMap.toUtf8()); parseFmtUrlMap(fmtUrlMap); } @@ -310,18 +305,6 @@ void Video::parseFmtUrlMap(const QString &fmtUrlMap, bool fromWebPage) { emit errorStreamUrl(tr("Cannot get video stream for %1").arg(m_webpage.toString())); } -void Video::foundVideoUrl(QString videoToken, int definitionCode) { - // qDebug() << "foundVideoUrl" << videoToken << definitionCode; - - QUrl videoUrl = QUrl(QString( - "http://www.youtube.com/get_video?video_id=%1&t=%2&eurl=&el=&ps=&asv=&fmt=%3" - ).arg(videoId, videoToken, QString::number(definitionCode))); - - m_streamUrl = videoUrl; - loadingStreamUrl = false; - emit gotStreamUrl(videoUrl); -} - void Video::errorVideoInfo(QNetworkReply *reply) { loadingStreamUrl = false; emit errorStreamUrl(tr("Network error: %1 for %2").arg(reply->errorString(), reply->url().toString())); @@ -331,7 +314,8 @@ void Video::scrapeWebPage(QByteArray data) { QString html = QString::fromUtf8(data); // qWarning() << html; - if (html.contains("player-age-gate-content\"")) { + QRegExp ageGateRE(JsFunctions::instance()->ageGateRE()); + if (ageGateRE.indexIn(html) != -1) { // qDebug() << "Found ageGate"; ageGate = true; elIndex = 4; @@ -339,18 +323,16 @@ void Video::scrapeWebPage(QByteArray data) { return; } - QRegExp re(".*\"url_encoded_fmt_stream_map\":\\s+\"([^\"]+)\".*"); - bool match = re.exactMatch(html); - // on regexp failure, stop and report error - if (!match) { - qWarning() << "Error parsing video page"; + QRegExp fmtMapRE(JsFunctions::instance()->webPageFmtMapRE()); + if (fmtMapRE.indexIn(html) == -1) { + // qWarning() << "Error parsing video page"; // emit errorStreamUrl("Error parsing video page"); // loadingStreamUrl = false; elIndex++; getVideoInfo(); return; } - fmtUrlMap = re.cap(1); + fmtUrlMap = fmtMapRE.cap(1); fmtUrlMap.replace("\\u0026", "&"); // parseFmtUrlMap(fmtUrlMap, true); @@ -367,7 +349,7 @@ void Video::scrapeWebPage(QByteArray data) { } #endif - QRegExp jsPlayerRe("\"assets\":.+\"js\":\\s*\"([^\"]+)\""); + QRegExp jsPlayerRe(JsFunctions::instance()->jsPlayerRE()); if (jsPlayerRe.indexIn(html) != -1) { QString jsPlayerUrl = jsPlayerRe.cap(1); jsPlayerUrl.remove('\\'); @@ -384,55 +366,15 @@ void Video::scrapeWebPage(QByteArray data) { } } -void Video::gotHeadHeaders(QNetworkReply* reply) { - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - // qDebug() << "gotHeaders" << statusCode; - if (statusCode == 200) { - foundVideoUrl(videoToken, definitionCode); - } else { - - // try next (lower quality) definition - /* - QStringList definitionNames = VideoDefinition::getDefinitionNames(); - int currentIndex = definitionNames.indexOf(currentDefinition); - int previousIndex = 0; - if (currentIndex > 0) { - previousIndex = currentIndex - 1; - } - if (previousIndex > 0) { - QString nextDefinitionName = definitionNames.at(previousIndex); - findVideoUrl(nextDefinitionName); - } else { - foundVideoUrl(videoToken, 18); - }*/ - - - QList definitionCodes = VideoDefinition::getDefinitionCodes(); - int currentIndex = definitionCodes.indexOf(definitionCode); - int previousIndex = 0; - if (currentIndex > 0) { - previousIndex = currentIndex - 1; - int definitionCode = definitionCodes.at(previousIndex); - if (definitionCode == 18) { - // This is assumed always available - foundVideoUrl(videoToken, 18); - } else { - findVideoUrl(definitionCode); - } - - } else { - foundVideoUrl(videoToken, 18); - } - - } -} - void Video::parseJsPlayer(QByteArray bytes) { QString js = QString::fromUtf8(bytes); // qWarning() << "jsPlayer" << js; - QRegExp funcNameRe("signature=([" + jsNameChars + "]+)"); + + // QRegExp funcNameRe("\"signature\"\\w*,\\w*([" + jsNameChars + "]+)"); + QRegExp funcNameRe(JsFunctions::instance()->signatureFunctionNameRE().arg(jsNameChars)); + if (funcNameRe.indexIn(js) == -1) { - qWarning() << "Cannot capture signature function name"; + qWarning() << "Cannot capture signature function name" << js; } else { sigFuncName = funcNameRe.cap(1); captureFunction(sigFuncName, js); @@ -548,20 +490,6 @@ QString Video::decryptSignature(const QString &s) { return value.toString(); } -void Video::findVideoUrl(int definitionCode) { - this->definitionCode = definitionCode; - - QUrl videoUrl = QUrl(QString( - "http://www.youtube.com/get_video?video_id=%1&t=%2&eurl=&el=&ps=&asv=&fmt=%3" - ).arg(videoId, videoToken, QString::number(definitionCode))); - - QObject *reply = The::http()->head(videoUrl); - connect(reply, SIGNAL(finished(QNetworkReply*)), SLOT(gotHeadHeaders(QNetworkReply*))); - // connect(reply, SIGNAL(error(QNetworkReply*)), SLOT(errorVideoInfo(QNetworkReply*))); - - // see you in gotHeadHeaders() -} - QString Video::formattedDuration() const { QString format = m_duration > 3600 ? "h:mm:ss" : "m:ss"; return QTime().addSecs(m_duration).toString(format);