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.
 
 
 
 
 
 

154 lines
5.3 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;
bool isOutgoing = false;
bool isRead = false;
};
struct AccountRow {
quint64 nodeId = 0;
QString displayName;
QString avatarColor;
QString avatarLetter;
bool isContact = true;
};
struct ChannelMember {
quint64 nodeId = 0;
bool online = false;
QString name; // from nodes.name, empty if not set
QString localNick; // from peers.local_nick override, empty if not set
};
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; }
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;
/* ── Участники канала (UI) ── */
int getChannelMemberCount(const QString& chId) const;
QList<ChannelMember> getChannelMembers(const QString& chId, int offset, int limit) const;
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;
quint64 m_myNodeId = 0;
/* Кэш открытых курсоров для sync-операций */
mutable QMap<uint32_t, sqlite3_stmt*> m_cursors;
mutable uint32_t m_nextCursorId = 1;
};
#endif