MythTV  master
rssparse.cpp
Go to the documentation of this file.
1 #include "rssparse.h"
2 
3 #include <QFile>
4 #include <QDataStream>
5 #include <QDomDocument>
6 #include <QDomImplementation>
7 #include <QHash>
8 #include <QLocale>
9 #include <QUrl>
10 #include <QFileInfo>
11 
12 #include "libmythbase/mythdate.h"
13 #include "libmythbase/mythdirs.h"
16 #include "libmythbase/stringutil.h"
17 
18 #if QT_VERSION < QT_VERSION_CHECK(5,15,2)
19 #define capturedView capturedRef
20 #endif
21 
22 ResultItem::ResultItem(const QString& title, const QString& sortTitle,
23  const QString& subtitle, const QString& sortSubtitle,
24  const QString& desc, const QString& URL,
25  const QString& thumbnail, const QString& mediaURL,
26  const QString& author, const QDateTime& date,
27  const QString& time, const QString& rating,
28  const off_t filesize, const QString& player,
29  const QStringList& playerargs, const QString& download,
30  const QStringList& downloadargs, const uint width,
31  const uint height, const QString& language,
32  const bool downloadable, const QStringList& countries,
33  const uint season, const uint episode,
34  const bool customhtml)
35 {
36  m_title = title;
37  m_sorttitle = sortTitle;
38  m_subtitle = subtitle;
39  m_sortsubtitle = sortSubtitle;
40  m_desc = desc;
41  m_url = URL;
42  m_thumbnail = thumbnail;
43  m_mediaURL = mediaURL;
44  m_author = author;
45  if (!date.isNull())
46  m_date = date;
47  else
48  m_date = QDateTime();
49  m_time = time;
50  m_rating = rating;
51  m_filesize = filesize;
52  m_player = player;
53  m_playerargs = playerargs;
54  m_download = download;
55  m_downloadargs = downloadargs;
56  m_width = width;
57  m_height = height;
58  m_language = language;
59  m_downloadable = downloadable;
60  m_countries = countries;
61  m_season = season;
62  m_episode = episode;
63  m_customhtml = customhtml;
64 
66 }
67 
69 {
70  std::shared_ptr<MythSortHelper>sh = getMythSortHelper();
71 
72  if (m_sorttitle.isEmpty() and not m_title.isEmpty())
73  m_sorttitle = sh->doTitle(m_title);
74  if (m_sortsubtitle.isEmpty() and not m_subtitle.isEmpty())
75  m_sortsubtitle = sh->doTitle(m_subtitle);
76 }
77 
78 void ResultItem::toMap(InfoMap &metadataMap)
79 {
80  metadataMap["title"] = m_title;
81  metadataMap["sorttitle"] = m_sorttitle;
82  metadataMap["subtitle"] = m_subtitle;
83  metadataMap["sortsubtitle"] = m_sortsubtitle;
84  metadataMap["description"] = m_desc;
85  metadataMap["url"] = m_url;
86  metadataMap["thumbnail"] = m_thumbnail;
87  metadataMap["mediaurl"] = m_mediaURL;
88  metadataMap["author"] = m_author;
89 
90  if (m_date.isNull())
91  metadataMap["date"] = QString();
92  else
93  metadataMap["date"] = MythDate::toString(m_date, MythDate::kDateFull);
94 
95  if (m_time.toInt() == 0)
96  metadataMap["length"] = QString();
97  else
98  {
99  QTime time(0,0,0,0);
100  int secs = m_time.toInt();
101  QTime fin = time.addSecs(secs);
102  QString format;
103  if (secs >= 3600)
104  format = "H:mm:ss";
105  else if (secs >= 600)
106  format = "mm:ss";
107  else if (secs >= 60)
108  format = "m:ss";
109  else
110  format = ":ss";
111  metadataMap["length"] = fin.toString(format);
112  }
113 
114  if (m_rating == nullptr || m_rating.isNull())
115  metadataMap["rating"] = QString();
116  else
117  metadataMap["rating"] = m_rating;
118 
119  if (m_filesize == -1)
120  metadataMap["filesize"] = QString();
121  else if (m_filesize == 0 && !m_downloadable)
122  metadataMap["filesize"] = QObject::tr("Web Only");
123  else if (m_filesize == 0 && m_downloadable)
124  metadataMap["filesize"] = QObject::tr("Downloadable");
125  else
126  metadataMap["filesize"] = QString::number(m_filesize);
127 
128  QString tmpSize = QString("%1 ")
129  .arg(m_filesize / 1024.0 / 1024.0, 0,'f',2);
130  tmpSize += QObject::tr("MB", "Megabytes");
131  if (m_filesize == -1)
132  metadataMap["filesize_str"] = QString();
133  else if (m_filesize == 0 && !m_downloadable)
134  metadataMap["filesize_str"] = QObject::tr("Web Only");
135  else if (m_filesize == 0 && m_downloadable)
136  metadataMap["filesize_str"] = QObject::tr("Downloadable");
137  else
138  metadataMap["filesize"] = tmpSize;
139 
140  metadataMap["player"] = m_player;
141  metadataMap["playerargs"] = m_playerargs.join(", ");
142  metadataMap["downloader"] = m_download;
143  metadataMap["downloadargs"] = m_downloadargs.join(", ");
144  if (m_width == 0)
145  metadataMap["width"] = QString();
146  else
147  metadataMap["width"] = QString::number(m_width);
148  if (m_height == 0)
149  metadataMap["height"] = QString();
150  else
151  metadataMap["height"] = QString::number(m_height);
152  if (m_width == 0 || m_height == 0)
153  metadataMap["resolution"] = QString();
154  else
155  metadataMap["resolution"] = QString("%1x%2").arg(m_width).arg(m_height);
156  metadataMap["language"] = m_language;
157  metadataMap["countries"] = m_countries.join(", ");
158 
159 
160  if (m_season > 0 || m_episode > 0)
161  {
162  metadataMap["season"] = StringUtil::intToPaddedString(m_season, 1);
163  metadataMap["episode"] = StringUtil::intToPaddedString(m_episode, 1);
164  metadataMap["s##e##"] = metadataMap["s00e00"] = QString("s%1e%2")
167  metadataMap["##x##"] = metadataMap["00x00"] = QString("%1x%2")
170  }
171  else
172  {
173  metadataMap["season"] = QString();
174  metadataMap["episode"] = QString();
175  metadataMap["s##e##"] = metadataMap["s00e00"] = QString();
176  metadataMap["##x##"] = metadataMap["00x00"] = QString();
177  }
178 }
179 
180 namespace
181 {
182  QList<QDomNode> GetDirectChildrenNS(const QDomElement& elem,
183  const QString& ns, const QString& name)
184  {
185  QList<QDomNode> result;
186  QDomNodeList unf = elem.elementsByTagNameNS(ns, name);
187  for (int i = 0, size = unf.size(); i < size; ++i)
188  if (unf.at(i).parentNode() == elem)
189  result << unf.at(i);
190  return result;
191  }
192 }
193 
195 {
197  {
198  QString m_url;
199  QString m_rating;
200  QString m_ratingScheme;
201  QString m_title;
202  QString m_description;
203  QString m_keywords;
204  QString m_copyrightUrl;
207  int m_ratingCount {0};
208  int m_ratingMin {0};
209  int m_ratingMax {0};
210  int m_views {0};
211  int m_favs {0};
212  QString m_tags;
213  QList<MRSSThumbnail> m_thumbnails;
214  QList<MRSSCredit> m_credits;
215  QList<MRSSComment> m_comments;
216  QList<MRSSPeerLink> m_peerLinks;
217  QList<MRSSScene> m_scenes;
218 
219  ArbitraryLocatedData() = default;
220 
225  {
226  if (!child.m_url.isEmpty())
227  m_url = child.m_url;
228  if (!child.m_rating.isEmpty())
229  m_rating = child.m_rating;
230  if (!child.m_ratingScheme.isEmpty())
232  if (!child.m_title.isEmpty())
233  m_title = child.m_title;
234  if (!child.m_description.isEmpty())
236  if (!child.m_keywords.isEmpty())
237  m_keywords = child.m_keywords;
238  if (!child.m_copyrightUrl.isEmpty())
240  if (!child.m_copyrightText.isEmpty())
242  if (child.m_ratingAverage != 0)
244  if (child.m_ratingCount != 0)
246  if (child.m_ratingMin != 0)
247  m_ratingMin = child.m_ratingMin;
248  if (child.m_ratingMax != 0)
249  m_ratingMax = child.m_ratingMax;
250  if (child.m_views != 0)
251  m_views = child.m_views;
252  if (child.m_favs != 0)
253  m_favs = child.m_favs;
254  if (!child.m_tags.isEmpty())
255  m_tags = child.m_tags;
256 
257  m_thumbnails += child.m_thumbnails;
258  m_credits += child.m_credits;
259  m_comments += child.m_comments;
260  m_peerLinks += child.m_peerLinks;
261  m_scenes += child.m_scenes;
262  return *this;
263  }
264  };
265 
266 
267 public:
268  MRSSParser() = default;
269 
270  QList<MRSSEntry> operator() (const QDomElement& item)
271  {
272  QList<MRSSEntry> result;
273 
274  QDomNodeList groups = item.elementsByTagNameNS(Parse::kMediaRSS,
275  "group");
276 
277  for (int i = 0; i < groups.size(); ++i)
278  result += CollectChildren(groups.at(i).toElement());
279 
280  result += CollectChildren(item);
281 
282  return result;
283  }
284 
285 private:
286 
287  static QList<MRSSEntry> CollectChildren(const QDomElement& holder)
288  {
289  QList<MRSSEntry> result;
290  QDomNodeList entries = holder.elementsByTagNameNS(Parse::kMediaRSS,
291  "content");
292 
293  for (int i = 0; i < entries.size(); ++i)
294  {
295  MRSSEntry entry;
296 
297  QDomElement en = entries.at(i).toElement();
299 
300  if (en.hasAttribute("url"))
301  entry.URL = en.attribute("url");
302  else
303  entry.URL = d.m_url;
304 
305  entry.Size = en.attribute("fileSize").toInt();
306  entry.Type = en.attribute("type");
307  entry.Medium = en.attribute("medium");
308  entry.IsDefault = (en.attribute("isDefault") == "true");
309  entry.Expression = en.attribute("expression");
310  if (entry.Expression.isEmpty())
311  entry.Expression = "full";
312  entry.Bitrate = en.attribute("bitrate").toInt();
313  entry.Framerate = en.attribute("framerate").toDouble();
314  entry.SamplingRate = en.attribute("samplingrate").toDouble();
315  entry.Channels = en.attribute("channels").toInt();
316  if (!en.attribute("duration").isNull())
317  entry.Duration = en.attribute("duration").toInt();
318  else
319  entry.Duration = 0;
320  if (!en.attribute("width").isNull())
321  entry.Width = en.attribute("width").toInt();
322  else
323  entry.Width = 0;
324  if (!en.attribute("height").isNull())
325  entry.Height = en.attribute("height").toInt();
326  else
327  entry.Height = 0;
328  if (!en.attribute("lang").isNull())
329  entry.Lang = en.attribute("lang");
330  else
331  entry.Lang = QString();
332 
333  if (!en.attribute("rating").isNull())
334  entry.Rating = d.m_rating;
335  else
336  entry.Rating = QString();
337  entry.RatingScheme = d.m_ratingScheme;
338  entry.Title = d.m_title;
339  entry.Description = d.m_description;
340  entry.Keywords = d.m_keywords;
341  entry.CopyrightURL = d.m_copyrightUrl;
342  entry.CopyrightText = d.m_copyrightText;
343  if (d.m_ratingAverage != 0)
344  entry.RatingAverage = d.m_ratingAverage;
345  else
346  entry.RatingAverage = 0;
347  entry.RatingCount = d.m_ratingCount;
348  entry.RatingMin = d.m_ratingMin;
349  entry.RatingMax = d.m_ratingMax;
350  entry.Views = d.m_views;
351  entry.Favs = d.m_favs;
352  entry.Tags = d.m_tags;
353  entry.Thumbnails = d.m_thumbnails;
354  entry.Credits = d.m_credits;
355  entry.Comments = d.m_comments;
356  entry.PeerLinks = d.m_peerLinks;
357  entry.Scenes = d.m_scenes;
358 
359  result << entry;
360  }
361  return result;
362  }
363 
364  static ArbitraryLocatedData GetArbitraryLocatedDataFor(const QDomElement& holder)
365  {
366  ArbitraryLocatedData result;
367 
368  QList<QDomElement> parents;
369  QDomElement parent = holder;
370  while (!parent.isNull())
371  {
372  parents.prepend(parent);
373  parent = parent.parentNode().toElement();
374  }
375 
376  for (const auto& p : qAsConst(parents))
377  result += CollectArbitraryLocatedData(p);
378 
379  return result;
380  }
381 
382  static QString GetURL(const QDomElement& element)
383  {
384  QList<QDomNode> elems = GetDirectChildrenNS(element, Parse::kMediaRSS,
385  "player");
386  if (elems.empty())
387  return {};
388 
389  return elems.at(0).toElement().attribute("url");
390  }
391 
392  static QString GetTitle(const QDomElement& element)
393  {
394  QList<QDomNode> elems = GetDirectChildrenNS(element, Parse::kMediaRSS,
395  "title");
396 
397  if (elems.empty())
398  return {};
399 
400  QDomElement telem = elems.at(0).toElement();
401  return Parse::UnescapeHTML(telem.text());
402  }
403 
404  static QString GetDescription(const QDomElement& element)
405  {
406  QList<QDomNode> elems = GetDirectChildrenNS(element, Parse::kMediaRSS,
407  "description");
408 
409  if (elems.empty())
410  return {};
411 
412  QDomElement telem = elems.at(0).toElement();
413  return Parse::UnescapeHTML(telem.text());
414  }
415 
416  static QString GetKeywords(const QDomElement& element)
417  {
418  QList<QDomNode> elems = GetDirectChildrenNS(element, Parse::kMediaRSS,
419  "keywords");
420 
421  if (elems.empty())
422  return {};
423 
424  QDomElement telem = elems.at(0).toElement();
425  return telem.text();
426  }
427 
428  static int GetInt(const QDomElement& elem, const QString& attrname)
429  {
430  if (elem.hasAttribute(attrname))
431  {
432  bool ok = false;
433  int result = elem.attribute(attrname).toInt(&ok);
434  if (ok)
435  return result;
436  }
437  return int();
438  }
439 
440  static QList<MRSSThumbnail> GetThumbnails(const QDomElement& element)
441  {
442  QList<MRSSThumbnail> result;
443  QList<QDomNode> thumbs = GetDirectChildrenNS(element, Parse::kMediaRSS,
444  "thumbnail");
445  for (const auto& dom : qAsConst(thumbs))
446  {
447  QDomElement thumbNode = dom.toElement();
448  int widthOpt = GetInt(thumbNode, "width");
449  int width = widthOpt ? widthOpt : 0;
450  int heightOpt = GetInt(thumbNode, "height");
451  int height = heightOpt ? heightOpt : 0;
452  MRSSThumbnail thumb =
453  {
454  thumbNode.attribute("url"),
455  width,
456  height,
457  thumbNode.attribute("time")
458  };
459  result << thumb;
460  }
461  return result;
462  }
463 
464  static QList<MRSSCredit> GetCredits(const QDomElement& element)
465  {
466  QList<MRSSCredit> result;
467  QList<QDomNode> credits = GetDirectChildrenNS(element, Parse::kMediaRSS,
468  "credit");
469 
470  for (const auto& dom : qAsConst(credits))
471  {
472  QDomElement creditNode = dom.toElement();
473  if (!creditNode.hasAttribute("role"))
474  continue;
475  MRSSCredit credit =
476  {
477  creditNode.attribute("role"),
478  creditNode.text()
479  };
480  result << credit;
481  }
482  return result;
483  }
484 
485  static QList<MRSSComment> GetComments(const QDomElement& element)
486  {
487  QList<MRSSComment> result;
488  QList<QDomNode> commParents = GetDirectChildrenNS(element, Parse::kMediaRSS,
489  "comments");
490 
491  if (!commParents.empty())
492  {
493  QDomNodeList comments = commParents.at(0).toElement()
494  .elementsByTagNameNS(Parse::kMediaRSS,
495  "comment");
496  for (int i = 0; i < comments.size(); ++i)
497  {
498  MRSSComment comment =
499  {
500  QObject::tr("Comments"),
501  comments.at(i).toElement().text()
502  };
503  result << comment;
504  }
505  }
506 
507  QList<QDomNode> respParents = GetDirectChildrenNS(element, Parse::kMediaRSS,
508  "responses");
509 
510  if (!respParents.empty())
511  {
512  QDomNodeList responses = respParents.at(0).toElement()
513  .elementsByTagNameNS(Parse::kMediaRSS,
514  "response");
515  for (int i = 0; i < responses.size(); ++i)
516  {
517  MRSSComment comment =
518  {
519  QObject::tr("Responses"),
520  responses.at(i).toElement().text()
521  };
522  result << comment;
523  }
524  }
525 
526  QList<QDomNode> backParents = GetDirectChildrenNS(element, Parse::kMediaRSS,
527  "backLinks");
528 
529  if (!backParents.empty())
530  {
531  QDomNodeList backlinks = backParents.at(0).toElement()
532  .elementsByTagNameNS(Parse::kMediaRSS,
533  "backLink");
534  for (int i = 0; i < backlinks.size(); ++i)
535  {
536  MRSSComment comment =
537  {
538  QObject::tr("Backlinks"),
539  backlinks.at(i).toElement().text()
540  };
541  result << comment;
542  }
543  }
544  return result;
545  }
546 
547  static QList<MRSSPeerLink> GetPeerLinks(const QDomElement& element)
548  {
549  QList<MRSSPeerLink> result;
550  QList<QDomNode> links = GetDirectChildrenNS(element, Parse::kMediaRSS,
551  "peerLink");
552 
553  for (const auto& dom : qAsConst(links))
554  {
555  QDomElement linkNode = dom.toElement();
556  MRSSPeerLink pl =
557  {
558  linkNode.attribute("type"),
559  linkNode.attribute("href")
560  };
561  result << pl;
562  }
563  return result;
564  }
565 
566  static QList<MRSSScene> GetScenes(const QDomElement& element)
567  {
568  QList<MRSSScene> result;
569  QList<QDomNode> scenesNode = GetDirectChildrenNS(element, Parse::kMediaRSS,
570  "scenes");
571 
572  if (!scenesNode.empty())
573  {
574  QDomNodeList scenesNodes = scenesNode.at(0).toElement()
575  .elementsByTagNameNS(Parse::kMediaRSS, "scene");
576 
577  for (int i = 0; i < scenesNodes.size(); ++i)
578  {
579  QDomElement sceneNode = scenesNodes.at(i).toElement();
580  MRSSScene scene =
581  {
582  sceneNode.firstChildElement("sceneTitle").text(),
583  sceneNode.firstChildElement("sceneDescription").text(),
584  sceneNode.firstChildElement("sceneStartTime").text(),
585  sceneNode.firstChildElement("sceneEndTime").text()
586  };
587  result << scene;
588  }
589  }
590  return result;
591  }
592 
593  static ArbitraryLocatedData CollectArbitraryLocatedData(const QDomElement& element)
594  {
595 
596  QString rating;
597  QString rscheme;
598  {
599  QList<QDomNode> elems = GetDirectChildrenNS(element, Parse::kMediaRSS,
600  "rating");
601 
602  if (!elems.empty())
603  {
604  QDomElement relem = elems.at(0).toElement();
605  rating = relem.text();
606  if (relem.hasAttribute("scheme"))
607  rscheme = relem.attribute("scheme");
608  else
609  rscheme = "urn:simple";
610  }
611  }
612 
613  QString curl;
614  QString ctext;
615  {
616  QList<QDomNode> elems = GetDirectChildrenNS(element, Parse::kMediaRSS,
617  "copyright");
618 
619  if (!elems.empty())
620  {
621  QDomElement celem = elems.at(0).toElement();
622  ctext = celem.text();
623  if (celem.hasAttribute("url"))
624  curl = celem.attribute("url");
625  }
626  }
627 
628  int raverage = 0;
629  int rcount = 0;
630  int rmin = 0;
631  int rmax = 0;
632  int views = 0;
633  int favs = 0;
634  QString tags;
635  {
636  QList<QDomNode> comms = GetDirectChildrenNS(element, Parse::kMediaRSS,
637  "community");
638  if (!comms.empty())
639  {
640  QDomElement comm = comms.at(0).toElement();
641  QDomNodeList stars = comm.elementsByTagNameNS(Parse::kMediaRSS,
642  "starRating");
643  if (stars.size())
644  {
645  QDomElement ratingDom = stars.at(0).toElement();
646  raverage = GetInt(ratingDom, "average");
647  rcount = GetInt(ratingDom, "count");
648  rmin = GetInt(ratingDom, "min");
649  rmax = GetInt(ratingDom, "max");
650  }
651 
652  QDomNodeList stats = comm.elementsByTagNameNS(Parse::kMediaRSS,
653  "statistics");
654  if (stats.size())
655  {
656  QDomElement stat = stats.at(0).toElement();
657  views = GetInt(stat, "views");
658  favs = GetInt(stat, "favorites");
659  }
660 
661  QDomNodeList tagsNode = comm.elementsByTagNameNS(Parse::kMediaRSS,
662  "tags");
663  if (tagsNode.size())
664  {
665  QDomElement tag = tagsNode.at(0).toElement();
666  tags = tag.text();
667  }
668  }
669  }
670 
671  ArbitraryLocatedData result;
672  result.m_url = GetURL(element);
673  result.m_rating = rating;
674  result.m_ratingScheme = rscheme;
675  result.m_title = GetTitle(element);
676  result.m_description = GetDescription(element);
677  result.m_keywords = GetKeywords(element);
678  result.m_copyrightUrl = curl;
679  result.m_copyrightText = ctext;
680  result.m_ratingAverage = raverage;
681  result.m_ratingCount = rcount;
682  result.m_ratingMin = rmin;
683  result.m_ratingMax = rmax;
684  result.m_views = views;
685  result.m_favs = favs;
686  result.m_tags = tags;
687  result.m_thumbnails = GetThumbnails(element);
688  result.m_credits = GetCredits(element);
689  result.m_comments = GetComments(element);
690  result.m_peerLinks = GetPeerLinks(element);
691  result.m_scenes = GetScenes(element);
692 
693  return result;
694  }
695 };
696 
697 
698 //========================================================================================
699 // Search Construction, Destruction
700 //========================================================================================
701 
702 const QString Parse::kDC = "http://purl.org/dc/elements/1.1/";
703 const QString Parse::kWFW = "http://wellformedweb.org/CommentAPI/";
704 const QString Parse::kAtom = "http://www.w3.org/2005/Atom";
705 const QString Parse::kRDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
706 const QString Parse::kSlash = "http://purl.org/rss/1.0/modules/slash/";
707 const QString Parse::kEnc = "http://purl.oclc.org/net/rss_2.0/enc#";
708 const QString Parse::kITunes = "http://www.itunes.com/dtds/podcast-1.0.dtd";
709 const QString Parse::kGeoRSSSimple = "http://www.georss.org/georss";
710 const QString Parse::kGeoRSSW3 = "http://www.w3.org/2003/01/geo/wgs84_pos#";
711 const QString Parse::kMediaRSS = "http://search.yahoo.com/mrss/";
712 const QString Parse::kMythRSS = "http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format";
713 
714 QMap<QString, int> Parse::m_timezoneOffsets {
715  { "EDT" , -4 },
716  { "EST" , -5 }
717 };
718 
719 ResultItem::resultList Parse::parseRSS(const QDomDocument& domDoc)
720 {
722 
723  QString document = domDoc.toString();
724  LOG(VB_GENERAL, LOG_DEBUG, "Will Be Parsing: " + document);
725 
726  QDomElement root = domDoc.documentElement();
727  QDomElement channel = root.firstChildElement("channel");
728  while (!channel.isNull())
729  {
730  QDomElement item = channel.firstChildElement("item");
731  while (!item.isNull())
732  {
733  vList.append(ParseItem(item));
734  item = item.nextSiblingElement("item");
735  }
736  channel = channel.nextSiblingElement("channel");
737  }
738 
739  return vList;
740 }
741 
742 ResultItem* Parse::ParseItem(const QDomElement& item)
743 {
744  QString title("");
745  QString subtitle("");
746  QString description("");
747  QString url("");
748  QString author("");
749  QString duration("");
750  QString rating("");
751  QString thumbnail("");
752  QString mediaURL("");
753  QString player("");
754  QString language("");
755  QString download("");
756  off_t filesize = 0;
757  uint width = 0;
758  uint height = 0;
759  uint season = 0;
760  uint episode = 0;
761  QDateTime date;
762  QStringList playerargs;
763  QStringList downloadargs;
764  QStringList countries;
765  bool downloadable = true;
766  bool customhtml = false;
767 
768  // Get the title of the article/video
769  title = item.firstChildElement("title").text();
770  title = UnescapeHTML(title);
771  if (title.isEmpty())
772  title = "";
773 
774  // Get the subtitle of this item.
775  QDomNodeList subt = item.elementsByTagNameNS(kMythRSS, "subtitle");
776  if (subt.size())
777  {
778  subtitle = subt.at(0).toElement().text();
779  }
780 
781  // Parse the description of the article/video
782  QDomElement descriptiontemp = item.firstChildElement("description");
783  if (!descriptiontemp.isNull())
784  description = descriptiontemp.text();
785  if (description.isEmpty())
786  {
787  QDomNodeList nodes = item.elementsByTagNameNS(kITunes, "summary");
788  if (nodes.size())
789  description = nodes.at(0).toElement().text();
790  }
791  // Unescape and remove HTML tags from the description.
792  if (description.isEmpty())
793  description = "";
794  else
795  description = UnescapeHTML(description);
796 
797  // Get the link (web playable)
798  url = item.firstChildElement("link").text();
799 
800  // Parse the item author
801  QDomElement authortemp = item.firstChildElement("author");
802  if (!authortemp.isNull())
803  author = authortemp.text();
804  if (author.isEmpty())
805  author = GetAuthor(item);
806 
807  // Turn the RFC-822 pubdate into a QDateTime
808  date = RFC822TimeToQDateTime(item.firstChildElement("pubDate").text());
809  if (!date.isValid() || date.isNull())
810  date = GetDCDateTime(item);
811  if (!date.isValid() || date.isNull())
812  date = MythDate::current();
813 
814  // Parse the insane iTunes duration (HH:MM:SS or H:MM:SS or MM:SS or M:SS or SS)
815  QDomNodeList dur = item.elementsByTagNameNS(kITunes, "duration");
816  if (dur.size())
817  {
818  QString itunestime = dur.at(0).toElement().text();
819  QString dateformat;
820 
821  if (itunestime.count() == 8)
822  dateformat = "hh:mm:ss";
823  else if (itunestime.count() == 7)
824  dateformat = "h:mm:ss";
825  else if (itunestime.count() == 5)
826  dateformat = "mm:ss";
827  else if (itunestime.count() == 4)
828  dateformat = "m:ss";
829  else if (itunestime.count() == 2)
830  dateformat = "ss";
831  else
832  duration = "0";
833 
834  if (!dateformat.isNull())
835  {
836  QTime itime = QTime::fromString(itunestime, dateformat);
837  if (itime.isValid())
838  {
839  int seconds = itime.second() + (itime.minute() * 60) + (itime.hour() * 3600);
840  duration = QString::number(seconds);
841  }
842  }
843  }
844 
845  // Get the rating
846  QDomElement ratingtemp = item.firstChildElement("rating");
847  if (!ratingtemp.isNull())
848  rating = ratingtemp.text();
849 
850  // Get the external player binary
851  QDomElement playertemp = item.firstChildElement("player");
852  if (!playertemp.isNull())
853  player = playertemp.text();
854 
855  // Get the arguments to pass to the external player
856  QDomElement playerargstemp = item.firstChildElement("playerargs");
857  if (!playerargstemp.isNull())
858  playerargs = playerargstemp.text().split(" ");
859 
860  // Get the external downloader binary/script
861  QDomElement downloadtemp = item.firstChildElement("download");
862  if (!downloadtemp.isNull())
863  download = downloadtemp.text();
864 
865  // Get the arguments to pass to the external downloader
866  QDomElement downloadargstemp = item.firstChildElement("downloadargs");
867  if (!downloadargstemp.isNull())
868  downloadargs = downloadargstemp.text().split(" ");
869 
870  // Get the countries in which this item is playable
871  QDomNodeList cties = item.elementsByTagNameNS(kMythRSS, "country");
872  if (cties.size())
873  {
874  int i = 0;
875  while (i < cties.size())
876  {
877  countries.append(cties.at(i).toElement().text());
878  i++;
879  }
880  }
881 
882  // Get the season number of this item.
883  QDomNodeList seas = item.elementsByTagNameNS(kMythRSS, "season");
884  if (seas.size())
885  {
886  season = seas.at(0).toElement().text().toUInt();
887  }
888 
889  // Get the Episode number of this item.
890  QDomNodeList ep = item.elementsByTagNameNS(kMythRSS, "episode");
891  if (ep.size())
892  {
893  episode = ep.at(0).toElement().text().toUInt();
894  }
895 
896  // Does this grabber return custom HTML?
897  QDomNodeList html = item.elementsByTagNameNS(kMythRSS, "customhtml");
898  if (html.size())
899  {
900  QString htmlstring = html.at(0).toElement().text();
901  if (htmlstring.contains("true", Qt::CaseInsensitive) || htmlstring == "1" ||
902  htmlstring.contains("yes", Qt::CaseInsensitive))
903  customhtml = true;
904  }
905 
906  QList<MRSSEntry> enclosures = GetMediaRSS(item);
907 
908  if (!enclosures.empty())
909  {
910  MRSSEntry media = enclosures.takeAt(0);
911 
912  QList<MRSSThumbnail> thumbs = media.Thumbnails;
913  if (!thumbs.empty())
914  {
915  MRSSThumbnail thumb = thumbs.takeAt(0);
916  thumbnail = thumb.URL;
917  }
918 
919  mediaURL = media.URL;
920 
921  width = media.Width;
922  height = media.Height;
923  language = media.Lang;
924 
925  if (duration.isEmpty())
926  duration = QString::number(media.Duration);
927 
928  if (filesize == 0)
929  filesize = media.Size;
930 
931  if (rating.isEmpty())
932  rating = QString::number(media.RatingAverage);
933  }
934  if (mediaURL.isEmpty())
935  {
936  QList<Enclosure> stdEnc = GetEnclosures(item);
937 
938  if (!stdEnc.empty())
939  {
940  Enclosure e = stdEnc.takeAt(0);
941 
942  mediaURL = e.URL;
943 
944  if (filesize == 0)
945  filesize = e.Length;
946  }
947  }
948 
949  if (mediaURL.isNull() || mediaURL == url)
950  downloadable = false;
951 
952  std::shared_ptr<MythSortHelper>sh = getMythSortHelper();
953  return(new ResultItem(title, sh->doTitle(title),
954  subtitle, sh->doTitle(subtitle), description,
955  url, thumbnail, mediaURL, author, date, duration,
956  rating, filesize, player, playerargs,
957  download, downloadargs, width, height,
958  language, downloadable, countries, season,
959  episode, customhtml));
960 }
961 
962 QString Parse::GetLink(const QDomElement& parent)
963 {
964  QString result;
965  QDomElement link = parent.firstChildElement("link");
966  while(!link.isNull())
967  {
968  if (!link.hasAttribute("rel") || link.attribute("rel") == "alternate")
969  {
970  if (!link.hasAttribute("href"))
971  result = link.text();
972  else
973  result = link.attribute("href");
974  break;
975  }
976  link = link.nextSiblingElement("link");
977  }
978  return result;
979 }
980 
981 QString Parse::GetAuthor(const QDomElement& parent)
982 {
983  QString result("");
984  QDomNodeList nodes = parent.elementsByTagNameNS(kITunes,
985  "author");
986  if (nodes.size())
987  {
988  result = nodes.at(0).toElement().text();
989  return result;
990  }
991 
992  nodes = parent.elementsByTagNameNS(kDC,
993  "creator");
994  if (nodes.size())
995  {
996  result = nodes.at(0).toElement().text();
997  return result;
998  }
999 
1000  return result;
1001 }
1002 
1003 QString Parse::GetCommentsRSS(const QDomElement& parent)
1004 {
1005  QString result;
1006  QDomNodeList nodes = parent.elementsByTagNameNS(kWFW,
1007  "commentRss");
1008  if (nodes.size())
1009  result = nodes.at(0).toElement().text();
1010  return result;
1011 }
1012 
1013 QString Parse::GetCommentsLink(const QDomElement& parent)
1014 {
1015  QString result;
1016  QDomNodeList nodes = parent.elementsByTagNameNS("", "comments");
1017  if (nodes.size())
1018  result = nodes.at(0).toElement().text();
1019  return result;
1020 }
1021 
1022 QDateTime Parse::GetDCDateTime(const QDomElement& parent)
1023 {
1024  QDomNodeList dates = parent.elementsByTagNameNS(kDC, "date");
1025  if (!dates.size())
1026  return {};
1027  return FromRFC3339(dates.at(0).toElement().text());
1028 }
1029 
1030 QDateTime Parse::RFC822TimeToQDateTime(const QString& t)
1031 {
1032  static const QRegularExpression kNonDigitRE { R"(\D)" };
1033 
1034  if (t.size() < 20)
1035  return {};
1036 
1037  QString time = t.simplified();
1038  short int hoursShift = 0;
1039  short int minutesShift = 0;
1040 
1041  QStringList tmp = time.split(' ');
1042  if (tmp.isEmpty())
1043  return {};
1044  if (tmp.at(0).contains(kNonDigitRE))
1045  tmp.removeFirst();
1046  if (tmp.size() != 5)
1047  return {};
1048  QString tmpTimezone = tmp.takeAt(tmp.size() -1);
1049  if (tmpTimezone.size() == 5)
1050  {
1051  bool ok = false;
1052  int tz = tmpTimezone.toInt(&ok);
1053  if(ok)
1054  {
1055  hoursShift = tz / 100;
1056  minutesShift = tz % 100;
1057  }
1058  }
1059  else
1060  hoursShift = m_timezoneOffsets.value(tmpTimezone, 0);
1061 
1062  if (tmp.at(0).size() == 1)
1063  tmp[0].prepend("0");
1064  tmp [1].truncate(3);
1065 
1066  time = tmp.join(" ");
1067 
1068  QDateTime result;
1069  if (tmp.at(2).size() == 4)
1070  result = QLocale::c().toDateTime(time, "dd MMM yyyy hh:mm:ss");
1071  else
1072  result = QLocale::c().toDateTime(time, "dd MMM yy hh:mm:ss");
1073  if (result.isNull() || !result.isValid())
1074  return {};
1075  result = result.addSecs(hoursShift * 3600 * (-1) + minutesShift *60 * (-1));
1076  result.setTimeSpec(Qt::UTC);
1077  return result;
1078 }
1079 
1080 QDateTime Parse::FromRFC3339(const QString& t)
1081 {
1082  if (t.size() < 19)
1083  return {};
1084  QDateTime result = MythDate::fromString(t.left(19).toUpper());
1085  static const QRegularExpression fractionalSeconds { R"(\.(\d+))" };
1086  auto match = fractionalSeconds.match(t);
1087  if (match.hasMatch())
1088  {
1089  bool ok = false;
1090  int fractional = match.capturedView(1).toInt(&ok);
1091  if (ok)
1092  {
1093  if (fractional < 100)
1094  fractional *= 10;
1095  if (fractional <10)
1096  fractional *= 100;
1097  result = result.addMSecs(fractional);
1098  }
1099  }
1100  static const QRegularExpression timeZone { R"((\+|\-)(\d\d):(\d\d)$)" };
1101  match = timeZone.match(t);
1102  if (match.hasMatch())
1103  {
1104  short int multiplier = -1;
1105  if (match.captured(1) == "-")
1106  multiplier = 1;
1107  int hoursShift = match.capturedView(2).toInt();
1108  int minutesShift = match.capturedView(3).toInt();
1109  result = result.addSecs(hoursShift * 3600 * multiplier + minutesShift * 60 * multiplier);
1110  }
1111  result.setTimeSpec(Qt::UTC);
1112  return result;
1113 }
1114 
1115 QList<Enclosure> Parse::GetEnclosures(const QDomElement& entry)
1116 {
1117  QList<Enclosure> result;
1118  QDomNodeList links = entry.elementsByTagName("enclosure");
1119  for (int i = 0; i < links.size(); ++i)
1120  {
1121  QDomElement link = links.at(i).toElement();
1122 
1123  Enclosure e =
1124  {
1125  link.attribute("url"),
1126  link.attribute("type"),
1127  link.attribute("length", "-1").toLongLong(),
1128  link.attribute("hreflang")
1129  };
1130 
1131  result << e;
1132  }
1133  return result;
1134 }
1135 
1136 QList<MRSSEntry> Parse::GetMediaRSS(const QDomElement& item)
1137 {
1138  return MRSSParser() (item);
1139 }
1140 
1141 QString Parse::UnescapeHTML(const QString& escaped)
1142 {
1143  QString result = escaped;
1144  result.replace("&amp;", "&");
1145  result.replace("&lt;", "<");
1146  result.replace("&gt;", ">");
1147  result.replace("&apos;", "\'");
1148  result.replace("&rsquo;", "\'");
1149  result.replace("&#x2019;", "\'");
1150  result.replace("&quot;", "\"");
1151  result.replace("&#8230;",QChar(8230));
1152  result.replace("&#233;",QChar(233));
1153  result.replace("&mdash;", QChar(8212));
1154  result.replace("&nbsp;", " ");
1155  result.replace("&#160;", QChar(160));
1156  result.replace("&#225;", QChar(225));
1157  result.replace("&#8216;", QChar(8216));
1158  result.replace("&#8217;", QChar(8217));
1159  result.replace("&#039;", "\'");
1160  result.replace("&ndash;", QChar(8211));
1161  result.replace("&auml;", QChar(0x00e4));
1162  result.replace("&ouml;", QChar(0x00f6));
1163  result.replace("&uuml;", QChar(0x00fc));
1164  result.replace("&Auml;", QChar(0x00c4));
1165  result.replace("&Ouml;", QChar(0x00d6));
1166  result.replace("&Uuml;", QChar(0x00dc));
1167  result.replace("&szlig;", QChar(0x00df));
1168  result.replace("&euro;", "€");
1169  result.replace("&#8230;", "...");
1170  result.replace("&#x00AE;", QChar(0x00ae));
1171  result.replace("&#x201C;", QChar(0x201c));
1172  result.replace("&#x201D;", QChar(0x201d));
1173  result.replace("<p>", "\n");
1174 
1175  static const QRegularExpression kStripHtmlRE {"<.*?>"};
1176  result.remove(kStripHtmlRE);
1177 
1178  return result;
1179 }
MRSSEntry::Expression
QString Expression
Definition: rssparse.h:78
MRSSParser::GetURL
static QString GetURL(const QDomElement &element)
Definition: rssparse.cpp:382
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:84
ResultItem::ensureSortFields
void ensureSortFields(void)
Definition: rssparse.cpp:68
ResultItem::m_url
QString m_url
Definition: rssparse.h:166
Parse::kRDF
static const QString kRDF
Definition: rssparse.h:219
Parse::kGeoRSSW3
static const QString kGeoRSSW3
Definition: rssparse.h:224
Parse::RFC822TimeToQDateTime
static QDateTime RFC822TimeToQDateTime(const QString &parent)
Definition: rssparse.cpp:1030
mythburn.dateformat
string dateformat
Definition: mythburn.py:170
getMythSortHelper
std::shared_ptr< MythSortHelper > getMythSortHelper(void)
Get a pointer to the MythSortHelper singleton.
Definition: mythsorthelper.cpp:133
MRSSParser::ArbitraryLocatedData::m_rating
QString m_rating
Definition: rssparse.cpp:199
ResultItem::m_countries
QStringList m_countries
Definition: rssparse.h:182
ResultItem::m_episode
uint m_episode
Definition: rssparse.h:184
ResultItem::m_sorttitle
QString m_sorttitle
Definition: rssparse.h:162
MRSSEntry::RatingCount
int RatingCount
Definition: rssparse.h:96
MRSSParser::ArbitraryLocatedData::m_ratingMin
int m_ratingMin
Definition: rssparse.cpp:208
MRSSParser::CollectChildren
static QList< MRSSEntry > CollectChildren(const QDomElement &holder)
Definition: rssparse.cpp:287
MRSSEntry::Comments
QList< MRSSComment > Comments
Definition: rssparse.h:104
ResultItem::m_height
uint m_height
Definition: rssparse.h:179
MRSSEntry::Views
int Views
Definition: rssparse.h:99
MRSSEntry::Scenes
QList< MRSSScene > Scenes
Definition: rssparse.h:106
MRSSEntry::RatingScheme
QString RatingScheme
Definition: rssparse.h:89
Parse::kAtom
static const QString kAtom
Definition: rssparse.h:218
Parse::UnescapeHTML
static QString UnescapeHTML(const QString &escaped)
Definition: rssparse.cpp:1141
ResultItem::m_time
QString m_time
Definition: rssparse.h:171
ResultItem::m_customhtml
bool m_customhtml
Definition: rssparse.h:185
ResultItem::m_download
QString m_download
Definition: rssparse.h:176
ResultItem::ResultItem
ResultItem()=default
ResultItem::m_thumbnail
QString m_thumbnail
Definition: rssparse.h:167
MRSSParser::ArbitraryLocatedData::m_ratingAverage
int m_ratingAverage
Definition: rssparse.cpp:206
MRSSParser::ArbitraryLocatedData::m_scenes
QList< MRSSScene > m_scenes
Definition: rssparse.cpp:217
rssparse.h
MRSSParser::ArbitraryLocatedData::m_ratingCount
int m_ratingCount
Definition: rssparse.cpp:207
Parse::kMythRSS
static const QString kMythRSS
Definition: rssparse.h:226
Parse::GetMediaRSS
static QList< MRSSEntry > GetMediaRSS(const QDomElement &item)
Definition: rssparse.cpp:1136
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
ResultItem::m_downloadargs
QStringList m_downloadargs
Definition: rssparse.h:177
mythdirs.h
MRSSScene
Definition: rssparse.h:63
mythsorthelper.h
MRSSEntry::Medium
QString Medium
Definition: rssparse.h:76
MRSSEntry::Favs
int Favs
Definition: rssparse.h:100
MRSSParser::ArbitraryLocatedData::m_url
QString m_url
Definition: rssparse.cpp:198
ResultItem::m_title
QString m_title
Definition: rssparse.h:161
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
MRSSEntry::Lang
QString Lang
Definition: rssparse.h:86
MRSSParser::ArbitraryLocatedData::m_title
QString m_title
Definition: rssparse.cpp:201
MRSSEntry::URL
QString URL
Definition: rssparse.h:73
MRSSParser::GetArbitraryLocatedDataFor
static ArbitraryLocatedData GetArbitraryLocatedDataFor(const QDomElement &holder)
Definition: rssparse.cpp:364
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
ResultItem::m_date
QDateTime m_date
Definition: rssparse.h:170
ResultItem::m_player
QString m_player
Definition: rssparse.h:174
InfoMap
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
MRSSEntry::RatingMax
int RatingMax
Definition: rssparse.h:98
Parse::kSlash
static const QString kSlash
Definition: rssparse.h:220
MRSSParser::GetTitle
static QString GetTitle(const QDomElement &element)
Definition: rssparse.cpp:392
ResultItem::m_desc
QString m_desc
Definition: rssparse.h:165
Parse::kDC
static const QString kDC
Definition: rssparse.h:216
MRSSEntry::Tags
QString Tags
Definition: rssparse.h:101
mythdate.h
mythlogging.h
MRSSEntry::Size
qint64 Size
Definition: rssparse.h:74
MRSSParser::ArbitraryLocatedData::m_keywords
QString m_keywords
Definition: rssparse.cpp:203
hardwareprofile.config.p
p
Definition: config.py:33
hardwareprofile.i18n.t
t
Definition: i18n.py:36
MRSSParser::operator()
QList< MRSSEntry > operator()(const QDomElement &item)
Definition: rssparse.cpp:270
MRSSParser::GetPeerLinks
static QList< MRSSPeerLink > GetPeerLinks(const QDomElement &element)
Definition: rssparse.cpp:547
MRSSEntry::RatingMin
int RatingMin
Definition: rssparse.h:97
MRSSEntry::SamplingRate
double SamplingRate
Definition: rssparse.h:81
Parse::kEnc
static const QString kEnc
Definition: rssparse.h:221
ResultItem::m_downloadable
bool m_downloadable
Definition: rssparse.h:181
MRSSEntry::Rating
QString Rating
Definition: rssparse.h:88
hardwareprofile.scan.rating
def rating(profile, smoonURL, gate)
Definition: scan.py:39
MRSSEntry
Definition: rssparse.h:71
MRSSParser::GetInt
static int GetInt(const QDomElement &elem, const QString &attrname)
Definition: rssparse.cpp:428
MRSSEntry::IsDefault
bool IsDefault
Definition: rssparse.h:77
MRSSEntry::CopyrightURL
QString CopyrightURL
Definition: rssparse.h:93
MRSSEntry::RatingAverage
int RatingAverage
Definition: rssparse.h:95
ResultItem::m_author
QString m_author
Definition: rssparse.h:169
stringutil.h
MRSSParser::ArbitraryLocatedData::m_copyrightUrl
QString m_copyrightUrl
Definition: rssparse.cpp:204
MRSSThumbnail::URL
QString URL
Definition: rssparse.h:39
MRSSParser::GetThumbnails
static QList< MRSSThumbnail > GetThumbnails(const QDomElement &element)
Definition: rssparse.cpp:440
Parse::m_timezoneOffsets
static QMap< QString, int > m_timezoneOffsets
Definition: rssparse.h:213
ResultItem::m_filesize
off_t m_filesize
Definition: rssparse.h:173
MRSSEntry::CopyrightText
QString CopyrightText
Definition: rssparse.h:94
Parse::GetDCDateTime
static QDateTime GetDCDateTime(const QDomElement &parent)
Definition: rssparse.cpp:1022
MRSSParser::ArbitraryLocatedData::m_peerLinks
QList< MRSSPeerLink > m_peerLinks
Definition: rssparse.cpp:216
ResultItem::m_width
uint m_width
Definition: rssparse.h:178
Parse::kITunes
static const QString kITunes
Definition: rssparse.h:222
ResultItem::m_subtitle
QString m_subtitle
Definition: rssparse.h:163
ResultItem::toMap
void toMap(InfoMap &metadataMap)
Definition: rssparse.cpp:78
Parse::kMediaRSS
static const QString kMediaRSS
Definition: rssparse.h:225
StringUtil::intToPaddedString
QString intToPaddedString(int n, int width=2)
Creates a zero padded string representation of an integer.
Definition: stringutil.h:24
MRSSEntry::Credits
QList< MRSSCredit > Credits
Definition: rssparse.h:103
Enclosure
Describes an enclosure associated with an item.
Definition: rssparse.h:29
uint
unsigned int uint
Definition: compat.h:79
MRSSParser::ArbitraryLocatedData::m_favs
int m_favs
Definition: rssparse.cpp:211
MRSSParser::ArbitraryLocatedData::m_credits
QList< MRSSCredit > m_credits
Definition: rssparse.cpp:214
MRSSEntry::Title
QString Title
Definition: rssparse.h:90
MRSSCredit
Definition: rssparse.h:45
MRSSParser::GetCredits
static QList< MRSSCredit > GetCredits(const QDomElement &element)
Definition: rssparse.cpp:464
MRSSEntry::Type
QString Type
Definition: rssparse.h:75
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:34
off_t
#define off_t
Definition: mythiowrapper.cpp:241
MRSSParser::ArbitraryLocatedData::m_ratingMax
int m_ratingMax
Definition: rssparse.cpp:209
Parse::GetCommentsLink
static QString GetCommentsLink(const QDomElement &parent)
Definition: rssparse.cpp:1013
Parse::kWFW
static const QString kWFW
Definition: rssparse.h:217
MRSSEntry::PeerLinks
QList< MRSSPeerLink > PeerLinks
Definition: rssparse.h:105
MRSSEntry::Thumbnails
QList< MRSSThumbnail > Thumbnails
Definition: rssparse.h:102
MRSSParser::GetComments
static QList< MRSSComment > GetComments(const QDomElement &element)
Definition: rssparse.cpp:485
MRSSParser::GetDescription
static QString GetDescription(const QDomElement &element)
Definition: rssparse.cpp:404
MRSSParser::ArbitraryLocatedData::m_tags
QString m_tags
Definition: rssparse.cpp:212
MRSSEntry::Height
int Height
Definition: rssparse.h:85
MRSSEntry::Channels
int Channels
Definition: rssparse.h:82
MRSSParser::ArbitraryLocatedData::ArbitraryLocatedData
ArbitraryLocatedData()=default
MRSSEntry::Bitrate
int Bitrate
Definition: rssparse.h:79
MRSSThumbnail
Definition: rssparse.h:37
Parse::GetAuthor
static QString GetAuthor(const QDomElement &parent)
Definition: rssparse.cpp:981
Enclosure::URL
QString URL
Definition: rssparse.h:31
MRSSParser::GetScenes
static QList< MRSSScene > GetScenes(const QDomElement &element)
Definition: rssparse.cpp:566
MRSSParser::ArbitraryLocatedData::m_comments
QList< MRSSComment > m_comments
Definition: rssparse.cpp:215
ResultItem
Definition: rssparse.h:109
Parse::ParseItem
static ResultItem * ParseItem(const QDomElement &item)
Definition: rssparse.cpp:742
Parse::kGeoRSSSimple
static const QString kGeoRSSSimple
Definition: rssparse.h:223
ResultItem::m_sortsubtitle
QString m_sortsubtitle
Definition: rssparse.h:164
MRSSParser
Definition: rssparse.cpp:194
MRSSParser::ArbitraryLocatedData
Definition: rssparse.cpp:196
MRSSParser::CollectArbitraryLocatedData
static ArbitraryLocatedData CollectArbitraryLocatedData(const QDomElement &element)
Definition: rssparse.cpp:593
ResultItem::m_rating
QString m_rating
Definition: rssparse.h:172
MRSSParser::ArbitraryLocatedData::m_description
QString m_description
Definition: rssparse.cpp:202
Parse::FromRFC3339
static QDateTime FromRFC3339(const QString &t)
Definition: rssparse.cpp:1080
MRSSEntry::Width
int Width
Definition: rssparse.h:84
MRSSParser::ArbitraryLocatedData::m_views
int m_views
Definition: rssparse.cpp:210
ResultItem::resultList
QList< ResultItem * > resultList
Definition: rssparse.h:114
MythDate::kDateFull
@ kDateFull
Default local time.
Definition: mythdate.h:19
ResultItem::m_playerargs
QStringList m_playerargs
Definition: rssparse.h:175
Enclosure::Length
qint64 Length
Definition: rssparse.h:33
ResultItem::m_season
uint m_season
Definition: rssparse.h:183
MRSSParser::ArbitraryLocatedData::m_ratingScheme
QString m_ratingScheme
Definition: rssparse.cpp:200
Parse::parseRSS
static ResultItem::resultList parseRSS(const QDomDocument &domDoc)
Definition: rssparse.cpp:719
MRSSEntry::Keywords
QString Keywords
Definition: rssparse.h:92
ResultItem::m_language
QString m_language
Definition: rssparse.h:180
Parse::GetLink
static QString GetLink(const QDomElement &parent)
Definition: rssparse.cpp:962
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
MRSSComment
Definition: rssparse.h:51
Parse::GetCommentsRSS
static QString GetCommentsRSS(const QDomElement &parent)
Definition: rssparse.cpp:1003
MRSSParser::ArbitraryLocatedData::operator+=
ArbitraryLocatedData & operator+=(const ArbitraryLocatedData &child)
Updates *this's fields according to the child.
Definition: rssparse.cpp:224
MRSSParser::ArbitraryLocatedData::m_thumbnails
QList< MRSSThumbnail > m_thumbnails
Definition: rssparse.cpp:213
MRSSParser::GetKeywords
static QString GetKeywords(const QDomElement &element)
Definition: rssparse.cpp:416
MRSSEntry::Framerate
double Framerate
Definition: rssparse.h:80
MRSSParser::MRSSParser
MRSSParser()=default
Parse::MRSSParser
friend class MRSSParser
Definition: rssparse.h:191
MRSSEntry::Description
QString Description
Definition: rssparse.h:91
MRSSEntry::Duration
int Duration
Definition: rssparse.h:83
ResultItem::m_mediaURL
QString m_mediaURL
Definition: rssparse.h:168
Parse::GetEnclosures
static QList< Enclosure > GetEnclosures(const QDomElement &entry)
Definition: rssparse.cpp:1115
MRSSParser::ArbitraryLocatedData::m_copyrightText
QString m_copyrightText
Definition: rssparse.cpp:205