|
|
@ -28,14 +28,16 @@ |
|
|
|
* Contact : chris@qbittorrent.org |
|
|
|
* Contact : chris@qbittorrent.org |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
#include <QRegExp> |
|
|
|
|
|
|
|
#include <QDebug> |
|
|
|
#include <QDebug> |
|
|
|
#include <QDir> |
|
|
|
#include <QDir> |
|
|
|
|
|
|
|
#include <QRegExp> |
|
|
|
|
|
|
|
#include <QRegularExpression> |
|
|
|
#include <QString> |
|
|
|
#include <QString> |
|
|
|
#include <QStringList> |
|
|
|
#include <QStringList> |
|
|
|
|
|
|
|
|
|
|
|
#include "base/preferences.h" |
|
|
|
#include "base/preferences.h" |
|
|
|
#include "base/utils/fs.h" |
|
|
|
#include "base/utils/fs.h" |
|
|
|
|
|
|
|
#include "base/utils/string.h" |
|
|
|
#include "rssfeed.h" |
|
|
|
#include "rssfeed.h" |
|
|
|
#include "rssarticle.h" |
|
|
|
#include "rssarticle.h" |
|
|
|
#include "rssdownloadrule.h" |
|
|
|
#include "rssdownloadrule.h" |
|
|
@ -52,23 +54,23 @@ DownloadRule::DownloadRule() |
|
|
|
|
|
|
|
|
|
|
|
bool DownloadRule::matches(const QString &articleTitle, const QString &expression) const |
|
|
|
bool DownloadRule::matches(const QString &articleTitle, const QString &expression) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
static QRegExp whitespace("\\s+"); |
|
|
|
static QRegularExpression whitespace("\\s+"); |
|
|
|
|
|
|
|
|
|
|
|
if (expression.isEmpty()) { |
|
|
|
if (expression.isEmpty()) { |
|
|
|
// A regex of the form "expr|" will always match, so do the same for wildcards
|
|
|
|
// A regex of the form "expr|" will always match, so do the same for wildcards
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (m_useRegex) { |
|
|
|
else if (m_useRegex) { |
|
|
|
QRegExp reg(expression, Qt::CaseInsensitive, QRegExp::RegExp); |
|
|
|
QRegularExpression reg(expression, QRegularExpression::CaseInsensitiveOption); |
|
|
|
return reg.indexIn(articleTitle) > -1; |
|
|
|
return reg.match(articleTitle).hasMatch(); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
// Only match if every wildcard token (separated by spaces) is present in the article name.
|
|
|
|
// Only match if every wildcard token (separated by spaces) is present in the article name.
|
|
|
|
// Order of wildcard tokens is unimportant (if order is important, they should have used *).
|
|
|
|
// Order of wildcard tokens is unimportant (if order is important, they should have used *).
|
|
|
|
foreach (const QString &wildcard, expression.split(whitespace, QString::SplitBehavior::SkipEmptyParts)) { |
|
|
|
foreach (const QString &wildcard, expression.split(whitespace, QString::SplitBehavior::SkipEmptyParts)) { |
|
|
|
QRegExp reg(wildcard, Qt::CaseInsensitive, QRegExp::Wildcard); |
|
|
|
QRegularExpression reg(Utils::String::wildcardToRegex(wildcard), QRegularExpression::CaseInsensitiveOption); |
|
|
|
|
|
|
|
|
|
|
|
if (reg.indexIn(articleTitle) == -1) |
|
|
|
if (!reg.match(articleTitle).hasMatch()) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -124,14 +126,15 @@ bool DownloadRule::matches(const QString &articleTitle) const |
|
|
|
|
|
|
|
|
|
|
|
if (!m_episodeFilter.isEmpty()) { |
|
|
|
if (!m_episodeFilter.isEmpty()) { |
|
|
|
qDebug() << "Checking episode filter:" << m_episodeFilter; |
|
|
|
qDebug() << "Checking episode filter:" << m_episodeFilter; |
|
|
|
QRegExp f("(^\\d{1,4})x(.*;$)"); |
|
|
|
QRegularExpression f("(^\\d{1,4})x(.*;$)"); |
|
|
|
int pos = f.indexIn(m_episodeFilter); |
|
|
|
QRegularExpressionMatch matcher = f.match(m_episodeFilter); |
|
|
|
|
|
|
|
bool matched = matcher.hasMatch(); |
|
|
|
|
|
|
|
|
|
|
|
if (pos < 0) |
|
|
|
if (!matched) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
QString s = f.cap(1); |
|
|
|
QString s = matcher.captured(1); |
|
|
|
QStringList eps = f.cap(2).split(";"); |
|
|
|
QStringList eps = matcher.captured(2).split(";"); |
|
|
|
int sOurs = s.toInt(); |
|
|
|
int sOurs = s.toInt(); |
|
|
|
|
|
|
|
|
|
|
|
foreach (QString ep, eps) { |
|
|
|
foreach (QString ep, eps) { |
|
|
@ -145,22 +148,24 @@ bool DownloadRule::matches(const QString &articleTitle) const |
|
|
|
if (ep.indexOf('-') != -1) { // Range detected
|
|
|
|
if (ep.indexOf('-') != -1) { // Range detected
|
|
|
|
QString partialPattern1 = "\\bs0?(\\d{1,4})[ -_\\.]?e(0?\\d{1,4})(?:\\D|\\b)"; |
|
|
|
QString partialPattern1 = "\\bs0?(\\d{1,4})[ -_\\.]?e(0?\\d{1,4})(?:\\D|\\b)"; |
|
|
|
QString partialPattern2 = "\\b(\\d{1,4})x(0?\\d{1,4})(?:\\D|\\b)"; |
|
|
|
QString partialPattern2 = "\\b(\\d{1,4})x(0?\\d{1,4})(?:\\D|\\b)"; |
|
|
|
QRegExp reg(partialPattern1, Qt::CaseInsensitive); |
|
|
|
QRegularExpression reg(partialPattern1, QRegularExpression::CaseInsensitiveOption); |
|
|
|
|
|
|
|
|
|
|
|
if (ep.endsWith('-')) { // Infinite range
|
|
|
|
if (ep.endsWith('-')) { // Infinite range
|
|
|
|
int epOurs = ep.left(ep.size() - 1).toInt(); |
|
|
|
int epOurs = ep.left(ep.size() - 1).toInt(); |
|
|
|
|
|
|
|
|
|
|
|
// Extract partial match from article and compare as digits
|
|
|
|
// Extract partial match from article and compare as digits
|
|
|
|
pos = reg.indexIn(articleTitle); |
|
|
|
matcher = reg.match(articleTitle); |
|
|
|
|
|
|
|
matched = matcher.hasMatch(); |
|
|
|
|
|
|
|
|
|
|
|
if (pos == -1) { |
|
|
|
if (!matched) { |
|
|
|
reg = QRegExp(partialPattern2, Qt::CaseInsensitive); |
|
|
|
reg = QRegularExpression(partialPattern2, QRegularExpression::CaseInsensitiveOption); |
|
|
|
pos = reg.indexIn(articleTitle); |
|
|
|
matcher = reg.match(articleTitle); |
|
|
|
|
|
|
|
matched = matcher.hasMatch(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (pos != -1) { |
|
|
|
if (matched) { |
|
|
|
int sTheirs = reg.cap(1).toInt(); |
|
|
|
int sTheirs = matcher.captured(1).toInt(); |
|
|
|
int epTheirs = reg.cap(2).toInt(); |
|
|
|
int epTheirs = matcher.captured(2).toInt(); |
|
|
|
if (((sTheirs == sOurs) && (epTheirs >= epOurs)) || (sTheirs > sOurs)) { |
|
|
|
if (((sTheirs == sOurs) && (epTheirs >= epOurs)) || (sTheirs > sOurs)) { |
|
|
|
qDebug() << "Matched episode:" << ep; |
|
|
|
qDebug() << "Matched episode:" << ep; |
|
|
|
qDebug() << "Matched article:" << articleTitle; |
|
|
|
qDebug() << "Matched article:" << articleTitle; |
|
|
@ -178,16 +183,18 @@ bool DownloadRule::matches(const QString &articleTitle) const |
|
|
|
int epOursLast = range.last().toInt(); |
|
|
|
int epOursLast = range.last().toInt(); |
|
|
|
|
|
|
|
|
|
|
|
// Extract partial match from article and compare as digits
|
|
|
|
// Extract partial match from article and compare as digits
|
|
|
|
pos = reg.indexIn(articleTitle); |
|
|
|
matcher = reg.match(articleTitle); |
|
|
|
|
|
|
|
matched = matcher.hasMatch(); |
|
|
|
|
|
|
|
|
|
|
|
if (pos == -1) { |
|
|
|
if (!matched) { |
|
|
|
reg = QRegExp(partialPattern2, Qt::CaseInsensitive); |
|
|
|
reg = QRegularExpression(partialPattern2, QRegularExpression::CaseInsensitiveOption); |
|
|
|
pos = reg.indexIn(articleTitle); |
|
|
|
matcher = reg.match(articleTitle); |
|
|
|
|
|
|
|
matched = matcher.hasMatch(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (pos != -1) { |
|
|
|
if (matched) { |
|
|
|
int sTheirs = reg.cap(1).toInt(); |
|
|
|
int sTheirs = matcher.captured(1).toInt(); |
|
|
|
int epTheirs = reg.cap(2).toInt(); |
|
|
|
int epTheirs = matcher.captured(2).toInt(); |
|
|
|
if ((sTheirs == sOurs) && ((epOursFirst <= epTheirs) && (epOursLast >= epTheirs))) { |
|
|
|
if ((sTheirs == sOurs) && ((epOursFirst <= epTheirs) && (epOursLast >= epTheirs))) { |
|
|
|
qDebug() << "Matched episode:" << ep; |
|
|
|
qDebug() << "Matched episode:" << ep; |
|
|
|
qDebug() << "Matched article:" << articleTitle; |
|
|
|
qDebug() << "Matched article:" << articleTitle; |
|
|
@ -198,8 +205,8 @@ bool DownloadRule::matches(const QString &articleTitle) const |
|
|
|
} |
|
|
|
} |
|
|
|
else { // Single number
|
|
|
|
else { // Single number
|
|
|
|
QString expStr("\\b(?:s0?" + s + "[ -_\\.]?" + "e0?" + ep + "|" + s + "x" + "0?" + ep + ")(?:\\D|\\b)"); |
|
|
|
QString expStr("\\b(?:s0?" + s + "[ -_\\.]?" + "e0?" + ep + "|" + s + "x" + "0?" + ep + ")(?:\\D|\\b)"); |
|
|
|
QRegExp reg(expStr, Qt::CaseInsensitive); |
|
|
|
QRegularExpression reg(expStr, QRegularExpression::CaseInsensitiveOption); |
|
|
|
if (reg.indexIn(articleTitle) != -1) { |
|
|
|
if (reg.match(articleTitle).hasMatch()) { |
|
|
|
qDebug() << "Matched episode:" << ep; |
|
|
|
qDebug() << "Matched episode:" << ep; |
|
|
|
qDebug() << "Matched article:" << articleTitle; |
|
|
|
qDebug() << "Matched article:" << articleTitle; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|