You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
5.1 KiB
150 lines
5.1 KiB
#ifndef DB_MANAGER_H |
|
#define DB_MANAGER_H |
|
|
|
#include <sqlite3.h> |
|
#include <QString> |
|
#include <QList> |
|
#include <QMap> |
|
#include <QObject> |
|
#include <cstdint> |
|
|
|
enum class ChannelSortMode { Alphabetical, Recent }; |
|
|
|
struct ChannelRow { |
|
QString channelId; |
|
QString name; |
|
quint64 ownerNodeId = 0; |
|
QByteArray x25519_pubkey; |
|
QByteArray x25519_privkey; |
|
QByteArray ed25519_pubkey; |
|
QByteArray ed25519_privkey; |
|
QByteArray signature; // Ed25519 подпись всех полей записи privkey канала |
|
|
|
qint64 lastReadMsgId = 0; |
|
qint64 lastPosMsgId = 0; |
|
qint64 lastMsgAt = 0; |
|
qint64 createdAt = 0; |
|
int unreadCount = 0; |
|
}; |
|
|
|
struct MessageRow { |
|
qint64 id = 0; |
|
quint64 authorNodeId = 0; |
|
QString contentType; |
|
QByteArray data; |
|
qint64 timestamp = 0; |
|
uint64_t datahash = 0; |
|
QByteArray chainHash; |
|
QByteArray signature; |
|
QByteArray localAttrs; |
|
bool isOutgoing = false; |
|
bool isRead = false; |
|
}; |
|
|
|
struct AccountRow { |
|
quint64 nodeId = 0; |
|
QString displayName; |
|
QString avatarColor; |
|
QString avatarLetter; |
|
bool isContact = true; |
|
}; |
|
|
|
struct NodeAddr { |
|
quint64 nodeId = 0; |
|
int family = 0; |
|
int protocol = 0; // битмаска: 1=UDP, 2=TCP, 3=TCP+UDP |
|
QByteArray address; |
|
quint16 port = 0; |
|
int rtt = 0; |
|
int addrType = 0; // ADDR_TYPE_* |
|
int socketId = 0; // socket_id из ETCP |
|
}; |
|
|
|
struct IntegrityResult { |
|
bool ok = false; |
|
QString message; |
|
QStringList errors; |
|
int elapsedMs = 0; |
|
}; |
|
|
|
class DbManager : public QObject { |
|
Q_OBJECT |
|
public: |
|
explicit DbManager(QObject* parent = nullptr); |
|
~DbManager() override; |
|
|
|
bool isOpen() const { return m_db != nullptr; } |
|
void setDb(sqlite3* db) { m_db = db; } |
|
void setDbPath(const QString& path) { m_dbPath = path; } |
|
QString dbPath() const { return m_dbPath; } |
|
quint64 myNodeId() const { return m_myNodeId; } |
|
void setMyNodeId(quint64 nodeId) { m_myNodeId = nodeId; } |
|
|
|
/* ── Каналы ── */ |
|
QList<ChannelRow> getChannels(ChannelSortMode sort = ChannelSortMode::Alphabetical) const; |
|
QString getChannelLastMessage(const QString& channelId) const; |
|
int getUnreadCount(const QString& channelId, qint64 lastReadMsgId) const; |
|
|
|
/* ── UI state for channel read/scroll ── */ |
|
qint64 getUiStateInt64(const QString& key, qint64 defaultVal = 0) const; |
|
|
|
/* ── Сообщения (UI) ── */ |
|
QList<MessageRow> getMessages(const QString& chId, int limit = 50) const; |
|
QList<MessageRow> getMessagesSince(const QString& chId, qint64 sinceId) const; |
|
MessageRow getMessageById(const QString& chId, qint64 msgId) const; |
|
|
|
/* ── Участники канала (UI) ── */ |
|
void cleanOrphanedPeers(const QString& chId) const; |
|
QString getDisplayName(quint64 nodeId) const; |
|
QMap<quint64, QString> getLocalNicknames(const QString& chId) const; |
|
|
|
/* ── Узлы ── */ |
|
QByteArray loadNodeInfo(quint64 nodeId) const; |
|
QList<quint64> getOnlinePeers() const; |
|
QByteArray getNodeEdPub(quint64 nodeId) const; |
|
QList<NodeAddr> getOnlinePeerAddresses(quint64 excludeNodeId) const; |
|
|
|
/* ── Аккаунты ── */ |
|
QList<AccountRow> getAccounts(bool contactsOnly = false) const; |
|
AccountRow getAccount(quint64 nodeId) const; |
|
|
|
/* ── UI state (read-only используем QSettings, оставлен для совместимости) ── */ |
|
QString getUiState(const QString& key) const; |
|
int getUiStateInt(const QString& key, int defaultVal) const; |
|
|
|
/* ── Sync-операции (read-only, для gui_bridge/inline) ── */ |
|
QByteArray syncListChannels() const; |
|
QByteArray syncCount(const QString& chId) const; |
|
QByteArray syncChainHashAt(const QString& chId, uint32_t pos) const; |
|
QByteArray syncCursorOpen(const QString& chId); |
|
QByteArray syncCursorNext(uint32_t cursorId); |
|
void syncCursorClose(uint32_t cursorId); |
|
QByteArray syncListPeers(const QString& chId) const; |
|
|
|
|
|
sqlite3_stmt* prepareOrNull(const char* sql) const; |
|
static QString colText(sqlite3_stmt* stmt, int col); |
|
static QByteArray colBlob(sqlite3_stmt* stmt, int col); |
|
|
|
QString msgTableName(const QString& chId) const; |
|
QString peersTableName(const QString& chId) const; |
|
static QString sanitizeTableName(const QString& chId); |
|
static uint64_t computeDatahash(const QByteArray& data); |
|
static QByteArray computeChainHash(const QByteArray& prevChain, |
|
qint64 timestamp, uint64_t datahash); |
|
QByteArray getLastChainHash(const QString& chId) const; |
|
|
|
IntegrityResult integrityCheckQuick() const; |
|
IntegrityResult integrityCheckFull() const; |
|
IntegrityResult integrityOptimize() const; |
|
|
|
sqlite3* m_db = nullptr; |
|
QString m_dbPath; |
|
quint64 m_myNodeId = 0; |
|
|
|
/* Кэш открытых курсоров для sync-операций */ |
|
mutable QMap<uint32_t, sqlite3_stmt*> m_cursors; |
|
mutable uint32_t m_nextCursorId = 1; |
|
}; |
|
|
|
#endif
|
|
|