Merge branch 'master' of github.com:martinrotter/rssguard

This commit is contained in:
Martin Rotter 2018-01-02 20:50:30 +01:00
commit 6272bf92c5
16 changed files with 97 additions and 31 deletions

View file

@ -15,7 +15,7 @@ Welcome to RSS Guard website. You can find here basic information.
RSS Guard is simple, light and easy-to-use RSS/ATOM feed aggregator developed using Qt framework which supports online feed synchronization.
#### You can support this project via donations:
* [PATREON](https://www.patreon.com/martinrotter),
* [LIBERAPAY](https://liberapay.com/martinrotter),
* [PAYPAL](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XMWPLPK893VH4).
#### See [Wiki](https://github.com/martinrotter/rssguard/wiki) for more information about features, download links and other stuff.

@ -1 +1 @@
Subproject commit ae7084718c41afc01919779e58cd449e0eebd401
Subproject commit 4a01edaec7d67d3b2ae81aeea2a3c876216fbab8

View file

@ -2,6 +2,8 @@
—————
Fixed:
▪ Bad handling of null/empty strings when inserting messages into DB. (bug #169)
▪ Bad conversion of "created on" date/time in TT-RSS plugin. (bug #172)
▪ Missing obligatory attribute in OPML 2.0 files. (bug #166)
3.5.5

View file

@ -63,7 +63,7 @@ APP_URL_ISSUES = "https://github.com/martinrotter/rssguard/issues
APP_URL_ISSUES_NEW = "https://github.com/martinrotter/rssguard/issues/new"
APP_URL_WIKI = "https://github.com/martinrotter/rssguard/wiki"
APP_USERAGENT = "RSS Guard/$$APP_VERSION (github.com/martinrotter/rssguard)"
APP_DONATE_URL = "https://goo.gl/YFVJ0j"
APP_DONATE_URL = "https://liberapay.com/martinrotter"
APP_WIN_ARCH = "win64"
isEmpty(PREFIX) {

View file

@ -48,7 +48,7 @@ QString Enclosures::encodeEnclosuresToString(const QList<Enclosure>& enclosures)
}
Message::Message() {
m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = QSL("");
m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = "";
m_enclosures = QList<Enclosure>();
m_accountId = m_id = 0;
m_isRead = m_isImportant = false;

View file

@ -525,7 +525,7 @@
</action>
<action name="m_actionDonate">
<property name="text">
<string>&amp;Donate via PayPal</string>
<string>&amp;Donate...</string>
</property>
<property name="shortcut">
<string notr="true"/>

View file

@ -30,6 +30,8 @@
#include <QUrl>
#include <QVariant>
#define EMPT_STR_NULL(x) ( ## x ## .isNull() ? "" : x)
bool DatabaseQueries::markMessagesReadUnread(QSqlDatabase db, const QStringList& ids, RootItem::ReadStatus read) {
QSqlQuery q(db);
@ -516,10 +518,10 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
if (message.m_customId.isEmpty()) {
// We need to recognize existing messages according URL & AUTHOR & TITLE.
// NOTE: This particularly concerns messages from standard account.
query_select_with_url.bindValue(QSL(":feed"), feed_custom_id);
query_select_with_url.bindValue(QSL(":title"), message.m_title);
query_select_with_url.bindValue(QSL(":url"), message.m_url);
query_select_with_url.bindValue(QSL(":author"), message.m_author);
query_select_with_url.bindValue(QSL(":feed"), EMPT_STR_NULL(feed_custom_id));
query_select_with_url.bindValue(QSL(":title"), EMPT_STR_NULL(message.m_title));
query_select_with_url.bindValue(QSL(":url"), EMPT_STR_NULL(message.m_url));
query_select_with_url.bindValue(QSL(":author"), EMPT_STR_NULL(message.m_author));
query_select_with_url.bindValue(QSL(":account_id"), account_id);
qDebug("Checking if message with title '%s', url '%s' and author '%s' is present in DB.",
@ -545,7 +547,7 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
// We can recognize existing messages via their custom ID.
// NOTE: This concerns messages from custom accounts, like TT-RSS or ownCloud News.
query_select_with_id.bindValue(QSL(":account_id"), account_id);
query_select_with_id.bindValue(QSL(":custom_id"), message.m_customId);
query_select_with_id.bindValue(QSL(":custom_id"), EMPT_STR_NULL(message.m_customId));
qDebug("Checking if message with custom ID %s is present in DB.", qPrintable(message.m_customId));
@ -582,15 +584,15 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
/* 2 */ (message.m_createdFromFeed && message.m_created.toMSecsSinceEpoch() != date_existing_message
&& message.m_contents != contents_existing_message)) {
// Message exists, it is changed, update it.
query_update.bindValue(QSL(":title"), message.m_title);
query_update.bindValue(QSL(":title"), EMPT_STR_NULL(message.m_title));
query_update.bindValue(QSL(":is_read"), (int) message.m_isRead);
query_update.bindValue(QSL(":is_important"), (int) message.m_isImportant);
query_update.bindValue(QSL(":url"), message.m_url);
query_update.bindValue(QSL(":author"), message.m_author);
query_update.bindValue(QSL(":url"), EMPT_STR_NULL(message.m_url));
query_update.bindValue(QSL(":author"), EMPT_STR_NULL(message.m_author));
query_update.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch());
query_update.bindValue(QSL(":contents"), message.m_contents);
query_update.bindValue(QSL(":contents"), EMPT_STR_NULL(message.m_contents));
query_update.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures));
query_update.bindValue(QSL(":feed"), message.m_feedId);
query_update.bindValue(QSL(":feed"), EMPT_STR_NULL(feed_id_existing_message));
query_update.bindValue(QSL(":id"), id_existing_message);
*any_message_changed = true;
@ -610,17 +612,17 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
}
else {
// Message with this URL is not fetched in this feed yet.
query_insert.bindValue(QSL(":feed"), feed_custom_id);
query_insert.bindValue(QSL(":title"), message.m_title);
query_insert.bindValue(QSL(":feed"), EMPT_STR_NULL(feed_custom_id));
query_insert.bindValue(QSL(":title"), EMPT_STR_NULL(message.m_title));
query_insert.bindValue(QSL(":is_read"), (int) message.m_isRead);
query_insert.bindValue(QSL(":is_important"), (int) message.m_isImportant);
query_insert.bindValue(QSL(":url"), message.m_url);
query_insert.bindValue(QSL(":author"), message.m_author);
query_insert.bindValue(QSL(":url"), EMPT_STR_NULL( message.m_url));
query_insert.bindValue(QSL(":author"), EMPT_STR_NULL(message.m_author));
query_insert.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch());
query_insert.bindValue(QSL(":contents"), message.m_contents);
query_insert.bindValue(QSL(":contents"), EMPT_STR_NULL(message.m_contents));
query_insert.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures));
query_insert.bindValue(QSL(":custom_id"), message.m_customId);
query_insert.bindValue(QSL(":custom_hash"), message.m_customHash);
query_insert.bindValue(QSL(":custom_id"), EMPT_STR_NULL(message.m_customId));
query_insert.bindValue(QSL(":custom_hash"), EMPT_STR_NULL(message.m_customHash));
query_insert.bindValue(QSL(":account_id"), account_id);
if (query_insert.exec() && query_insert.numRowsAffected() == 1) {

View file

@ -26,6 +26,7 @@
#include "definitions/definitions.h"
#include "miscellaneous/application.h"
#include "network-web/networkfactory.h"
#include "network-web/webfactory.h"
#include "services/inoreader/definitions.h"
@ -186,7 +187,10 @@ void OAuth2Service::tokenRequestFinished(QNetworkReply* network_reply) {
qDebug() << "Token response:" << json_document.toJson();
if (root_obj.keys().contains("error")) {
if (network_reply->error() != QNetworkReply::NetworkError::NoError) {
emit tokensRetrieveError(QString(), NetworkFactory::networkErrorText(network_reply->error()));
}
else if (root_obj.keys().contains("error")) {
QString error = root_obj.value("error").toString();
QString error_description = root_obj.value("error_description").toString();

View file

@ -164,11 +164,11 @@ void GmailServiceRoot::start(bool freshly_activated) {
loadFromDatabase();
loadCacheFromFile(accountId());
m_network->oauth()->login();
if (childCount() <= 1) {
syncIn();
}
m_network->oauth()->login();
}
void GmailServiceRoot::stop() {

View file

@ -269,6 +269,8 @@ void GmailNetworkFactory::onTokensError(const QString& error, const QString& err
QSystemTrayIcon::Critical,
nullptr, false,
[this]() {
m_oauth2->setAccessToken(QString());
m_oauth2->setRefreshToken(QString());
m_oauth2->login();
});
}

View file

@ -122,11 +122,12 @@ void InoreaderServiceRoot::start(bool freshly_activated) {
loadFromDatabase();
loadCacheFromFile(accountId());
m_network->oauth()->login();
if (childCount() <= 1) {
syncIn();
}
else {
m_network->oauth()->login();
}
}
void InoreaderServiceRoot::stop() {

View file

@ -283,6 +283,8 @@ void InoreaderNetworkFactory::onTokensError(const QString& error, const QString&
QSystemTrayIcon::Critical,
nullptr, false,
[this]() {
m_oauth2->setAccessToken(QString());
m_oauth2->setRefreshToken(QString());
m_oauth2->login();
});
}

View file

@ -59,6 +59,7 @@ Message AtomParser::extractMessage(const QDomElement& msg_element, QDateTime cur
new_message.m_title = qApp->web()->stripTags(title);
new_message.m_contents = summary;
new_message.m_author = qApp->web()->escapeHtml(messageAuthor(msg_element));
QString updated = textsFromPath(msg_element, m_atomNamespace, QSL("updated"), true).join(QSL(", "));
if (updated.isEmpty()) {

View file

@ -49,6 +49,7 @@ void FormStandardImportExport::setMode(const FeedsImportExportModel::Mode& mode)
m_ui->m_lblRootNode->setVisible(false);
m_ui->m_groupFile->setTitle(tr("Destination file"));
m_ui->m_groupFeeds->setTitle(tr("Source feeds && categories"));
m_ui->m_buttonBox->button(QDialogButtonBox::StandardButton::Ok)->setText(tr("&Export to file"));
setWindowTitle(tr("Export feeds"));
setWindowIcon(qApp->icons()->fromTheme(QSL("document-export")));
break;
@ -58,6 +59,7 @@ void FormStandardImportExport::setMode(const FeedsImportExportModel::Mode& mode)
m_ui->m_groupFile->setTitle(tr("Source file"));
m_ui->m_groupFeeds->setTitle(tr("Target feeds && categories"));
m_ui->m_groupFeeds->setDisabled(true);
m_ui->m_buttonBox->button(QDialogButtonBox::StandardButton::Ok)->setText(tr("&Import from file"));
// Load categories.
loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot);

View file

@ -20,6 +20,18 @@
<string/>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item row="0" column="0">
<widget class="QPushButton" name="m_btnSelectFile">
<property name="text">
@ -73,6 +85,18 @@
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item row="1" column="1">
<widget class="QPushButton" name="m_btnCheckAllItems">
<property name="text">
@ -137,6 +161,18 @@
<string>Operation results</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item row="0" column="0">
<widget class="LabelWithStatus" name="m_lblResult" native="true">
<property name="layoutDirection">
@ -154,6 +190,19 @@
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="m_buttonBox">
<property name="orientation">
@ -176,10 +225,10 @@
</customwidgets>
<tabstops>
<tabstop>m_btnSelectFile</tabstop>
<tabstop>m_cmbRootNode</tabstop>
<tabstop>m_btnCheckAllItems</tabstop>
<tabstop>m_btnUncheckAllItems</tabstop>
<tabstop>m_treeFeeds</tabstop>
<tabstop>m_buttonBox</tabstop>
</tabstops>
<resources/>
<connections>

View file

@ -225,7 +225,7 @@ TtRssGetHeadlinesResponse TtRssNetworkFactory::getHeadlines(int feed_id, int lim
result = TtRssGetHeadlinesResponse(QString::fromUtf8(result_raw));
}
IOFactory::writeFile("aaa", result_raw);
//IOFactory::writeFile("aaa", result_raw);
if (network_reply.first != QNetworkReply::NoError) {
qWarning("TT-RSS: getHeadlines failed with error %d.", network_reply.first);
@ -580,8 +580,9 @@ QList<Message> TtRssGetHeadlinesResponse::messages() const {
message.m_contents = mapped["content"].toString();
// Multiply by 1000 because Tiny Tiny RSS API does not include miliseconds in Unix
// date/time number.
message.m_created = TextFactory::parseDateTime(int(mapped["updated"].toDouble()) * 1000);
// date/time number.
const qint64 t = static_cast<qint64>(mapped["updated"].toDouble()) * 1000;
message.m_created = TextFactory::parseDateTime(t);
message.m_createdFromFeed = true;
message.m_customId = QString::number(mapped["id"].toInt());
message.m_feedId = mapped["feed_id"].toString();