- Add the ability to parse the RSS feeds from reddit groups (in particular the image feed groups like EarthPorn) and display them

This commit is contained in:
Alfred Reynolds
2021-08-22 15:10:26 +12:00
parent 3557b6041f
commit 833e7ef915
9 changed files with 271 additions and 15 deletions

View File

@@ -5,6 +5,8 @@
#include <QDirIterator>
#include <QDir>
#include <QFileInfo>
#include <QDomDocument>
#include <QDomAttr>
#include <iostream>
#include <stdlib.h> /* srand, rand */
@@ -108,5 +110,132 @@ ImageDisplayOptions ImageListPathTraverser::UpdateOptionsForImage(const std::str
// no per file options modification supported
Q_UNUSED(filename);
Q_UNUSED(baseOptions);
return ImageDisplayOptions();
return baseOptions;
}
RedditRSSFeedPathTraverser::RedditRSSFeedPathTraverser(const std::string& rssFeedURLIn, QNetworkAccessManager& networkManager, bool debugModeIn) :
PathTraverser("",debugModeIn), rssFeedURL(rssFeedURLIn), webCtrl(networkManager)
{
connect( &webCtrl, SIGNAL (finished(QNetworkReply*)), this, SLOT (fileDownloaded(QNetworkReply*)));
RequestRSSFeed();
}
RedditRSSFeedPathTraverser::~RedditRSSFeedPathTraverser()
{
}
void RedditRSSFeedPathTraverser::RequestRSSFeed()
{
if (pendingReply)
{
pendingReply->abort();
}
if (debugMode)
{
std::cout << "Requesting RSS feed:" << rssFeedURL << std::endl;
}
rssRequestedTime = QDateTime::currentDateTime();
QNetworkRequest request(QUrl(rssFeedURL.c_str()));
pendingReply = webCtrl.get(request);
}
void RedditRSSFeedPathTraverser::fileDownloaded(QNetworkReply* netReply)
{
if (netReply != pendingReply)
return;
pendingReply = nullptr;
QNetworkReply::NetworkError err = netReply->error();
if (err != QNetworkReply::NoError)
{
std::cout << "Failed to load Reddit RSS URL: " << err << std::endl;
return;
}
QString str (netReply->readAll());
QVariant vt = netReply->attribute(QNetworkRequest::RedirectionTargetAttribute);
netReply->deleteLater();
if (!vt.isNull())
{
if (debugMode)
{
std::cout << "Redirected to:" << vt.toUrl().toString().toStdString() << std::endl;
}
webCtrl.get(QNetworkRequest(vt.toUrl()));
}
else
{
QDomDocument doc;
QString error;
if (!doc.setContent(str, false, &error))
{
if (debugMode)
{
std::cout << "Failed to load page:" << error.toStdString() << std::endl;
}
}
else
{
QDomElement docElem = doc.documentElement();
QDomNodeList nodeList = docElem.elementsByTagName("entry");
for (int iEntry = 0; iEntry < nodeList.length(); ++iEntry)
{
QDomNode node = nodeList.item(iEntry);
QDomElement e = node.toElement();
QDomNode contentNode = e.elementsByTagName("content").item(0).firstChild();
QDomDocument docContent;
if (!docContent.setContent(contentNode.nodeValue(), false, &error))
{
continue;
}
QDomNodeList addressEntries = docContent.documentElement().elementsByTagName("a");
for (int iAddr = 0; iAddr < addressEntries.length(); ++iAddr)
{
QDomNode node = addressEntries.item(iAddr);
/*QString output;
QTextStream stream(&output);
node.save(stream, 0);
qDebug() << "nodeValue: " << output;*/
if (node.toElement().text() == "[link]" && node.hasAttributes() )
{
QDomAttr a = node.toElement().attributeNode("href");
// check if the URL matches one of our supported formats
for ( const QString& format : supportedFormats )
{
if (a.value().endsWith(format))
{
imageURLS.append(a.value());
}
}
}
}
}
}
}
}
QStringList RedditRSSFeedPathTraverser::getImages() const
{
// refresh the feed after 5 hours
if (rssRequestedTime.secsTo(QDateTime::currentDateTime()) > 60*60*5 )
{
const_cast<RedditRSSFeedPathTraverser *>(this)->RequestRSSFeed();
}
return imageURLS;
}
const std::string RedditRSSFeedPathTraverser::getImagePath(const std::string image) const
{
return image;
}
ImageDisplayOptions RedditRSSFeedPathTraverser::UpdateOptionsForImage(const std::string& filename, const ImageDisplayOptions& baseOptions) const
{
// no per file options modification supported
Q_UNUSED(filename);
return baseOptions;
}