Files
TTW_Bot/user_manager.cpp
T
2026-01-26 22:26:19 +03:00

317 lines
8.0 KiB
C++

#include "user_manager.h"
#include "twitchmessage.h"
#include <QFile>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QDateTime>
#include <QDebug>
UserManager::UserManager(QObject *parent)
: QObject(parent)
, m_totalMessages(0)
, m_maxUsers(10000)
, m_cleanupInterval(60)
, m_lastCleanup(QDateTime::currentDateTime())
{
}
UserManager::~UserManager()
{
clear();
}
QString UserManager::checkUser(const QString &displayName, const TwitchMessage &msg)
{
QString normalizedDisplayName = displayName.trimmed();
// Проверяем, есть ли пользователь
if (m_users.contains(normalizedDisplayName)) {
User &user = m_users[normalizedDisplayName];
// Обновляем из сообщения, если передано
if (!msg.displayName.isEmpty()) {
updateUserFromMessage(normalizedDisplayName, msg);
}
emit userMessageCountChanged(user.id, user.messageCount);
emit userUpdated(user);
return user.id;
}
// Пользователя нет - создаем нового
User newUser;
if (!msg.displayName.isEmpty()) {
// Заполняем из сообщения
newUser.updateFromTwitchMessage(msg);
} else {
// Минимальные данные
newUser.displayName = normalizedDisplayName;
newUser.login = normalizedDisplayName.toLower();
newUser.id = generateUserId();
}
// Добавляем в базу
addUser(newUser);
return newUser.id;
}
User* UserManager::findUser(const QString &displayName)
{
if (m_users.contains(displayName)) {
return &m_users[displayName];
}
// Пробуем найти по login
if (m_loginToDisplayName.contains(displayName.toLower())) {
QString actualDisplayName = m_loginToDisplayName[displayName.toLower()];
return &m_users[actualDisplayName];
}
return nullptr;
}
User* UserManager::findUserById(const QString &userId)
{
if (m_userIdToDisplayName.contains(userId)) {
QString displayName = m_userIdToDisplayName[userId];
return &m_users[displayName];
}
return nullptr;
}
void UserManager::updateUserFromMessage(const QString &displayName, const TwitchMessage &msg)
{
if (!m_users.contains(displayName)) {
return;
}
User &user = m_users[displayName];
// ВАЖНО: передаем displayName как параметр, а не берем из msg
// если displayName из параметра отличается от msg.displayName,
// нам нужно обновить ключ в map
QString newDisplayName = msg.displayName;
if (!newDisplayName.isEmpty() && newDisplayName != displayName) {
// Display name изменился - нужно переместить пользователя
User userCopy = user;
userCopy.updateFromTwitchMessage(msg);
// Удаляем старую запись
removeUser(displayName);
// Добавляем с новым displayName
userCopy.displayName = newDisplayName;
addUser(userCopy);
return;
}
// Display name не изменился - просто обновляем
user.updateFromTwitchMessage(msg);
// Обновляем индексы
updateIndexes(displayName, user);
emit userUpdated(user);
}
void UserManager::updateUserStatus(const QString &userId, bool isMod, bool isVIP, bool isSubscriber)
{
User* user = findUserById(userId);
if (user) {
user->isModerator = isMod;
user->isVIP = isVIP;
user->isSubscriber = isSubscriber;
emit userUpdated(*user);
}
}
void UserManager::addUser(const User &user)
{
QString displayName = user.displayName;
if (displayName.isEmpty()) {
qWarning() << "Cannot add user with empty display name";
return;
}
// Очистка старых пользователей, если нужно
if (m_users.size() >= m_maxUsers) {
cleanupOldUsers();
}
m_users[displayName] = user;
updateIndexes(displayName, user);
emit userAdded(user);
}
void UserManager::removeUser(const QString &displayName)
{
if (m_users.contains(displayName)) {
User user = m_users[displayName];
// Удаляем из индексов
m_userIdToDisplayName.remove(user.id);
m_loginToDisplayName.remove(user.login.toLower());
// Удаляем из основного списка
m_users.remove(displayName);
emit userRemoved(user.id, displayName); // Передаем и id, и displayName
}
}
void UserManager::clear()
{
m_users.clear();
m_userIdToDisplayName.clear();
m_loginToDisplayName.clear();
m_totalMessages = 0;
}
QVector<User*> UserManager::getModerators() const
{
QVector<User*> moderators;
for (auto it = m_users.begin(); it != m_users.end(); ++it) {
if (it.value().isModerator) {
moderators.append(const_cast<User*>(&it.value()));
}
}
return moderators;
}
QVector<User*> UserManager::getVIPs() const
{
QVector<User*> vips;
for (auto it = m_users.begin(); it != m_users.end(); ++it) {
if (it.value().isVIP) {
vips.append(const_cast<User*>(&it.value()));
}
}
return vips;
}
QVector<User*> UserManager::getSubscribers() const
{
QVector<User*> subscribers;
for (auto it = m_users.begin(); it != m_users.end(); ++it) {
if (it.value().isSubscriber) {
subscribers.append(const_cast<User*>(&it.value()));
}
}
return subscribers;
}
QVector<User*> UserManager::getActiveUsers(int minutes) const
{
QVector<User*> activeUsers;
QDateTime cutoff = QDateTime::currentDateTime().addSecs(-minutes * 60);
for (auto it = m_users.begin(); it != m_users.end(); ++it) {
if (it.value().lastMessageTime >= cutoff) {
activeUsers.append(const_cast<User*>(&it.value()));
}
}
return activeUsers;
}
void UserManager::updateIndexes(const QString &displayName, const User &user)
{
if (!user.id.isEmpty()) {
m_userIdToDisplayName[user.id] = displayName;
}
if (!user.login.isEmpty()) {
m_loginToDisplayName[user.login.toLower()] = displayName;
}
}
void UserManager::cleanupOldUsers()
{
QDateTime cutoff = QDateTime::currentDateTime().addDays(-7); // Удаляем неактивных неделю
QVector<QString> usersToRemove;
for (auto it = m_users.begin(); it != m_users.end(); ++it) {
// Удаляем если:
// 1. Не писал больше недели
// 2. Не модератор/VIP/подписчик
if (it.value().lastMessageTime < cutoff &&
!it.value().isModerator &&
!it.value().isVIP &&
!it.value().isSubscriber &&
it.value().messageCount < 5) { // И написано меньше 5 сообщений
usersToRemove.append(it.key());
}
}
for (const QString &displayName : usersToRemove) {
removeUser(displayName);
}
m_lastCleanup = QDateTime::currentDateTime();
}
int UserManager::getUserCount() const
{
return m_users.size();
}
int UserManager::getMessageCount() const
{
return m_totalMessages;
}
QVector<User*> UserManager::findUsersByLogin(const QString &login)
{
QVector<User*> result;
QString lowerLogin = login.toLower();
for (auto it = m_users.begin(); it != m_users.end(); ++it) {
if (it.value().login.toLower().contains(lowerLogin)) {
result.append(&it.value());
}
}
return result;
}
User* UserManager::getUserByIndex(int index)
{
if (index >= 0 && index < m_users.size()) {
auto it = m_users.begin();
std::advance(it, index);
return &it.value();
}
return nullptr;
}
const QMap<QString, User>& UserManager::getAllUsers() const
{
return m_users;
}
QString UserManager::generateUserId() const
{
return QString("user_%1").arg(QDateTime::currentMSecsSinceEpoch());
}