00001
00002 #include <QString>
00003 #include <QFile>
00004 #include <QDir>
00005
00006 #include "mythdirs.h"
00007 #include "mythcontext.h"
00008 #include "mythlogging.h"
00009
00010 #include "mythrssmanager.h"
00011 #include "netutils.h"
00012 #include "rssparse.h"
00013
00014 using namespace std;
00015
00016 #define LOC QString("RSSSite: ")
00017
00018
00019
00020 RSSManager::RSSManager()
00021 {
00022 m_updateFreq = (gCoreContext->GetNumSetting(
00023 "rss.updateFreq", 6) * 3600 * 1000);
00024
00025 m_timer = new QTimer();
00026
00027 connect( m_timer, SIGNAL(timeout()),
00028 this, SLOT(doUpdate()));
00029 }
00030
00031 RSSManager::~RSSManager()
00032 {
00033 delete m_timer;
00034 }
00035
00036 void RSSManager::startTimer()
00037 {
00038 m_timer->start(m_updateFreq);
00039 }
00040
00041 void RSSManager::stopTimer()
00042 {
00043 m_timer->stop();
00044 }
00045
00046 void RSSManager::doUpdate()
00047 {
00048 m_sites = findAllDBRSS();
00049
00050 for (RSSSite::rssList::iterator i = m_sites.begin();
00051 i != m_sites.end(); ++i)
00052 {
00053 LOG(VB_GENERAL, LOG_INFO, LOC +
00054 QString("Updating RSS Feed %1") .arg((*i)->GetTitle()));
00055
00056 connect(*i, SIGNAL(finished(RSSSite*)),
00057 this, SLOT(slotRSSRetrieved(RSSSite*)));
00058 }
00059
00060 slotRefreshRSS();
00061
00062 m_timer->start(m_updateFreq);
00063 }
00064
00065 void RSSManager::slotRefreshRSS()
00066 {
00067 if (m_sites.empty())
00068 {
00069 emit finished();
00070 return;
00071 }
00072
00073 RSSSite::rssList::iterator i = m_sites.begin();
00074 for (; i != m_sites.end(); ++i)
00075 {
00076 (*i)->retrieve();
00077 m_inprogress.append(*i);
00078 }
00079 }
00080
00081 void RSSManager::processAndInsertRSS(RSSSite *site)
00082 {
00083 if (!site)
00084 return;
00085
00086 clearRSSArticles(site->GetTitle(), site->GetType());
00087
00088 ResultItem::resultList rss = site->GetVideoList();
00089 ResultItem::resultList::iterator it = rss.begin();
00090 for (; it != rss.end(); ++it)
00091 {
00092
00093 insertRSSArticleInDB(site->GetTitle(), *it, site->GetType());
00094 m_inprogress.removeOne(site);
00095 }
00096
00097 if (!m_inprogress.count())
00098 emit finished();
00099 }
00100
00101 void RSSManager::slotRSSRetrieved(RSSSite *site)
00102 {
00103 markUpdated(site);
00104 processAndInsertRSS(site);
00105 }
00106
00107
00108 RSSSite::RSSSite(const QString& title,
00109 const QString& image,
00110 const ArticleType& type,
00111 const QString& description,
00112 const QString& url,
00113 const QString& author,
00114 const bool& download,
00115 const QDateTime& updated) :
00116 QObject(),
00117 m_lock(QMutex::Recursive),
00118 m_reply(NULL),
00119 m_manager(NULL)
00120 {
00121 m_title = title;
00122 m_image = image;
00123 m_type = type;
00124 m_description = description;
00125 m_url = url;
00126 m_author = author;
00127 m_download = download;
00128 m_updated = updated;
00129 }
00130
00131 RSSSite::~RSSSite()
00132 {
00133 }
00134
00135 void RSSSite::insertRSSArticle(ResultItem *item)
00136 {
00137 QMutexLocker locker(&m_lock);
00138 m_articleList.append(item);
00139 }
00140
00141 void RSSSite::clearRSSArticles(void)
00142 {
00143 QMutexLocker locker(&m_lock);
00144 m_articleList.clear();
00145 }
00146
00147 void RSSSite::retrieve(void)
00148 {
00149 QMutexLocker locker(&m_lock);
00150 m_data.resize(0);
00151 m_articleList.clear();
00152 m_urlReq = QUrl(m_url);
00153 if (!m_manager)
00154 {
00155 m_manager = new QNetworkAccessManager();
00156 connect(m_manager, SIGNAL(finished(QNetworkReply*)), this,
00157 SLOT(slotCheckRedirect(QNetworkReply*)));
00158 }
00159
00160 m_reply = m_manager->get(QNetworkRequest(m_urlReq));
00161 }
00162
00163 QUrl RSSSite::redirectUrl(const QUrl& possibleRedirectUrl,
00164 const QUrl& oldRedirectUrl) const
00165 {
00166 QUrl redirectUrl;
00167 if(!possibleRedirectUrl.isEmpty() && possibleRedirectUrl != oldRedirectUrl)
00168 redirectUrl = possibleRedirectUrl;
00169 return redirectUrl;
00170 }
00171
00172 void RSSSite::slotCheckRedirect(QNetworkReply* reply)
00173 {
00174 QVariant possibleRedirectUrl =
00175 reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
00176
00177 QUrl urlRedirectedTo = redirectUrl(possibleRedirectUrl.toUrl(),
00178 urlRedirectedTo);
00179
00180 if(!urlRedirectedTo.isEmpty())
00181 {
00182 m_manager->get(QNetworkRequest(urlRedirectedTo));
00183 }
00184 else
00185 {
00186 m_data = m_reply->readAll();
00187 process();
00188 }
00189
00190 reply->deleteLater();
00191 }
00192
00193 ResultItem::resultList RSSSite::GetVideoList(void) const
00194 {
00195 QMutexLocker locker(&m_lock);
00196 return m_articleList;
00197 }
00198
00199 unsigned int RSSSite::timeSinceLastUpdate(void) const
00200 {
00201 QMutexLocker locker(&m_lock);
00202
00203 QDateTime curTime(QDateTime::currentDateTime());
00204 unsigned int min = m_updated.secsTo(curTime)/60;
00205 return min;
00206 }
00207
00208 void RSSSite::process(void)
00209 {
00210 QMutexLocker locker(&m_lock);
00211
00212 m_articleList.clear();
00213
00214 if (!m_data.size())
00215 return;
00216
00217 QDomDocument domDoc;
00218
00219 if (!domDoc.setContent(m_data, true))
00220 {
00221 LOG(VB_GENERAL, LOG_ERR, LOC +
00222 "Failed to set content from downloaded XML");
00223 return;
00224 }
00225
00226
00227 QString rootName = domDoc.documentElement().nodeName();
00228 if (rootName == "rss" || rootName == "rdf:RDF")
00229 {
00230 ResultItem::resultList items;
00231 Parse parser;
00232 items = parser.parseRSS(domDoc);
00233
00234 for (ResultItem::resultList::iterator i = items.begin();
00235 i != items.end(); ++i)
00236 {
00237 insertRSSArticle(new ResultItem((*i)->GetTitle(),
00238 QString(), (*i)->GetDescription(), (*i)->GetURL(),
00239 (*i)->GetThumbnail(), (*i)->GetMediaURL(),
00240 (*i)->GetAuthor(), (*i)->GetDate(),
00241 (*i)->GetTime(), (*i)->GetRating(),
00242 (*i)->GetFilesize(), (*i)->GetPlayer(),
00243 (*i)->GetPlayerArguments(),
00244 (*i)->GetDownloader(),
00245 (*i)->GetDownloaderArguments(),
00246 (*i)->GetWidth(),
00247 (*i)->GetHeight(),
00248 (*i)->GetLanguage(),
00249 (*i)->GetDownloadable(),
00250 (*i)->GetCountries(),
00251 (*i)->GetSeason(),
00252 (*i)->GetEpisode(), false));
00253 }
00254 emit finished(this);
00255 }
00256 else
00257 {
00258 LOG(VB_GENERAL, LOG_ERR, LOC + "Data is not valid RSS-feed");
00259 emit finished(this);
00260 }
00261 }