2020-03-16 22:37:04 +01:00
/**
* Copyright 2020 Tobias Fella < fella @ posteo . de >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation ; either version 2 of
* the License or ( at your option ) version 3 or any later version
* accepted by the membership of KDE e . V . ( or its successor approved
* by the membership of KDE e . V . ) , which shall act as a proxy
* defined in Section 14 of version 3 of the license .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < https : //www.gnu.org/licenses/>.
*/
2020-04-22 02:17:57 +02:00
# include <QDateTime>
2020-03-16 22:37:04 +01:00
# include <QDir>
# include <QSqlDatabase>
2020-04-22 02:17:57 +02:00
# include <QSqlError>
# include <QStandardPaths>
2020-03-16 22:37:04 +01:00
2020-03-26 20:24:28 +01:00
# include "alligatorsettings.h"
2020-04-22 02:17:57 +02:00
# include "database.h"
2020-05-11 21:13:27 +02:00
# include "fetcher.h"
2020-03-16 22:37:04 +01:00
2020-04-22 02:17:57 +02:00
# define TRUE_OR_RETURN(x) \
if ( ! x ) \
return false ;
2020-03-16 22:37:04 +01:00
Database : : Database ( )
{
QSqlDatabase db = QSqlDatabase : : addDatabase ( QStringLiteral ( " QSQLITE " ) ) ;
QString databasePath = QStandardPaths : : writableLocation ( QStandardPaths : : AppDataLocation ) ;
QDir ( databasePath ) . mkpath ( databasePath ) ;
db . setDatabaseName ( databasePath + QStringLiteral ( " /database.db3 " ) ) ;
db . open ( ) ;
2020-04-22 02:17:57 +02:00
if ( ! migrate ( ) ) {
2020-04-10 17:28:26 +02:00
qCritical ( ) < < " Failed to migrate the database " ;
2020-03-16 22:37:04 +01:00
}
2020-03-26 20:24:28 +01:00
cleanup ( ) ;
2020-03-16 22:37:04 +01:00
}
2020-04-22 02:17:57 +02:00
bool Database : : migrate ( )
{
if ( version ( ) < 1 )
TRUE_OR_RETURN ( migrateTo1 ( ) ) ;
2020-03-16 22:37:04 +01:00
return true ;
}
2020-04-22 02:17:57 +02:00
bool Database : : migrateTo1 ( )
{
2020-04-18 21:07:49 +02:00
qDebug ( ) < < " Migrating database to version 1 " ;
2020-07-06 18:14:43 +02:00
TRUE_OR_RETURN ( execute ( QStringLiteral ( " CREATE TABLE IF NOT EXISTS Feeds (name TEXT, url TEXT, image TEXT, link TEXT, description TEXT, deleteAfterCount INTEGER, deleteAfterType INTEGER, subscribed INTEGER, lastUpdated INTEGER, notify BOOL); " ) ) ) ;
2020-06-06 00:05:32 +02:00
TRUE_OR_RETURN ( execute ( QStringLiteral ( " CREATE TABLE IF NOT EXISTS Entries (feed TEXT, id TEXT UNIQUE, title TEXT, content TEXT, created INTEGER, updated INTEGER, link TEXT, read bool); " ) ) ) ;
2020-04-20 02:06:21 +02:00
TRUE_OR_RETURN ( execute ( QStringLiteral ( " CREATE TABLE IF NOT EXISTS Authors (feed TEXT, id TEXT, name TEXT, uri TEXT, email TEXT); " ) ) ) ;
2020-05-18 17:02:46 +02:00
TRUE_OR_RETURN ( execute ( QStringLiteral ( " CREATE TABLE IF NOT EXISTS Enclosures (feed TEXT, id TEXT, duration INTEGER, size INTEGER, title TEXT, type STRING, url STRING); " ) ) ) ;
2020-03-16 22:37:04 +01:00
TRUE_OR_RETURN ( execute ( QStringLiteral ( " PRAGMA user_version = 1; " ) ) ) ;
return true ;
}
2020-04-22 02:17:57 +02:00
bool Database : : execute ( QString query )
{
2020-03-16 22:37:04 +01:00
QSqlQuery q ;
q . prepare ( query ) ;
return execute ( q ) ;
}
2020-04-22 02:17:57 +02:00
bool Database : : execute ( QSqlQuery & query )
{
if ( ! query . exec ( ) ) {
2020-04-10 17:28:26 +02:00
qWarning ( ) < < " Failed to execute SQL Query " ;
qWarning ( ) < < query . lastQuery ( ) ;
qWarning ( ) < < query . lastError ( ) ;
2020-03-16 22:37:04 +01:00
return false ;
}
return true ;
}
2020-04-22 02:17:57 +02:00
int Database : : version ( )
{
2020-03-16 22:37:04 +01:00
QSqlQuery query ;
query . prepare ( QStringLiteral ( " PRAGMA user_version; " ) ) ;
execute ( query ) ;
2020-04-22 02:17:57 +02:00
if ( query . next ( ) ) {
2020-03-16 22:37:04 +01:00
bool ok ;
int value = query . value ( 0 ) . toInt ( & ok ) ;
2020-04-10 17:28:26 +02:00
qDebug ( ) < < " Database version " < < value ;
2020-04-22 02:17:57 +02:00
if ( ok )
return value ;
2020-03-16 22:37:04 +01:00
} else {
2020-04-10 17:28:26 +02:00
qCritical ( ) < < " Failed to check database version " ;
2020-03-16 22:37:04 +01:00
}
return - 1 ;
}
2020-03-26 20:24:28 +01:00
2020-04-22 02:17:57 +02:00
void Database : : cleanup ( )
{
2020-03-26 20:24:28 +01:00
AlligatorSettings settings ;
int count = settings . deleteAfterCount ( ) ;
int type = settings . deleteAfterType ( ) ;
2020-06-06 00:05:32 +02:00
if ( type = = 0 ) { // Never delete Entries
2020-06-03 00:20:29 +02:00
return ;
}
if ( type = = 1 ) { // Delete after <count> posts per feed
2020-04-22 02:17:57 +02:00
// TODO
2020-03-26 20:24:28 +01:00
} else {
QDateTime dateTime = QDateTime : : currentDateTime ( ) ;
2020-06-03 00:20:29 +02:00
if ( type = = 2 )
2020-04-22 02:17:57 +02:00
dateTime = dateTime . addDays ( - count ) ;
else if ( type = = 3 )
2020-06-03 00:20:29 +02:00
dateTime = dateTime . addDays ( - 7 * count ) ;
else if ( type = = 4 )
2020-04-22 02:17:57 +02:00
dateTime = dateTime . addMonths ( - count ) ;
2020-03-26 20:24:28 +01:00
qint64 sinceEpoch = dateTime . toSecsSinceEpoch ( ) ;
QSqlQuery query ;
2020-04-21 23:27:15 +02:00
query . prepare ( QStringLiteral ( " DELETE FROM Entries WHERE updated < :sinceEpoch; " ) ) ;
query . bindValue ( QStringLiteral ( " :sinceEpoch " ) , sinceEpoch ) ;
2020-03-26 20:24:28 +01:00
execute ( query ) ;
}
}
2020-05-11 21:13:27 +02:00
bool Database : : feedExists ( QString url )
{
QSqlQuery query ;
query . prepare ( QStringLiteral ( " SELECT COUNT (url) FROM Feeds WHERE url=:url; " ) ) ;
query . bindValue ( QStringLiteral ( " :url " ) , url ) ;
Database : : instance ( ) . execute ( query ) ;
query . next ( ) ;
return query . value ( 0 ) . toInt ( ) ! = 0 ;
}
void Database : : addFeed ( QString url )
{
qDebug ( ) < < " Adding feed " ;
if ( feedExists ( url ) ) {
qDebug ( ) < < " Feed already exists " ;
return ;
}
qDebug ( ) < < " Feed does not yet exist " ;
2020-07-05 00:11:59 +02:00
QUrl urlFromInput = QUrl : : fromUserInput ( url ) ;
2020-05-11 21:13:27 +02:00
QSqlQuery query ;
2020-07-06 18:14:43 +02:00
query . prepare ( QStringLiteral ( " INSERT INTO Feeds VALUES (:name, :url, :image, :link, :description, :deleteAfterCount, :deleteAfterType, :subscribed, :lastUpdated, :notify); " ) ) ;
2020-07-05 00:11:59 +02:00
query . bindValue ( QStringLiteral ( " :name " ) , urlFromInput . toString ( ) ) ;
query . bindValue ( QStringLiteral ( " :url " ) , urlFromInput . toString ( ) ) ;
2020-05-11 21:13:27 +02:00
query . bindValue ( QStringLiteral ( " :image " ) , QLatin1String ( " " ) ) ;
2020-05-30 17:33:08 +02:00
query . bindValue ( QStringLiteral ( " :link " ) , QLatin1String ( " " ) ) ;
query . bindValue ( QStringLiteral ( " :description " ) , QLatin1String ( " " ) ) ;
2020-06-06 00:05:32 +02:00
query . bindValue ( QStringLiteral ( " :deleteAfterCount " ) , 0 ) ;
query . bindValue ( QStringLiteral ( " :deleteAfterType " ) , 0 ) ;
query . bindValue ( QStringLiteral ( " :subscribed " ) , QDateTime : : currentDateTime ( ) . toSecsSinceEpoch ( ) ) ;
query . bindValue ( QStringLiteral ( " :lastUpdated " ) , 0 ) ;
query . bindValue ( QStringLiteral ( " :notify " ) , false ) ;
2020-05-11 21:13:27 +02:00
execute ( query ) ;
2020-07-05 00:11:59 +02:00
Q_EMIT feedAdded ( urlFromInput . toString ( ) ) ;
2020-05-26 16:32:07 +02:00
2020-07-05 00:11:59 +02:00
Fetcher : : instance ( ) . fetch ( urlFromInput . toString ( ) ) ;
2020-05-11 21:13:27 +02:00
}