17 static const QRegularExpression
kStereo { R
"(\b\(?[sS]tereo\)?\b)" };
19 static const QRegularExpression
kDotAtEnd {
"\\.$" };
21 #if QT_VERSION < QT_VERSION_CHECK(5,15,2)
22 #define capturedView capturedRef
25 static const QMap<QChar,quint16>
r2v = {
26 {
'I' , 1}, {
'V' , 5}, {
'X' , 10}, {
'L' , 50},
27 {
'C' , 100}, {
'D' , 500}, {
'M' , 1000},
37 for (
int i = 0; i < roman.size() - 1; i++)
39 int v1 =
r2v[roman.at(i)];
40 int v2 =
r2v[roman.at(i+1)];
41 result += (v1 >= v2) ? v1 : -v1;
43 return result +
r2v[roman.back()];
52 event.m_subtitle = QString(
"");
56 event.m_description =
event.m_subtitle;
57 event.m_subtitle = QString(
"");
65 event.m_videoProps |= VID_HDTV;
148 static const QRegularExpression emptyParens { R
"(\(\s*\))" };
151 event.m_title.remove(QChar(
'\0')).remove(emptyParens);
152 event.m_title =
event.m_title.simplified();
157 event.m_subtitle.remove(QChar(
'\0'));
158 event.m_subtitle.remove(emptyParens);
159 event.m_subtitle =
event.m_subtitle.simplified();
164 event.m_description.remove(QChar(
'\0'));
165 event.m_description.remove(emptyParens);
166 event.m_description =
event.m_description.simplified();
179 for (
auto i = event.
m_items.begin(); i != event.
m_items.end(); ++i)
181 LOG(VB_EIT, LOG_DEBUG, QString(
"Unhandled item in EIT for"
182 " channel id \"%1\", \"%2\": %3").arg(event.
m_chanid)
183 .arg(i.key(), i.value()));
209 QString crid =
id.toLower();
212 if (crid.startsWith(
"crid://"))
216 if (crid.length() >= 1 && crid[0] !=
'/')
220 if (authority.isEmpty())
223 return authority + crid;
234 int position =
event.m_description.indexOf(
'\r');
240 event.m_subtitle =
event.m_description.left(position);
241 event.m_description =
event.m_description.right(
247 position =
event.m_description.indexOf(
".");
255 event.m_category =
"Unknown";
264 position =
event.m_description.indexOf(
".");
266 position =
event.m_description.indexOf(
". ");
269 if ((position > -1) && position < 20)
271 const QString stmp =
event.m_description;
272 event.m_description = stmp.right(stmp.length() - position - 2);
273 event.m_category = stmp.left(position);
275 int position_p =
event.m_category.indexOf(
"(");
276 if (position_p == -1)
277 event.m_description = stmp.right(stmp.length() - position - 2);
279 event.m_category =
"Unknown";
283 event.m_category =
"Unknown";
289 event.m_category =
"OffAir";
292 event.m_category =
"Unknown";
297 event.m_description =
event.m_description.replace(theme,
"");
299 event.m_description =
event.m_description.right(event.
m_description.length() - 1);
301 event.m_description =
event.m_description.right(event.
m_description.length() - 1);
305 static const QRegularExpression bellYear { R
"(\([0-9]{4}\))" };
306 position = event.m_description.indexOf(bellYear);
307 if (position != -1 && !event.
m_category.isEmpty())
311 uint y =
event.m_description.mid(position + 1, 4).toUInt(&ok);
314 event.m_originalairdate = QDate(y, 1, 1);
316 event.m_previouslyshown =
true;
322 static const QRegularExpression bellActors { R
"(\set\s|,)" };
323 QString tmp = event.m_description.left(position-3);
324 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
326 tmp.split(bellActors, QString::SkipEmptyParts);
329 tmp.split(bellActors, Qt::SkipEmptyParts);
334 for (
const auto & actor : qAsConst(actors))
338 event.m_description =
event.m_description.right(
344 position =
event.m_description.indexOf(
"(CC)");
347 event.m_subtitleType |= SUB_HARDHEAR;
348 event.m_description =
event.m_description.replace(
"(CC)",
"");
353 if (match.hasMatch())
355 event.m_audioProps |= AUD_STEREO;
356 event.m_description.remove(match.capturedStart(0),
357 match.capturedLength(0));
361 static const QRegularExpression bellPPVTitleAllDayHD { R
"(\s*\(All Day\, HD\)\s*$)" };
362 match = bellPPVTitleAllDayHD.match(event.m_title);
363 if (match.hasMatch())
365 event.m_title.remove(match.capturedStart(), match.capturedLength());
366 event.m_videoProps |= VID_HDTV;
370 static const QRegularExpression bellPPVTitleAllDay { R
"(\s*\(All Day.*\)\s*$)" };
371 match = bellPPVTitleAllDay.match(event.m_title);
372 if (match.hasMatch())
373 event.m_title.remove(match.capturedStart(), match.capturedLength());
376 static const QRegularExpression bellPPVTitleHD { R
"(^HD\s?-\s?)" };
377 match = bellPPVTitleHD.match(event.m_title);
378 if (match.hasMatch())
380 event.m_title.remove(match.capturedStart(), match.capturedLength());
381 event.m_videoProps |= VID_HDTV;
385 position =
event.m_description.indexOf(
"(HD)");
388 event.m_description =
event.m_description.replace(
"(HD)",
"");
389 event.m_videoProps |= VID_HDTV;
393 position =
event.m_title.indexOf(
"(HD)");
396 event.m_title =
event.m_title.replace(
"(HD)",
"");
397 event.m_videoProps |= VID_HDTV;
401 static const QRegularExpression dishPPVTitleHD { R
"(\sHD\s*$)" };
402 match = dishPPVTitleHD.match(event.m_title);
403 if (match.hasMatch())
405 event.m_title.remove(match.capturedStart(), match.capturedLength());
406 event.m_videoProps |= VID_HDTV;
410 position =
event.m_description.indexOf(
"(DD)");
413 event.m_description =
event.m_description.replace(
"(DD)",
"");
414 event.m_audioProps |= AUD_DOLBY;
415 event.m_audioProps |= AUD_STEREO;
419 position =
event.m_description.indexOf(
"(SAP)");
422 event.m_description =
event.m_description.replace(
"(SAP",
"");
423 event.m_subtitleType |= SUB_HARDHEAR;
427 static const QRegularExpression dishPPVTitleColon { R
"(\:\s*$)" };
428 match = dishPPVTitleColon.match(event.m_title);
429 if (match.hasMatch())
430 event.m_title.remove(match.capturedStart(), match.capturedLength());
433 static const QRegularExpression dishDescriptionNew { R
"(\s*New\.\s*)" };
435 if (match.hasMatch())
437 event.m_previouslyshown =
false;
438 event.m_description.remove(match.capturedStart(), match.capturedLength());
442 static const QRegularExpression dishDescriptionFinale { R
"(\s*(Series|Season)\sFinale\.\s*)" };
444 if (match.hasMatch())
446 event.m_previouslyshown =
false;
447 event.m_description.remove(match.capturedStart(), match.capturedLength());
451 static const QRegularExpression dishDescriptionFinale2 { R
"(\s*Finale\.\s*)" };
453 if (match.hasMatch())
455 event.m_previouslyshown =
false;
456 event.m_description.remove(match.capturedStart(), match.capturedLength());
460 static const QRegularExpression dishDescriptionPremiere { R
"(\s*(Series|Season)\s(Premier|Premiere)\.\s*)" };
462 if (match.hasMatch())
464 event.m_previouslyshown =
false;
465 event.m_description.remove(match.capturedStart(), match.capturedLength());
469 static const QRegularExpression dishDescriptionPremiere2 { R
"(\s*(Premier|Premiere)\.\s*)" };
471 if (match.hasMatch())
473 event.m_previouslyshown =
false;
474 event.m_description.remove(match.capturedStart(), match.capturedLength());
478 static const QRegularExpression ppvcode { R
"(\s*\(([A-Z]|[0-9]){5}\)\s*$)",
479 QRegularExpression::CaseInsensitiveOption };
481 if (match.hasMatch())
482 event.m_description.remove(match.capturedStart(), match.capturedLength());
485 static const QRegularExpression dishPPVSpacePerenEnd { R
"(\s\)\s*$)" };
487 if (match.hasMatch())
488 event.m_description.remove(match.capturedStart(), match.capturedLength());
491 static const QRegularExpression bellPPVSubtitleAllDay { R
"(^All Day \(.*\sEastern\)\s*$)" };
492 match = bellPPVSubtitleAllDay.match(event.m_subtitle);
493 if (match.hasMatch())
494 event.m_subtitle.remove(match.capturedStart(), match.capturedLength());
497 static const QRegularExpression bellPPVDescriptionAllDay { R
"(^\(.*\sEastern\))" };
499 if (match.hasMatch())
500 event.m_description.remove(match.capturedStart(), match.capturedLength());
503 static const QRegularExpression bellPPVDescriptionAllDay2 { R
"(^\([0-9].*am-[0-9].*am\sET\))" };
504 match = bellPPVDescriptionAllDay2.match(event.m_description);
505 if (match.hasMatch())
506 event.m_description.remove(match.capturedStart(), match.capturedLength());
509 static const QRegularExpression bellPPVDescriptionEventId { R
"(\([0-9]{5}\))" };
510 match = bellPPVDescriptionEventId.match(event.m_description);
511 if (match.hasMatch())
512 event.m_description.remove(match.capturedStart(), match.capturedLength());
520 QStringList strListColon =
event.m_description.split(
":");
521 QStringList strListEnd;
524 bool fQuotedSubtitle =
false;
526 if (strListColon.count()>1)
528 bool fDoubleDot =
false;
529 bool fSingleDot =
true;
530 int nLength = strListColon[0].length();
532 int nPosition1 =
event.m_description.indexOf(
"..");
533 if ((nPosition1 < nLength) && (nPosition1 >= 0))
535 nPosition1 =
event.m_description.indexOf(
".");
538 if (nPosition1 > nLength)
542 QString strTmp =
event.m_description.mid(nPosition1+1,
545 QStringList
tmp = strTmp.split(
" ");
552 strListEnd = strListColon;
555 else if (!fSingleDot)
557 QStringList strListTmp;
560 for (
int i =0; (i<strListColon.count()) && (nTitleMax==-1);i++)
562 const QStringList
tmp = strListColon[i].split(
" ");
564 nTitle +=
tmp.size();
567 strListTmp.push_back(strListColon[i]);
572 for (
int i=0;i<(nTitleMax-1);i++)
573 strPartial+=strListTmp[i]+
":";
576 strPartial+=strListTmp[nTitleMax-1];
577 strListEnd.push_back(strPartial);
579 for (
int i=nTitleMax+1;i<strListColon.count();i++)
580 strListEnd.push_back(strListColon[i]);
584 static const QRegularExpression ukQuotedSubtitle { R
"(^'([\w\s\-,]+?)\.' )" };
586 if (match.hasMatch())
588 event.m_subtitle = match.captured(1);
589 event.m_description.remove(match.capturedStart(0),
590 match.capturedLength(0));
591 fQuotedSubtitle =
true;
593 QStringList strListPeriod;
594 QStringList strListQuestion;
595 QStringList strListExcl;
596 if (!(fColon || fQuotedSubtitle))
598 strListPeriod =
event.m_description.split(
".");
599 if (strListPeriod.count() >1)
601 int nPosition1 =
event.m_description.indexOf(
".");
602 int nPosition2 =
event.m_description.indexOf(
"..");
603 if ((nPosition1 < nPosition2) || (nPosition2==-1))
604 strListEnd = strListPeriod;
607 strListQuestion =
event.m_description.split(
"?");
608 strListExcl =
event.m_description.split(
"!");
609 if ((strListQuestion.size() > 1) &&
612 strListEnd = strListQuestion;
615 else if ((strListExcl.size() > 1) &&
618 strListEnd = strListExcl;
625 if (!strListEnd.empty())
627 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
628 QStringList strListSpace = strListEnd[0].split(
629 " ", QString::SkipEmptyParts);
631 QStringList strListSpace = strListEnd[0].split(
632 " ", Qt::SkipEmptyParts);
638 static const QRegularExpression ukExclusionFromSubtitle {
639 "(starring|stars\\s|drama|seres|sitcom)",
640 QRegularExpression::CaseInsensitiveOption };
641 if (strListSpace.filter(ukExclusionFromSubtitle).empty())
643 event.m_subtitle = strListEnd[0]+strEnd;
646 event.m_description.mid(strListEnd[0].length()+1);
658 static const QRegularExpression uk24ep { R
"(^\d{1,2}:00[ap]m to \d{1,2}:00[ap]m: )" };
659 static const QRegularExpression ukTime { R
"(\d{1,2}[\.:]\d{1,2}\s*(am|pm|))" };
662 bool isMovie =
event.m_category.startsWith(
"Movie",Qt::CaseInsensitive) ||
663 event.m_category.startsWith(
"Film",Qt::CaseInsensitive);
665 static const QRegularExpression ukThen { R
"(\s*?(Then|Followed by) 60 Seconds\.)",
666 QRegularExpression::CaseInsensitiveOption };
667 static const QRegularExpression ukNew { R
"((New\.|\s*?(Brand New|New)\s*?(Series|Episode)\s*?[:\.\-]))",
668 QRegularExpression::CaseInsensitiveOption };
669 static const QRegularExpression ukNewTitle { R
"(^(Brand New|New:)\s*)",
670 QRegularExpression::CaseInsensitiveOption };
671 event.m_description =
event.m_description.remove(ukThen);
672 event.m_description =
event.m_description.remove(ukNew);
673 event.m_title =
event.m_title.remove(ukNewTitle);
676 static const QRegularExpression ukTitleRemove {
"^(?:[tT]4:|Schools\\s*?:)" };
677 static const QRegularExpression ukDescriptionRemove { R
"(^(?:CBBC\s*?\.|CBeebies\s*?\.|Class TV\s*?:|BBC Switch\.))" };
678 event.m_title =
event.m_title.remove(ukTitleRemove);
679 event.m_description =
event.m_description.remove(ukDescriptionRemove);
682 static const QRegularExpression ukBBC34 { R
"(BBC (?:THREE|FOUR) on BBC (?:ONE|TWO)\.)",
683 QRegularExpression::CaseInsensitiveOption };
684 event.m_description =
event.m_description.remove(ukBBC34);
687 static const QRegularExpression ukBBC7rpt { R
"(\[Rptd?[^]]+?\d{1,2}\.\d{1,2}[ap]m\]\.)" };
688 event.m_description =
event.m_description.remove(ukBBC7rpt);
691 static const QRegularExpression ukAllNew { R
"(All New To 4Music!\s?)" };
692 event.m_description =
event.m_description.remove(ukAllNew);
695 static const QRegularExpression ukAlsoInHD { R
"(\s*Also in HD\.)",
696 QRegularExpression::CaseInsensitiveOption };
697 event.m_description =
event.m_description.remove(ukAlsoInHD);
700 static const QRegularExpression ukCC { R
"(\[(?:(AD|SL|S|W|HD),?)+\])" };
702 while (match.hasMatch())
704 QStringList tmpCCitems = match.captured(0).remove(
"[").remove(
"]").split(
",");
705 if (tmpCCitems.contains(
"AD"))
706 event.m_audioProps |= AUD_VISUALIMPAIR;
707 if (tmpCCitems.contains(
"HD"))
708 event.m_videoProps |= VID_HDTV;
709 if (tmpCCitems.contains(
"S"))
710 event.m_subtitleType |= SUB_NORMAL;
711 if (tmpCCitems.contains(
"SL"))
712 event.m_subtitleType |= SUB_SIGNED;
713 if (tmpCCitems.contains(
"W"))
714 event.m_videoProps |= VID_WIDESCREEN;
715 event.m_description.remove(match.capturedStart(0),
716 match.capturedLength(0));
717 match = ukCC.match(event.
m_description, match.capturedStart(0));
720 event.m_title =
event.m_title.trimmed();
721 event.m_description =
event.m_description.trimmed();
727 static const QString seasonStr = R
"(\b(?:Season|Series|S)\s*(\d+)\s*,?)";
734 static const QString longEp = R
"(\b(?:Ep|Episode)\s*(\d+)\s*(?:(?:/|of)\s*(\d*))?)";
738 static const QString longSeasEp = QString(
"\\(?(?:%1)?\\s*%2").arg(seasonStr, longEp);
742 static const QString longContext = QString(R
"(\(*%1\s*\)?\s*\.?)").arg(longSeasEp);
746 static const QString shortEp = R
"((\d+)\s*(?:/|of)\s*(\d+))";
753 static const QString shortContext =
754 QString(R
"((?:^|\.)(\s*\(*\s*%1[\s)]*(?:[).:]|$)))").arg(shortEp);
759 static const QRegularExpression ukSeries {
"(?:" + longContext +
"|" + shortContext +
")",
760 QRegularExpression::CaseInsensitiveOption };
763 bool fromTitle =
true;
764 match = ukSeries.match(event.
m_title);
765 if (!match.hasMatch())
770 if (match.hasMatch())
772 if (!match.captured(1).isEmpty())
774 event.m_season = match.captured(1).toUInt();
778 if (!match.captured(2).isEmpty())
780 event.m_episode = match.captured(2).toUInt();
783 else if (!match.captured(5).isEmpty())
785 event.m_episode = match.captured(5).toUInt();
789 if (!match.captured(3).isEmpty())
791 event.m_totalepisodes = match.captured(3).toUInt();
794 else if (!match.captured(6).isEmpty())
796 event.m_totalepisodes = match.captured(6).toUInt();
801 int form = match.captured(4).isEmpty() ? 0 : 4;
805 LOG(VB_EIT, LOG_DEBUG, QString(
"Extracted S%1E%2/%3 from title (%4) \"%5\"")
809 event.m_title.remove(match.capturedStart(form),
810 match.capturedLength(form));
814 LOG(VB_EIT, LOG_DEBUG, QString(
"Extracted S%1E%2/%3 from description (%4) \"%5\"")
818 if (match.capturedStart(form) == 0)
822 event.m_description.remove(match.capturedStart(form),
823 match.capturedLength(form));
835 static const QRegularExpression ukPart { R
"([-(\:,.]\s*(?:Part|Pt)\s*(\d+)\s*(?:(?:of|/)\s*(\d+))?\s*[-):,.])",
836 QRegularExpression::CaseInsensitiveOption };
837 match = ukPart.match(event.m_title);
839 if (match.hasMatch())
841 event.m_partnumber = match.captured(1).toUInt();
842 event.m_parttotal = match.captured(2).toUInt();
844 LOG(VB_EIT, LOG_DEBUG, QString(
"Extracted Part %1/%2 from title (%3)")
848 event.m_title.remove(match.capturedStart(0),
849 match.capturedLength(0));
851 else if (match2.hasMatch())
853 event.m_partnumber = match2.captured(1).toUInt();
854 event.m_parttotal = match2.captured(2).toUInt();
856 LOG(VB_EIT, LOG_DEBUG, QString(
"Extracted Part %1/%2 from description (%3) \"%4\"")
862 if (match2.capturedStart(0) == 0)
865 QString sub = match2.captured(0).contains(
":") ?
":" :
"";
866 event.m_description =
event.m_description.replace(match2.captured(0), sub);
870 static const QRegularExpression ukStarring { R
"((?:Western\s)?[Ss]tarring ([\w\s\-']+?)[Aa]nd\s([\w\s\-']+?)[\.|,]\s*(\d{4})?(?:\.\s)?)" };
872 if (match.hasMatch())
879 if (match.captured(3).length() > 0)
882 uint y = match.captured(3).toUInt(&ok);
886 event.m_originalairdate = QDate(y, 1, 1);
891 static const QRegularExpression ukLaONoSplit {
"^Law & Order: (?:Criminal Intent|LA|"
892 "Special Victims Unit|Trial by Jury|UK|You the Jury)" };
893 if (!event.
m_title.startsWith(
"CSI:") && !event.
m_title.startsWith(
"CD:") &&
894 !event.
m_title.contains(ukLaONoSplit) &&
895 !event.
m_title.startsWith(
"Mission: Impossible"))
897 static const QRegularExpression ukDoubleDotStart { R
"(^\.\.+)" };
898 static const QRegularExpression ukDoubleDotEnd { R
"(\.\.+$)" };
899 if ((event.
m_title.indexOf(ukDoubleDotEnd) != -1) &&
902 QString strPart=
event.m_title.remove(ukDoubleDotEnd)+
" ";
903 strFull = strPart +
event.m_description.remove(ukDoubleDotStart);
905 static const QRegularExpression ukCEPQ { R
"([:\!\.\?]\s)" };
906 static const QRegularExpression ukSpaceStart {
"^ " };
908 ((position1 = strFull.indexOf(ukCEPQ,strPart.length())) != -1))
910 if (strFull[position1] ==
'!' || strFull[position1] ==
'?'
911 || (position1>2 && strFull[position1] ==
'.' && strFull[position1-2] ==
'.'))
913 event.m_title = strFull.left(position1);
914 event.m_description = strFull.mid(position1 + 1);
915 event.m_description.remove(ukSpaceStart);
917 else if ((position1 = strFull.indexOf(ukCEPQ)) != -1)
919 if (strFull[position1] ==
'!' || strFull[position1] ==
'?'
920 || (position1>2 && strFull[position1] ==
'.' && strFull[position1-2] ==
'.'))
922 event.m_title = strFull.left(position1);
923 event.m_description = strFull.mid(position1 + 1);
924 event.m_description.remove(ukSpaceStart);
931 if (match24.hasMatch())
935 event.m_subtitle =
event.m_description.mid(match24.capturedStart(0),
936 match24.captured(0).length() - 2);
937 event.m_description =
event.m_description.remove(match24.captured(0));
942 static const QRegularExpression ukYearColon { R
"(^[\d]{4}:)" };
943 if (!isMovie && (event.
m_title.indexOf(ukYearColon) < 0))
946 if (((position1 = event.
m_title.indexOf(
":")) != -1) &&
949 static const QRegularExpression ukCompleteDots { R
"(^\.\.+$)" };
950 if (event.
m_title.mid(position1+1).indexOf(ukCompleteDots)==0)
953 QString strTmp =
event.m_title.mid(position1+1);
954 event.m_title.resize(position1);
955 event.m_subtitle = strTmp+
event.m_subtitle;
959 event.m_subtitle =
event.m_title.mid(position1 + 1);
960 event.m_title =
event.m_title.left(position1);
970 !event.
m_title.startsWith(
"The X-Files"))
975 static const QRegularExpression ukColonPeriod { R
"([:\.])" };
976 int position2 =
event.m_description.indexOf(ukColonPeriod);
977 if ((position2>=0) && (position2 < (position1-2)))
980 else if ((position1=event.
m_title.indexOf(
"-")) != -1)
984 event.m_subtitle =
event.m_title.mid(position1 + 1);
986 event.m_title =
event.m_title.left(position1);
994 static const QRegularExpression ukYear { R
"([\[\(]([\d]{4})[\)\]])" };
996 if (match.hasMatch())
998 event.m_description.remove(match.capturedStart(0),
999 match.capturedLength(0));
1001 uint y = match.captured(1).toUInt(&ok);
1004 event.m_airdate = y;
1005 event.m_originalairdate = QDate(y, 1, 1);
1010 static const QRegularExpression ukDotSpaceStart { R
"(^\. )" };
1011 static const QRegularExpression ukDotEnd { R
"(\.$)" };
1012 event.m_subtitle.remove(ukDotSpaceStart);
1014 event.m_subtitle.remove(ukDotEnd);
1019 event.m_description=
event.m_subtitle;
1020 event.m_subtitle.clear();
1030 int position =
event.m_description.indexOf(
':');
1033 const QString stmp =
event.m_description;
1034 event.m_subtitle = stmp.left(position);
1035 event.m_description = stmp.right(stmp.length() - position - 2);
1044 static const QRegularExpression comHemPersSeparator { R
"((, |\soch\s))" };
1049 event.m_subtitle =
event.m_description;
1050 event.m_description =
"";
1054 event.m_subtitle =
"";
1056 bool isSeries =
false;
1058 static const QRegularExpression comHemSeries1
1059 { R
"(\s?(?:[dD]el|[eE]pisode)\s([0-9]+)(?:\s?(?:/|:|av)\s?([0-9]+))?\.)" };
1060 static const QRegularExpression comHemSeries2 { R
"(\s?-?\s?([Dd]el\s+([0-9]+)))" };
1062 auto match2 = comHemSeries2.match(event.
m_title);
1063 if (match2.hasMatch())
1065 event.m_partnumber = match2.capturedView(2).toUInt();
1066 event.m_title.remove(match2.capturedStart(), match2.capturedLength());
1068 else if (match.hasMatch())
1070 if (match.capturedStart(1) != -1)
1071 event.m_partnumber = match.capturedView(1).toUInt();
1072 if (match.capturedStart(2) != -1)
1073 event.m_parttotal = match.capturedView(2).toUInt();
1077 if (match.capturedStart() > 0)
1078 event.m_description.remove(match.capturedStart(),
1079 match.capturedLength());
1087 event.m_subtitle = QString(
"Del %1").arg(event.
m_partnumber);
1089 event.m_subtitle += QString(
" av %1").arg(event.
m_parttotal);
1093 static const QRegularExpression comHemTSub { R
"(\s+-\s+([^\-]+))" };
1094 match = comHemTSub.match(event.m_title);
1095 if (match.hasMatch())
1097 event.m_subtitle = match.captured(1);
1098 event.m_title.remove(match.capturedStart(), match.capturedLength());
1107 static const QRegularExpression comHemCountry
1108 { R
"(^(\(.+\))?\s?([^ ]+)\s([^\.0-9]+)\sfrån\s([0-9]{4})(?:\smed\s([^\.]+))?\.?)" };
1110 if (match.hasMatch())
1112 QString replacement;
1116 if (!match.capturedView(1).isEmpty())
1118 replacement = match.captured(1) +
" ";
1123 if (!match.capturedView(2).isEmpty())
1125 replacement += match.captured(2) +
" ";
1130 if (!match.capturedView(3).isEmpty())
1132 replacement += match.captured(3) +
".";
1135 event.m_category = match.captured(3);
1138 if(match.captured(3).indexOf(
"serie")!=-1)
1145 if (!match.capturedView(4).isEmpty())
1148 uint y = match.capturedView(4).trimmed().toUInt(&ok);
1150 event.m_airdate = y;
1154 if (!match.capturedView(5).isEmpty())
1156 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1157 const QStringList actors =
1158 match.captured(5).split(comHemPersSeparator, QString::SkipEmptyParts);
1160 const QStringList actors =
1161 match.captured(5).split(comHemPersSeparator, Qt::SkipEmptyParts);
1165 for (
const auto & actor : qAsConst(actors))
1172 event.m_description =
event.m_description.replace(match.captured(0),replacement);
1179 static const QRegularExpression comHemPersons
1180 { R
"(\s?([Rr]egi|[Ss]kådespelare|[Pp]rogramledare|[Ii] rollerna):\s([^\.]+)\.)" };
1182 while (iter.hasNext())
1184 auto pmatch = iter.next();
1187 static const QRegularExpression comHemDirector {
"[Rr]egi" };
1188 static const QRegularExpression comHemActor {
"[Ss]kådespelare|[Ii] rollerna" };
1189 static const QRegularExpression comHemHost {
"[Pp]rogramledare" };
1190 auto dmatch = comHemDirector.match(pmatch.capturedView(1));
1191 auto amatch = comHemActor.match(pmatch.capturedView(1));
1192 auto hmatch = comHemHost.match(pmatch.capturedView(1));
1193 if (dmatch.hasMatch())
1195 else if (amatch.hasMatch())
1197 else if (hmatch.hasMatch())
1201 event.m_description.remove(pmatch.capturedStart(), pmatch.capturedLength());
1205 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1206 const QStringList actors =
1207 pmatch.captured(2).split(comHemPersSeparator, QString::SkipEmptyParts);
1209 const QStringList actors =
1210 pmatch.captured(2).split(comHemPersSeparator, Qt::SkipEmptyParts);
1214 for (
const auto & actor : qAsConst(actors))
1215 event.AddPerson(role, actor);
1218 event.m_description=
event.m_description.replace(pmatch.captured(0),
"");
1225 if (process_subtitle)
1227 static const QRegularExpression comHemSub { R
"([.\?\!] )" };
1228 int pos2 =
event.m_description.indexOf(comHemSub);
1229 bool pvalid = pos2 != -1 && pos2 <= 55;
1230 if (pvalid && (event.
m_description.length() - (pos2 + 2)) > 0)
1232 event.m_subtitle =
event.m_description.left(
1234 event.m_description =
event.m_description.mid(pos2 + 2);
1239 static const QRegularExpression comHemTT {
"[Tt]ext-[Tt][Vv]" };
1241 event.m_subtitleType |= SUB_NORMAL;
1244 static const QRegularExpression comHemRerun1 { R
"([Rr]epris\sfrån\s([^\.]+)(?:\.|$))" };
1245 static const QRegularExpression comHemRerun2 { R
"(([0-9]+)/([0-9]+)(?:\s-\s([0-9]{4}))?)" };
1247 if (!match.hasMatch())
1251 if (match.captured(1) ==
"i dag")
1253 event.m_originalairdate =
event.m_starttime.date();
1258 if (match.captured(1) ==
"eftermiddagen")
1260 event.m_originalairdate =
event.m_starttime.date().addDays(-1);
1265 match2 = comHemRerun2.match(match.capturedView(1));
1266 if (match2.hasMatch())
1268 int day = match2.capturedView(1).toInt();
1269 int month = match2.capturedView(2).toInt();
1276 if (day > 0 && month > 0)
1278 QDate date(event.
m_starttime.date().year(), month, day);
1281 date = date.addYears(-1);
1282 event.m_originalairdate = date;
1293 event.m_category =
event.m_subtitle;
1295 int position =
event.m_description.indexOf(
':');
1298 const QString stmp =
event.m_description;
1299 event.m_subtitle = stmp.left(position);
1300 event.m_description = stmp.right(stmp.length() - position - 2);
1311 event.m_description =
"";
1313 if (event.
m_description.endsWith(
"Copyright West TV Ltd. 2011)"))
1314 event.m_description.resize(event.
m_description.length()-40);
1318 event.m_description =
event.m_subtitle;
1319 event.m_subtitle.clear();
1322 event.m_description.remove(0,event.
m_title.length()+3);
1323 if (event.
m_title.startsWith(
"LIVE: ", Qt::CaseInsensitive))
1325 event.m_title.remove(0, 6);
1326 event.m_description.prepend(
"(Live) ");
1335 static const QRegularExpression
rating {
"\\((G|PG|M|MA)\\)" };
1337 if (match.hasMatch())
1341 event.m_ratings.push_back(prograting);
1342 event.m_description.remove(0,match.capturedLength()+1);
1346 event.m_videoProps |= VID_HDTV;
1347 event.m_description.remove(0,5);
1351 event.m_subtitleType |= SUB_NORMAL;
1352 event.m_description.remove(0,5);
1356 event.m_subtitle.clear();
1360 event.m_description.remove(0,event.
m_title.length()+1);
1370 event.m_previouslyshown =
true;
1373 static const QRegularExpression year {
"(\\d{4})$" };
1375 if (match.hasMatch())
1377 event.m_airdate = match.capturedView(1).toUInt();
1382 event.m_subtitleType |= SUB_NORMAL;
1386 static const QRegularExpression adv {
"(\\([A-Z,]+\\))$" };
1388 if (match.hasMatch())
1390 advisories = match.captured(1);
1391 event.m_description.remove(match.capturedStart()-1, match.capturedLength()+1);
1393 static const QRegularExpression
rating {
"(C|G|PG|M|MA)$" };
1395 if (match.hasMatch())
1399 if (!advisories.isEmpty())
1400 prograting.
m_rating.append(
" ").append(advisories);
1401 event.m_ratings.push_back(prograting);
1402 event.m_description.remove(match.capturedStart()-1, match.capturedLength()+1);
1414 event.m_description =
event.m_description.trimmed();
1416 static const QRegularExpression auFreeviewSY { R
"((.*) \((.+)\) \(([12][0-9][0-9][0-9])\)$)" };
1418 if (match.hasMatch())
1421 event.m_subtitle = match.captured(2);
1422 event.m_airdate = match.capturedView(3).toUInt();
1423 event.m_description = match.captured(1);
1426 static const QRegularExpression auFreeviewY {
"(.*) \\(([12][0-9][0-9][0-9])\\)$" };
1428 if (match.hasMatch())
1430 event.m_airdate = match.capturedView(2).toUInt();
1431 event.m_description = match.captured(1);
1434 static const QRegularExpression auFreeviewSYC { R
"((.*) \((.+)\) \(([12][0-9][0-9][0-9])\) \((.+)\)$)" };
1436 if (match.hasMatch())
1439 event.m_subtitle = match.captured(2);
1440 event.m_airdate = match.capturedView(3).toUInt();
1441 QStringList actors = match.captured(4).split(
"/");
1444 for (
const QString& actor : qAsConst(actors))
1446 event.m_description = match.captured(1);
1449 static const QRegularExpression auFreeviewYC { R
"((.*) \(([12][0-9][0-9][0-9])\) \((.+)\)$)" };
1451 if (match.hasMatch())
1453 event.m_airdate = match.capturedView(2).toUInt();
1454 QStringList actors = match.captured(3).split(
"/");
1457 for (
const QString& actor : qAsConst(actors))
1459 event.m_description = match.captured(1);
1468 const uint SUBTITLE_PCT = 60;
1469 const uint lSUBTITLE_MAX_LEN = 128;
1472 event.m_subtitle = QString(
"");
1479 static const QRegularExpression mcaIncompleteTitle { R
"((.*).\.\.\.$)" };
1480 auto match = mcaIncompleteTitle.match(event.
m_title);
1481 if (match.hasMatch())
1483 static const QString mcaCompleteTitlea {
"^'?(" };
1484 static const QString mcaCompleteTitleb { R
"([^\.\?]+[^\'])'?[\.\?]\s+(.+))" };
1485 static const QRegularExpression mcaCompleteTitle
1486 { mcaCompleteTitlea + match.captured(1) + mcaCompleteTitleb,
1487 QRegularExpression::CaseInsensitiveOption};
1489 if (match.hasMatch())
1491 event.m_title = match.captured(1).trimmed();
1492 event.m_description = match.captured(2).trimmed();
1497 static const QRegularExpression mcaSubtitle { R
"(^'([^\.]+)'\.\s+(.+))" };
1499 if (match.hasMatch())
1501 uint matchLen = match.capturedLength(1);
1504 if ((matchLen < lSUBTITLE_MAX_LEN) &&
1505 ((matchLen * 100 / evDescLen) < SUBTITLE_PCT))
1507 event.m_subtitle = match.captured(1);
1508 event.m_description = match.captured(2);
1513 static const QRegularExpression mcaSeries { R
"(^S?(\d+)\/E?(\d+)\s-\s(.*)$)" };
1515 if (match.hasMatch())
1517 uint season = match.capturedView(1).toUInt();
1518 uint episode = match.capturedView(2).toUInt();
1519 event.m_subtitle = match.captured(3).trimmed();
1520 event.m_syndicatedepisodenumber =
1521 QString(
"S%1E%2").arg(season).arg(episode);
1522 event.m_season = season;
1523 event.m_episode = episode;
1528 static const QRegularExpression mcaCC { R
"(,?\s(HI|English) Subtitles\.?)" };
1529 int position =
event.m_description.indexOf(mcaCC);
1532 event.m_subtitleType |= SUB_HARDHEAR;
1533 event.m_description.remove(mcaCC);
1537 static const QRegularExpression mcaDD { R
"(,?\sDD\.?)" };
1538 position = event.m_description.indexOf(mcaDD);
1539 if ((position > 0) && (position > event.
m_description.length() - 7))
1541 event.m_audioProps |= AUD_DOLBY;
1542 event.m_description.remove(mcaDD);
1546 static const QRegularExpression mcaAvail { R
"(\s(Only available on [^\.]*bouquet|Not available in RSA [^\.]*)\.?)" };
1547 event.m_description.remove(mcaAvail);
1550 bool isMovie =
false;
1551 static const QRegularExpression mcaCredits { R
"((.*)\s\((\d{4})\)\s*([^\.]+)\.?\s*$)" };
1553 if (match.hasMatch())
1556 event.m_description = match.captured(1).trimmed();
1558 uint y = match.captured(2).trimmed().toUInt(&ok);
1560 event.m_airdate = y;
1566 static const QRegularExpression mcaYear { R
"((.*)\s\((\d{4})\)\s*$)" };
1568 if (match.hasMatch())
1571 event.m_description = match.captured(1).trimmed();
1573 uint y = match.captured(2).trimmed().toUInt(&ok);
1575 event.m_airdate = y;
1581 static const QRegularExpression mcaActors { R
"((.*\.)\s+([^\.]+\s[A-Z][^\.]+)\.\s*)" };
1583 if (match.hasMatch())
1585 static const QRegularExpression mcaActorsSeparator {
"(,\\s+)" };
1586 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1587 const QStringList actors = match.captured(2).split(
1588 mcaActorsSeparator, QString::SkipEmptyParts);
1590 const QStringList actors = match.captured(2).split(
1591 mcaActorsSeparator, Qt::SkipEmptyParts);
1595 for (
const auto & actor : qAsConst(actors))
1597 event.m_description = match.captured(1).trimmed();
1609 static const QRegularExpression superRTLSubtitle { R
"(^Folge\s(\d{1,3}):\s'(.*)')" };
1610 auto match = superRTLSubtitle.match(event.
m_subtitle);
1611 if (match.hasMatch())
1614 event.m_episode = match.capturedView(1).toUInt();
1615 event.m_subtitle = match.captured(2);
1623 static const QRegularExpression rtlRepeat
1624 { R
"([\s\(]?Wiederholung.+vo[m|n].+(\d{2}\.\d{2}\.\d{4}|\d{2}[:\.]\d{2}\sUhr)\)?)" };
1626 if (match.hasMatch())
1629 int pos = match.capturedStart(0);
1630 int length = match.capturedLength(0) + (pos ? 0 : 1);
1631 event.m_description =
event.m_description.remove(pos, length).trimmed();
1635 static const QRegularExpression rtlSubtitle1 { R
"(^Folge\s(\d{1,4})\s*:\s+'(.*)'(?:\s|\.\s*|$))" };
1636 static const QRegularExpression rtlSubtitle2 { R
"(^Folge\s(\d{1,4})\s+(.{0,5}[^\?!\.]{0,120})[\?!\.]\s*)" };
1637 static const QRegularExpression rtlSubtitle3 { R
"(^(?:Folge\s)?(\d{1,4}(?:\/[IVX]+)?)\s+(.{0,5}[^\?!\.]{0,120})[\?!\.]\s*)" };
1638 static const QRegularExpression rtlSubtitle4 { R
"(^Thema.{0,5}:\s([^\.]+)\.\s*)" };
1639 static const QRegularExpression rtlSubtitle5 {
"^'(.+)'\\.\\s*" };
1640 static const QRegularExpression rtlEpisodeNo1 { R
"(^(Folge\s\d{1,4})\.*\s*)" };
1641 static const QRegularExpression rtlEpisodeNo2 { R
"(^(\d{1,2}\/[IVX]+)\.*\s*)" };
1652 if (match1.hasMatch())
1654 event.m_syndicatedepisodenumber = match1.captured(1);
1655 event.m_subtitle = match1.captured(2);
1656 event.m_description =
1657 event.m_description.remove(0, match1.capturedLength());
1660 else if (match2.hasMatch())
1662 event.m_syndicatedepisodenumber = match2.captured(1);
1663 event.m_subtitle = match2.captured(2);
1664 event.m_description =
1665 event.m_description.remove(0, match2.capturedLength());
1668 else if (match3.hasMatch())
1670 event.m_syndicatedepisodenumber = match3.captured(1);
1671 event.m_subtitle = match3.captured(2);
1672 event.m_description =
1673 event.m_description.remove(0, match3.capturedLength());
1676 else if (match4.hasMatch())
1678 event.m_subtitle = match4.captured(1);
1679 event.m_description =
1680 event.m_description.remove(0, match4.capturedLength());
1683 else if (match5.hasMatch())
1685 event.m_subtitle = match5.captured(1);
1686 event.m_description =
1687 event.m_description.remove(0, match5.capturedLength());
1690 else if (match6.hasMatch())
1692 event.m_syndicatedepisodenumber = match6.captured(2);
1693 event.m_subtitle = match6.captured(1);
1694 event.m_description =
1695 event.m_description.remove(0, match6.capturedLength());
1698 else if (match7.hasMatch())
1700 event.m_syndicatedepisodenumber = match7.captured(2);
1701 event.m_subtitle = match7.captured(1);
1702 event.m_description =
1703 event.m_description.remove(0, match7.capturedLength());
1713 const uint SUBTITLE_PCT = 35;
1714 const uint lSUBTITLE_MAX_LEN = 50;
1716 static const QRegularExpression rtlSubtitle { R
"(^([^\.]{3,})\.\s+(.+))" };
1718 if (match.hasMatch())
1720 uint matchLen = match.capturedLength(1);
1723 if ((matchLen < lSUBTITLE_MAX_LEN) &&
1724 (matchLen * 100 / evDescLen < SUBTITLE_PCT))
1726 event.m_subtitle = match.captured(1);
1727 event.m_description = match.captured(2);
1745 static const QRegularExpression pro7Subtitle { R
"(,{0,1}([^,]*?),([^,]+?)\s{0,1}(\d{4})$)" };
1746 auto match = pro7Subtitle.match(event.
m_subtitle);
1747 if (match.hasMatch())
1751 event.m_airdate = match.captured(3).toUInt();
1753 event.m_subtitle.remove(match.capturedStart(0),
1754 match.capturedLength(0));
1758 static const QRegularExpression pro7Cast {
"\n\nDarsteller:\n(.*)$",
1759 QRegularExpression::DotMatchesEverythingOption };
1761 if (match.hasMatch())
1763 QStringList cast = match.captured(1).split(
"\n");
1764 for (
const auto& line : qAsConst(cast))
1766 static const QRegularExpression pro7CastOne { R
"(^([^\(]*?)\((.*)\)$)" };
1767 auto match2 = pro7CastOne.match(line);
1768 if (match2.hasMatch())
1775 event.m_description.remove(match.capturedStart(0),
1776 match.capturedLength(0));
1782 static const QRegularExpression pro7Crew {
"\n\n(Regie:.*)$",
1783 QRegularExpression::DotMatchesEverythingOption };
1785 if (match.hasMatch())
1787 QStringList crew = match.captured(1).split(
"\n");
1788 for (
const auto& line : qAsConst(crew))
1790 static const QRegularExpression pro7CrewOne { R
"(^(.*?):\s+(.*)$)" };
1791 auto match2 = pro7CrewOne.match(line);
1792 if (match2.hasMatch())
1797 QStringList names = match2.captured(2).simplified().split(R
"(\s*,\s*)");
1798 for (
const auto & name : qAsConst(names))
1803 event.AddPerson (role, name);
1807 event.m_description.remove(match.capturedStart(0),
1808 match.capturedLength(0));
1821 static const QRegularExpression deDisneyChannelSubtitle { R
"(,([^,]+?)\s{0,1}(\d{4})$)" };
1822 auto match = deDisneyChannelSubtitle.match(event.
m_subtitle);
1823 if (match.hasMatch())
1827 event.m_airdate = match.captured(3).toUInt();
1829 event.m_subtitle.remove(match.capturedStart(0),
1830 match.capturedLength(0));
1832 static const QRegularExpression
tmp { R
"(\s[^\s]+?-(Serie))" };
1834 if (match.hasMatch())
1837 event.m_category=match.captured(0).trimmed();
1838 event.m_subtitle.remove(match.capturedStart(0),
1839 match.capturedLength(0));
1848 static const QRegularExpression atvSubtitle { R
"(,{0,1}\sFolge\s(\d{1,3})$)" };
1849 event.m_subtitle.replace(atvSubtitle,
"");
1858 static const QRegularExpression fiRerun { R
"(\s?Uusinta[a-zA-Z\s]*\.?)" };
1860 if (match.hasMatch())
1862 event.m_previouslyshown =
true;
1863 event.m_description.remove(match.capturedStart(), match.capturedLength());
1866 static const QRegularExpression fiRerun2 { R
"(\([Uu]\))" };
1868 if (match.hasMatch())
1870 event.m_previouslyshown =
true;
1871 event.m_description.remove(match.capturedStart(), match.capturedLength());
1876 if (match.hasMatch())
1878 event.m_audioProps |= AUD_STEREO;
1879 event.m_description.remove(match.capturedStart(), match.capturedLength());
1883 static const QRegularExpression fiAgeLimit { R
"(\((\d{1,2}|[ST])\)$)" };
1884 match = fiAgeLimit.match(event.m_title);
1885 if (match.hasMatch())
1889 event.m_ratings.push_back(prograting);
1890 event.m_title.remove(match.capturedStart(), match.capturedLength());
1894 static const QRegularExpression fiFilm {
"^(Film|Elokuva): " };
1895 match = fiFilm.match(event.
m_title);
1896 if (match.hasMatch())
1898 event.m_category =
"Film";
1900 event.m_title.remove(match.capturedStart(), match.capturedLength());
1910 QString country =
"";
1912 static const QRegularExpression dePremiereLength { R
"(\s?[0-9]+\sMin\.)" };
1913 event.m_description =
event.m_description.replace(dePremiereLength,
"");
1915 static const QRegularExpression dePremiereAirdate { R
"(\s?([^\s^\.]+)\s((?:1|2)[0-9]{3})\.)" };
1917 if ( match.hasMatch())
1919 country = match.captured(1).trimmed();
1921 uint y = match.captured(2).toUInt(&ok);
1923 event.m_airdate = y;
1924 event.m_description.remove(match.capturedStart(0),
1925 match.capturedLength(0));
1928 static const QRegularExpression dePremiereCredits { R
"(\sVon\s([^,]+)(?:,|\su\.\sa\.)\smit\s([^\.]*)\.)" };
1930 if (match.hasMatch())
1933 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1934 const QStringList actors = match.captured(2).split(
1935 ", ", QString::SkipEmptyParts);
1937 const QStringList actors = match.captured(2).split(
1938 ", ", Qt::SkipEmptyParts);
1942 for (
const auto & actor : qAsConst(actors))
1944 event.m_description.remove(match.capturedStart(0),
1945 match.capturedLength(0));
1948 event.m_description =
event.m_description.replace(
"\u000A$",
"");
1949 event.m_description =
event.m_description.replace(
"\u000A",
" ");
1952 static const QRegularExpression dePremiereOTitle { R
"(\s*\(([^\)]*)\)$)" };
1953 match = dePremiereOTitle.match(event.m_title);
1954 if (match.hasMatch())
1956 event.m_subtitle = QString(
"%1, %2").arg(match.captured(1), country);
1957 event.m_title.remove(match.capturedStart(0),
1958 match.capturedLength(0));
1962 static const QRegularExpression deSkyDescriptionSeasonEpisode { R
"(^(\d{1,2}).\sStaffel,\sFolge\s(\d{1,2}):\s)" };
1963 match = deSkyDescriptionSeasonEpisode.match(event.m_description);
1964 if (match.hasMatch())
1966 event.m_season = match.captured(1).trimmed().toUInt();
1967 event.m_episode = match.captured(2).trimmed().toUInt();
1968 event.m_description.remove(match.capturedStart(0),
1969 match.capturedLength(0));
1990 {
"Movie - Soap/melodrama/folkloric",
2005 QString fullinfo =
event.m_subtitle +
event.m_description;
2006 event.m_subtitle =
"";
2014 event.m_category = name;
2015 event.m_categoryType =
type;
2023 auto match =
kStereo.match(fullinfo);
2024 if (match.hasMatch())
2026 event.m_audioProps |= AUD_STEREO;
2027 fullinfo.remove(match.capturedStart(), match.capturedLength());
2031 static const QRegularExpression nlWide {
"breedbeeld" };
2032 match = nlWide.match(fullinfo);
2033 if (match.hasMatch())
2035 event.m_videoProps |= VID_WIDESCREEN;
2036 fullinfo = fullinfo.replace(
"breedbeeld",
".");
2040 static const QRegularExpression nlRepeat {
"herh." };
2041 match = nlRepeat.match(fullinfo);
2042 if (match.hasMatch())
2043 fullinfo = fullinfo.replace(
"herh.",
".");
2046 static const QRegularExpression nlTxt {
"txt" };
2047 match = nlTxt.match(fullinfo);
2048 if (match.hasMatch())
2050 event.m_subtitleType |= SUB_NORMAL;
2051 fullinfo = fullinfo.replace(
"txt",
".");
2055 static const QRegularExpression nlHD { R
"(\sHD$)" };
2056 match = nlHD.match(event.m_title);
2057 if (match.hasMatch())
2059 event.m_videoProps |= VID_HDTV;
2060 event.m_title.remove(match.capturedStart(), match.capturedLength());
2064 static const QRegularExpression nlSub { R
"(\sAfl\.:\s([^\.]+)\.)" };
2065 match = nlSub.match(fullinfo);
2066 if (match.hasMatch())
2068 QString tmpSubString = match.captured(0);
2069 tmpSubString = tmpSubString.right(match.capturedLength() - 7);
2070 event.m_subtitle = tmpSubString.left(tmpSubString.length() -1);
2071 fullinfo.remove(match.capturedStart(), match.capturedLength());
2075 static const QRegularExpression nlSub2 { R
"(\s\"([^\"]+)\")" };
2076 match = nlSub2.match(fullinfo);
2077 if (match.hasMatch())
2079 QString tmpSubString = match.captured(0);
2080 tmpSubString = tmpSubString.right(match.capturedLength() - 2);
2081 event.m_subtitle = tmpSubString.left(tmpSubString.length() -1);
2082 fullinfo.remove(match.capturedStart(), match.capturedLength());
2089 if (((position = event.
m_title.indexOf(
":")) != -1) &&
2090 (event.
m_title[position + 1].toUpper() == event.
m_title[position + 1]) &&
2093 event.m_subtitle =
event.m_title.mid(position + 1);
2094 event.m_title =
event.m_title.left(position);
2099 static const QRegularExpression nlActors { R
"(\sMet:\s.+e\.a\.)" };
2100 static const QRegularExpression nlPersSeparator { R
"((, |\sen\s))" };
2101 match = nlActors.match(fullinfo);
2102 if (match.hasMatch())
2104 QString tmpActorsString = match.captured(0);
2105 tmpActorsString = tmpActorsString.right(tmpActorsString.length() - 6);
2106 tmpActorsString = tmpActorsString.left(tmpActorsString.length() - 5);
2107 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2108 const QStringList actors =
2109 tmpActorsString.split(nlPersSeparator, QString::SkipEmptyParts);
2111 const QStringList actors =
2112 tmpActorsString.split(nlPersSeparator, Qt::SkipEmptyParts);
2116 for (
const auto & actor : qAsConst(actors))
2118 fullinfo.remove(match.capturedStart(), match.capturedLength());
2122 static const QRegularExpression nlPres { R
"(\sPresentatie:\s([^\.]+)\.)" };
2123 match = nlPres.match(fullinfo);
2124 if (match.hasMatch())
2126 QString tmpPresString = match.captured(0);
2127 tmpPresString = tmpPresString.right(tmpPresString.length() - 14);
2128 tmpPresString = tmpPresString.left(tmpPresString.length() -1);
2129 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2130 const QStringList presenters =
2131 tmpPresString.split(nlPersSeparator, QString::SkipEmptyParts);
2133 const QStringList presenters =
2134 tmpPresString.split(nlPersSeparator, Qt::SkipEmptyParts);
2136 for (
const auto & presenter : qAsConst(presenters))
2138 fullinfo.remove(match.capturedStart(), match.capturedLength());
2142 static const QRegularExpression nlYear1 { R
"(\suit\s([1-2][0-9]{3}))" };
2143 static const QRegularExpression nlYear2 { R
"((\s\([A-Z]{0,3}/?)([1-2][0-9]{3})\))",
2144 QRegularExpression::CaseInsensitiveOption };
2145 match = nlYear1.match(fullinfo);
2146 if (match.hasMatch())
2149 uint y = match.capturedView(1).toUInt(&ok);
2151 event.m_originalairdate = QDate(y, 1, 1);
2154 match = nlYear2.match(fullinfo);
2155 if (match.hasMatch())
2158 uint y = match.capturedView(2).toUInt(&ok);
2160 event.m_originalairdate = QDate(y, 1, 1);
2164 static const QRegularExpression nlDirector { R
"(\svan\s(([A-Z][a-z]+\s)|([A-Z]\.\s)))" };
2165 match = nlDirector.match(fullinfo);
2166 if (match.hasMatch())
2170 static const QRegularExpression nlRub { R
"(\s?\(\W+\)\s?)" };
2171 fullinfo.remove(nlRub);
2174 static const QRegularExpression nlCat {
"^(Amusement|Muziek|Informatief|Nieuws/actualiteiten|Jeugd|Animatie|Sport|Serie/soap|Kunst/Cultuur|Documentaire|Film|Natuur|Erotiek|Comedy|Misdaad|Religieus)\\.\\s" };
2175 fullinfo.remove(nlCat);
2178 static const QRegularExpression nlOmroep { R
"(\s\(([A-Z]+/?)+\)$)" };
2179 event.m_title.remove(nlOmroep);
2183 event.m_description = fullinfo;
2203 static const QRegularExpression noRerun {
"\\(R\\)" };
2204 auto match = noRerun.match(event.
m_title);
2205 if (match.hasMatch())
2207 event.m_previouslyshown =
true;
2208 event.m_title.remove(match.capturedStart(), match.capturedLength());
2211 static const QRegularExpression noHD { R
"([\(\[]HD[\)\]])" };
2213 if (match.hasMatch())
2215 event.m_videoProps |= VID_HDTV;
2216 event.m_subtitle.remove(match.capturedStart(), match.capturedLength());
2220 if (match.hasMatch())
2222 event.m_videoProps |= VID_HDTV;
2223 event.m_description.remove(match.capturedStart(), match.capturedLength());
2233 static const QRegularExpression noRerun {
"\\(R\\)" };
2234 auto match = noRerun.match(event.
m_title);
2235 if (match.hasMatch())
2237 event.m_previouslyshown =
true;
2238 event.m_title.remove(match.capturedStart(), match.capturedLength());
2242 if (match.hasMatch())
2244 event.m_previouslyshown =
true;
2249 static const QRegularExpression noNRKCategories
2250 {
"^(Superstrek[ea]r|Supersomm[ea]r|Superjul|Barne-tv|Fantorangen|Kuraffen|Supermorg[eo]n|Julemorg[eo]n|Sommermorg[eo]n|"
2251 "Kuraffen-TV|Sport i dag|NRKs sportsl.rdag|NRKs sportss.ndag|Dagens dokumentar|"
2252 "NRK2s historiekveld|Detektimen|Nattkino|Filmklassiker|Film|Kortfilm|P.skemorg[eo]n|"
2253 "Radioteatret|Opera|P2-Akademiet|Nyhetsmorg[eo]n i P2 og Alltid Nyheter:): (.+)" };
2254 match = noNRKCategories.match(event.
m_title);
2255 if (match.hasMatch() && (match.capturedLength(2) > 1))
2257 event.m_title = match.captured(2);
2258 event.m_description =
"(" + match.captured(1) +
") " +
event.m_description;
2262 static const QRegularExpression noPremiere {
"\\s+-\\s+(Sesongpremiere|Premiere|premiere)!?$" };
2263 match = noPremiere.match(event.
m_title);
2264 if (match.hasMatch() && (match.capturedStart() >= 3))
2265 event.m_title.remove(match.capturedStart(), match.capturedLength());
2268 if (!event.
m_title.startsWith(
"CSI:") &&
2269 !event.
m_title.startsWith(
"CD:") &&
2270 !event.
m_title.startsWith(
"Distriktsnyheter: fra"))
2272 static const QRegularExpression noColonSubtitle {
"^([^:]+): (.+)" };
2273 match = noColonSubtitle.match(event.
m_title);
2274 if (match.hasMatch())
2278 event.m_title = match.captured(1);
2279 event.m_subtitle = match.captured(2);
2281 else if (event.
m_subtitle == match.captured(2))
2283 event.m_title = match.captured(1);
2301 static const QRegularExpression dkEpisode { R
"(\(([0-9]+)\))" };
2302 auto match = dkEpisode.match(event.
m_title);
2303 if (match.hasMatch())
2305 episode = match.capturedView(1).toInt();
2306 event.m_partnumber = match.capturedView(1).toInt();
2307 event.m_title.remove(match.capturedStart(), match.capturedLength());
2310 static const QRegularExpression dkPart { R
"(\(([0-9]+):([0-9]+)\))" };
2311 match = dkPart.match(event.m_title);
2312 if (match.hasMatch())
2314 episode = match.capturedView(1).toInt();
2315 event.m_partnumber = match.capturedView(1).toInt();
2316 event.m_parttotal = match.capturedView(2).toInt();
2317 event.m_title.remove(match.capturedStart(), match.capturedLength());
2321 static const QRegularExpression dkSubtitle1 {
"^([^:]+): (.+)" };
2322 match = dkSubtitle1.match(event.
m_title);
2323 if (match.hasMatch())
2325 event.m_title = match.captured(1);
2326 event.m_subtitle = match.captured(2);
2330 static const QRegularExpression dkSubtitle2 {
"^([^:]+) - (.+)" };
2331 match = dkSubtitle2.match(event.
m_title);
2332 if (match.hasMatch())
2334 event.m_title = match.captured(1);
2335 event.m_subtitle = match.captured(2);
2342 static const QRegularExpression dkSeason1 {
"Sæson ([0-9]+)\\." };
2344 if (match.hasMatch())
2346 season = match.capturedView(1).toInt();
2350 static const QRegularExpression dkSeason2 {
"- år ([0-9]+) :" };
2352 if (match.hasMatch())
2354 season = match.capturedView(1).toInt();
2359 event.m_episode = episode;
2362 event.m_season = season;
2365 static const QRegularExpression dkFeatures {
"Features:(.+)" };
2367 if (match.hasMatch())
2369 QString features = match.captured(1);
2370 event.m_description.remove(match.capturedStart(),
2371 match.capturedLength());
2373 static const QRegularExpression dkWidescreen {
" 16:9" };
2374 if (features.indexOf(dkWidescreen) != -1)
2375 event.m_videoProps |= VID_WIDESCREEN;
2377 static const QRegularExpression dkHD {
" HD" };
2378 if (features.indexOf(dkHD) != -1)
2379 event.m_videoProps |= VID_HDTV;
2381 static const QRegularExpression dkDolby {
" 5:1" };
2382 if (features.indexOf(dkDolby) != -1)
2383 event.m_audioProps |= AUD_DOLBY;
2385 static const QRegularExpression dkSurround { R
"( \(\(S\)\))" };
2386 if (features.indexOf(dkSurround) != -1)
2387 event.m_audioProps |= AUD_SURROUND;
2389 static const QRegularExpression dkStereo {
" S" };
2390 if (features.indexOf(dkStereo) != -1)
2391 event.m_audioProps |= AUD_STEREO;
2393 static const QRegularExpression dkReplay {
" \\(G\\)" };
2394 if (features.indexOf(dkReplay) != -1)
2395 event.m_previouslyshown =
true;
2397 static const QRegularExpression dkTxt {
" TTV" };
2398 if (features.indexOf(dkTxt) != -1)
2399 event.m_subtitleType |= SUB_NORMAL;
2412 newid = QString(
"%1%2").arg(event.
m_chanid).
2417 newid =
event.m_seriesId.mid(2,8);
2419 event.m_seriesId = newid;
2423 event.m_programId[0]=
'_';
2428 event.m_subtitle = QString(
"%1 (%2").arg(event.
m_subtitle).arg(episode);
2430 event.m_subtitle = QString(
"%1:%2").arg(event.
m_subtitle).
2434 event.m_season = season;
2435 event.m_episode = episode;
2436 event.m_syndicatedepisodenumber =
2437 QString(
"S%1E%2").arg(season).arg(episode);
2438 event.m_subtitle = QString(
"%1 Sæson %2").arg(event.
m_subtitle).
2441 event.m_subtitle = QString(
"%1)").arg(event.
m_subtitle);
2445 static const QRegularExpression dkDirector {
"(?:Instr.: |Instrukt.r: )(.+)$" };
2446 static const QRegularExpression dkPersonsSeparator {
"(, )|(og )" };
2447 QStringList directors {};
2449 if (match.hasMatch())
2451 QString tmpDirectorsString = match.captured(1);
2452 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2453 directors = tmpDirectorsString.split(dkPersonsSeparator, QString::SkipEmptyParts);
2455 directors = tmpDirectorsString.split(dkPersonsSeparator, Qt::SkipEmptyParts);
2457 for (
const auto & director : qAsConst(directors))
2459 tmpDirectorsString = director.split(
":").last().trimmed().
2461 if (tmpDirectorsString !=
"")
2467 static const QRegularExpression dkActors {
"(?:Medvirkende: |Medv\\.: )(.+)" };
2469 if (match.hasMatch())
2471 QString tmpActorsString = match.captured(1);
2472 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2473 const QStringList actors =
2474 tmpActorsString.split(dkPersonsSeparator, QString::SkipEmptyParts);
2476 const QStringList actors =
2477 tmpActorsString.split(dkPersonsSeparator, Qt::SkipEmptyParts);
2479 for (
const auto & actor : qAsConst(actors))
2481 tmpActorsString = actor.split(
":").last().trimmed().remove(
kDotAtEnd);
2482 if (!tmpActorsString.isEmpty() && !directors.contains(tmpActorsString))
2489 static const QRegularExpression dkYear {
" fra ([0-9]{4})[ \\.]" };
2491 if (match.hasMatch())
2494 uint y = match.capturedView(1).toUInt(&ok);
2496 event.m_originalairdate = QDate(y, 1, 1);
2505 LOG(VB_EIT, LOG_INFO, QString(
"Applying html strip to %1").arg(event.
m_title));
2506 static const QRegularExpression html {
"</?EM>", QRegularExpression::CaseInsensitiveOption };
2507 event.m_title.remove(html);
2518 event.m_description = QString(
"");
2522 if (event.
m_subtitle.trimmed().right(1) !=
".'" )
2523 event.m_subtitle =
event.m_subtitle.trimmed() +
".";
2524 event.m_description =
event.m_subtitle.trimmed() + QString(
" ") +
event.m_description;
2525 event.m_subtitle = QString(
"");
2532 static const QRegularExpression grRating { R
"(\[(K|Κ|8|12|16|18)\]\s*)",
2533 QRegularExpression::CaseInsensitiveOption };
2534 auto match = grRating.match(event.
m_title);
2535 if (match.hasMatch())
2539 event.m_ratings.push_back(prograting);
2540 event.m_title.remove(match.capturedStart(), match.capturedLength());
2541 event.m_title =
event.m_title.trimmed();
2545 int position =
event.m_title.indexOf(
"(Ζ)");
2548 event.m_title =
event.m_title.replace(
"(Ζ)",
"");
2549 event.m_description.prepend(
"Ζωντανή Μετάδοση. ");
2553 static const QRegularExpression grNotPreviouslyShown {
2554 R
"(\W?(?:-\s*)*(?:\b[Α1]['΄η]?\s*(?:τηλεοπτικ[ηή]\s*)?(?:μετ[αά]δοση|προβολ[ηή]))\W?)",
2555 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2556 match = grNotPreviouslyShown.match(event.m_title);
2557 if (match.hasMatch())
2559 event.m_previouslyshown =
false;
2560 event.m_title.remove(match.capturedStart(), match.capturedLength());
2566 static const QRegularExpression grReplay { R
"(\([ΕE]\))" };
2567 match = grReplay.match(event.m_title);
2568 if (match.hasMatch())
2570 event.m_previouslyshown =
true;
2571 event.m_title.remove(match.capturedStart(), match.capturedLength());
2575 position =
event.m_description.indexOf(
"(HD)");
2578 event.m_description =
event.m_description.replace(
"(HD)",
"");
2579 event.m_videoProps |= VID_HDTV;
2583 position =
event.m_description.indexOf(
"(Full HD)");
2586 event.m_description =
event.m_description.replace(
"(Full HD)",
"");
2587 event.m_videoProps |= VID_HDTV;
2590 static const QRegularExpression grFixnofullstopActors { R
"(\w\s(Παίζουν:|Πρωταγων))" };
2592 if (match.hasMatch())
2593 event.m_description.insert(match.capturedStart() + 1,
".");
2596 static const QRegularExpression grFixnofullstopDirectors { R
"(\w\s(Σκηνοθ[εέ]))" };
2597 match = grFixnofullstopDirectors.match(event.m_description);
2598 if (match.hasMatch())
2599 event.m_description.insert(match.capturedStart() + 1,
".");
2607 static const QRegularExpression grActors { R
"((?:[Ππ]α[ιί]ζουν:|[ΜMμ]ε τους:|Πρωταγωνιστο[υύ]ν:|Πρωταγωνιστε[ιί]:?)(?:\s+στο ρόλο(?: του| της)?\s(?:\w+\s[οη]\s))?([-\w\s']+(?:,[-\w\s']+)*)(?:κ\.[αά])?\W?)" };
2609 static const QRegularExpression grPeopleSeparator { R
"(([,-]\s+))" };
2611 if (match.hasMatch())
2613 QString tmpActorsString = match.captured(1);
2614 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2615 const QStringList actors =
2616 tmpActorsString.split(grPeopleSeparator, QString::SkipEmptyParts);
2618 const QStringList actors =
2619 tmpActorsString.split(grPeopleSeparator, Qt::SkipEmptyParts);
2621 for (
const auto & actor : qAsConst(actors))
2623 tmpActorsString = actor.split(
":").last().trimmed().remove(
kDotAtEnd);
2624 if (tmpActorsString !=
"")
2627 event.m_description.remove(match.capturedStart(), match.capturedLength());
2631 static const QRegularExpression grDirector { R
"((?:Σκηνοθεσία: |Σκηνοθέτης: |Σκηνοθέτης - Επιμέλεια: )(\w+\s\w+\s?)(?:\W?))" };
2633 if (match.hasMatch())
2635 QString tmpDirectorsString = match.captured(1);
2636 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2637 const QStringList directors =
2638 tmpDirectorsString.split(grPeopleSeparator, QString::SkipEmptyParts);
2640 const QStringList directors =
2641 tmpDirectorsString.split(grPeopleSeparator, Qt::SkipEmptyParts);
2643 for (
const auto & director : qAsConst(directors))
2645 tmpDirectorsString = director.split(
":").last().trimmed().
2647 if (tmpDirectorsString !=
"")
2652 event.m_description.remove(match.capturedStart(), match.capturedLength());
2656 static const QRegularExpression grPres { R
"((?:Παρουσ[ιί]αση:(?:\b)*|Παρουσι[αά]ζ(?:ουν|ει)(?::|\sο|\sη)|Παρουσι[αά]στ(?:[ηή]ς|ρια|ριες|[εέ]ς)(?::|\sο|\sη)|Με τ(?:ον |ην )(?:[\s|:|ο|η])*(?:\b)*)([-\w\s]+(?:,[-\w\s]+)*)\W?)",
2657 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2659 if (match.hasMatch())
2661 QString tmpPresentersString = match.captured(1);
2662 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2663 const QStringList presenters =
2664 tmpPresentersString.split(grPeopleSeparator, QString::SkipEmptyParts);
2666 const QStringList presenters =
2667 tmpPresentersString.split(grPeopleSeparator, Qt::SkipEmptyParts);
2669 for (
const auto & presenter : qAsConst(presenters))
2671 tmpPresentersString = presenter.split(
":").last().trimmed().
2673 if (tmpPresentersString !=
"")
2678 event.m_description.remove(match.capturedStart(), match.capturedLength());
2683 static const QRegularExpression grYear { R
"(\W?(?:\s?παραγωγ[ηή]ς|\s?-|,)\s*([1-2][0-9]{3})(?:-\d{1,4})?)",
2684 QRegularExpression::CaseInsensitiveOption };
2686 if (match.hasMatch())
2689 uint y = match.capturedView(1).toUInt(&ok);
2692 event.m_originalairdate = QDate(y, 1, 1);
2693 event.m_description.remove(match.capturedStart(), match.capturedLength());
2697 event.m_description =
event.m_description.replace(
" .",
".").trimmed();
2700 static const QRegularExpression grCountry {
2701 R
"((?:\W|\b)(?:(ελλην|τουρκ|αμερικ[αά]ν|γαλλ|αγγλ|βρεττ?αν|γερμαν|ρωσσ?|ιταλ|ελβετ|σουηδ|ισπαν|πορτογαλ|μεξικ[αά]ν|κιν[εέ]ζικ|ιαπων|καναδ|βραζιλι[αά]ν)(ικ[ηή][ςσ])))",
2702 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2704 if (match.hasMatch())
2705 event.m_description.remove(match.capturedStart(), match.capturedLength());
2709 bool series =
false;
2710 static const QRegularExpression grSeason {
2711 R
"((?:\W-?)*(?:\(-\s*)?\b(([Α-Ω|A|B|E|Z|H|I|K|M|N]{1,2})(?:'|΄)?|(\d{1,2})(?:ος|ου|oς|os)?)(?:\s*[ΚκKk][υύ]κλο(?:[σς]|υ))\s?)",
2712 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2715 match = grSeason.match(event.
m_title);
2716 if (match.hasMatch())
2718 if (!match.capturedView(2).isEmpty())
2722 int tmpinteger = match.capturedView(2).toUInt();
2725 if (match.captured(2) ==
"ΣΤ")
2729 static const QString LettToNumber =
"0ΑΒΓΔΕ6ΖΗΘΙΚΛΜΝ";
2730 tmpinteger = LettToNumber.indexOf(match.capturedView(2));
2731 if (tmpinteger != -1)
2732 event.m_season = tmpinteger;
2736 static const QString LettToNumber2 =
"0ABΓΔE6ZHΘIKΛMN";
2737 tmpinteger = LettToNumber2.indexOf(match.capturedView(2));
2738 if (tmpinteger != -1)
2739 event.m_season = tmpinteger;
2744 else if (!match.capturedView(3).isEmpty())
2746 event.m_season = match.capturedView(3).toUInt();
2749 event.m_title.remove(match.capturedStart(), match.capturedLength());
2754 if (match.hasMatch())
2756 if (!match.capturedView(2).isEmpty())
2760 int tmpinteger = match.capturedView(2).toUInt();
2763 if (match.captured(2) ==
"ΣΤ")
2767 static const QString LettToNumber =
"0ΑΒΓΔΕ6ΖΗΘΙΚΛΜΝ";
2768 tmpinteger = LettToNumber.indexOf(match.capturedView(2));
2769 if (tmpinteger != -1)
2770 event.m_season = tmpinteger;
2774 else if (!match.capturedView(3).isEmpty())
2776 event.m_season = match.capturedView(3).toUInt();
2779 event.m_description.remove(match.capturedStart(), match.capturedLength());
2784 static const QRegularExpression grSeasonAsRomanNumerals {
",\\s*([MDCLXVIΙΧ]+)$",
2785 QRegularExpression::CaseInsensitiveOption };
2786 match = grSeasonAsRomanNumerals.match(event.
m_title);
2787 auto match2 = grSeasonAsRomanNumerals.match(event.
m_description);
2788 if (match.hasMatch())
2790 if (!match.capturedView(1).isEmpty())
2791 event.m_season =
parseRoman(match.captured(1).toUpper());
2793 event.m_title.remove(match.capturedStart(), match.capturedLength());
2794 event.m_title =
event.m_title.trimmed();
2795 if (event.
m_title.right(1) ==
",")
2796 event.m_title.chop(1);
2798 else if (match2.hasMatch())
2800 if (!match2.capturedView(1).isEmpty())
2801 event.m_season =
parseRoman(match2.captured(1).toUpper());
2803 event.m_description.remove(match2.capturedStart(), match2.capturedLength());
2804 event.m_description =
event.m_description.trimmed();
2806 event.m_description.chop(1);
2809 static const QRegularExpression grlongEp { R
"(\b(?:Επ.|επεισ[οό]διο:?)\s*(\d+)\W?)",
2810 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2812 match = grlongEp.match(event.
m_title);
2814 if (match.hasMatch() || match2.hasMatch())
2816 if (!match.capturedView(1).isEmpty())
2818 event.m_episode = match.capturedView(1).toUInt();
2820 event.m_title.remove(match.capturedStart(), match.capturedLength());
2822 else if (!match2.capturedView(1).isEmpty())
2824 event.m_episode = match2.capturedView(1).toUInt();
2826 event.m_description.remove(match2.capturedStart(), match2.capturedLength());
2837 static const QRegularExpression grCommentsinTitle { R
"(\(([Α-Ωα-ω\s\d-]+)\)(?:\s*$)*)" };
2840 match = grCommentsinTitle.match(event.
m_title);
2841 if (match.hasMatch())
2842 event.m_title.remove(match.capturedStart(), match.capturedLength());
2850 static const QRegularExpression grRealTitleInDescription { R
"(^\(([A-Za-z\s\d-]+)\)\s*)" };
2853 match = grRealTitleInDescription.match(event.
m_description);
2854 if (match.hasMatch())
2856 event.m_description.remove(0, match.capturedLength());
2857 if (match.captured(0) != event.
m_title.trimmed())
2859 event.m_description =
"(" +
event.m_title.trimmed() +
"). " +
event.m_description;
2861 event.m_title = match.captured(1);
2866 static const QRegularExpression grRealTitleInTitle { R
"(\(([A-Za-z\s\d-]+)\)(?:\s*$)?)" };
2869 match = grRealTitleInTitle.match(event.
m_title);
2870 if (match.hasMatch())
2872 event.m_title.remove(match.capturedStart(), match.capturedLength());
2873 QString tmpTranslTitle =
event.m_title;
2875 event.m_title = match.captured(1);
2876 event.m_description =
"(" + tmpTranslTitle.trimmed() +
"). " +
event.m_description;
2881 static const QRegularExpression grEpisodeAsSubtitle { R
"(^Επεισ[οό]διο:\s?([\w\s\-,']+)\.\s?)" };
2883 if (match.hasMatch())
2885 event.m_subtitle = match.captured(1).trimmed();
2886 event.m_description.remove(match.capturedStart(), match.capturedLength());
2888 static const QRegularExpression grMovie { R
"(\bταιν[ιί]α\b)",
2889 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2890 bool isMovie = (
event.m_description.indexOf(grMovie) !=-1) ;
2896 event.m_description.replace(
",,",
",");
2903 struct grCategoryEntry {
2904 QRegularExpression expr;
2907 static const QRegularExpression grCategFood {
"\\W?(?:εκπομπ[ηή]\\W)?(Γαστρονομ[ιί]α[σς]?|μαγειρικ[ηή][σς]?|chef|συνταγ[εέηή]|διατροφ|wine|μ[αά]γειρα[σς]?)\\W?",
2908 QRegularExpression::CaseInsensitiveOption };
2909 static const QRegularExpression grCategDrama {
"\\W?(κοινωνικ[ηήό]|δραματικ[ηή]|δρ[αά]μα)\\W(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2910 QRegularExpression::CaseInsensitiveOption};
2911 static const QRegularExpression grCategComedy {
"\\W?(κωμικ[ηήοό]|χιουμοριστικ[ηήοό]|κωμωδ[ιί]α)\\W(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2912 QRegularExpression::CaseInsensitiveOption};
2913 static const QRegularExpression grCategChildren {
"\\W?(παιδικ[ηήοό]|κινο[υύ]μ[εέ]ν(ων|α)\\sσχ[εέ]δ[ιί](ων|α))\\W(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2914 QRegularExpression::CaseInsensitiveOption};
2915 static const QRegularExpression grCategMystery {
"(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?\\W?(μυστηρ[ιί]ου)\\W?",
2916 QRegularExpression::CaseInsensitiveOption};
2917 static const QRegularExpression grCategFantasy {
"(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?\\W?(φαντασ[ιί]ας)\\W?",
2918 QRegularExpression::CaseInsensitiveOption};
2919 static const QRegularExpression grCategHistory {
"\\W?(ιστορικ[ηήοό])\\W?(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2920 QRegularExpression::CaseInsensitiveOption};
2921 static const QRegularExpression grCategTeleMag {
"\\W?(ενημερωτικ[ηή]|ψυχαγωγικ[ηή]|τηλεπεριοδικ[οό]|μαγκαζ[ιί]νο)\\W?(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2922 QRegularExpression::CaseInsensitiveOption};
2923 static const QRegularExpression grCategTeleShop {
"\\W?(οδηγ[οό][σς]?\\sαγορ[ωώ]ν|τηλεπ[ωώ]λ[ηή]σ|τηλεαγορ|τηλεμ[αά]ρκετ|telemarket)\\W?(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2924 QRegularExpression::CaseInsensitiveOption};
2925 static const QRegularExpression grCategGameShow {
"\\W?(τηλεπαιχν[ιί]δι|quiz)\\W?",
2926 QRegularExpression::CaseInsensitiveOption};
2927 static const QRegularExpression grCategDocumentary {
"\\W?(ντοκ[ιυ]μαντ[εέ]ρ)\\W?",
2928 QRegularExpression::CaseInsensitiveOption};
2929 static const QRegularExpression grCategBiography {
"\\W?(βιογραφ[ιί]α|βιογραφικ[οό][σς]?)\\W?",
2930 QRegularExpression::CaseInsensitiveOption};
2931 static const QRegularExpression grCategNews {
"\\W?(δελτ[ιί]ο\\W?|ειδ[ηή]σε(ι[σς]|ων))\\W?",
2932 QRegularExpression::CaseInsensitiveOption};
2933 static const QRegularExpression grCategSports {
"\\W?(champion|αθλητικ[αάοόηή]|πρωτ[αά]θλημα|ποδ[οό]σφαιρο(ου)?|κολ[υύ]μβηση|πατιν[αά]ζ|formula|μπ[αά]σκετ|β[οό]λε[ιϊ])\\W?",
2934 QRegularExpression::CaseInsensitiveOption};
2935 static const QRegularExpression grCategMusic {
"\\W?(μουσικ[οόηή]|eurovision|τραγο[υύ]δι)\\W?",
2936 QRegularExpression::CaseInsensitiveOption};
2937 static const QRegularExpression grCategReality {
"\\W?(ρι[αά]λιτι|reality)\\W?",
2938 QRegularExpression::CaseInsensitiveOption};
2939 static const QRegularExpression grCategReligion {
"\\W?(θρησκε[ιί]α|θρησκευτικ|να[οό][σς]?|θε[ιί]α λειτουργ[ιί]α)\\W?",
2940 QRegularExpression::CaseInsensitiveOption};
2941 static const QRegularExpression grCategCulture {
"\\W?(τ[εέ]χν(η|ε[σς])|πολιτισμ)\\W?",
2942 QRegularExpression::CaseInsensitiveOption};
2943 static const QRegularExpression grCategNature {
"\\W?(φ[υύ]ση|περιβ[αά]λλο|κατασκευ|επιστ[ηή]μ(?!ονικ[ηή]ς φαντασ[ιί]ας))\\W?",
2944 QRegularExpression::CaseInsensitiveOption};
2945 static const QRegularExpression grCategSciFi {
"\\W?(επιστ(.|ημονικ[ηή]ς)\\s?φαντασ[ιί]ας)\\W?",
2946 QRegularExpression::CaseInsensitiveOption};
2947 static const QRegularExpression grCategHealth {
"\\W?(υγε[ιί]α|υγειιν|ιατρικ|διατροφ)\\W?",
2948 QRegularExpression::CaseInsensitiveOption};
2949 static const QRegularExpression grCategSpecial {
"\\W?(αφι[εέ]ρωμα)\\W?",
2950 QRegularExpression::CaseInsensitiveOption};
2951 static const QList<grCategoryEntry> grCategoryDescData = {
2952 { grCategComedy,
"Κωμωδία" },
2953 { grCategTeleMag,
"Τηλεπεριοδικό" },
2954 { grCategNature,
"Επιστήμη/Φύση" },
2955 { grCategHealth,
"Υγεία" },
2956 { grCategReality,
"Ριάλιτι" },
2957 { grCategDrama,
"Κοινωνικό" },
2958 { grCategChildren,
"Παιδικό" },
2959 { grCategSciFi,
"Επιστ.Φαντασίας" },
2960 { grCategMystery,
"Μυστηρίου" },
2961 { grCategFantasy,
"Φαντασίας" },
2962 { grCategHistory,
"Ιστορικό" },
2963 { grCategTeleShop,
"Τηλεπωλήσεις" },
2964 { grCategFood,
"Γαστρονομία" },
2965 { grCategGameShow,
"Τηλεπαιχνίδι" },
2966 { grCategBiography,
"Βιογραφία" },
2967 { grCategSports,
"Αθλητικά" },
2968 { grCategMusic,
"Μουσική" },
2969 { grCategDocumentary,
"Ντοκιμαντέρ" },
2970 { grCategReligion,
"Θρησκεία" },
2971 { grCategCulture,
"Τέχνες/Πολιτισμός" },
2972 { grCategSpecial,
"Αφιέρωμα" },
2974 static const QList<grCategoryEntry> grCategoryTitleData = {
2975 { grCategTeleShop,
"Τηλεπωλήσεις" },
2976 { grCategGameShow,
"Τηλεπαιχνίδι" },
2977 { grCategMusic,
"Μουσική" },
2978 { grCategNews,
"Ειδήσεις" },
2985 event.m_category =
"Φαντασίας/Μυστηρίου";
2990 for (
const auto& [expression, category] : grCategoryDescData)
2993 event.m_category = category;
2999 for (
const auto& [expression, category] : grCategoryTitleData)
3001 if (event.
m_title.indexOf(expression) != -1) {
3002 event.m_category = category;
3016 event.m_subtitle =
"";
3021 auto i =
event.m_items.begin();
3022 while (i != event.
m_items.end())
3026 if ((QString::compare (i.key(),
"Role Player") == 0) ||
3027 (QString::compare (i.key(),
"Performing Artist") == 0))
3030 i =
event.m_items.erase (i);
3032 else if (QString::compare (i.key(),
"Director") == 0)
3035 i =
event.m_items.erase (i);
3037 else if (QString::compare (i.key(),
"Commentary or Commentator") == 0)
3040 i =
event.m_items.erase (i);
3042 else if (QString::compare (i.key(),
"Presenter") == 0)
3045 i =
event.m_items.erase (i);
3047 else if (QString::compare (i.key(),
"Producer") == 0)
3050 i =
event.m_items.erase (i);
3052 else if (QString::compare (i.key(),
"Scriptwriter") == 0)
3055 i =
event.m_items.erase (i);
3064 static const QRegularExpression unitymediaImdbrating { R
"(\s*IMDb Rating: (\d\.\d)\s?/10$)" };
3065 auto match = unitymediaImdbrating.match(event.
m_description);
3066 if (match.hasMatch())
3068 float stars = match.captured(1).toFloat();
3069 event.m_stars = stars / 10.0F;
3070 event.m_description.remove(match.capturedStart(0),
3071 match.capturedLength(0));