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