Merge branch 'master' of github.com:martinrotter/rssguard
This commit is contained in:
commit
6272bf92c5
16 changed files with 97 additions and 31 deletions
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -525,7 +525,7 @@
|
|||
</action>
|
||||
<action name="m_actionDonate">
|
||||
<property name="text">
|
||||
<string>&Donate via PayPal</string>
|
||||
<string>&Donate...</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string notr="true"/>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue