a-la-karte/src/itchimporter.cpp

129 lines
3.3 KiB
C++
Raw Normal View History

// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2026 A-La-Karte Contributors
#include "itchimporter.h"
#include <QDir>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
ItchImporter::ItchImporter(QObject *parent)
: PlatformImporter(parent)
{
}
QString ItchImporter::platformName() const
{
return QStringLiteral("itch.io");
}
QString ItchImporter::platformId() const
{
return QStringLiteral("itch");
}
QString ItchImporter::getItchDatabasePath() const
{
QStringList paths = {
expandPath(QStringLiteral("~/.config/itch/db/butler.db")),
expandPath(QStringLiteral("~/.var/app/io.itch.itch/config/itch/db/butler.db")),
};
for (const QString &path : paths) {
if (QFile::exists(path)) {
return path;
}
}
return QString();
}
bool ItchImporter::isAvailable() const
{
return !getItchDatabasePath().isEmpty();
}
QList<Game *> ItchImporter::parseItchDatabase(const QString &dbPath) const
{
QList<Game *> games;
// Use a unique connection name
QString connectionName = QStringLiteral("itch_import_%1").arg(reinterpret_cast<quintptr>(this));
{
QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), connectionName);
db.setDatabaseName(dbPath);
if (!db.open()) {
return games;
}
// Query caves table for installed games
QSqlQuery query(db);
query.prepare(
QStringLiteral("SELECT c.id, c.game_id, g.title, g.short_text, g.cover_url, c.install_folder_name "
"FROM caves c "
"LEFT JOIN games g ON c.game_id = g.id "
"WHERE c.install_folder_name IS NOT NULL"));
if (!query.exec()) {
db.close();
return games;
}
while (query.next()) {
QString caveId = query.value(0).toString();
QString gameId = query.value(1).toString();
QString title = query.value(2).toString();
QString shortText = query.value(3).toString();
QString coverUrl = query.value(4).toString();
QString installFolder = query.value(5).toString();
if (title.isEmpty()) {
continue;
}
QString id = QStringLiteral("itch_%1").arg(gameId);
Game *game = new Game(id, title);
game->setPlatform(platformName());
game->setPlatformId(platformId());
if (!shortText.isEmpty()) {
game->setDescription(shortText);
}
if (!coverUrl.isEmpty()) {
game->setCoverUrl(QUrl(coverUrl));
}
// Build launch command using itch app
QString launchCmd = QStringLiteral("itch://caves/%1/launch").arg(caveId);
game->setLaunchCommand(QStringLiteral("xdg-open \"%1\"").arg(launchCmd));
games.append(game);
}
db.close();
}
QSqlDatabase::removeDatabase(connectionName);
return games;
}
QList<Game *> ItchImporter::importGames()
{
QString dbPath = getItchDatabasePath();
if (dbPath.isEmpty()) {
return {};
}
return parseItchDatabase(dbPath);
}