5 #include <QCoreApplication>
9 #include <QRegularExpression>
25 (QEvent::Type) QEvent::registerEventType();
28 (QEvent::Type) QEvent::registerEventType();
107 else if (!nfo.isEmpty())
156 if (list.count() == 1 && list[0]->GetStep() ==
kLookupSearch)
173 if (list[0]->GetAutomatic() && list.count() > 1
198 if (qEnvironmentVariableIsSet(
"EXPERIMENTAL_METADATA_GRAB"))
216 QCoreApplication::postEvent(
m_parent,
221 LOG(VB_GENERAL, LOG_INFO,
222 QString(
"Returning Metadata Results: %1 %2 %3")
225 QCoreApplication::postEvent(
m_parent,
232 LOG(VB_GENERAL, LOG_INFO,
233 QString(
"Metadata Lookup Failed: No Results %1 %2 %3")
241 QCoreApplication::postEvent(
m_parent,
251 const QString &originaltitle,
254 unsigned int exactMatches = 0;
255 unsigned int exactMatchesWithArt = 0;
256 static const QRegularExpression year { R
"( \(\d{4}\)$)" };
258 for (
const auto& lkup : std::as_const(list))
261 QString titlewoyear = originaltitle;
262 auto match = year.match(titlewoyear);
263 if (match.hasMatch())
265 titlewoyear.remove(match.capturedStart(), match.capturedLength());
268 if ((QString::compare(lkup->GetTitle(), originaltitle, Qt::CaseInsensitive) == 0) ||
269 (QString::compare(lkup->GetTitle(), titlewoyear, Qt::CaseInsensitive) == 0))
277 exactMatchesWithArt++;
284 return exactMatchesWithArt;
289 const QString &originaltitle)
293 QDate exactTitleDate;
294 float exactTitlePopularity = 0.0F;
295 int exactMatches = 0;
296 int exactMatchesWithArt = 0;
297 bool foundMatchWithArt =
false;
298 bool foundMatchWithYear =
false;
301 QString titlewoyear = originaltitle;
303 static const QRegularExpression regexyear { R
"( \(\d{4}\)$)" };
305 auto match = regexyear.match(titlewoyear);
306 if (match.hasMatch())
308 titlewoyear.remove(match.capturedStart(), match.capturedLength());
309 year = match.captured(0).replace(
" (",
"").replace(
")",
"").toUInt();
310 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Looking for: '%1' with release year: '%2'")
311 .arg(titlewoyear, QString::number(year)));
315 for (
const auto& lkup : std::as_const(list))
317 QString title = lkup->GetTitle();
318 LOG(VB_GENERAL, LOG_INFO,
319 QString(
"Comparing metadata title '%1' [%2] to recording title '%3' [%4]")
320 .arg(title, lkup->GetReleaseDate().toString(), titlewoyear,
321 (year == 0) ?
"N/A" : QString::number(year)));
325 if ((QString::compare(title, originaltitle, Qt::CaseInsensitive) == 0) ||
326 (QString::compare(title, titlewoyear, Qt::CaseInsensitive) == 0))
328 bool hasArtwork = ((!(lkup->GetArtwork(
kArtworkFanart)).empty()) ||
332 if ((lkup->GetYear() != 0) && (year == lkup->GetYear()))
334 exactTitleDate = lkup->GetReleaseDate();
335 exactTitlePopularity = lkup->GetPopularity();
336 foundMatchWithYear =
true;
340 LOG(VB_GENERAL, LOG_INFO, QString(
"'%1', popularity = %2, ReleaseDate = %3, Year = %4")
342 .arg(lkup->GetPopularity())
343 .arg(lkup->GetReleaseDate().toString())
344 .arg(lkup->GetYear()));
353 if ((ret ==
nullptr) ||
354 (hasArtwork && !foundMatchWithYear &&
355 ((!foundMatchWithArt) ||
356 ((lkup->GetPopularity() > exactTitlePopularity)) ||
357 ((exactTitlePopularity == 0.0F) && (lkup->GetReleaseDate() > exactTitleDate)))))
359 exactTitleDate = lkup->GetReleaseDate();
360 exactTitlePopularity = lkup->GetPopularity();
367 foundMatchWithArt =
true;
368 exactMatchesWithArt++;
372 titles.append(title);
375 LOG(VB_GENERAL, LOG_DEBUG, QString(
"exactMatches = %1, exactMatchesWithArt = %2")
377 .arg(exactMatchesWithArt));
381 if (exactMatches > 0)
383 if (exactMatches == 1)
385 LOG(VB_GENERAL, LOG_INFO, QString(
"Single exact title match for '%1'")
386 .arg(originaltitle));
390 LOG(VB_GENERAL, LOG_INFO,
391 QString(
"Multiple exact title matches found for '%1'. "
392 "Selecting by exact year [%2] or most popular or most recent [%3]")
394 (year == 0) ?
"N/A" : QString::number(year),
395 exactTitleDate.toString()));
401 QString bestTitle =
nearestName(originaltitle, titles);
404 if (bestTitle.isEmpty())
406 LOG(VB_GENERAL, LOG_ERR,
407 QString(
"No adequate match or multiple "
408 "matches found for %1. Update manually.")
409 .arg(originaltitle));
413 LOG(VB_GENERAL, LOG_INFO, QString(
"Best Title Match For %1: %2")
414 .arg(originaltitle, bestTitle));
417 for (
const auto& item : std::as_const(list))
419 if (item->GetTitle() == bestTitle)
436 LOG(VB_GENERAL, LOG_INFO, QString(
"Running Grabber: %1 %2")
437 .arg(cmd,
args.join(
" ")));
441 QByteArray result = grabber.
ReadAll();
442 if (!result.isEmpty())
445 #if QT_VERSION < QT_VERSION_CHECK(6,5,0)
446 doc.setContent(result,
true);
448 doc.setContent(result, QDomDocument::ParseOption::UseNamespaceProcessing);
450 QDomElement root = doc.documentElement();
451 QDomElement item = root.firstChildElement(
"item");
453 while (!item.isNull())
459 item = item.nextSiblingElement(
"item");
489 LOG(VB_GENERAL, LOG_INFO,
490 QString(
"Movie grabber not functional. Aborting this run."));
501 LOG(VB_GENERAL, LOG_INFO,
502 QString(
"Television grabber not functional. Aborting this run."));
515 LOG(VB_GENERAL, LOG_INFO,
516 QString(
"Matching MXML file found. Parsing %1 for metadata...")
527 bool loaded = rf->SaveAs(mxmlraw);
531 #if QT_VERSION < QT_VERSION_CHECK(6,5,0)
532 bool success = doc.setContent(mxmlraw,
true);
534 auto parseResult = doc.setContent(mxmlraw, QDomDocument::ParseOption::UseNamespaceProcessing);
535 bool success { parseResult };
540 QDomElement root = doc.documentElement();
541 item = root.firstChildElement(
"item");
545 LOG(VB_GENERAL, LOG_ERR,
546 QString(
"Corrupt or invalid MXML file."));
568 LOG(VB_GENERAL, LOG_INFO,
569 QString(
"Matching NFO file found. Parsing %1 for metadata...")
582 bool loaded = rf->SaveAs(nforaw);
588 #if QT_VERSION < QT_VERSION_CHECK(6,5,0)
589 bool success = doc.setContent(nforaw,
true);
591 auto parseResult = doc.setContent(nforaw, QDomDocument::ParseOption::UseNamespaceProcessing);
592 bool success { parseResult };
597 item = doc.documentElement();
601 LOG(VB_GENERAL, LOG_ERR,
602 QString(
"Invalid NFO file found."));
718 bool searchcollection =
false;
732 if (list.isEmpty() && (!lookup->
GetSubtitle().isEmpty()))
742 searchcollection =
true;
744 else if (list.isEmpty())
750 searchcollection =
true;
778 if (!searchcollection && list.isEmpty() &&
791 for (
auto it = list.begin(); it != list.end(); ++it)
793 (*it)->SetIsCollection(searchcollection);
815 if (list.count() == 1)
846 if (origseason == 0 && origepisode == 0)
854 if (list.count() == 1)
874 QString ext = QFileInfo(qurl.path()).suffix();
879 newname =
filename +
"/" + QFileInfo(qurl.path()).fileName() +
"." +
type;