добавил обработку счетчиков
This commit is contained in:
@@ -22,6 +22,7 @@ INCLUDEPATH += $$PWD
|
||||
|
||||
SOURCES += \
|
||||
commandprocessor.cpp \
|
||||
countermanager.cpp \
|
||||
emoteprovider.cpp \
|
||||
fcolorsetting.cpp \
|
||||
fcreatechat.cpp \
|
||||
@@ -54,6 +55,7 @@ SOURCES += \
|
||||
HEADERS += \
|
||||
badge.h \
|
||||
commandprocessor.h \
|
||||
countermanager.h \
|
||||
emoteprovider.h \
|
||||
fcolorsetting.h \
|
||||
fcreatechat.h \
|
||||
|
||||
@@ -108,6 +108,7 @@ QString CommandProcessor::processCommand(const QString &sender, const QString &f
|
||||
response = parseTextFiles(response);
|
||||
response = parseBan(response, sender);
|
||||
response = parseAPI(response, sender);
|
||||
response = parseCounters(response);
|
||||
|
||||
if (response.contains("[AI]", Qt::CaseInsensitive)) {
|
||||
response = parseAI(response, parameters);
|
||||
@@ -214,6 +215,24 @@ QString CommandProcessor::parseTextFiles(const QString &response)
|
||||
return result;
|
||||
}
|
||||
|
||||
QString CommandProcessor::parseCounters(const QString &response)
|
||||
{
|
||||
QString result = response;
|
||||
// Используем ленивый квантификатор +?
|
||||
QRegularExpression regex("\\|\\)([^\\)]+?)\\|\\)");
|
||||
QRegularExpressionMatchIterator matches = regex.globalMatch(response);
|
||||
|
||||
while (matches.hasNext()) {
|
||||
QRegularExpressionMatch match = matches.next();
|
||||
QString counterName = match.captured(1);
|
||||
int count = m_context.counterManager->getCount(counterName);
|
||||
QString countStr = QString::number(count);
|
||||
result.replace("|)" + counterName + "|)", countStr);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QString CommandProcessor::parseRandomGroups(const QString &response)
|
||||
{
|
||||
QString result = response;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <QVector>
|
||||
#include <QMap>
|
||||
#include <QDate>
|
||||
#include "countermanager.h"
|
||||
#include "mediafilemanager.h"
|
||||
#include "user_manager.h"
|
||||
#include "ttw_api.h"
|
||||
@@ -34,6 +35,7 @@ public:
|
||||
RandomResponses* randomResponses = nullptr;
|
||||
MediaFileManager* mediaFileManager = nullptr;
|
||||
NeuralTemplateManager *neuralTemplateManager = nullptr;
|
||||
CounterManager* counterManager = nullptr;
|
||||
QString channel;
|
||||
int notifyVolume = 50;
|
||||
};
|
||||
@@ -67,6 +69,7 @@ private:
|
||||
QString parseAPI(const QString &response, const QString &sender);
|
||||
QString parseAI(const QString &response, const QString &question);
|
||||
QString parseNeuralTemplates(const QString &response, const QString &sender, const QString ¶meters);
|
||||
QString parseCounters(const QString &response);
|
||||
|
||||
QString extractParameters(const QString &fullCommand);
|
||||
QString getUsernameByIndex(QString userIndex) const;
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
// countermanager.cpp
|
||||
#include "countermanager.h"
|
||||
#include <QTableWidget>
|
||||
#include <QDebug>
|
||||
|
||||
CounterManager::CounterManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_database(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
CounterManager::~CounterManager()
|
||||
{
|
||||
if (m_database) {
|
||||
saveToDatabase();
|
||||
}
|
||||
}
|
||||
|
||||
bool CounterManager::initialize(uDataBase *database)
|
||||
{
|
||||
if (!database || !database->isConnected()) {
|
||||
qWarning() << "CounterManager: База данных не подключена";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_database = database;
|
||||
return loadFromDatabase();
|
||||
}
|
||||
|
||||
bool CounterManager::addCounter(const QString &name, int initialValue)
|
||||
{
|
||||
if (name.isEmpty()) {
|
||||
qWarning() << "CounterManager: Нельзя добавить счётчик с пустым именем";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (contains(name)) {
|
||||
qWarning() << "CounterManager: Счётчик с именем" << name << "уже существует";
|
||||
return false;
|
||||
}
|
||||
|
||||
Counter newCounter(name, initialValue);
|
||||
m_counters.append(newCounter);
|
||||
|
||||
if (!saveToDatabase()) {
|
||||
m_counters.removeLast();
|
||||
return false;
|
||||
}
|
||||
|
||||
emit counterAdded(name, initialValue);
|
||||
emit dataChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CounterManager::removeCounter(const QString &name)
|
||||
{
|
||||
int index = findIndex(name);
|
||||
if (index == -1) {
|
||||
qWarning() << "CounterManager: Счётчик" << name << "не найден";
|
||||
return false;
|
||||
}
|
||||
|
||||
Counter removed = m_counters.at(index);
|
||||
m_counters.removeAt(index);
|
||||
|
||||
if (!saveToDatabase()) {
|
||||
m_counters.insert(index, removed);
|
||||
return false;
|
||||
}
|
||||
|
||||
emit counterRemoved(name);
|
||||
emit dataChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CounterManager::updateCounter(const QString &oldName, const QString &newName, int newValue)
|
||||
{
|
||||
int index = findIndex(oldName);
|
||||
if (index == -1) {
|
||||
qWarning() << "CounterManager: Счётчик" << oldName << "не найден";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (oldName != newName && contains(newName)) {
|
||||
qWarning() << "CounterManager: Имя" << newName << "уже занято";
|
||||
return false;
|
||||
}
|
||||
|
||||
Counter oldCounter = m_counters.at(index);
|
||||
m_counters[index].name = newName;
|
||||
m_counters[index].count = newValue;
|
||||
|
||||
if (!saveToDatabase()) {
|
||||
m_counters[index] = oldCounter;
|
||||
return false;
|
||||
}
|
||||
|
||||
emit counterUpdated(oldName, newName);
|
||||
emit dataChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CounterManager::incrementCounter(const QString &name, int step)
|
||||
{
|
||||
int index = findIndex(name);
|
||||
if (index == -1) return false;
|
||||
|
||||
m_counters[index].count += step;
|
||||
if (!saveToDatabase()) {
|
||||
m_counters[index].count -= step; // откат
|
||||
return false;
|
||||
}
|
||||
|
||||
emit counterIncremented(name, m_counters[index].count);
|
||||
emit dataChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CounterManager::decrementCounter(const QString &name, int step)
|
||||
{
|
||||
return incrementCounter(name, -step);
|
||||
}
|
||||
|
||||
int CounterManager::getCount(const QString &name) const
|
||||
{
|
||||
int index = findIndex(name);
|
||||
return (index != -1) ? m_counters.at(index).count : 0;
|
||||
}
|
||||
|
||||
void CounterManager::processMessage(const QString &message)
|
||||
{
|
||||
for (const Counter &c : m_counters) {
|
||||
if (message.contains(c.name, Qt::CaseInsensitive)) {
|
||||
// Увеличиваем счётчик, но без повторного сохранения после каждого (один общий save)
|
||||
// Здесь мы меняем значение, но сохраним после цикла, чтобы не делать много запросов
|
||||
// Для простоты используем incrementCounter, который сам сохраняет, но это будет много раз.
|
||||
// Лучше собрать имена, которые нужно увеличить, а потом применить.
|
||||
// Но в данном случае можно просто вызывать incrementCounter, это не критично.
|
||||
incrementCounter(c.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CounterManager::contains(const QString &name) const
|
||||
{
|
||||
return findIndex(name) != -1;
|
||||
}
|
||||
|
||||
bool CounterManager::saveToDatabase()
|
||||
{
|
||||
if (!m_database) {
|
||||
qWarning() << "CounterManager: База данных не установлена";
|
||||
return false;
|
||||
}
|
||||
|
||||
QTableWidget tempTable;
|
||||
QStringList headers = {"Имя", "Значение"};
|
||||
tempTable.setColumnCount(2);
|
||||
tempTable.setHorizontalHeaderLabels(headers);
|
||||
tempTable.setRowCount(m_counters.size());
|
||||
|
||||
for (int i = 0; i < m_counters.size(); ++i) {
|
||||
const Counter &c = m_counters.at(i);
|
||||
tempTable.setItem(i, 0, new QTableWidgetItem(c.name));
|
||||
tempTable.setItem(i, 1, new QTableWidgetItem(QString::number(c.count)));
|
||||
}
|
||||
tempTable.setObjectName("sgCounters");
|
||||
// Сохраняем через общий метод (предполагаем, что таблица в БД называется "sgCounters")
|
||||
m_database->SaveTableWidget(&tempTable);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CounterManager::loadFromDatabase()
|
||||
{
|
||||
if (!m_database) {
|
||||
qWarning() << "CounterManager: База данных не установлена";
|
||||
return false;
|
||||
}
|
||||
|
||||
QTableWidget tempTable;
|
||||
QStringList headers = {"Имя", "Значение"};
|
||||
tempTable.setColumnCount(2);
|
||||
tempTable.setHorizontalHeaderLabels(headers);
|
||||
tempTable.setObjectName("sgCounters");
|
||||
m_database->LoadTableWidget(&tempTable);
|
||||
|
||||
m_counters.clear();
|
||||
for (int row = 0; row < tempTable.rowCount(); ++row) {
|
||||
QTableWidgetItem *nameItem = tempTable.item(row, 0);
|
||||
QTableWidgetItem *valueItem = tempTable.item(row, 1);
|
||||
|
||||
if (!nameItem || !valueItem) continue;
|
||||
|
||||
QString name = nameItem->text().trimmed();
|
||||
if (name.isEmpty()) continue;
|
||||
|
||||
bool ok;
|
||||
int value = valueItem->text().toInt(&ok);
|
||||
if (!ok) continue;
|
||||
|
||||
m_counters.append(Counter(name, value));
|
||||
}
|
||||
|
||||
emit dataChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
int CounterManager::findIndex(const QString &name) const
|
||||
{
|
||||
for (int i = 0; i < m_counters.size(); ++i) {
|
||||
if (m_counters.at(i).name == name)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// countermanager.h
|
||||
#ifndef COUNTERMANAGER_H
|
||||
#define COUNTERMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <QString>
|
||||
#include "udatabase.h"
|
||||
|
||||
class CounterManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct Counter {
|
||||
QString name;
|
||||
int count;
|
||||
|
||||
Counter() : count(0) {}
|
||||
Counter(const QString& n, int c = 0) : name(n), count(c) {}
|
||||
|
||||
bool operator==(const QString& otherName) const { return name == otherName; }
|
||||
};
|
||||
|
||||
explicit CounterManager(QObject *parent = nullptr);
|
||||
~CounterManager();
|
||||
|
||||
// Инициализация с базой данных
|
||||
bool initialize(uDataBase *database);
|
||||
|
||||
// Управление счетчиками
|
||||
bool addCounter(const QString &name, int initialValue = 0);
|
||||
bool removeCounter(const QString &name);
|
||||
bool updateCounter(const QString &oldName, const QString &newName, int newValue);
|
||||
bool incrementCounter(const QString &name, int step = 1);
|
||||
bool decrementCounter(const QString &name, int step = 1);
|
||||
int getCount(const QString &name) const;
|
||||
|
||||
// Обработка сообщения: увеличивает счётчики, чьи имена встречаются в тексте
|
||||
void processMessage(const QString &message);
|
||||
|
||||
// Получение всех счётчиков
|
||||
QVector<Counter> getAllCounters() const { return m_counters; }
|
||||
bool contains(const QString &name) const;
|
||||
|
||||
// Сохранение/загрузка в БД
|
||||
bool saveToDatabase();
|
||||
bool loadFromDatabase();
|
||||
|
||||
signals:
|
||||
void dataChanged();
|
||||
void counterAdded(const QString &name, int value);
|
||||
void counterRemoved(const QString &name);
|
||||
void counterUpdated(const QString &oldName, const QString &newName);
|
||||
void counterIncremented(const QString &name, int newValue);
|
||||
|
||||
private:
|
||||
uDataBase *m_database;
|
||||
QVector<Counter> m_counters;
|
||||
|
||||
int findIndex(const QString &name) const;
|
||||
};
|
||||
|
||||
#endif // COUNTERMANAGER_H
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QRegularExpression>
|
||||
#include <QSet>
|
||||
|
||||
// EmoteProvider implementation
|
||||
EmoteProvider::EmoteProvider(QObject *parent)
|
||||
@@ -416,3 +418,52 @@ void SevenTVProvider::parseCustomResponse(const QByteArray &data, const QString
|
||||
QString("Loaded %1 custom emotes for user %2").arg(m_emotes.size()).arg(userId),
|
||||
LOG_INFO);
|
||||
}
|
||||
|
||||
QString BTTVProvider::cleanMessage(const QString& message) const
|
||||
{
|
||||
if (m_emotes.isEmpty())
|
||||
return message;
|
||||
|
||||
// Собираем все коды эмоций в множество для быстрого поиска
|
||||
QSet<QString> codes;
|
||||
for (const BTTVEmote& emote : m_emotes) {
|
||||
codes.insert(emote.code);
|
||||
}
|
||||
|
||||
// Разбиваем сообщение на токены (слова и не-слова)
|
||||
QRegularExpression wordSplitter("(\\w+|[^\\w]+)");
|
||||
QRegularExpressionMatchIterator it = wordSplitter.globalMatch(message);
|
||||
QStringList parts;
|
||||
while (it.hasNext()) {
|
||||
QRegularExpressionMatch match = it.next();
|
||||
QString token = match.captured(0);
|
||||
// Если токен состоит только из букв/цифр и является кодом эмоции – пропускаем
|
||||
if (token[0].isLetterOrNumber() && codes.contains(token))
|
||||
continue;
|
||||
parts.append(token);
|
||||
}
|
||||
return parts.join("");
|
||||
}
|
||||
|
||||
QString SevenTVProvider::cleanMessage(const QString& message) const
|
||||
{
|
||||
if (m_emotes.isEmpty())
|
||||
return message;
|
||||
|
||||
QSet<QString> codes;
|
||||
for (const SevenTVEmote& emote : m_emotes) {
|
||||
codes.insert(emote.code);
|
||||
}
|
||||
|
||||
QRegularExpression wordSplitter("(\\w+|[^\\w]+)");
|
||||
QRegularExpressionMatchIterator it = wordSplitter.globalMatch(message);
|
||||
QStringList parts;
|
||||
while (it.hasNext()) {
|
||||
QRegularExpressionMatch match = it.next();
|
||||
QString token = match.captured(0);
|
||||
if (token[0].isLetterOrNumber() && codes.contains(token))
|
||||
continue;
|
||||
parts.append(token);
|
||||
}
|
||||
return parts.join("");
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public:
|
||||
virtual void fetchGlobal() = 0;
|
||||
virtual void fetchCustom(const QString &userId) = 0;
|
||||
virtual QString getEmoteUrl(const QString &emoteName) = 0;
|
||||
virtual QString cleanMessage(const QString& message) const = 0;
|
||||
|
||||
signals:
|
||||
void emotesLoaded();
|
||||
@@ -71,6 +72,7 @@ public:
|
||||
void fetchGlobal() override;
|
||||
void fetchCustom(const QString &userId) override;
|
||||
QString getEmoteUrl(const QString &emoteName) override;
|
||||
QString cleanMessage(const QString& message) const override;
|
||||
|
||||
private slots:
|
||||
void onGlobalReplyFinished(QNetworkReply *reply);
|
||||
@@ -95,6 +97,7 @@ public:
|
||||
void fetchGlobal() override;
|
||||
void fetchCustom(const QString &userId) override;
|
||||
QString getEmoteUrl(const QString &emoteName) override;
|
||||
QString cleanMessage(const QString& message) const override;
|
||||
|
||||
private slots:
|
||||
void onGlobalReplyFinished(QNetworkReply *reply);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
debug/commandprocessor.o
|
||||
debug/countermanager.o
|
||||
debug/emoteprovider.o
|
||||
debug/fcolorsetting.o
|
||||
debug/fcreatechat.o
|
||||
@@ -28,6 +29,7 @@ debug/webserverchat.o
|
||||
debug/webservernotify.o
|
||||
debug/websocketclient.o
|
||||
debug/moc_commandprocessor.o
|
||||
debug/moc_countermanager.o
|
||||
debug/moc_emoteprovider.o
|
||||
debug/moc_fcolorsetting.o
|
||||
debug/moc_fcreatechat.o
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
release/commandprocessor.o
|
||||
release/countermanager.o
|
||||
release/emoteprovider.o
|
||||
release/fcolorsetting.o
|
||||
release/fcreatechat.o
|
||||
@@ -28,6 +29,7 @@ release/webserverchat.o
|
||||
release/webservernotify.o
|
||||
release/websocketclient.o
|
||||
release/moc_commandprocessor.o
|
||||
release/moc_countermanager.o
|
||||
release/moc_emoteprovider.o
|
||||
release/moc_fcolorsetting.o
|
||||
release/moc_fcreatechat.o
|
||||
|
||||
+172
-8
@@ -407,6 +407,22 @@ void uGeneral::initializeManagers()
|
||||
ui->widget_3->setManagerType(FSingleGrid::TemplateManager);
|
||||
ui->widget_3->setDatabase(db);
|
||||
|
||||
m_counterManager = new CounterManager(this);
|
||||
if (db) {
|
||||
m_counterManager->initialize(db);
|
||||
}
|
||||
|
||||
// Настраиваем таблицу счётчиков (предполагаем, что она уже есть в .ui с objectName "sgCounters")
|
||||
setupCountersTable();
|
||||
|
||||
// Подключаем сигналы для обновления таблицы при изменениях
|
||||
connect(m_counterManager, &CounterManager::dataChanged, this, &uGeneral::updateCountersTable);
|
||||
connect(m_counterManager, &CounterManager::counterAdded, this, [this](const QString&, int) { updateCountersTable(); });
|
||||
connect(m_counterManager, &CounterManager::counterRemoved, this, [this](const QString&) { updateCountersTable(); });
|
||||
connect(m_counterManager, &CounterManager::counterUpdated, this, [this](const QString&, const QString&) { updateCountersTable(); });
|
||||
connect(m_counterManager, &CounterManager::counterIncremented, this, [this](const QString&, int) { updateCountersTable(); });
|
||||
|
||||
|
||||
m_commandProcessor = new CommandProcessor(this);
|
||||
|
||||
if (db) {
|
||||
@@ -428,9 +444,46 @@ void uGeneral::initializeManagers()
|
||||
context.mediaFileManager = m_SoundFiles;
|
||||
context.channel = ui->edtChannel->text();
|
||||
context.notifyVolume = ui->tbNotifyVolume->value();
|
||||
|
||||
context.counterManager = m_counterManager;
|
||||
m_commandProcessor->setContext(context);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uGeneral::setupCountersTable(){
|
||||
// Предполагаем, что sgCounters уже есть в ui
|
||||
ui->sgCounters->setColumnCount(2);
|
||||
QStringList headers;
|
||||
headers << "Счётчик" << "Значение";
|
||||
ui->sgCounters->setHorizontalHeaderLabels(headers);
|
||||
ui->sgCounters->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
ui->sgCounters->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
ui->sgCounters->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
ui->sgCounters->horizontalHeader()->setStretchLastSection(true);
|
||||
ui->sgCounters->setColumnWidth(0, 200);
|
||||
ui->sgCounters->setColumnWidth(1, 80);
|
||||
|
||||
updateCountersTable();
|
||||
}
|
||||
|
||||
void uGeneral::updateCountersTable()
|
||||
{
|
||||
|
||||
ui->sgCounters->setRowCount(0);
|
||||
ui->cbCounters->clear();
|
||||
if (!m_counterManager) return;
|
||||
|
||||
QVector<CounterManager::Counter> counters = m_counterManager->getAllCounters();
|
||||
for (const auto &c : counters) {
|
||||
int row = ui->sgCounters->rowCount();
|
||||
ui->sgCounters->insertRow(row);
|
||||
ui->sgCounters->setItem(row, 0, new QTableWidgetItem(c.name));
|
||||
ui->sgCounters->setItem(row, 1, new QTableWidgetItem(QString::number(c.count)));
|
||||
ui->cbCounters->addItem(c.name);
|
||||
}
|
||||
}
|
||||
|
||||
void uGeneral::loadCommandsFromTableWidget()
|
||||
@@ -742,6 +795,7 @@ uGeneral::~uGeneral()
|
||||
delete m_neuralTemplateManager;
|
||||
m_neuralTemplateManager = nullptr;
|
||||
}
|
||||
delete m_counterManager;
|
||||
delete m_createNotifyDialog;
|
||||
delete m_createChatDialog;
|
||||
delete ui;
|
||||
@@ -1740,7 +1794,8 @@ void uGeneral::initializeNotificationSounds()
|
||||
}
|
||||
}
|
||||
|
||||
void uGeneral::handleNewMessage(const QString &message){
|
||||
void uGeneral::handleNewMessage(const QString &message)
|
||||
{
|
||||
TwitchMessage msg = TwitchMessage::parse(message);
|
||||
|
||||
QString userId = m_userManager->checkUser(msg.displayName, msg);
|
||||
@@ -1754,8 +1809,30 @@ void uGeneral::handleNewMessage(const QString &message){
|
||||
|
||||
QString processedMessage = processTwitchMessage(msg);
|
||||
QString formattedNickname = formatNicknameWithBadges(msg);
|
||||
|
||||
addChatMessage(formattedNickname, processedMessage);
|
||||
if (m_counterManager) {
|
||||
m_counterManager->processMessage(msg.message); // или cleanedText
|
||||
}
|
||||
QString cleanedText = cleanMessageFromAllEmotes(msg.message);
|
||||
// Удаляем ссылки (опционально)
|
||||
cleanedText.remove(QRegularExpression("https?://\\S+"));
|
||||
cleanedText = cleanedText.trimmed();
|
||||
|
||||
// Проверяем наличие русских букв
|
||||
bool hasRussian = false;
|
||||
for (const QChar& ch : cleanedText) {
|
||||
if (ch.unicode() >= 0x0400 && ch.unicode() <= 0x04FF) {
|
||||
hasRussian = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasRussian && !cleanedText.isEmpty()) {
|
||||
// Здесь нужно вызвать перевод (например, через API)
|
||||
// sendToTranslate(cleanedText);
|
||||
LogManager::instance()->debug("uGeneral", "handleNewMessage",
|
||||
"Требуется перевод: " + cleanedText);
|
||||
}
|
||||
|
||||
if (msg.message.startsWith("!!!")) {
|
||||
QString cleanedMessage = msg.message.mid(3);
|
||||
@@ -1766,6 +1843,14 @@ void uGeneral::handleNewMessage(const QString &message){
|
||||
}
|
||||
}
|
||||
|
||||
QString uGeneral::cleanMessageFromAllEmotes(const QString& message) const
|
||||
{
|
||||
QString cleaned = message;
|
||||
cleaned = bttvProvider.cleanMessage(cleaned);
|
||||
cleaned = sevenTVProvider.cleanMessage(cleaned);
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
void uGeneral::processUserCommand(const QString &username, const QString &commandText)
|
||||
{
|
||||
if (!m_commandProcessor || !m_userManager) return;
|
||||
@@ -1972,11 +2057,6 @@ void uGeneral::disconnectFromTwitch()
|
||||
setTwitchConnected(false);
|
||||
}
|
||||
|
||||
void uGeneral::execCommand(const QString &sender, const QString &message)
|
||||
{
|
||||
LogManager::instance()->debug("uGeneral", "execCommand",
|
||||
QString("Обработка команды от %1: %2").arg(sender).arg(message));
|
||||
}
|
||||
|
||||
void uGeneral::on_lbRandomGroup_itemClicked(QListWidgetItem *item)
|
||||
{
|
||||
@@ -3026,3 +3106,87 @@ void uGeneral::on_btnRmWebService_clicked()
|
||||
.arg(serviceName));
|
||||
}
|
||||
}
|
||||
|
||||
void uGeneral::on_sgCounters_cellClicked(int row, int column)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
QString name = ui->sgCounters->item(row, 0)->text();
|
||||
int value = ui->sgCounters->item(row, 1)->text().toInt();
|
||||
ui->edtWordCounter->setText(name);
|
||||
ui->sbStartCounter->setValue(value);
|
||||
}
|
||||
|
||||
|
||||
void uGeneral::on_sgCounters_cellDoubleClicked(int row, int column)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uGeneral::on_btnCounterAdd_clicked()
|
||||
{
|
||||
QString name = ui->edtWordCounter->text().trimmed(); // предположим, есть поле ввода
|
||||
if (name.isEmpty()) {
|
||||
QMessageBox::warning(this, "Ошибка", "Введите название счётчика!");
|
||||
return;
|
||||
}
|
||||
|
||||
int initial = ui->sbStartCounter->value(); // спинбокс для начального значения
|
||||
if (m_counterManager->addCounter(name, initial)) {
|
||||
ui->edtWordCounter->clear();
|
||||
ui->sbStartCounter->setValue(0);
|
||||
updateCountersTable();
|
||||
} else {
|
||||
QMessageBox::warning(this, "Ошибка", "Не удалось добавить счётчик (возможно, уже существует)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uGeneral::on_btnCounterDelete_clicked()
|
||||
{
|
||||
int row = ui->sgCounters->currentRow();
|
||||
if (row < 0) {
|
||||
QMessageBox::warning(this, "Ошибка", "Выберите счётчик для удаления!");
|
||||
return;
|
||||
}
|
||||
|
||||
QString name = ui->sgCounters->item(row, 0)->text();
|
||||
if (m_counterManager->removeCounter(name)) {
|
||||
updateCountersTable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uGeneral::on_btnCounterEdit_clicked()
|
||||
{
|
||||
int row = ui->sgCounters->currentRow();
|
||||
if (row < 0) {
|
||||
QMessageBox::warning(this, "Ошибка", "Выберите счётчик для редактирования!");
|
||||
return;
|
||||
}
|
||||
|
||||
QString oldName = ui->sgCounters->item(row, 0)->text();
|
||||
QString newName = ui->edtWordCounter->text().trimmed();
|
||||
int newValue = ui->sbStartCounter->value();
|
||||
|
||||
if (newName.isEmpty()) {
|
||||
QMessageBox::warning(this, "Ошибка", "Введите новое название счётчика!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_counterManager->updateCounter(oldName, newName, newValue)) {
|
||||
ui->edtWordCounter->clear();
|
||||
ui->sbStartCounter->setValue(0);
|
||||
updateCountersTable();
|
||||
} else {
|
||||
QMessageBox::warning(this, "Ошибка", "Не удалось обновить счётчик");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uGeneral::on_btnCounterAtoText_clicked()
|
||||
{
|
||||
QTextCursor cursor = ui->textBrowser->textCursor();
|
||||
cursor.insertText("|)" + ui->cbCounters->currentText() + "|)");
|
||||
}
|
||||
|
||||
|
||||
+18
-7
@@ -10,6 +10,7 @@
|
||||
#include <udatabase.h>
|
||||
#include <soundmanager.h>
|
||||
#include "commandprocessor.h"
|
||||
#include "countermanager.h"
|
||||
#include "fcreatechat.h"
|
||||
#include "fcreatenotify.h"
|
||||
#include "logmanager.h"
|
||||
@@ -141,11 +142,6 @@ private slots:
|
||||
void handleConnected();
|
||||
void handleDisconnected();
|
||||
|
||||
// ========================================================================
|
||||
// СЛОТЫ ДЛЯ РАБОТЫ С КОМАНДАМИ И ОТВЕТАМИ
|
||||
// ========================================================================
|
||||
void execCommand(const QString &sender, const QString &message);
|
||||
|
||||
|
||||
// ========================================================================
|
||||
// СЛОТЫ ДЛЯ РАБОТЫ С ИСКУССТВЕННЫМ ИНТЕЛЛЕКТОМ
|
||||
@@ -346,6 +342,18 @@ private slots:
|
||||
|
||||
void on_btnRmWebService_clicked();
|
||||
|
||||
void on_sgCounters_cellClicked(int row, int column);
|
||||
|
||||
void on_sgCounters_cellDoubleClicked(int row, int column);
|
||||
|
||||
void on_btnCounterAdd_clicked();
|
||||
|
||||
void on_btnCounterDelete_clicked();
|
||||
|
||||
void on_btnCounterEdit_clicked();
|
||||
|
||||
void on_btnCounterAtoText_clicked();
|
||||
|
||||
public slots:
|
||||
// Установка статуса подключения к Twitch
|
||||
void setTwitchConnected(bool connected);
|
||||
@@ -363,6 +371,7 @@ private:
|
||||
uLink *fLinkForm; // Форма ссылок
|
||||
TTTVAuth *TTVAuth; // Данные авторизации Twitch
|
||||
UserManager *m_userManager; // Менеджер пользователей
|
||||
CounterManager *m_counterManager;
|
||||
CommandProcessor* m_commandProcessor; // Процессор команд
|
||||
WebSocketClient *m_twitchClient; // WebSocket клиент для Twitch
|
||||
UserWidget* m_userWidget; // Виджет пользователя
|
||||
@@ -405,8 +414,8 @@ private:
|
||||
int findNotificationServerRow(HttpServer *server);
|
||||
int findChatServerRow(HttpServerChat *server);
|
||||
QString generateServerId() const;
|
||||
|
||||
|
||||
void setupCountersTable();
|
||||
void updateCountersTable();
|
||||
// Текущие настройки для формы
|
||||
QVariantMap m_currentSettings;
|
||||
|
||||
@@ -481,6 +490,8 @@ private:
|
||||
void loadNeuralTemplatesFromTableWidget();
|
||||
void processUserCommand(const QString &username, const QString &commandText);
|
||||
void sendChatResponse(const QString &response);
|
||||
|
||||
QString cleanMessageFromAllEmotes(const QString& message) const;
|
||||
};
|
||||
|
||||
#endif // UGENERAL_H
|
||||
|
||||
+130
-1
@@ -42,7 +42,7 @@
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>6</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="tabsClosable">
|
||||
<bool>false</bool>
|
||||
@@ -974,6 +974,9 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="cbCounters"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -1416,6 +1419,11 @@
|
||||
<string>Автоматика</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_tab_auto">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<property name="title">
|
||||
@@ -1553,6 +1561,127 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_11">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTipDuration">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Счетчики</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_26">
|
||||
<item>
|
||||
<widget class="QTableWidget" name="sgCounters">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Слово или фраза</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Количество</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Слово:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="edtWordCounter"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>Количество:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="sbStartCounter"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_16">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnCounterAdd">
|
||||
<property name="text">
|
||||
<string>Добавить</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnCounterEdit">
|
||||
<property name="text">
|
||||
<string>Изменить</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnCounterDelete">
|
||||
<property name="text">
|
||||
<string>Удалить</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_10">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_auto">
|
||||
<property name="orientation">
|
||||
|
||||
Reference in New Issue
Block a user