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