/** * SPDX-FileCopyrightText: 2020 Tobias Fella * * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL */ #include #include #include #include #include #include #include #include #include "alligatorsettings.h" #include "database.h" #include "fetcher.h" #define TRUE_OR_RETURN(x) \ if (!x) \ return false; 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(); if (!migrate()) { qCritical() << "Failed to migrate the database"; } cleanup(); } bool Database::migrate() { if (version() < 1) TRUE_OR_RETURN(migrateTo1()); return true; } bool Database::migrateTo1() { qDebug() << "Migrating database to version 1"; 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);"))); 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, new bool, hasEnclosure BOOL, image TEXT);"))); TRUE_OR_RETURN(execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Authors (feed TEXT, id TEXT, name TEXT, uri TEXT, email TEXT);"))); TRUE_OR_RETURN(execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Enclosures (feed TEXT, id TEXT, duration INTEGER, size INTEGER, title TEXT, type TEXT, url TEXT, playposition INTEGER);"))); //, filename TEXT);"))); TRUE_OR_RETURN(execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Queue (listnr INTEGER, feed TEXT, id TEXT);"))); TRUE_OR_RETURN(execute(QStringLiteral("PRAGMA user_version = 1;"))); return true; } bool Database::execute(const QString &query) { QSqlQuery q; q.prepare(query); return execute(q); } bool Database::execute(QSqlQuery &query) { if (!query.exec()) { qWarning() << "Failed to execute SQL Query"; qWarning() << query.lastQuery(); qWarning() << query.lastError(); return false; } return true; } int Database::version() { QSqlQuery query; query.prepare(QStringLiteral("PRAGMA user_version;")); execute(query); if (query.next()) { bool ok; int value = query.value(0).toInt(&ok); qDebug() << "Database version " << value; if (ok) return value; } else { qCritical() << "Failed to check database version"; } return -1; } void Database::cleanup() { AlligatorSettings settings; int count = settings.deleteAfterCount(); int type = settings.deleteAfterType(); if (type == 0) { // Never delete Entries return; } if (type == 1) { // Delete after posts per feed // TODO } else { QDateTime dateTime = QDateTime::currentDateTime(); if (type == 2) dateTime = dateTime.addDays(-count); else if (type == 3) dateTime = dateTime.addDays(-7 * count); else if (type == 4) dateTime = dateTime.addMonths(-count); qint64 sinceEpoch = dateTime.toSecsSinceEpoch(); QSqlQuery query; query.prepare(QStringLiteral("DELETE FROM Entries WHERE updated < :sinceEpoch;")); query.bindValue(QStringLiteral(":sinceEpoch"), sinceEpoch); execute(query); // TODO: also delete enclosures and authors(?) } }