6 #include <QRegularExpression>
20 static const QRegularExpression
kStereo { R
"(\b\(?[sS]tereo\)?\b)" };
22 static const QRegularExpression
kDotAtEnd {
"\\.$" };
24 #if QT_VERSION < QT_VERSION_CHECK(5,15,2)
25 #define capturedView capturedRef
28 static const QMap<QChar,quint16>
r2v = {
29 {
'I' , 1}, {
'V' , 5}, {
'X' , 10}, {
'L' , 50},
30 {
'C' , 100}, {
'D' , 500}, {
'M' , 1000},
40 for (
int i = 0; i < roman.size() - 1; i++)
42 int v1 =
r2v[roman.at(i)];
43 int v2 =
r2v[roman.at(i+1)];
44 result += (v1 >= v2) ? v1 : -v1;
46 return result +
r2v[roman.back()];
55 event.m_subtitle = QString(
"");
59 event.m_description =
event.m_subtitle;
60 event.m_subtitle = QString(
"");
68 event.m_videoProps |= VID_HDTV;
151 static const QRegularExpression emptyParens { R
"(\(\s*\))" };
154 event.m_title.remove(QChar(
'\0')).remove(emptyParens);
155 event.m_title =
event.m_title.simplified();
160 event.m_subtitle.remove(QChar(
'\0'));
161 event.m_subtitle.remove(emptyParens);
162 event.m_subtitle =
event.m_subtitle.simplified();
167 event.m_description.remove(QChar(
'\0'));
168 event.m_description.remove(emptyParens);
169 event.m_description =
event.m_description.simplified();
182 for (
auto i = event.
m_items.begin(); i != event.
m_items.end(); ++i)
184 LOG(VB_EIT, LOG_DEBUG, QString(
"Unhandled item in EIT for"
185 " channel id \"%1\", \"%2\": %3").arg(event.
m_chanid)
186 .arg(i.key(), i.value()));
212 QString crid =
id.toLower();
215 if (crid.startsWith(
"crid://"))
219 if (crid.length() >= 1 && crid[0] !=
'/')
223 if (authority.isEmpty())
226 return authority + crid;
237 int position =
event.m_description.indexOf(
'\r');
243 event.m_subtitle =
event.m_description.left(position);
244 event.m_description =
event.m_description.right(
250 position =
event.m_description.indexOf(
".");
258 event.m_category =
"Unknown";
267 position =
event.m_description.indexOf(
".");
269 position =
event.m_description.indexOf(
". ");
272 if ((position > -1) && position < 20)
274 const QString stmp =
event.m_description;
275 event.m_description = stmp.right(stmp.length() - position - 2);
276 event.m_category = stmp.left(position);
278 int position_p =
event.m_category.indexOf(
"(");
279 if (position_p == -1)
280 event.m_description = stmp.right(stmp.length() - position - 2);
282 event.m_category =
"Unknown";
286 event.m_category =
"Unknown";
292 event.m_category =
"OffAir";
295 event.m_category =
"Unknown";
300 event.m_description =
event.m_description.replace(theme,
"");
302 event.m_description =
event.m_description.right(event.
m_description.length() - 1);
304 event.m_description =
event.m_description.right(event.
m_description.length() - 1);
308 static const QRegularExpression bellYear { R
"(\([0-9]{4}\))" };
309 position = event.m_description.indexOf(bellYear);
310 if (position != -1 && !event.
m_category.isEmpty())
314 uint y =
event.m_description.mid(position + 1, 4).toUInt(&ok);
317 event.m_originalairdate = QDate(y, 1, 1);
319 event.m_previouslyshown =
true;
325 static const QRegularExpression bellActors { R
"(\set\s|,)" };
326 QString tmp = event.m_description.left(position-3);
327 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
329 tmp.split(bellActors, QString::SkipEmptyParts);
332 tmp.split(bellActors, Qt::SkipEmptyParts);
337 for (
const auto & actor : qAsConst(actors))
341 event.m_description =
event.m_description.right(
347 position =
event.m_description.indexOf(
"(CC)");
350 event.m_subtitleType |= SUB_HARDHEAR;
351 event.m_description =
event.m_description.replace(
"(CC)",
"");
356 if (match.hasMatch())
358 event.m_audioProps |= AUD_STEREO;
359 event.m_description.remove(match.capturedStart(0),
360 match.capturedLength(0));
364 static const QRegularExpression bellPPVTitleAllDayHD { R
"(\s*\(All Day\, HD\)\s*$)" };
365 match = bellPPVTitleAllDayHD.match(event.m_title);
366 if (match.hasMatch())
368 event.m_title.remove(match.capturedStart(), match.capturedLength());
369 event.m_videoProps |= VID_HDTV;
373 static const QRegularExpression bellPPVTitleAllDay { R
"(\s*\(All Day.*\)\s*$)" };
374 match = bellPPVTitleAllDay.match(event.m_title);
375 if (match.hasMatch())
376 event.m_title.remove(match.capturedStart(), match.capturedLength());
379 static const QRegularExpression bellPPVTitleHD { R
"(^HD\s?-\s?)" };
380 match = bellPPVTitleHD.match(event.m_title);
381 if (match.hasMatch())
383 event.m_title.remove(match.capturedStart(), match.capturedLength());
384 event.m_videoProps |= VID_HDTV;
388 position =
event.m_description.indexOf(
"(HD)");
391 event.m_description =
event.m_description.replace(
"(HD)",
"");
392 event.m_videoProps |= VID_HDTV;
396 position =
event.m_title.indexOf(
"(HD)");
399 event.m_title =
event.m_title.replace(
"(HD)",
"");
400 event.m_videoProps |= VID_HDTV;
404 static const QRegularExpression dishPPVTitleHD { R
"(\sHD\s*$)" };
405 match = dishPPVTitleHD.match(event.m_title);
406 if (match.hasMatch())
408 event.m_title.remove(match.capturedStart(), match.capturedLength());
409 event.m_videoProps |= VID_HDTV;
413 position =
event.m_description.indexOf(
"(DD)");
416 event.m_description =
event.m_description.replace(
"(DD)",
"");
417 event.m_audioProps |= AUD_DOLBY;
418 event.m_audioProps |= AUD_STEREO;
422 position =
event.m_description.indexOf(
"(SAP)");
425 event.m_description =
event.m_description.replace(
"(SAP",
"");
426 event.m_subtitleType |= SUB_HARDHEAR;
430 static const QRegularExpression dishPPVTitleColon { R
"(\:\s*$)" };
431 match = dishPPVTitleColon.match(event.m_title);
432 if (match.hasMatch())
433 event.m_title.remove(match.capturedStart(), match.capturedLength());
436 static const QRegularExpression dishDescriptionNew { R
"(\s*New\.\s*)" };
438 if (match.hasMatch())
440 event.m_previouslyshown =
false;
441 event.m_description.remove(match.capturedStart(), match.capturedLength());
445 static const QRegularExpression dishDescriptionFinale { R
"(\s*(Series|Season)\sFinale\.\s*)" };
447 if (match.hasMatch())
449 event.m_previouslyshown =
false;
450 event.m_description.remove(match.capturedStart(), match.capturedLength());
454 static const QRegularExpression dishDescriptionFinale2 { R
"(\s*Finale\.\s*)" };
456 if (match.hasMatch())
458 event.m_previouslyshown =
false;
459 event.m_description.remove(match.capturedStart(), match.capturedLength());
463 static const QRegularExpression dishDescriptionPremiere { R
"(\s*(Series|Season)\s(Premier|Premiere)\.\s*)" };
465 if (match.hasMatch())
467 event.m_previouslyshown =
false;
468 event.m_description.remove(match.capturedStart(), match.capturedLength());
472 static const QRegularExpression dishDescriptionPremiere2 { R
"(\s*(Premier|Premiere)\.\s*)" };
474 if (match.hasMatch())
476 event.m_previouslyshown =
false;
477 event.m_description.remove(match.capturedStart(), match.capturedLength());
481 static const QRegularExpression ppvcode { R
"(\s*\(([A-Z]|[0-9]){5}\)\s*$)",
482 QRegularExpression::CaseInsensitiveOption };
484 if (match.hasMatch())
485 event.m_description.remove(match.capturedStart(), match.capturedLength());
488 static const QRegularExpression dishPPVSpacePerenEnd { R
"(\s\)\s*$)" };
490 if (match.hasMatch())
491 event.m_description.remove(match.capturedStart(), match.capturedLength());
494 static const QRegularExpression bellPPVSubtitleAllDay { R
"(^All Day \(.*\sEastern\)\s*$)" };
495 match = bellPPVSubtitleAllDay.match(event.m_subtitle);
496 if (match.hasMatch())
497 event.m_subtitle.remove(match.capturedStart(), match.capturedLength());
500 static const QRegularExpression bellPPVDescriptionAllDay { R
"(^\(.*\sEastern\))" };
502 if (match.hasMatch())
503 event.m_description.remove(match.capturedStart(), match.capturedLength());
506 static const QRegularExpression bellPPVDescriptionAllDay2 { R
"(^\([0-9].*am-[0-9].*am\sET\))" };
507 match = bellPPVDescriptionAllDay2.match(event.m_description);
508 if (match.hasMatch())
509 event.m_description.remove(match.capturedStart(), match.capturedLength());
512 static const QRegularExpression bellPPVDescriptionEventId { R
"(\([0-9]{5}\))" };
513 match = bellPPVDescriptionEventId.match(event.m_description);
514 if (match.hasMatch())
515 event.m_description.remove(match.capturedStart(), match.capturedLength());
523 QStringList strListColon =
event.m_description.split(
":");
524 QStringList strListEnd;
527 bool fQuotedSubtitle =
false;
529 if (strListColon.count()>1)
531 bool fDoubleDot =
false;
532 bool fSingleDot =
true;
533 int nLength = strListColon[0].length();
535 int nPosition1 =
event.m_description.indexOf(
"..");
536 if ((nPosition1 < nLength) && (nPosition1 >= 0))
538 nPosition1 =
event.m_description.indexOf(
".");
541 if (nPosition1 > nLength)
545 QString strTmp =
event.m_description.mid(nPosition1+1,
548 QStringList
tmp = strTmp.split(
" ");
555 strListEnd = strListColon;
558 else if (!fSingleDot)
560 QStringList strListTmp;
563 for (
int i =0; (i<strListColon.count()) && (nTitleMax==-1);i++)
565 const QStringList
tmp = strListColon[i].split(
" ");
567 nTitle +=
tmp.size();
570 strListTmp.push_back(strListColon[i]);
575 for (
int i=0;i<(nTitleMax-1);i++)
576 strPartial+=strListTmp[i]+
":";
579 strPartial+=strListTmp[nTitleMax-1];
580 strListEnd.push_back(strPartial);
582 for (
int i=nTitleMax+1;i<strListColon.count();i++)
583 strListEnd.push_back(strListColon[i]);
587 static const QRegularExpression ukQuotedSubtitle { R
"(^'([\w\s\-,]+?)\.' )" };
589 if (match.hasMatch())
591 event.m_subtitle = match.captured(1);
592 event.m_description.remove(match.capturedStart(0),
593 match.capturedLength(0));
594 fQuotedSubtitle =
true;
596 QStringList strListPeriod;
597 QStringList strListQuestion;
598 QStringList strListExcl;
599 if (!(fColon || fQuotedSubtitle))
601 strListPeriod =
event.m_description.split(
".");
602 if (strListPeriod.count() >1)
604 int nPosition1 =
event.m_description.indexOf(
".");
605 int nPosition2 =
event.m_description.indexOf(
"..");
606 if ((nPosition1 < nPosition2) || (nPosition2==-1))
607 strListEnd = strListPeriod;
610 strListQuestion =
event.m_description.split(
"?");
611 strListExcl =
event.m_description.split(
"!");
612 if ((strListQuestion.size() > 1) &&
615 strListEnd = strListQuestion;
618 else if ((strListExcl.size() > 1) &&
621 strListEnd = strListExcl;
628 if (!strListEnd.empty())
630 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
631 QStringList strListSpace = strListEnd[0].split(
632 " ", QString::SkipEmptyParts);
634 QStringList strListSpace = strListEnd[0].split(
635 " ", Qt::SkipEmptyParts);
641 static const QRegularExpression ukExclusionFromSubtitle {
642 "(starring|stars\\s|drama|seres|sitcom)",
643 QRegularExpression::CaseInsensitiveOption };
644 if (strListSpace.filter(ukExclusionFromSubtitle).empty())
646 event.m_subtitle = strListEnd[0]+strEnd;
649 event.m_description.mid(strListEnd[0].length()+1);
661 static const QRegularExpression uk24ep { R
"(^\d{1,2}:00[ap]m to \d{1,2}:00[ap]m: )" };
662 static const QRegularExpression ukTime { R
"(\d{1,2}[\.:]\d{1,2}\s*(am|pm|))" };
665 bool isMovie =
event.m_category.startsWith(
"Movie",Qt::CaseInsensitive) ||
666 event.m_category.startsWith(
"Film",Qt::CaseInsensitive);
668 static const QRegularExpression ukThen { R
"(\s*?(Then|Followed by) 60 Seconds\.)",
669 QRegularExpression::CaseInsensitiveOption };
670 static const QRegularExpression ukNew { R
"((New\.|\s*?(Brand New|New)\s*?(Series|Episode)\s*?[:\.\-]))",
671 QRegularExpression::CaseInsensitiveOption };
672 static const QRegularExpression ukNewTitle { R
"(^(Brand New|New:)\s*)",
673 QRegularExpression::CaseInsensitiveOption };
674 event.m_description =
event.m_description.remove(ukThen);
675 event.m_description =
event.m_description.remove(ukNew);
676 event.m_title =
event.m_title.remove(ukNewTitle);
679 static const QRegularExpression ukTitleRemove {
"^(?:[tT]4:|Schools\\s*?:)" };
680 static const QRegularExpression ukDescriptionRemove { R
"(^(?:CBBC\s*?\.|CBeebies\s*?\.|Class TV\s*?:|BBC Switch\.))" };
681 event.m_title =
event.m_title.remove(ukTitleRemove);
682 event.m_description =
event.m_description.remove(ukDescriptionRemove);
685 static const QRegularExpression ukBBC34 { R
"(BBC (?:THREE|FOUR) on BBC (?:ONE|TWO)\.)",
686 QRegularExpression::CaseInsensitiveOption };
687 event.m_description =
event.m_description.remove(ukBBC34);
690 static const QRegularExpression ukBBC7rpt { R
"(\[Rptd?[^]]+?\d{1,2}\.\d{1,2}[ap]m\]\.)" };
691 event.m_description =
event.m_description.remove(ukBBC7rpt);
694 static const QRegularExpression ukAllNew { R
"(All New To 4Music!\s?)" };
695 event.m_description =
event.m_description.remove(ukAllNew);
698 static const QRegularExpression ukAlsoInHD { R
"(\s*Also in HD\.)",
699 QRegularExpression::CaseInsensitiveOption };
700 event.m_description =
event.m_description.remove(ukAlsoInHD);
703 static const QRegularExpression ukCC { R
"(\[(?:(AD|SL|S|W|HD),?)+\])" };
705 while (match.hasMatch())
707 QStringList tmpCCitems = match.captured(0).remove(
"[").remove(
"]").split(
",");
708 if (tmpCCitems.contains(
"AD"))
709 event.m_audioProps |= AUD_VISUALIMPAIR;
710 if (tmpCCitems.contains(
"HD"))
711 event.m_videoProps |= VID_HDTV;
712 if (tmpCCitems.contains(
"S"))
713 event.m_subtitleType |= SUB_NORMAL;
714 if (tmpCCitems.contains(
"SL"))
715 event.m_subtitleType |= SUB_SIGNED;
716 if (tmpCCitems.contains(
"W"))
717 event.m_videoProps |= VID_WIDESCREEN;
718 event.m_description.remove(match.capturedStart(0),
719 match.capturedLength(0));
720 match = ukCC.match(event.
m_description, match.capturedStart(0));
723 event.m_title =
event.m_title.trimmed();
724 event.m_description =
event.m_description.trimmed();
730 static const QString seasonStr = R
"(\b(?:Season|Series|S)\s*(\d+)\s*,?)";
737 static const QString longEp = R
"(\b(?:Ep|Episode)\s*(\d+)\s*(?:(?:/|of)\s*(\d*))?)";
741 static const QString longSeasEp = QString(
"\\(?(?:%1)?\\s*%2").arg(seasonStr, longEp);
745 static const QString longContext = QString(R
"(\(*%1\s*\)?\s*\.?)").arg(longSeasEp);
749 static const QString shortEp = R
"((\d+)\s*(?:/|of)\s*(\d+))";
756 static const QString shortContext =
757 QString(R
"((?:^|\.)(\s*\(*\s*%1[\s)]*(?:[).:]|$)))").arg(shortEp);
762 static const QRegularExpression ukSeries {
"(?:" + longContext +
"|" + shortContext +
")",
763 QRegularExpression::CaseInsensitiveOption };
766 bool fromTitle =
true;
767 match = ukSeries.match(event.
m_title);
768 if (!match.hasMatch())
773 if (match.hasMatch())
775 if (!match.captured(1).isEmpty())
777 event.m_season = match.captured(1).toUInt();
781 if (!match.captured(2).isEmpty())
783 event.m_episode = match.captured(2).toUInt();
786 else if (!match.captured(5).isEmpty())
788 event.m_episode = match.captured(5).toUInt();
792 if (!match.captured(3).isEmpty())
794 event.m_totalepisodes = match.captured(3).toUInt();
797 else if (!match.captured(6).isEmpty())
799 event.m_totalepisodes = match.captured(6).toUInt();
804 int form = match.captured(4).isEmpty() ? 0 : 4;
808 LOG(VB_EIT, LOG_DEBUG, QString(
"Extracted S%1E%2/%3 from title (%4) \"%5\"")
812 event.m_title.remove(match.capturedStart(form),
813 match.capturedLength(form));
817 LOG(VB_EIT, LOG_DEBUG, QString(
"Extracted S%1E%2/%3 from description (%4) \"%5\"")
821 if (match.capturedStart(form) == 0)
825 event.m_description.remove(match.capturedStart(form),
826 match.capturedLength(form));
838 static const QRegularExpression ukPart { R
"([-(\:,.]\s*(?:Part|Pt)\s*(\d+)\s*(?:(?:of|/)\s*(\d+))?\s*[-):,.])",
839 QRegularExpression::CaseInsensitiveOption };
840 match = ukPart.match(event.m_title);
842 if (match.hasMatch())
844 event.m_partnumber = match.captured(1).toUInt();
845 event.m_parttotal = match.captured(2).toUInt();
847 LOG(VB_EIT, LOG_DEBUG, QString(
"Extracted Part %1/%2 from title (%3)")
851 event.m_title.remove(match.capturedStart(0),
852 match.capturedLength(0));
854 else if (match2.hasMatch())
856 event.m_partnumber = match2.captured(1).toUInt();
857 event.m_parttotal = match2.captured(2).toUInt();
859 LOG(VB_EIT, LOG_DEBUG, QString(
"Extracted Part %1/%2 from description (%3) \"%4\"")
865 if (match2.capturedStart(0) == 0)
868 QString sub = match2.captured(0).contains(
":") ?
":" :
"";
869 event.m_description =
event.m_description.replace(match2.captured(0), sub);
873 static const QRegularExpression ukStarring { R
"((?:Western\s)?[Ss]tarring ([\w\s\-']+?)[Aa]nd\s([\w\s\-']+?)[\.|,]\s*(\d{4})?(?:\.\s)?)" };
875 if (match.hasMatch())
882 if (match.captured(3).length() > 0)
885 uint y = match.captured(3).toUInt(&ok);
889 event.m_originalairdate = QDate(y, 1, 1);
894 static const QRegularExpression ukLaONoSplit {
"^Law & Order: (?:Criminal Intent|LA|"
895 "Special Victims Unit|Trial by Jury|UK|You the Jury)" };
896 if (!event.
m_title.startsWith(
"CSI:") && !event.
m_title.startsWith(
"CD:") &&
897 !event.
m_title.contains(ukLaONoSplit) &&
898 !event.
m_title.startsWith(
"Mission: Impossible"))
900 static const QRegularExpression ukDoubleDotStart { R
"(^\.\.+)" };
901 static const QRegularExpression ukDoubleDotEnd { R
"(\.\.+$)" };
902 if ((event.
m_title.indexOf(ukDoubleDotEnd) != -1) &&
905 QString strPart=
event.m_title.remove(ukDoubleDotEnd)+
" ";
906 strFull = strPart +
event.m_description.remove(ukDoubleDotStart);
908 static const QRegularExpression ukCEPQ { R
"([:\!\.\?]\s)" };
909 static const QRegularExpression ukSpaceStart {
"^ " };
911 ((position1 = strFull.indexOf(ukCEPQ,strPart.length())) != -1))
913 if (strFull[position1] ==
'!' || strFull[position1] ==
'?'
914 || (position1>2 && strFull[position1] ==
'.' && strFull[position1-2] ==
'.'))
916 event.m_title = strFull.left(position1);
917 event.m_description = strFull.mid(position1 + 1);
918 event.m_description.remove(ukSpaceStart);
920 else if ((position1 = strFull.indexOf(ukCEPQ)) != -1)
922 if (strFull[position1] ==
'!' || strFull[position1] ==
'?'
923 || (position1>2 && strFull[position1] ==
'.' && strFull[position1-2] ==
'.'))
925 event.m_title = strFull.left(position1);
926 event.m_description = strFull.mid(position1 + 1);
927 event.m_description.remove(ukSpaceStart);
934 if (match24.hasMatch())
938 event.m_subtitle =
event.m_description.mid(match24.capturedStart(0),
939 match24.captured(0).length() - 2);
940 event.m_description =
event.m_description.remove(match24.captured(0));
945 static const QRegularExpression ukYearColon { R
"(^[\d]{4}:)" };
946 if (!isMovie && (event.
m_title.indexOf(ukYearColon) < 0))
949 if (((position1 = event.
m_title.indexOf(
":")) != -1) &&
952 static const QRegularExpression ukCompleteDots { R
"(^\.\.+$)" };
953 if (event.
m_title.mid(position1+1).indexOf(ukCompleteDots)==0)
956 QString strTmp =
event.m_title.mid(position1+1);
957 event.m_title.resize(position1);
958 event.m_subtitle = strTmp+
event.m_subtitle;
962 event.m_subtitle =
event.m_title.mid(position1 + 1);
963 event.m_title =
event.m_title.left(position1);
973 !event.
m_title.startsWith(
"The X-Files"))
978 static const QRegularExpression ukColonPeriod { R
"([:\.])" };
979 int position2 =
event.m_description.indexOf(ukColonPeriod);
980 if ((position2>=0) && (position2 < (position1-2)))
983 else if ((position1=event.
m_title.indexOf(
"-")) != -1)
987 event.m_subtitle =
event.m_title.mid(position1 + 1);
989 event.m_title =
event.m_title.left(position1);
997 static const QRegularExpression ukYear { R
"([\[\(]([\d]{4})[\)\]])" };
999 if (match.hasMatch())
1001 event.m_description.remove(match.capturedStart(0),
1002 match.capturedLength(0));
1004 uint y = match.captured(1).toUInt(&ok);
1007 event.m_airdate = y;
1008 event.m_originalairdate = QDate(y, 1, 1);
1013 static const QRegularExpression ukDotSpaceStart { R
"(^\. )" };
1014 static const QRegularExpression ukDotEnd { R
"(\.$)" };
1015 event.m_subtitle.remove(ukDotSpaceStart);
1017 event.m_subtitle.remove(ukDotEnd);
1022 event.m_description=
event.m_subtitle;
1023 event.m_subtitle.clear();
1033 int position =
event.m_description.indexOf(
':');
1036 const QString stmp =
event.m_description;
1037 event.m_subtitle = stmp.left(position);
1038 event.m_description = stmp.right(stmp.length() - position - 2);
1047 static const QRegularExpression comHemPersSeparator { R
"((, |\soch\s))" };
1052 event.m_subtitle =
event.m_description;
1053 event.m_description =
"";
1057 event.m_subtitle =
"";
1059 bool isSeries =
false;
1061 static const QRegularExpression comHemSeries1
1062 { R
"(\s?(?:[dD]el|[eE]pisode)\s([0-9]+)(?:\s?(?:/|:|av)\s?([0-9]+))?\.)" };
1063 static const QRegularExpression comHemSeries2 { R
"(\s?-?\s?([Dd]el\s+([0-9]+)))" };
1065 auto match2 = comHemSeries2.match(event.
m_title);
1066 if (match2.hasMatch())
1068 event.m_partnumber = match2.capturedView(2).toUInt();
1069 event.m_title.remove(match2.capturedStart(), match2.capturedLength());
1071 else if (match.hasMatch())
1073 if (match.capturedStart(1) != -1)
1074 event.m_partnumber = match.capturedView(1).toUInt();
1075 if (match.capturedStart(2) != -1)
1076 event.m_parttotal = match.capturedView(2).toUInt();
1080 if (match.capturedStart() > 0)
1081 event.m_description.remove(match.capturedStart(),
1082 match.capturedLength());
1090 event.m_subtitle = QString(
"Del %1").arg(event.
m_partnumber);
1092 event.m_subtitle += QString(
" av %1").arg(event.
m_parttotal);
1096 static const QRegularExpression comHemTSub { R
"(\s+-\s+([^\-]+))" };
1097 match = comHemTSub.match(event.m_title);
1098 if (match.hasMatch())
1100 event.m_subtitle = match.captured(1);
1101 event.m_title.remove(match.capturedStart(), match.capturedLength());
1110 static const QRegularExpression comHemCountry
1111 { R
"(^(\(.+\))?\s?([^ ]+)\s([^\.0-9]+)\sfrån\s([0-9]{4})(?:\smed\s([^\.]+))?\.?)" };
1113 if (match.hasMatch())
1115 QString replacement;
1119 if (!match.capturedView(1).isEmpty())
1121 replacement = match.captured(1) +
" ";
1126 if (!match.capturedView(2).isEmpty())
1128 replacement += match.captured(2) +
" ";
1133 if (!match.capturedView(3).isEmpty())
1135 replacement += match.captured(3) +
".";
1138 event.m_category = match.captured(3);
1141 if(match.captured(3).indexOf(
"serie")!=-1)
1148 if (!match.capturedView(4).isEmpty())
1151 uint y = match.capturedView(4).trimmed().toUInt(&ok);
1153 event.m_airdate = y;
1157 if (!match.capturedView(5).isEmpty())
1159 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1160 const QStringList actors =
1161 match.captured(5).split(comHemPersSeparator, QString::SkipEmptyParts);
1163 const QStringList actors =
1164 match.captured(5).split(comHemPersSeparator, Qt::SkipEmptyParts);
1168 for (
const auto & actor : qAsConst(actors))
1175 event.m_description =
event.m_description.replace(match.captured(0),replacement);
1182 static const QRegularExpression comHemPersons
1183 { R
"(\s?([Rr]egi|[Ss]kådespelare|[Pp]rogramledare|[Ii] rollerna):\s([^\.]+)\.)" };
1185 while (iter.hasNext())
1187 auto pmatch = iter.next();
1190 static const QRegularExpression comHemDirector {
"[Rr]egi" };
1191 static const QRegularExpression comHemActor {
"[Ss]kådespelare|[Ii] rollerna" };
1192 static const QRegularExpression comHemHost {
"[Pp]rogramledare" };
1193 auto dmatch = comHemDirector.match(pmatch.capturedView(1));
1194 auto amatch = comHemActor.match(pmatch.capturedView(1));
1195 auto hmatch = comHemHost.match(pmatch.capturedView(1));
1196 if (dmatch.hasMatch())
1198 else if (amatch.hasMatch())
1200 else if (hmatch.hasMatch())
1204 event.m_description.remove(pmatch.capturedStart(), pmatch.capturedLength());
1208 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1209 const QStringList actors =
1210 pmatch.captured(2).split(comHemPersSeparator, QString::SkipEmptyParts);
1212 const QStringList actors =
1213 pmatch.captured(2).split(comHemPersSeparator, Qt::SkipEmptyParts);
1217 for (
const auto & actor : qAsConst(actors))
1218 event.AddPerson(role, actor);
1221 event.m_description=
event.m_description.replace(pmatch.captured(0),
"");
1228 if (process_subtitle)
1230 static const QRegularExpression comHemSub { R
"([.\?\!] )" };
1231 int pos2 =
event.m_description.indexOf(comHemSub);
1232 bool pvalid = pos2 != -1 && pos2 <= 55;
1233 if (pvalid && (event.
m_description.length() - (pos2 + 2)) > 0)
1235 event.m_subtitle =
event.m_description.left(
1237 event.m_description =
event.m_description.mid(pos2 + 2);
1242 static const QRegularExpression comHemTT {
"[Tt]ext-[Tt][Vv]" };
1244 event.m_subtitleType |= SUB_NORMAL;
1247 static const QRegularExpression comHemRerun1 { R
"([Rr]epris\sfrån\s([^\.]+)(?:\.|$))" };
1248 static const QRegularExpression comHemRerun2 { R
"(([0-9]+)/([0-9]+)(?:\s-\s([0-9]{4}))?)" };
1250 if (!match.hasMatch())
1254 if (match.captured(1) ==
"i dag")
1256 event.m_originalairdate =
event.m_starttime.date();
1261 if (match.captured(1) ==
"eftermiddagen")
1263 event.m_originalairdate =
event.m_starttime.date().addDays(-1);
1268 match2 = comHemRerun2.match(match.capturedView(1));
1269 if (match2.hasMatch())
1271 int day = match2.capturedView(1).toInt();
1272 int month = match2.capturedView(2).toInt();
1279 if (day > 0 && month > 0)
1281 QDate date(event.
m_starttime.date().year(), month, day);
1284 date = date.addYears(-1);
1285 event.m_originalairdate = date;
1296 event.m_category =
event.m_subtitle;
1298 int position =
event.m_description.indexOf(
':');
1301 const QString stmp =
event.m_description;
1302 event.m_subtitle = stmp.left(position);
1303 event.m_description = stmp.right(stmp.length() - position - 2);
1314 event.m_description =
"";
1316 if (event.
m_description.endsWith(
"Copyright West TV Ltd. 2011)"))
1317 event.m_description.resize(event.
m_description.length()-40);
1321 event.m_description =
event.m_subtitle;
1322 event.m_subtitle.clear();
1325 event.m_description.remove(0,event.
m_title.length()+3);
1326 if (event.
m_title.startsWith(
"LIVE: ", Qt::CaseInsensitive))
1328 event.m_title.remove(0, 6);
1329 event.m_description.prepend(
"(Live) ");
1338 static const QRegularExpression
rating {
"\\((G|PG|M|MA)\\)" };
1340 if (match.hasMatch())
1344 event.m_ratings.push_back(prograting);
1345 event.m_description.remove(0,match.capturedLength()+1);
1349 event.m_videoProps |= VID_HDTV;
1350 event.m_description.remove(0,5);
1354 event.m_subtitleType |= SUB_NORMAL;
1355 event.m_description.remove(0,5);
1359 event.m_subtitle.clear();
1363 event.m_description.remove(0,event.
m_title.length()+1);
1373 event.m_previouslyshown =
true;
1376 static const QRegularExpression year {
"(\\d{4})$" };
1378 if (match.hasMatch())
1380 event.m_airdate = match.capturedView(1).toUInt();
1385 event.m_subtitleType |= SUB_NORMAL;
1389 static const QRegularExpression adv {
"(\\([A-Z,]+\\))$" };
1391 if (match.hasMatch())
1393 advisories = match.captured(1);
1394 event.m_description.remove(match.capturedStart()-1, match.capturedLength()+1);
1396 static const QRegularExpression
rating {
"(C|G|PG|M|MA)$" };
1398 if (match.hasMatch())
1402 if (!advisories.isEmpty())
1403 prograting.
m_rating.append(
" ").append(advisories);
1404 event.m_ratings.push_back(prograting);
1405 event.m_description.remove(match.capturedStart()-1, match.capturedLength()+1);
1417 event.m_description =
event.m_description.trimmed();
1419 static const QRegularExpression auFreeviewSY { R
"((.*) \((.+)\) \(([12][0-9][0-9][0-9])\)$)" };
1421 if (match.hasMatch())
1424 event.m_subtitle = match.captured(2);
1425 event.m_airdate = match.capturedView(3).toUInt();
1426 event.m_description = match.captured(1);
1429 static const QRegularExpression auFreeviewY {
"(.*) \\(([12][0-9][0-9][0-9])\\)$" };
1431 if (match.hasMatch())
1433 event.m_airdate = match.capturedView(2).toUInt();
1434 event.m_description = match.captured(1);
1437 static const QRegularExpression auFreeviewSYC { R
"((.*) \((.+)\) \(([12][0-9][0-9][0-9])\) \((.+)\)$)" };
1439 if (match.hasMatch())
1442 event.m_subtitle = match.captured(2);
1443 event.m_airdate = match.capturedView(3).toUInt();
1444 QStringList actors = match.captured(4).split(
"/");
1447 for (
const QString& actor : qAsConst(actors))
1449 event.m_description = match.captured(1);
1452 static const QRegularExpression auFreeviewYC { R
"((.*) \(([12][0-9][0-9][0-9])\) \((.+)\)$)" };
1454 if (match.hasMatch())
1456 event.m_airdate = match.capturedView(2).toUInt();
1457 QStringList actors = match.captured(3).split(
"/");
1460 for (
const QString& actor : qAsConst(actors))
1462 event.m_description = match.captured(1);
1471 const uint SUBTITLE_PCT = 60;
1472 const uint lSUBTITLE_MAX_LEN = 128;
1475 event.m_subtitle = QString(
"");
1482 static const QRegularExpression mcaIncompleteTitle { R
"((.*).\.\.\.$)" };
1483 auto match = mcaIncompleteTitle.match(event.
m_title);
1484 if (match.hasMatch())
1486 static const QString mcaCompleteTitlea {
"^'?(" };
1487 static const QString mcaCompleteTitleb { R
"([^\.\?]+[^\'])'?[\.\?]\s+(.+))" };
1488 static const QRegularExpression mcaCompleteTitle
1489 { mcaCompleteTitlea + match.captured(1) + mcaCompleteTitleb,
1490 QRegularExpression::CaseInsensitiveOption};
1492 if (match.hasMatch())
1494 event.m_title = match.captured(1).trimmed();
1495 event.m_description = match.captured(2).trimmed();
1500 static const QRegularExpression mcaSubtitle { R
"(^'([^\.]+)'\.\s+(.+))" };
1502 if (match.hasMatch())
1504 uint matchLen = match.capturedLength(1);
1507 if ((matchLen < lSUBTITLE_MAX_LEN) &&
1508 ((matchLen * 100 / evDescLen) < SUBTITLE_PCT))
1510 event.m_subtitle = match.captured(1);
1511 event.m_description = match.captured(2);
1516 static const QRegularExpression mcaSeries { R
"(^S?(\d+)\/E?(\d+)\s-\s(.*)$)" };
1518 if (match.hasMatch())
1520 uint season = match.capturedView(1).toUInt();
1521 uint episode = match.capturedView(2).toUInt();
1522 event.m_subtitle = match.captured(3).trimmed();
1523 event.m_syndicatedepisodenumber =
1524 QString(
"S%1E%2").arg(season).arg(episode);
1525 event.m_season = season;
1526 event.m_episode = episode;
1531 static const QRegularExpression mcaCC { R
"(,?\s(HI|English) Subtitles\.?)" };
1532 int position =
event.m_description.indexOf(mcaCC);
1535 event.m_subtitleType |= SUB_HARDHEAR;
1536 event.m_description.remove(mcaCC);
1540 static const QRegularExpression mcaDD { R
"(,?\sDD\.?)" };
1541 position = event.m_description.indexOf(mcaDD);
1542 if ((position > 0) && (position > event.
m_description.length() - 7))
1544 event.m_audioProps |= AUD_DOLBY;
1545 event.m_description.remove(mcaDD);
1549 static const QRegularExpression mcaAvail { R
"(\s(Only available on [^\.]*bouquet|Not available in RSA [^\.]*)\.?)" };
1550 event.m_description.remove(mcaAvail);
1553 bool isMovie =
false;
1554 static const QRegularExpression mcaCredits { R
"((.*)\s\((\d{4})\)\s*([^\.]+)\.?\s*$)" };
1556 if (match.hasMatch())
1559 event.m_description = match.captured(1).trimmed();
1561 uint y = match.captured(2).trimmed().toUInt(&ok);
1563 event.m_airdate = y;
1569 static const QRegularExpression mcaYear { R
"((.*)\s\((\d{4})\)\s*$)" };
1571 if (match.hasMatch())
1574 event.m_description = match.captured(1).trimmed();
1576 uint y = match.captured(2).trimmed().toUInt(&ok);
1578 event.m_airdate = y;
1584 static const QRegularExpression mcaActors { R
"((.*\.)\s+([^\.]+\s[A-Z][^\.]+)\.\s*)" };
1586 if (match.hasMatch())
1588 static const QRegularExpression mcaActorsSeparator {
"(,\\s+)" };
1589 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1590 const QStringList actors = match.captured(2).split(
1591 mcaActorsSeparator, QString::SkipEmptyParts);
1593 const QStringList actors = match.captured(2).split(
1594 mcaActorsSeparator, Qt::SkipEmptyParts);
1598 for (
const auto & actor : qAsConst(actors))
1600 event.m_description = match.captured(1).trimmed();
1612 static const QRegularExpression superRTLSubtitle { R
"(^Folge\s(\d{1,3}):\s'(.*)')" };
1613 auto match = superRTLSubtitle.match(event.
m_subtitle);
1614 if (match.hasMatch())
1617 event.m_episode = match.capturedView(1).toUInt();
1618 event.m_subtitle = match.captured(2);
1626 static const QRegularExpression rtlRepeat
1627 { R
"([\s\(]?Wiederholung.+vo[m|n].+(\d{2}\.\d{2}\.\d{4}|\d{2}[:\.]\d{2}\sUhr)\)?)" };
1629 if (match.hasMatch())
1632 int pos = match.capturedStart(0);
1633 int length = match.capturedLength(0) + (pos ? 0 : 1);
1634 event.m_description =
event.m_description.remove(pos, length).trimmed();
1638 static const QRegularExpression rtlSubtitle1 { R
"(^Folge\s(\d{1,4})\s*:\s+'(.*)'(?:\s|\.\s*|$))" };
1639 static const QRegularExpression rtlSubtitle2 { R
"(^Folge\s(\d{1,4})\s+(.{0,5}[^\?!\.]{0,120})[\?!\.]\s*)" };
1640 static const QRegularExpression rtlSubtitle3 { R
"(^(?:Folge\s)?(\d{1,4}(?:\/[IVX]+)?)\s+(.{0,5}[^\?!\.]{0,120})[\?!\.]\s*)" };
1641 static const QRegularExpression rtlSubtitle4 { R
"(^Thema.{0,5}:\s([^\.]+)\.\s*)" };
1642 static const QRegularExpression rtlSubtitle5 {
"^'(.+)'\\.\\s*" };
1643 static const QRegularExpression rtlEpisodeNo1 { R
"(^(Folge\s\d{1,4})\.*\s*)" };
1644 static const QRegularExpression rtlEpisodeNo2 { R
"(^(\d{1,2}\/[IVX]+)\.*\s*)" };
1655 if (match1.hasMatch())
1657 event.m_syndicatedepisodenumber = match1.captured(1);
1658 event.m_subtitle = match1.captured(2);
1659 event.m_description =
1660 event.m_description.remove(0, match1.capturedLength());
1663 else if (match2.hasMatch())
1665 event.m_syndicatedepisodenumber = match2.captured(1);
1666 event.m_subtitle = match2.captured(2);
1667 event.m_description =
1668 event.m_description.remove(0, match2.capturedLength());
1671 else if (match3.hasMatch())
1673 event.m_syndicatedepisodenumber = match3.captured(1);
1674 event.m_subtitle = match3.captured(2);
1675 event.m_description =
1676 event.m_description.remove(0, match3.capturedLength());
1679 else if (match4.hasMatch())
1681 event.m_subtitle = match4.captured(1);
1682 event.m_description =
1683 event.m_description.remove(0, match4.capturedLength());
1686 else if (match5.hasMatch())
1688 event.m_subtitle = match5.captured(1);
1689 event.m_description =
1690 event.m_description.remove(0, match5.capturedLength());
1693 else if (match6.hasMatch())
1695 event.m_syndicatedepisodenumber = match6.captured(2);
1696 event.m_subtitle = match6.captured(1);
1697 event.m_description =
1698 event.m_description.remove(0, match6.capturedLength());
1701 else if (match7.hasMatch())
1703 event.m_syndicatedepisodenumber = match7.captured(2);
1704 event.m_subtitle = match7.captured(1);
1705 event.m_description =
1706 event.m_description.remove(0, match7.capturedLength());
1716 const uint SUBTITLE_PCT = 35;
1717 const uint lSUBTITLE_MAX_LEN = 50;
1719 static const QRegularExpression rtlSubtitle { R
"(^([^\.]{3,})\.\s+(.+))" };
1721 if (match.hasMatch())
1723 uint matchLen = match.capturedLength(1);
1726 if ((matchLen < lSUBTITLE_MAX_LEN) &&
1727 (matchLen * 100 / evDescLen < SUBTITLE_PCT))
1729 event.m_subtitle = match.captured(1);
1730 event.m_description = match.captured(2);
1748 static const QRegularExpression pro7Subtitle { R
"(,{0,1}([^,]*?),([^,]+?)\s{0,1}(\d{4})$)" };
1749 auto match = pro7Subtitle.match(event.
m_subtitle);
1750 if (match.hasMatch())
1754 event.m_airdate = match.captured(3).toUInt();
1756 event.m_subtitle.remove(match.capturedStart(0),
1757 match.capturedLength(0));
1761 static const QRegularExpression pro7Cast {
"\n\nDarsteller:\n(.*)$",
1762 QRegularExpression::DotMatchesEverythingOption };
1764 if (match.hasMatch())
1766 QStringList cast = match.captured(1).split(
"\n");
1767 for (
const auto& line : qAsConst(cast))
1769 static const QRegularExpression pro7CastOne { R
"(^([^\(]*?)\((.*)\)$)" };
1770 auto match2 = pro7CastOne.match(line);
1771 if (match2.hasMatch())
1778 event.m_description.remove(match.capturedStart(0),
1779 match.capturedLength(0));
1785 static const QRegularExpression pro7Crew {
"\n\n(Regie:.*)$",
1786 QRegularExpression::DotMatchesEverythingOption };
1788 if (match.hasMatch())
1790 QStringList crew = match.captured(1).split(
"\n");
1791 for (
const auto& line : qAsConst(crew))
1793 static const QRegularExpression pro7CrewOne { R
"(^(.*?):\s+(.*)$)" };
1794 auto match2 = pro7CrewOne.match(line);
1795 if (match2.hasMatch())
1800 QStringList names = match2.captured(2).simplified().split(R
"(\s*,\s*)");
1801 for (
const auto & name : qAsConst(names))
1806 event.AddPerson (role, name);
1810 event.m_description.remove(match.capturedStart(0),
1811 match.capturedLength(0));
1824 static const QRegularExpression deDisneyChannelSubtitle { R
"(,([^,]+?)\s{0,1}(\d{4})$)" };
1825 auto match = deDisneyChannelSubtitle.match(event.
m_subtitle);
1826 if (match.hasMatch())
1830 event.m_airdate = match.captured(3).toUInt();
1832 event.m_subtitle.remove(match.capturedStart(0),
1833 match.capturedLength(0));
1835 static const QRegularExpression
tmp { R
"(\s[^\s]+?-(Serie))" };
1837 if (match.hasMatch())
1840 event.m_category=match.captured(0).trimmed();
1841 event.m_subtitle.remove(match.capturedStart(0),
1842 match.capturedLength(0));
1851 static const QRegularExpression atvSubtitle { R
"(,{0,1}\sFolge\s(\d{1,3})$)" };
1852 event.m_subtitle.replace(atvSubtitle,
"");
1861 static const QRegularExpression fiRerun { R
"(\s?Uusinta[a-zA-Z\s]*\.?)" };
1863 if (match.hasMatch())
1865 event.m_previouslyshown =
true;
1866 event.m_description.remove(match.capturedStart(), match.capturedLength());
1869 static const QRegularExpression fiRerun2 { R
"(\([Uu]\))" };
1871 if (match.hasMatch())
1873 event.m_previouslyshown =
true;
1874 event.m_description.remove(match.capturedStart(), match.capturedLength());
1879 if (match.hasMatch())
1881 event.m_audioProps |= AUD_STEREO;
1882 event.m_description.remove(match.capturedStart(), match.capturedLength());
1886 static const QRegularExpression fiAgeLimit { R
"(\((\d{1,2}|[ST])\)$)" };
1887 match = fiAgeLimit.match(event.m_title);
1888 if (match.hasMatch())
1892 event.m_ratings.push_back(prograting);
1893 event.m_title.remove(match.capturedStart(), match.capturedLength());
1897 static const QRegularExpression fiFilm {
"^(Film|Elokuva): " };
1898 match = fiFilm.match(event.
m_title);
1899 if (match.hasMatch())
1901 event.m_category =
"Film";
1903 event.m_title.remove(match.capturedStart(), match.capturedLength());
1913 QString country =
"";
1915 static const QRegularExpression dePremiereLength { R
"(\s?[0-9]+\sMin\.)" };
1916 event.m_description =
event.m_description.replace(dePremiereLength,
"");
1918 static const QRegularExpression dePremiereAirdate { R
"(\s?([^\s^\.]+)\s((?:1|2)[0-9]{3})\.)" };
1920 if ( match.hasMatch())
1922 country = match.captured(1).trimmed();
1924 uint y = match.captured(2).toUInt(&ok);
1926 event.m_airdate = y;
1927 event.m_description.remove(match.capturedStart(0),
1928 match.capturedLength(0));
1931 static const QRegularExpression dePremiereCredits { R
"(\sVon\s([^,]+)(?:,|\su\.\sa\.)\smit\s([^\.]*)\.)" };
1933 if (match.hasMatch())
1936 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1937 const QStringList actors = match.captured(2).split(
1938 ", ", QString::SkipEmptyParts);
1940 const QStringList actors = match.captured(2).split(
1941 ", ", Qt::SkipEmptyParts);
1945 for (
const auto & actor : qAsConst(actors))
1947 event.m_description.remove(match.capturedStart(0),
1948 match.capturedLength(0));
1951 event.m_description =
event.m_description.replace(
"\u000A$",
"");
1952 event.m_description =
event.m_description.replace(
"\u000A",
" ");
1955 static const QRegularExpression dePremiereOTitle { R
"(\s*\(([^\)]*)\)$)" };
1956 match = dePremiereOTitle.match(event.m_title);
1957 if (match.hasMatch())
1959 event.m_subtitle = QString(
"%1, %2").arg(match.captured(1), country);
1960 event.m_title.remove(match.capturedStart(0),
1961 match.capturedLength(0));
1965 static const QRegularExpression deSkyDescriptionSeasonEpisode { R
"(^(\d{1,2}).\sStaffel,\sFolge\s(\d{1,2}):\s)" };
1966 match = deSkyDescriptionSeasonEpisode.match(event.m_description);
1967 if (match.hasMatch())
1969 event.m_season = match.captured(1).trimmed().toUInt();
1970 event.m_episode = match.captured(2).trimmed().toUInt();
1971 event.m_description.remove(match.capturedStart(0),
1972 match.capturedLength(0));
1993 {
"Movie - Soap/melodrama/folkloric",
2008 QString fullinfo =
event.m_subtitle +
event.m_description;
2009 event.m_subtitle =
"";
2017 event.m_category = name;
2018 event.m_categoryType =
type;
2026 auto match =
kStereo.match(fullinfo);
2027 if (match.hasMatch())
2029 event.m_audioProps |= AUD_STEREO;
2030 fullinfo.remove(match.capturedStart(), match.capturedLength());
2034 static const QRegularExpression nlWide {
"breedbeeld" };
2035 match = nlWide.match(fullinfo);
2036 if (match.hasMatch())
2038 event.m_videoProps |= VID_WIDESCREEN;
2039 fullinfo = fullinfo.replace(
"breedbeeld",
".");
2043 static const QRegularExpression nlRepeat {
"herh." };
2044 match = nlRepeat.match(fullinfo);
2045 if (match.hasMatch())
2046 fullinfo = fullinfo.replace(
"herh.",
".");
2049 static const QRegularExpression nlTxt {
"txt" };
2050 match = nlTxt.match(fullinfo);
2051 if (match.hasMatch())
2053 event.m_subtitleType |= SUB_NORMAL;
2054 fullinfo = fullinfo.replace(
"txt",
".");
2058 static const QRegularExpression nlHD { R
"(\sHD$)" };
2059 match = nlHD.match(event.m_title);
2060 if (match.hasMatch())
2062 event.m_videoProps |= VID_HDTV;
2063 event.m_title.remove(match.capturedStart(), match.capturedLength());
2067 static const QRegularExpression nlSub { R
"(\sAfl\.:\s([^\.]+)\.)" };
2068 match = nlSub.match(fullinfo);
2069 if (match.hasMatch())
2071 QString tmpSubString = match.captured(0);
2072 tmpSubString = tmpSubString.right(match.capturedLength() - 7);
2073 event.m_subtitle = tmpSubString.left(tmpSubString.length() -1);
2074 fullinfo.remove(match.capturedStart(), match.capturedLength());
2078 static const QRegularExpression nlSub2 { R
"(\s\"([^\"]+)\")" };
2079 match = nlSub2.match(fullinfo);
2080 if (match.hasMatch())
2082 QString tmpSubString = match.captured(0);
2083 tmpSubString = tmpSubString.right(match.capturedLength() - 2);
2084 event.m_subtitle = tmpSubString.left(tmpSubString.length() -1);
2085 fullinfo.remove(match.capturedStart(), match.capturedLength());
2092 if (((position = event.
m_title.indexOf(
":")) != -1) &&
2093 (event.
m_title[position + 1].toUpper() == event.
m_title[position + 1]) &&
2096 event.m_subtitle =
event.m_title.mid(position + 1);
2097 event.m_title =
event.m_title.left(position);
2102 static const QRegularExpression nlActors { R
"(\sMet:\s.+e\.a\.)" };
2103 static const QRegularExpression nlPersSeparator { R
"((, |\sen\s))" };
2104 match = nlActors.match(fullinfo);
2105 if (match.hasMatch())
2107 QString tmpActorsString = match.captured(0);
2108 tmpActorsString = tmpActorsString.right(tmpActorsString.length() - 6);
2109 tmpActorsString = tmpActorsString.left(tmpActorsString.length() - 5);
2110 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2111 const QStringList actors =
2112 tmpActorsString.split(nlPersSeparator, QString::SkipEmptyParts);
2114 const QStringList actors =
2115 tmpActorsString.split(nlPersSeparator, Qt::SkipEmptyParts);
2119 for (
const auto & actor : qAsConst(actors))
2121 fullinfo.remove(match.capturedStart(), match.capturedLength());
2125 static const QRegularExpression nlPres { R
"(\sPresentatie:\s([^\.]+)\.)" };
2126 match = nlPres.match(fullinfo);
2127 if (match.hasMatch())
2129 QString tmpPresString = match.captured(0);
2130 tmpPresString = tmpPresString.right(tmpPresString.length() - 14);
2131 tmpPresString = tmpPresString.left(tmpPresString.length() -1);
2132 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2133 const QStringList presenters =
2134 tmpPresString.split(nlPersSeparator, QString::SkipEmptyParts);
2136 const QStringList presenters =
2137 tmpPresString.split(nlPersSeparator, Qt::SkipEmptyParts);
2139 for (
const auto & presenter : qAsConst(presenters))
2141 fullinfo.remove(match.capturedStart(), match.capturedLength());
2145 static const QRegularExpression nlYear1 { R
"(\suit\s([1-2][0-9]{3}))" };
2146 static const QRegularExpression nlYear2 { R
"((\s\([A-Z]{0,3}/?)([1-2][0-9]{3})\))",
2147 QRegularExpression::CaseInsensitiveOption };
2148 match = nlYear1.match(fullinfo);
2149 if (match.hasMatch())
2152 uint y = match.capturedView(1).toUInt(&ok);
2154 event.m_originalairdate = QDate(y, 1, 1);
2157 match = nlYear2.match(fullinfo);
2158 if (match.hasMatch())
2161 uint y = match.capturedView(2).toUInt(&ok);
2163 event.m_originalairdate = QDate(y, 1, 1);
2167 static const QRegularExpression nlDirector { R
"(\svan\s(([A-Z][a-z]+\s)|([A-Z]\.\s)))" };
2168 match = nlDirector.match(fullinfo);
2169 if (match.hasMatch())
2173 static const QRegularExpression nlRub { R
"(\s?\(\W+\)\s?)" };
2174 fullinfo.remove(nlRub);
2177 static const QRegularExpression nlCat {
"^(Amusement|Muziek|Informatief|Nieuws/actualiteiten|Jeugd|Animatie|Sport|Serie/soap|Kunst/Cultuur|Documentaire|Film|Natuur|Erotiek|Comedy|Misdaad|Religieus)\\.\\s" };
2178 fullinfo.remove(nlCat);
2181 static const QRegularExpression nlOmroep { R
"(\s\(([A-Z]+/?)+\)$)" };
2182 event.m_title.remove(nlOmroep);
2186 event.m_description = fullinfo;
2206 static const QRegularExpression noRerun {
"\\(R\\)" };
2207 auto match = noRerun.match(event.
m_title);
2208 if (match.hasMatch())
2210 event.m_previouslyshown =
true;
2211 event.m_title.remove(match.capturedStart(), match.capturedLength());
2214 static const QRegularExpression noHD { R
"([\(\[]HD[\)\]])" };
2216 if (match.hasMatch())
2218 event.m_videoProps |= VID_HDTV;
2219 event.m_subtitle.remove(match.capturedStart(), match.capturedLength());
2223 if (match.hasMatch())
2225 event.m_videoProps |= VID_HDTV;
2226 event.m_description.remove(match.capturedStart(), match.capturedLength());
2236 static const QRegularExpression noRerun {
"\\(R\\)" };
2237 auto match = noRerun.match(event.
m_title);
2238 if (match.hasMatch())
2240 event.m_previouslyshown =
true;
2241 event.m_title.remove(match.capturedStart(), match.capturedLength());
2245 if (match.hasMatch())
2247 event.m_previouslyshown =
true;
2252 static const QRegularExpression noNRKCategories
2253 {
"^(Superstrek[ea]r|Supersomm[ea]r|Superjul|Barne-tv|Fantorangen|Kuraffen|Supermorg[eo]n|Julemorg[eo]n|Sommermorg[eo]n|"
2254 "Kuraffen-TV|Sport i dag|NRKs sportsl.rdag|NRKs sportss.ndag|Dagens dokumentar|"
2255 "NRK2s historiekveld|Detektimen|Nattkino|Filmklassiker|Film|Kortfilm|P.skemorg[eo]n|"
2256 "Radioteatret|Opera|P2-Akademiet|Nyhetsmorg[eo]n i P2 og Alltid Nyheter:): (.+)" };
2257 match = noNRKCategories.match(event.
m_title);
2258 if (match.hasMatch() && (match.capturedLength(2) > 1))
2260 event.m_title = match.captured(2);
2261 event.m_description =
"(" + match.captured(1) +
") " +
event.m_description;
2265 static const QRegularExpression noPremiere {
"\\s+-\\s+(Sesongpremiere|Premiere|premiere)!?$" };
2266 match = noPremiere.match(event.
m_title);
2267 if (match.hasMatch() && (match.capturedStart() >= 3))
2268 event.m_title.remove(match.capturedStart(), match.capturedLength());
2271 if (!event.
m_title.startsWith(
"CSI:") &&
2272 !event.
m_title.startsWith(
"CD:") &&
2273 !event.
m_title.startsWith(
"Distriktsnyheter: fra"))
2275 static const QRegularExpression noColonSubtitle {
"^([^:]+): (.+)" };
2276 match = noColonSubtitle.match(event.
m_title);
2277 if (match.hasMatch())
2281 event.m_title = match.captured(1);
2282 event.m_subtitle = match.captured(2);
2284 else if (event.
m_subtitle == match.captured(2))
2286 event.m_title = match.captured(1);
2304 static const QRegularExpression dkEpisode { R
"(\(([0-9]+)\))" };
2305 auto match = dkEpisode.match(event.
m_title);
2306 if (match.hasMatch())
2308 episode = match.capturedView(1).toInt();
2309 event.m_partnumber = match.capturedView(1).toInt();
2310 event.m_title.remove(match.capturedStart(), match.capturedLength());
2313 static const QRegularExpression dkPart { R
"(\(([0-9]+):([0-9]+)\))" };
2314 match = dkPart.match(event.m_title);
2315 if (match.hasMatch())
2317 episode = match.capturedView(1).toInt();
2318 event.m_partnumber = match.capturedView(1).toInt();
2319 event.m_parttotal = match.capturedView(2).toInt();
2320 event.m_title.remove(match.capturedStart(), match.capturedLength());
2324 static const QRegularExpression dkSubtitle1 {
"^([^:]+): (.+)" };
2325 match = dkSubtitle1.match(event.
m_title);
2326 if (match.hasMatch())
2328 event.m_title = match.captured(1);
2329 event.m_subtitle = match.captured(2);
2333 static const QRegularExpression dkSubtitle2 {
"^([^:]+) - (.+)" };
2334 match = dkSubtitle2.match(event.
m_title);
2335 if (match.hasMatch())
2337 event.m_title = match.captured(1);
2338 event.m_subtitle = match.captured(2);
2345 static const QRegularExpression dkSeason1 {
"Sæson ([0-9]+)\\." };
2347 if (match.hasMatch())
2349 season = match.capturedView(1).toInt();
2353 static const QRegularExpression dkSeason2 {
"- år ([0-9]+) :" };
2355 if (match.hasMatch())
2357 season = match.capturedView(1).toInt();
2362 event.m_episode = episode;
2365 event.m_season = season;
2368 static const QRegularExpression dkFeatures {
"Features:(.+)" };
2370 if (match.hasMatch())
2372 QString features = match.captured(1);
2373 event.m_description.remove(match.capturedStart(),
2374 match.capturedLength());
2376 static const QRegularExpression dkWidescreen {
" 16:9" };
2377 if (features.indexOf(dkWidescreen) != -1)
2378 event.m_videoProps |= VID_WIDESCREEN;
2380 static const QRegularExpression dkHD {
" HD" };
2381 if (features.indexOf(dkHD) != -1)
2382 event.m_videoProps |= VID_HDTV;
2384 static const QRegularExpression dkDolby {
" 5:1" };
2385 if (features.indexOf(dkDolby) != -1)
2386 event.m_audioProps |= AUD_DOLBY;
2388 static const QRegularExpression dkSurround { R
"( \(\(S\)\))" };
2389 if (features.indexOf(dkSurround) != -1)
2390 event.m_audioProps |= AUD_SURROUND;
2392 static const QRegularExpression dkStereo {
" S" };
2393 if (features.indexOf(dkStereo) != -1)
2394 event.m_audioProps |= AUD_STEREO;
2396 static const QRegularExpression dkReplay {
" \\(G\\)" };
2397 if (features.indexOf(dkReplay) != -1)
2398 event.m_previouslyshown =
true;
2400 static const QRegularExpression dkTxt {
" TTV" };
2401 if (features.indexOf(dkTxt) != -1)
2402 event.m_subtitleType |= SUB_NORMAL;
2415 newid = QString(
"%1%2").arg(event.
m_chanid).
2420 newid =
event.m_seriesId.mid(2,8);
2422 event.m_seriesId = newid;
2426 event.m_programId[0]=
'_';
2431 event.m_subtitle = QString(
"%1 (%2").arg(event.
m_subtitle).arg(episode);
2433 event.m_subtitle = QString(
"%1:%2").arg(event.
m_subtitle).
2437 event.m_season = season;
2438 event.m_episode = episode;
2439 event.m_syndicatedepisodenumber =
2440 QString(
"S%1E%2").arg(season).arg(episode);
2441 event.m_subtitle = QString(
"%1 Sæson %2").arg(event.
m_subtitle).
2444 event.m_subtitle = QString(
"%1)").arg(event.
m_subtitle);
2448 static const QRegularExpression dkDirector {
"(?:Instr.: |Instrukt.r: )(.+)$" };
2449 static const QRegularExpression dkPersonsSeparator {
"(, )|(og )" };
2450 QStringList directors {};
2452 if (match.hasMatch())
2454 QString tmpDirectorsString = match.captured(1);
2455 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2456 directors = tmpDirectorsString.split(dkPersonsSeparator, QString::SkipEmptyParts);
2458 directors = tmpDirectorsString.split(dkPersonsSeparator, Qt::SkipEmptyParts);
2460 for (
const auto & director : qAsConst(directors))
2462 tmpDirectorsString = director.split(
":").last().trimmed().
2464 if (tmpDirectorsString !=
"")
2470 static const QRegularExpression dkActors {
"(?:Medvirkende: |Medv\\.: )(.+)" };
2472 if (match.hasMatch())
2474 QString tmpActorsString = match.captured(1);
2475 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2476 const QStringList actors =
2477 tmpActorsString.split(dkPersonsSeparator, QString::SkipEmptyParts);
2479 const QStringList actors =
2480 tmpActorsString.split(dkPersonsSeparator, Qt::SkipEmptyParts);
2482 for (
const auto & actor : qAsConst(actors))
2484 tmpActorsString = actor.split(
":").last().trimmed().remove(
kDotAtEnd);
2485 if (!tmpActorsString.isEmpty() && !directors.contains(tmpActorsString))
2492 static const QRegularExpression dkYear {
" fra ([0-9]{4})[ \\.]" };
2494 if (match.hasMatch())
2497 uint y = match.capturedView(1).toUInt(&ok);
2499 event.m_originalairdate = QDate(y, 1, 1);
2508 LOG(VB_EIT, LOG_INFO, QString(
"Applying html strip to %1").arg(event.
m_title));
2509 static const QRegularExpression html {
"</?EM>", QRegularExpression::CaseInsensitiveOption };
2510 event.m_title.remove(html);
2521 event.m_description = QString(
"");
2525 if (event.
m_subtitle.trimmed().right(1) !=
".'" )
2526 event.m_subtitle =
event.m_subtitle.trimmed() +
".";
2527 event.m_description =
event.m_subtitle.trimmed() + QString(
" ") +
event.m_description;
2528 event.m_subtitle = QString(
"");
2535 static const QRegularExpression grRating { R
"(\[(K|Κ|8|12|16|18)\]\s*)",
2536 QRegularExpression::CaseInsensitiveOption };
2537 auto match = grRating.match(event.
m_title);
2538 if (match.hasMatch())
2542 event.m_ratings.push_back(prograting);
2543 event.m_title.remove(match.capturedStart(), match.capturedLength());
2544 event.m_title =
event.m_title.trimmed();
2548 int position =
event.m_title.indexOf(
"(Ζ)");
2551 event.m_title =
event.m_title.replace(
"(Ζ)",
"");
2552 event.m_description.prepend(
"Ζωντανή Μετάδοση. ");
2556 static const QRegularExpression grNotPreviouslyShown {
2557 R
"(\W?(?:-\s*)*(?:\b[Α1]['΄η]?\s*(?:τηλεοπτικ[ηή]\s*)?(?:μετ[αά]δοση|προβολ[ηή]))\W?)",
2558 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2559 match = grNotPreviouslyShown.match(event.m_title);
2560 if (match.hasMatch())
2562 event.m_previouslyshown =
false;
2563 event.m_title.remove(match.capturedStart(), match.capturedLength());
2569 static const QRegularExpression grReplay { R
"(\([ΕE]\))" };
2570 match = grReplay.match(event.m_title);
2571 if (match.hasMatch())
2573 event.m_previouslyshown =
true;
2574 event.m_title.remove(match.capturedStart(), match.capturedLength());
2578 position =
event.m_description.indexOf(
"(HD)");
2581 event.m_description =
event.m_description.replace(
"(HD)",
"");
2582 event.m_videoProps |= VID_HDTV;
2586 position =
event.m_description.indexOf(
"(Full HD)");
2589 event.m_description =
event.m_description.replace(
"(Full HD)",
"");
2590 event.m_videoProps |= VID_HDTV;
2593 static const QRegularExpression grFixnofullstopActors { R
"(\w\s(Παίζουν:|Πρωταγων))" };
2595 if (match.hasMatch())
2596 event.m_description.insert(match.capturedStart() + 1,
".");
2599 static const QRegularExpression grFixnofullstopDirectors { R
"(\w\s(Σκηνοθ[εέ]))" };
2600 match = grFixnofullstopDirectors.match(event.m_description);
2601 if (match.hasMatch())
2602 event.m_description.insert(match.capturedStart() + 1,
".");
2610 static const QRegularExpression grActors { R
"((?:[Ππ]α[ιί]ζουν:|[ΜMμ]ε τους:|Πρωταγωνιστο[υύ]ν:|Πρωταγωνιστε[ιί]:?)(?:\s+στο ρόλο(?: του| της)?\s(?:\w+\s[οη]\s))?([-\w\s']+(?:,[-\w\s']+)*)(?:κ\.[αά])?\W?)" };
2612 static const QRegularExpression grPeopleSeparator { R
"(([,-]\s+))" };
2614 if (match.hasMatch())
2616 QString tmpActorsString = match.captured(1);
2617 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2618 const QStringList actors =
2619 tmpActorsString.split(grPeopleSeparator, QString::SkipEmptyParts);
2621 const QStringList actors =
2622 tmpActorsString.split(grPeopleSeparator, Qt::SkipEmptyParts);
2624 for (
const auto & actor : qAsConst(actors))
2626 tmpActorsString = actor.split(
":").last().trimmed().remove(
kDotAtEnd);
2627 if (tmpActorsString !=
"")
2630 event.m_description.remove(match.capturedStart(), match.capturedLength());
2634 static const QRegularExpression grDirector { R
"((?:Σκηνοθεσία: |Σκηνοθέτης: |Σκηνοθέτης - Επιμέλεια: )(\w+\s\w+\s?)(?:\W?))" };
2636 if (match.hasMatch())
2638 QString tmpDirectorsString = match.captured(1);
2639 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2640 const QStringList directors =
2641 tmpDirectorsString.split(grPeopleSeparator, QString::SkipEmptyParts);
2643 const QStringList directors =
2644 tmpDirectorsString.split(grPeopleSeparator, Qt::SkipEmptyParts);
2646 for (
const auto & director : qAsConst(directors))
2648 tmpDirectorsString = director.split(
":").last().trimmed().
2650 if (tmpDirectorsString !=
"")
2655 event.m_description.remove(match.capturedStart(), match.capturedLength());
2659 static const QRegularExpression grPres { R
"((?:Παρουσ[ιί]αση:(?:\b)*|Παρουσι[αά]ζ(?:ουν|ει)(?::|\sο|\sη)|Παρουσι[αά]στ(?:[ηή]ς|ρια|ριες|[εέ]ς)(?::|\sο|\sη)|Με τ(?:ον |ην )(?:[\s|:|ο|η])*(?:\b)*)([-\w\s]+(?:,[-\w\s]+)*)\W?)",
2660 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2662 if (match.hasMatch())
2664 QString tmpPresentersString = match.captured(1);
2665 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
2666 const QStringList presenters =
2667 tmpPresentersString.split(grPeopleSeparator, QString::SkipEmptyParts);
2669 const QStringList presenters =
2670 tmpPresentersString.split(grPeopleSeparator, Qt::SkipEmptyParts);
2672 for (
const auto & presenter : qAsConst(presenters))
2674 tmpPresentersString = presenter.split(
":").last().trimmed().
2676 if (tmpPresentersString !=
"")
2681 event.m_description.remove(match.capturedStart(), match.capturedLength());
2686 static const QRegularExpression grYear { R
"(\W?(?:\s?παραγωγ[ηή]ς|\s?-|,)\s*([1-2][0-9]{3})(?:-\d{1,4})?)",
2687 QRegularExpression::CaseInsensitiveOption };
2689 if (match.hasMatch())
2692 uint y = match.capturedView(1).toUInt(&ok);
2695 event.m_originalairdate = QDate(y, 1, 1);
2696 event.m_description.remove(match.capturedStart(), match.capturedLength());
2700 event.m_description =
event.m_description.replace(
" .",
".").trimmed();
2703 static const QRegularExpression grCountry {
2704 R
"((?:\W|\b)(?:(ελλην|τουρκ|αμερικ[αά]ν|γαλλ|αγγλ|βρεττ?αν|γερμαν|ρωσσ?|ιταλ|ελβετ|σουηδ|ισπαν|πορτογαλ|μεξικ[αά]ν|κιν[εέ]ζικ|ιαπων|καναδ|βραζιλι[αά]ν)(ικ[ηή][ςσ])))",
2705 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2707 if (match.hasMatch())
2708 event.m_description.remove(match.capturedStart(), match.capturedLength());
2712 bool series =
false;
2713 static const QRegularExpression grSeason {
2714 R
"((?:\W-?)*(?:\(-\s*)?\b(([Α-Ω|A|B|E|Z|H|I|K|M|N]{1,2})(?:'|΄)?|(\d{1,2})(?:ος|ου|oς|os)?)(?:\s*[ΚκKk][υύ]κλο(?:[σς]|υ))\s?)",
2715 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2718 match = grSeason.match(event.
m_title);
2719 if (match.hasMatch())
2721 if (!match.capturedView(2).isEmpty())
2725 int tmpinteger = match.capturedView(2).toUInt();
2728 if (match.captured(2) ==
"ΣΤ")
2732 static const QString LettToNumber =
"0ΑΒΓΔΕ6ΖΗΘΙΚΛΜΝ";
2733 tmpinteger = LettToNumber.indexOf(match.capturedView(2));
2734 if (tmpinteger != -1)
2735 event.m_season = tmpinteger;
2739 static const QString LettToNumber2 =
"0ABΓΔE6ZHΘIKΛMN";
2740 tmpinteger = LettToNumber2.indexOf(match.capturedView(2));
2741 if (tmpinteger != -1)
2742 event.m_season = tmpinteger;
2747 else if (!match.capturedView(3).isEmpty())
2749 event.m_season = match.capturedView(3).toUInt();
2752 event.m_title.remove(match.capturedStart(), match.capturedLength());
2757 if (match.hasMatch())
2759 if (!match.capturedView(2).isEmpty())
2763 int tmpinteger = match.capturedView(2).toUInt();
2766 if (match.captured(2) ==
"ΣΤ")
2770 static const QString LettToNumber =
"0ΑΒΓΔΕ6ΖΗΘΙΚΛΜΝ";
2771 tmpinteger = LettToNumber.indexOf(match.capturedView(2));
2772 if (tmpinteger != -1)
2773 event.m_season = tmpinteger;
2777 else if (!match.capturedView(3).isEmpty())
2779 event.m_season = match.capturedView(3).toUInt();
2782 event.m_description.remove(match.capturedStart(), match.capturedLength());
2787 static const QRegularExpression grSeasonAsRomanNumerals {
",\\s*([MDCLXVIΙΧ]+)$",
2788 QRegularExpression::CaseInsensitiveOption };
2789 match = grSeasonAsRomanNumerals.match(event.
m_title);
2790 auto match2 = grSeasonAsRomanNumerals.match(event.
m_description);
2791 if (match.hasMatch())
2793 if (!match.capturedView(1).isEmpty())
2794 event.m_season =
parseRoman(match.captured(1).toUpper());
2796 event.m_title.remove(match.capturedStart(), match.capturedLength());
2797 event.m_title =
event.m_title.trimmed();
2798 if (event.
m_title.right(1) ==
",")
2799 event.m_title.chop(1);
2801 else if (match2.hasMatch())
2803 if (!match2.capturedView(1).isEmpty())
2804 event.m_season =
parseRoman(match2.captured(1).toUpper());
2806 event.m_description.remove(match2.capturedStart(), match2.capturedLength());
2807 event.m_description =
event.m_description.trimmed();
2809 event.m_description.chop(1);
2812 static const QRegularExpression grlongEp { R
"(\b(?:Επ.|επεισ[οό]διο:?)\s*(\d+)\W?)",
2813 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2815 match = grlongEp.match(event.
m_title);
2817 if (match.hasMatch() || match2.hasMatch())
2819 if (!match.capturedView(1).isEmpty())
2821 event.m_episode = match.capturedView(1).toUInt();
2823 event.m_title.remove(match.capturedStart(), match.capturedLength());
2825 else if (!match2.capturedView(1).isEmpty())
2827 event.m_episode = match2.capturedView(1).toUInt();
2829 event.m_description.remove(match2.capturedStart(), match2.capturedLength());
2840 static const QRegularExpression grCommentsinTitle { R
"(\(([Α-Ωα-ω\s\d-]+)\)(?:\s*$)*)" };
2843 match = grCommentsinTitle.match(event.
m_title);
2844 if (match.hasMatch())
2845 event.m_title.remove(match.capturedStart(), match.capturedLength());
2853 static const QRegularExpression grRealTitleInDescription { R
"(^\(([A-Za-z\s\d-]+)\)\s*)" };
2856 match = grRealTitleInDescription.match(event.
m_description);
2857 if (match.hasMatch())
2859 event.m_description.remove(0, match.capturedLength());
2860 if (match.captured(0) != event.
m_title.trimmed())
2862 event.m_description =
"(" +
event.m_title.trimmed() +
"). " +
event.m_description;
2864 event.m_title = match.captured(1);
2869 static const QRegularExpression grRealTitleInTitle { R
"(\(([A-Za-z\s\d-]+)\)(?:\s*$)?)" };
2872 match = grRealTitleInTitle.match(event.
m_title);
2873 if (match.hasMatch())
2875 event.m_title.remove(match.capturedStart(), match.capturedLength());
2876 QString tmpTranslTitle =
event.m_title;
2878 event.m_title = match.captured(1);
2879 event.m_description =
"(" + tmpTranslTitle.trimmed() +
"). " +
event.m_description;
2884 static const QRegularExpression grEpisodeAsSubtitle { R
"(^Επεισ[οό]διο:\s?([\w\s\-,']+)\.\s?)" };
2886 if (match.hasMatch())
2888 event.m_subtitle = match.captured(1).trimmed();
2889 event.m_description.remove(match.capturedStart(), match.capturedLength());
2891 static const QRegularExpression grMovie { R
"(\bταιν[ιί]α\b)",
2892 QRegularExpression::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption };
2893 bool isMovie = (
event.m_description.indexOf(grMovie) !=-1) ;
2899 event.m_description.replace(
",,",
",");
2906 struct grCategoryEntry {
2907 QRegularExpression expr;
2910 static const QRegularExpression grCategFood {
"\\W?(?:εκπομπ[ηή]\\W)?(Γαστρονομ[ιί]α[σς]?|μαγειρικ[ηή][σς]?|chef|συνταγ[εέηή]|διατροφ|wine|μ[αά]γειρα[σς]?)\\W?",
2911 QRegularExpression::CaseInsensitiveOption };
2912 static const QRegularExpression grCategDrama {
"\\W?(κοινωνικ[ηήό]|δραματικ[ηή]|δρ[αά]μα)\\W(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2913 QRegularExpression::CaseInsensitiveOption};
2914 static const QRegularExpression grCategComedy {
"\\W?(κωμικ[ηήοό]|χιουμοριστικ[ηήοό]|κωμωδ[ιί]α)\\W(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2915 QRegularExpression::CaseInsensitiveOption};
2916 static const QRegularExpression grCategChildren {
"\\W?(παιδικ[ηήοό]|κινο[υύ]μ[εέ]ν(ων|α)\\sσχ[εέ]δ[ιί](ων|α))\\W(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2917 QRegularExpression::CaseInsensitiveOption};
2918 static const QRegularExpression grCategMystery {
"(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?\\W?(μυστηρ[ιί]ου)\\W?",
2919 QRegularExpression::CaseInsensitiveOption};
2920 static const QRegularExpression grCategFantasy {
"(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?\\W?(φαντασ[ιί]ας)\\W?",
2921 QRegularExpression::CaseInsensitiveOption};
2922 static const QRegularExpression grCategHistory {
"\\W?(ιστορικ[ηήοό])\\W?(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2923 QRegularExpression::CaseInsensitiveOption};
2924 static const QRegularExpression grCategTeleMag {
"\\W?(ενημερωτικ[ηή]|ψυχαγωγικ[ηή]|τηλεπεριοδικ[οό]|μαγκαζ[ιί]νο)\\W?(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2925 QRegularExpression::CaseInsensitiveOption};
2926 static const QRegularExpression grCategTeleShop {
"\\W?(οδηγ[οό][σς]?\\sαγορ[ωώ]ν|τηλεπ[ωώ]λ[ηή]σ|τηλεαγορ|τηλεμ[αά]ρκετ|telemarket)\\W?(?:(?:εκπομπ[ηή]|σειρ[αά]|ταιν[ιί]α)\\W)?",
2927 QRegularExpression::CaseInsensitiveOption};
2928 static const QRegularExpression grCategGameShow {
"\\W?(τηλεπαιχν[ιί]δι|quiz)\\W?",
2929 QRegularExpression::CaseInsensitiveOption};
2930 static const QRegularExpression grCategDocumentary {
"\\W?(ντοκ[ιυ]μαντ[εέ]ρ)\\W?",
2931 QRegularExpression::CaseInsensitiveOption};
2932 static const QRegularExpression grCategBiography {
"\\W?(βιογραφ[ιί]α|βιογραφικ[οό][σς]?)\\W?",
2933 QRegularExpression::CaseInsensitiveOption};
2934 static const QRegularExpression grCategNews {
"\\W?(δελτ[ιί]ο\\W?|ειδ[ηή]σε(ι[σς]|ων))\\W?",
2935 QRegularExpression::CaseInsensitiveOption};
2936 static const QRegularExpression grCategSports {
"\\W?(champion|αθλητικ[αάοόηή]|πρωτ[αά]θλημα|ποδ[οό]σφαιρο(ου)?|κολ[υύ]μβηση|πατιν[αά]ζ|formula|μπ[αά]σκετ|β[οό]λε[ιϊ])\\W?",
2937 QRegularExpression::CaseInsensitiveOption};
2938 static const QRegularExpression grCategMusic {
"\\W?(μουσικ[οόηή]|eurovision|τραγο[υύ]δι)\\W?",
2939 QRegularExpression::CaseInsensitiveOption};
2940 static const QRegularExpression grCategReality {
"\\W?(ρι[αά]λιτι|reality)\\W?",
2941 QRegularExpression::CaseInsensitiveOption};
2942 static const QRegularExpression grCategReligion {
"\\W?(θρησκε[ιί]α|θρησκευτικ|να[οό][σς]?|θε[ιί]α λειτουργ[ιί]α)\\W?",
2943 QRegularExpression::CaseInsensitiveOption};
2944 static const QRegularExpression grCategCulture {
"\\W?(τ[εέ]χν(η|ε[σς])|πολιτισμ)\\W?",
2945 QRegularExpression::CaseInsensitiveOption};
2946 static const QRegularExpression grCategNature {
"\\W?(φ[υύ]ση|περιβ[αά]λλο|κατασκευ|επιστ[ηή]μ(?!ονικ[ηή]ς φαντασ[ιί]ας))\\W?",
2947 QRegularExpression::CaseInsensitiveOption};
2948 static const QRegularExpression grCategSciFi {
"\\W?(επιστ(.|ημονικ[ηή]ς)\\s?φαντασ[ιί]ας)\\W?",
2949 QRegularExpression::CaseInsensitiveOption};
2950 static const QRegularExpression grCategHealth {
"\\W?(υγε[ιί]α|υγειιν|ιατρικ|διατροφ)\\W?",
2951 QRegularExpression::CaseInsensitiveOption};
2952 static const QRegularExpression grCategSpecial {
"\\W?(αφι[εέ]ρωμα)\\W?",
2953 QRegularExpression::CaseInsensitiveOption};
2954 static const QList<grCategoryEntry> grCategoryDescData = {
2955 { grCategComedy,
"Κωμωδία" },
2956 { grCategTeleMag,
"Τηλεπεριοδικό" },
2957 { grCategNature,
"Επιστήμη/Φύση" },
2958 { grCategHealth,
"Υγεία" },
2959 { grCategReality,
"Ριάλιτι" },
2960 { grCategDrama,
"Κοινωνικό" },
2961 { grCategChildren,
"Παιδικό" },
2962 { grCategSciFi,
"Επιστ.Φαντασίας" },
2963 { grCategMystery,
"Μυστηρίου" },
2964 { grCategFantasy,
"Φαντασίας" },
2965 { grCategHistory,
"Ιστορικό" },
2966 { grCategTeleShop,
"Τηλεπωλήσεις" },
2967 { grCategFood,
"Γαστρονομία" },
2968 { grCategGameShow,
"Τηλεπαιχνίδι" },
2969 { grCategBiography,
"Βιογραφία" },
2970 { grCategSports,
"Αθλητικά" },
2971 { grCategMusic,
"Μουσική" },
2972 { grCategDocumentary,
"Ντοκιμαντέρ" },
2973 { grCategReligion,
"Θρησκεία" },
2974 { grCategCulture,
"Τέχνες/Πολιτισμός" },
2975 { grCategSpecial,
"Αφιέρωμα" },
2977 static const QList<grCategoryEntry> grCategoryTitleData = {
2978 { grCategTeleShop,
"Τηλεπωλήσεις" },
2979 { grCategGameShow,
"Τηλεπαιχνίδι" },
2980 { grCategMusic,
"Μουσική" },
2981 { grCategNews,
"Ειδήσεις" },
2988 event.m_category =
"Φαντασίας/Μυστηρίου";
2993 for (
const auto& [expression, category] : grCategoryDescData)
2996 event.m_category = category;
3002 for (
const auto& [expression, category] : grCategoryTitleData)
3004 if (event.
m_title.indexOf(expression) != -1) {
3005 event.m_category = category;
3019 event.m_subtitle =
"";
3024 auto i =
event.m_items.begin();
3025 while (i != event.
m_items.end())
3029 if ((QString::compare (i.key(),
"Role Player") == 0) ||
3030 (QString::compare (i.key(),
"Performing Artist") == 0))
3033 i =
event.m_items.erase (i);
3035 else if (QString::compare (i.key(),
"Director") == 0)
3038 i =
event.m_items.erase (i);
3040 else if (QString::compare (i.key(),
"Commentary or Commentator") == 0)
3043 i =
event.m_items.erase (i);
3045 else if (QString::compare (i.key(),
"Presenter") == 0)
3048 i =
event.m_items.erase (i);
3050 else if (QString::compare (i.key(),
"Producer") == 0)
3053 i =
event.m_items.erase (i);
3055 else if (QString::compare (i.key(),
"Scriptwriter") == 0)
3058 i =
event.m_items.erase (i);
3067 static const QRegularExpression unitymediaImdbrating { R
"(\s*IMDb Rating: (\d\.\d)\s?/10$)" };
3068 auto match = unitymediaImdbrating.match(event.
m_description);
3069 if (match.hasMatch())
3071 float stars = match.captured(1).toFloat();
3072 event.m_stars = stars / 10.0F;
3073 event.m_description.remove(match.capturedStart(0),
3074 match.capturedLength(0));