@ -1,132 +0,0 @@
|
||||
/* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "NewsChecker.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDomDocument>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
NewsChecker::NewsChecker(shared_qobject_ptr<QNetworkAccessManager> network, const QString& feedUrl)
|
||||
{
|
||||
m_network = network;
|
||||
m_feedUrl = feedUrl;
|
||||
}
|
||||
|
||||
void NewsChecker::reloadNews()
|
||||
{
|
||||
// Start a netjob to download the RSS feed and call rssDownloadFinished() when it's done.
|
||||
if (isLoadingNews())
|
||||
{
|
||||
qDebug() << "Ignored request to reload news. Currently reloading already.";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Reloading news.";
|
||||
|
||||
NetJob* job = new NetJob("News RSS Feed", m_network);
|
||||
job->addNetAction(Net::Download::makeByteArray(m_feedUrl, &newsData));
|
||||
QObject::connect(job, &NetJob::succeeded, this, &NewsChecker::rssDownloadFinished);
|
||||
QObject::connect(job, &NetJob::failed, this, &NewsChecker::rssDownloadFailed);
|
||||
m_newsNetJob.reset(job);
|
||||
job->start();
|
||||
}
|
||||
|
||||
void NewsChecker::rssDownloadFinished()
|
||||
{
|
||||
// Parse the XML file and process the RSS feed entries.
|
||||
qDebug() << "Finished loading RSS feed.";
|
||||
|
||||
m_newsNetJob.reset();
|
||||
QDomDocument doc;
|
||||
{
|
||||
// Stuff to store error info in.
|
||||
QString errorMsg = "Unknown error.";
|
||||
int errorLine = -1;
|
||||
int errorCol = -1;
|
||||
|
||||
// Parse the XML.
|
||||
if (!doc.setContent(newsData, false, &errorMsg, &errorLine, &errorCol))
|
||||
{
|
||||
QString fullErrorMsg = QString("Error parsing RSS feed XML. %s at %d:%d.").arg(errorMsg, errorLine, errorCol);
|
||||
fail(fullErrorMsg);
|
||||
newsData.clear();
|
||||
return;
|
||||
}
|
||||
newsData.clear();
|
||||
}
|
||||
|
||||
// If the parsing succeeded, read it.
|
||||
QDomNodeList items = doc.elementsByTagName("item");
|
||||
m_newsEntries.clear();
|
||||
for (int i = 0; i < items.length(); i++)
|
||||
{
|
||||
QDomElement element = items.at(i).toElement();
|
||||
NewsEntryPtr entry;
|
||||
entry.reset(new NewsEntry());
|
||||
QString errorMsg = "An unknown error occurred.";
|
||||
if (NewsEntry::fromXmlElement(element, entry.get(), &errorMsg))
|
||||
{
|
||||
qDebug() << "Loaded news entry" << entry->title;
|
||||
m_newsEntries.append(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "Failed to load news entry at index" << i << ":" << errorMsg;
|
||||
}
|
||||
}
|
||||
|
||||
succeed();
|
||||
}
|
||||
|
||||
void NewsChecker::rssDownloadFailed(QString reason)
|
||||
{
|
||||
// Set an error message and fail.
|
||||
fail(tr("Failed to load news RSS feed:\n%1").arg(reason));
|
||||
}
|
||||
|
||||
|
||||
QList<NewsEntryPtr> NewsChecker::getNewsEntries() const
|
||||
{
|
||||
return m_newsEntries;
|
||||
}
|
||||
|
||||
bool NewsChecker::isLoadingNews() const
|
||||
{
|
||||
return m_newsNetJob.get() != nullptr;
|
||||
}
|
||||
|
||||
QString NewsChecker::getLastLoadErrorMsg() const
|
||||
{
|
||||
return m_lastLoadError;
|
||||
}
|
||||
|
||||
void NewsChecker::succeed()
|
||||
{
|
||||
m_lastLoadError = "";
|
||||
qDebug() << "News loading succeeded.";
|
||||
m_newsNetJob.reset();
|
||||
emit newsLoaded();
|
||||
}
|
||||
|
||||
void NewsChecker::fail(const QString& errorMsg)
|
||||
{
|
||||
m_lastLoadError = errorMsg;
|
||||
qDebug() << "Failed to load news:" << errorMsg;
|
||||
m_newsNetJob.reset();
|
||||
emit newsLoadingFailed(errorMsg);
|
||||
}
|
||||
|
@ -1,105 +0,0 @@
|
||||
/* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
#include <net/NetJob.h>
|
||||
|
||||
#include "NewsEntry.h"
|
||||
|
||||
class NewsChecker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/*!
|
||||
* Constructs a news reader to read from the given RSS feed URL.
|
||||
*/
|
||||
NewsChecker(shared_qobject_ptr<QNetworkAccessManager> network, const QString& feedUrl);
|
||||
|
||||
/*!
|
||||
* Returns the error message for the last time the news was loaded.
|
||||
* Empty string if the last load was successful.
|
||||
*/
|
||||
QString getLastLoadErrorMsg() const;
|
||||
|
||||
/*!
|
||||
* Returns true if the news has been loaded successfully.
|
||||
*/
|
||||
bool isNewsLoaded() const;
|
||||
|
||||
//! True if the news is currently loading. If true, reloadNews() will do nothing.
|
||||
bool isLoadingNews() const;
|
||||
|
||||
/*!
|
||||
* Returns a list of news entries.
|
||||
*/
|
||||
QList<NewsEntryPtr> getNewsEntries() const;
|
||||
|
||||
/*!
|
||||
* Reloads the news from the website's RSS feed.
|
||||
* If the news is already loading, this does nothing.
|
||||
*/
|
||||
void Q_SLOT reloadNews();
|
||||
|
||||
signals:
|
||||
/*!
|
||||
* Signal fired after the news has finished loading.
|
||||
*/
|
||||
void newsLoaded();
|
||||
|
||||
/*!
|
||||
* Signal fired after the news fails to load.
|
||||
*/
|
||||
void newsLoadingFailed(QString errorMsg);
|
||||
|
||||
protected slots:
|
||||
void rssDownloadFinished();
|
||||
void rssDownloadFailed(QString reason);
|
||||
|
||||
protected: /* data */
|
||||
//! The URL for the RSS feed to fetch.
|
||||
QString m_feedUrl;
|
||||
|
||||
//! List of news entries.
|
||||
QList<NewsEntryPtr> m_newsEntries;
|
||||
|
||||
//! The network job to use to load the news.
|
||||
NetJob::Ptr m_newsNetJob;
|
||||
|
||||
//! True if news has been loaded.
|
||||
bool m_loadedNews;
|
||||
|
||||
QByteArray newsData;
|
||||
|
||||
/*!
|
||||
* Gets the error message that was given last time the news was loaded.
|
||||
* If the last news load succeeded, this will be an empty string.
|
||||
*/
|
||||
QString m_lastLoadError;
|
||||
|
||||
shared_qobject_ptr<QNetworkAccessManager> m_network;
|
||||
|
||||
protected slots:
|
||||
/// Emits newsLoaded() and sets m_lastLoadError to empty string.
|
||||
void succeed();
|
||||
|
||||
/// Emits newsLoadingFailed() and sets m_lastLoadError to the given message.
|
||||
void fail(const QString& errorMsg);
|
||||
};
|
||||
|
@ -1,77 +0,0 @@
|
||||
/* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "NewsEntry.h"
|
||||
|
||||
#include <QDomNodeList>
|
||||
#include <QVariant>
|
||||
|
||||
NewsEntry::NewsEntry(QObject* parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
this->title = tr("Untitled");
|
||||
this->content = tr("No content.");
|
||||
this->link = "";
|
||||
this->author = tr("Unknown Author");
|
||||
this->pubDate = QDateTime::currentDateTime();
|
||||
}
|
||||
|
||||
NewsEntry::NewsEntry(const QString& title, const QString& content, const QString& link, const QString& author, const QDateTime& pubDate, QObject* parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
this->title = title;
|
||||
this->content = content;
|
||||
this->link = link;
|
||||
this->author = author;
|
||||
this->pubDate = pubDate;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Gets the text content of the given child element as a QVariant.
|
||||
*/
|
||||
inline QString childValue(const QDomElement& element, const QString& childName, QString defaultVal="")
|
||||
{
|
||||
QDomNodeList nodes = element.elementsByTagName(childName);
|
||||
if (nodes.count() > 0)
|
||||
{
|
||||
QDomElement element = nodes.at(0).toElement();
|
||||
return element.text();
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
bool NewsEntry::fromXmlElement(const QDomElement& element, NewsEntry* entry, QString* errorMsg)
|
||||
{
|
||||
QString title = childValue(element, "title", tr("Untitled"));
|
||||
QString content = childValue(element, "description", tr("No content."));
|
||||
QString link = childValue(element, "link");
|
||||
QString author = childValue(element, "dc:creator", tr("Unknown Author"));
|
||||
QString pubDateStr = childValue(element, "pubDate");
|
||||
|
||||
// FIXME: For now, we're just ignoring timezones. We assume that all time zones in the RSS feed are the same.
|
||||
QString dateFormat("ddd, dd MMM yyyy hh:mm:ss");
|
||||
QDateTime pubDate = QDateTime::fromString(pubDateStr, dateFormat);
|
||||
|
||||
entry->title = title;
|
||||
entry->content = content;
|
||||
entry->link = link;
|
||||
entry->author = author;
|
||||
entry->pubDate = pubDate;
|
||||
return true;
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
/* Copyright 2013-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QDomElement>
|
||||
#include <QDateTime>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class NewsEntry : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty news entry.
|
||||
*/
|
||||
explicit NewsEntry(QObject* parent=0);
|
||||
|
||||
/*!
|
||||
* Constructs a new news entry.
|
||||
* Note that content may contain HTML.
|
||||
*/
|
||||
NewsEntry(const QString& title, const QString& content, const QString& link, const QString& author, const QDateTime& pubDate, QObject* parent=0);
|
||||
|
||||
/*!
|
||||
* Attempts to load information from the given XML element into the given news entry pointer.
|
||||
* If this fails, the function will return false and store an error message in the errorMsg pointer.
|
||||
*/
|
||||
static bool fromXmlElement(const QDomElement& element, NewsEntry* entry, QString* errorMsg=0);
|
||||
|
||||
|
||||
//! The post title.
|
||||
QString title;
|
||||
|
||||
//! The post's content. May contain HTML.
|
||||
QString content;
|
||||
|
||||
//! URL to the post.
|
||||
QString link;
|
||||
|
||||
//! The post's author.
|
||||
QString author;
|
||||
|
||||
//! The date and time that this post was published.
|
||||
QDateTime pubDate;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<NewsEntry> NewsEntryPtr;
|
||||
|
Reference in New Issue
Block a user