<< reply->url().toString() << reply->errorString();
}
-QString JsFunctions::evaluateFunction(const QString &function) {
+QString JsFunctions::evaluate(const QString &function) {
if (!engine) return QString();
QScriptValue value = engine->evaluate(function);
if (value.isUndefined())
}
QString JsFunctions::decryptSignature(const QString &s) {
- return evaluateFunction("decryptSignature('" + s + "')");
+ return evaluate("decryptSignature('" + s + "')");
}
QString JsFunctions::decryptAgeSignature(const QString &s) {
- return evaluateFunction("decryptAgeSignature('" + s + "')");
+ return evaluate("decryptAgeSignature('" + s + "')");
+}
+
+QString JsFunctions::videoIdRE() {
+ return evaluate("videoIdRE()");
+}
+
+QString JsFunctions::videoTokenRE() {
+ return evaluate("videoTokenRE()");
+}
+
+QString JsFunctions::videoInfoFmtMapRE() {
+ return evaluate("videoInfoFmtMapRE()");
+}
+
+QString JsFunctions::webPageFmtMapRE() {
+ return evaluate("webPageFmtMapRE()");
+}
+
+QString JsFunctions::jsPlayerRE() {
+ return evaluate("jsPlayerRE()");
+}
+
+QString JsFunctions::signatureFunctionNameRE() {
+ return evaluate("signatureFunctionNameRE()");
}
Video::Video() : m_duration(0),
m_viewCount(-1),
+ m_license(LicenseYouTube),
definitionCode(0),
elIndex(0),
ageGate(false),
- m_license(LicenseYouTube),
loadingStreamUrl(false),
loadingThumbnail(false)
{ }
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;
// 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();
// 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);
}
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);
}
#endif
- QRegExp jsPlayerRe("\"assets\":.+\"js\":\\s*\"([^\"]+)\"");
+ QRegExp jsPlayerRe(JsFunctions::instance()->jsPlayerRE());
if (jsPlayerRe.indexIn(html) != -1) {
QString jsPlayerUrl = jsPlayerRe.cap(1);
jsPlayerUrl.remove('\\');
}
}
-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<int> 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);
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);