6 #include <QMutexLocker>
7 #include <QRegularExpression>
21 #define LOC QString("Metadata Grabber: ")
24 static const QRegularExpression
kRetagRef { R
"(^([a-zA-Z0-9_\-\.]+\.[a-zA-Z0-9]{1,3})[:_](.*))" };
39 "metadata/Movie/tmdb3.py" } },
42 "metadata/Television/ttvdb4.py" } },
44 "mythgame.MetadataGrabber",
45 "metadata/Game/giantbomb.py" } },
65 QString tmptype =
type.toLower();
89 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Clearing grabber cache");
93 for (
const auto& grabberType : std::as_const(
grabberTypes))
95 QString path = (grabberType.m_path).arg(
GetShareDir());
96 QDir dir = QDir(path);
99 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
100 QString(
"No script directory %1").arg(path));
103 QStringList scripts = dir.entryList(QDir::Executable | QDir::Files);
104 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
105 QString(
"Found %1 scripts in %2").arg(scripts.count()).arg(path));
106 if (scripts.count() == 0)
111 for (
const auto& name : std::as_const(scripts))
113 QString cmd = QDir(path).filePath(name);
123 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Failed " + name);
134 for (
const auto& item : std::as_const(tmpGrabberList))
137 retGrabberList.append(item);
140 return retGrabberList;
161 auto grabber =
GetType(defaultType);
162 if (!grabber.m_valid)
166 name = QString(
"Type %1").arg(defaultType);
167 LOG(VB_GENERAL, LOG_INFO,
168 QString(
"Grabber '%1' is not configured. Do you need to set PYTHONPATH?").arg(name));
175 QString tmptype =
type.toLower();
197 for (
const auto& item : std::as_const(list))
198 if (item.GetPath().endsWith(cmd))
203 QString fullcmd = QString(
"%1%2").arg(
GetShareDir(), cmd);
220 for (
const auto& item : std::as_const(list))
222 if (item.GetCommand() == tag)
231 for (
const auto& item : std::as_const(list))
233 if (item.Accepts(tag))
247 static QMutex s_reLock;
248 QMutexLocker lock(&s_reLock);
251 if (match.hasMatch())
252 tag = match.captured(1);
267 static QMutex s_reLock;
268 QMutexLocker lock(&s_reLock);
272 if (match.hasMatch())
273 return match.captured(2);
278 m_fullcommand(std::move(path))
303 QByteArray result = grabber.
ReadAll();
304 if (result.isEmpty())
309 #if QT_VERSION < QT_VERSION_CHECK(6,5,0)
310 doc.setContent(result,
true);
312 doc.setContent(result, QDomDocument::ParseOption::UseNamespaceProcessing);
314 QDomElement root = doc.documentElement();
350 m_name = item.firstChildElement(
"name").text();
351 m_author = item.firstChildElement(
"author").text();
352 m_thumbnail = item.firstChildElement(
"thumbnail").text();
353 m_command = item.firstChildElement(
"command").text();
354 m_description = item.firstChildElement(
"description").text();
355 m_version = item.firstChildElement(
"version").text().toFloat();
356 m_typestring = item.firstChildElement(
"type").text().toLower();
363 QDomElement accepts = item.firstChildElement(
"accepts");
364 if (!accepts.isNull())
366 while (!accepts.isNull())
369 accepts = accepts.nextSiblingElement(
"accepts");
397 LOG(VB_GENERAL, LOG_INFO, QString(
"Running Grabber: %1 %2")
404 QByteArray result = grabber.
ReadAll();
405 if (!result.isEmpty())
408 #if QT_VERSION < QT_VERSION_CHECK(6,5,0)
409 doc.setContent(result,
true);
411 doc.setContent(result, QDomDocument::ParseOption::UseNamespaceProcessing);
413 QDomElement root = doc.documentElement();
414 QDomElement item = root.firstChildElement(
"item");
416 while (!item.isNull())
420 if (!
tmp->GetCollectionref().isEmpty())
422 tmp->SetCollectionref(QString(
"%1_%2")
428 item = item.nextSiblingElement(
"item");
445 metadataMap[
"name"] =
m_name;
450 metadataMap[
"version"] = QString::number(
m_version);
489 [[maybe_unused]]
const QString &title,
490 const QString &subtitle,
524 << QString::number(season)
525 << QString::number(episode);