Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1d3131ea8c | |||
| 47c0c7ed85 |
@@ -87,7 +87,13 @@ void TAuth::handleNewConnection()
|
|||||||
connect(m_clientSocket, &QTcpSocket::readyRead,
|
connect(m_clientSocket, &QTcpSocket::readyRead,
|
||||||
this, &TAuth::readClientData);
|
this, &TAuth::readClientData);
|
||||||
connect(m_clientSocket, &QTcpSocket::disconnected,
|
connect(m_clientSocket, &QTcpSocket::disconnected,
|
||||||
m_clientSocket, &QTcpSocket::deleteLater);
|
this, [this]() {
|
||||||
|
// Удаляем сокет после отключения
|
||||||
|
if (m_clientSocket) {
|
||||||
|
m_clientSocket->deleteLater();
|
||||||
|
m_clientSocket = nullptr;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +104,6 @@ void TAuth::readClientData()
|
|||||||
QByteArray requestData = m_clientSocket->readAll();
|
QByteArray requestData = m_clientSocket->readAll();
|
||||||
QString request = QString::fromUtf8(requestData);
|
QString request = QString::fromUtf8(requestData);
|
||||||
|
|
||||||
|
|
||||||
QStringList lines = request.split("\r\n");
|
QStringList lines = request.split("\r\n");
|
||||||
if (lines.isEmpty()) return;
|
if (lines.isEmpty()) return;
|
||||||
|
|
||||||
@@ -118,7 +123,6 @@ void TAuth::readClientData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Обрабатываем обычный redirect
|
// Обрабатываем обычный redirect
|
||||||
if (document.startsWith("/redirect")) {
|
if (document.startsWith("/redirect")) {
|
||||||
handleRedirectRequest(document, m_clientSocket);
|
handleRedirectRequest(document, m_clientSocket);
|
||||||
@@ -237,6 +241,13 @@ void TAuth::handleRedirectRequest(const QString &request, QTcpSocket *socket)
|
|||||||
"<h2>Authorization Successful!</h2>\n"
|
"<h2>Authorization Successful!</h2>\n"
|
||||||
"<p>Token received. You can close this window.</p>\n"
|
"<p>Token received. You can close this window.</p>\n"
|
||||||
"</body>\n</html>";
|
"</body>\n</html>";
|
||||||
|
|
||||||
|
// Отправляем ответ клиенту
|
||||||
|
sendResponse(socket, html);
|
||||||
|
|
||||||
|
// Останавливаем сервер СРАЗУ
|
||||||
|
QTimer::singleShot(100, this, &TAuth::stopServer);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// Проверяем наличие error_description
|
// Проверяем наличие error_description
|
||||||
else if (params.contains("error_description=")) {
|
else if (params.contains("error_description=")) {
|
||||||
@@ -260,6 +271,13 @@ void TAuth::handleRedirectRequest(const QString &request, QTcpSocket *socket)
|
|||||||
"<h2>Authorization Successful!</h2>\n"
|
"<h2>Authorization Successful!</h2>\n"
|
||||||
"<p>Code received. You can close this window.</p>\n"
|
"<p>Code received. You can close this window.</p>\n"
|
||||||
"</body>\n</html>";
|
"</body>\n</html>";
|
||||||
|
|
||||||
|
// Отправляем ответ клиенту
|
||||||
|
sendResponse(socket, html);
|
||||||
|
|
||||||
|
// Останавливаем сервер СРАЗУ
|
||||||
|
QTimer::singleShot(100, this, &TAuth::stopServer);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
html =
|
html =
|
||||||
@@ -269,13 +287,16 @@ void TAuth::handleRedirectRequest(const QString &request, QTcpSocket *socket)
|
|||||||
"<p>Try again or check your authorization URL.</p>\n"
|
"<p>Try again or check your authorization URL.</p>\n"
|
||||||
"</body>\n</html>";
|
"</body>\n</html>";
|
||||||
sendResponse(socket, html);
|
sendResponse(socket, html);
|
||||||
|
|
||||||
|
// Останавливаем сервер через 5 секунд если нет данных
|
||||||
|
QTimer::singleShot(5000, this, &TAuth::stopServer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendResponse(socket, html);
|
sendResponse(socket, html);
|
||||||
|
|
||||||
// Останавливаем сервер после обработки
|
// Останавливаем сервер через 5 секунд для других случаев
|
||||||
QTimer::singleShot(1000, this, &TAuth::stopServer);
|
QTimer::singleShot(5000, this, &TAuth::stopServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TAuth::extractParam(const QString ¶ms, const QString ¶mName)
|
QString TAuth::extractParam(const QString ¶ms, const QString ¶mName)
|
||||||
|
|||||||
+101
@@ -591,3 +591,104 @@ void TTwAPI::parseBadgesFromApi(const QString &jsonString, QVector<ChatBadge> &b
|
|||||||
badges.append(badge);
|
badges.append(badge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TTwAPI::validateTwitchToken(const QString &tokenName,
|
||||||
|
const QString &tokenValue,
|
||||||
|
int &daysValid)
|
||||||
|
{
|
||||||
|
daysValid = 0;
|
||||||
|
|
||||||
|
if (tokenValue.trimmed().isEmpty()) {
|
||||||
|
toLog(1, "TTwAPI::validateTwitchToken", "Пустой токен: " + tokenName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl url("https://id.twitch.tv/oauth2/validate");
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
|
||||||
|
// Устанавливаем заголовки
|
||||||
|
request.setHeader(QNetworkRequest::UserAgentHeader, "YourApp/1.0");
|
||||||
|
request.setRawHeader("Accept", "application/json");
|
||||||
|
|
||||||
|
// Формируем заголовок Authorization
|
||||||
|
QString authHeader = "OAuth " + tokenValue;
|
||||||
|
request.setRawHeader("Authorization", authHeader.toUtf8());
|
||||||
|
|
||||||
|
// Отправляем GET запрос
|
||||||
|
QNetworkReply *reply = m_networkManager->get(request);
|
||||||
|
|
||||||
|
if (!reply) {
|
||||||
|
toLog(2, "TTwAPI::validateTwitchToken", "Не удалось создать запрос для токена: " + tokenName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ожидание завершения запроса
|
||||||
|
QEventLoop loop;
|
||||||
|
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||||
|
loop.exec();
|
||||||
|
|
||||||
|
// Проверяем статус ответа
|
||||||
|
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
QByteArray responseData = reply->readAll();
|
||||||
|
QString responseText = QString::fromUtf8(responseData);
|
||||||
|
|
||||||
|
// Обрабатываем ошибки сети
|
||||||
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
QString errorMsg = QString("Ошибка сети: %1 - %2")
|
||||||
|
.arg(reply->error())
|
||||||
|
.arg(reply->errorString());
|
||||||
|
toLog(2, "TTwAPI::validateTwitchToken", errorMsg);
|
||||||
|
reply->deleteLater();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
// Обработка HTTP статусов
|
||||||
|
if (statusCode == 200) {
|
||||||
|
// Успешная валидация
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(responseData);
|
||||||
|
if (!doc.isObject()) {
|
||||||
|
toLog(2, "TTwAPI::validateTwitchToken", "Ошибка парсинга JSON для токена: " + tokenName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject jsonObj = doc.object();
|
||||||
|
|
||||||
|
// Извлекаем expires_in (в секундах)
|
||||||
|
if (jsonObj.contains("expires_in") && jsonObj["expires_in"].isDouble()) {
|
||||||
|
int expiresInSeconds = jsonObj["expires_in"].toInt();
|
||||||
|
daysValid = qRound(expiresInSeconds / 86400.0); // Конвертируем секунды в дни
|
||||||
|
|
||||||
|
// Логируем информацию о токене
|
||||||
|
QString logMsg = QString("Токен '%1' действителен. Осталось: %2 дней. "
|
||||||
|
"Client ID: %3, Логин: %4")
|
||||||
|
.arg(tokenName)
|
||||||
|
.arg(daysValid)
|
||||||
|
.arg(jsonObj.value("client_id").toString("N/A"))
|
||||||
|
.arg(jsonObj.value("login").toString("N/A"));
|
||||||
|
toLog(0, "TTwAPI::validateTwitchToken", logMsg);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
toLog(2, "TTwAPI::validateTwitchToken",
|
||||||
|
QString("В ответе отсутствует expires_in для токена: %1").arg(tokenName));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (statusCode == 401) {
|
||||||
|
// Невалидный токен
|
||||||
|
toLog(2, "TTwAPI::validateTwitchToken",
|
||||||
|
QString("Токен '%1' невалиден (HTTP 401)").arg(tokenName));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Другие HTTP ошибки
|
||||||
|
QString errorMsg = QString("HTTP %1 для токена '%2': %3")
|
||||||
|
.arg(statusCode)
|
||||||
|
.arg(tokenName)
|
||||||
|
.arg(responseText);
|
||||||
|
toLog(2, "TTwAPI::validateTwitchToken", errorMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+162
-12
@@ -1584,7 +1584,7 @@ void uGeneral::on_btnGetTockenBot_clicked()
|
|||||||
fLinkForm = new uLink(this);
|
fLinkForm = new uLink(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Устанавливаем ссылку в окно (предполагается, что в uLink есть метод setLink)
|
// Устанавливаем ссылку в окно
|
||||||
fLinkForm->setLinkText(authUrl);
|
fLinkForm->setLinkText(authUrl);
|
||||||
fLinkForm->show();
|
fLinkForm->show();
|
||||||
|
|
||||||
@@ -1604,7 +1604,6 @@ void uGeneral::on_btnOpenFolderSettings_clicked()
|
|||||||
void uGeneral::on_btnGetTokenStreamer_clicked()
|
void uGeneral::on_btnGetTokenStreamer_clicked()
|
||||||
{
|
{
|
||||||
|
|
||||||
//ykui0quht3tvr06vfqhdj5idmhginn
|
|
||||||
QString clientId = ui->edtBotClientID->text();
|
QString clientId = ui->edtBotClientID->text();
|
||||||
if (clientId.isEmpty()) {
|
if (clientId.isEmpty()) {
|
||||||
QMessageBox::warning(this, "Ошибка", "Введите Client ID");
|
QMessageBox::warning(this, "Ошибка", "Введите Client ID");
|
||||||
@@ -1630,24 +1629,36 @@ void uGeneral::on_btnGetTokenStreamer_clicked()
|
|||||||
// Запускаем сервер с открытием браузера (true)
|
// Запускаем сервер с открытием браузера (true)
|
||||||
m_authStreamer->startServer(authUrl, true);
|
m_authStreamer->startServer(authUrl, true);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обработчик получения токена
|
// Обработчик получения токена
|
||||||
void uGeneral::onTokenReceived(const QString &token)
|
void uGeneral::onTokenReceived(const QString &token)
|
||||||
{
|
{
|
||||||
ui->edtBotToken->setText(token);
|
ui->edtBotToken->setText(token);
|
||||||
|
|
||||||
|
// Закрываем окно с ссылкой, если оно открыто
|
||||||
|
if (fLinkForm && fLinkForm->isVisible()) {
|
||||||
|
fLinkForm->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сохраняем настройки
|
||||||
|
db->writeSetting(ui->edtBotToken->objectName(), ui->edtBotToken->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
void uGeneral::onTokenReceived2(const QString &token)
|
void uGeneral::onTokenReceived2(const QString &token)
|
||||||
{
|
{
|
||||||
ui->edtBotTokenStreamer->setText(token);
|
ui->edtBotTokenStreamer->setText(token);
|
||||||
fLinkForm->close();
|
|
||||||
|
// Сохраняем настройки
|
||||||
|
db->writeSetting(ui->edtBotTokenStreamer->objectName(), ui->edtBotTokenStreamer->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
void uGeneral::onTokenReceived3(const QString &token)
|
void uGeneral::onTokenReceived3(const QString &token)
|
||||||
{
|
{
|
||||||
ui->edtDACode->setText(token);
|
ui->edtDACode->setText(token);
|
||||||
|
|
||||||
|
// Сохраняем настройки
|
||||||
|
db->writeSetting(ui->edtDACode->objectName(), ui->edtDACode->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
void uGeneral::onAuthError(const QString &error)
|
void uGeneral::onAuthError(const QString &error)
|
||||||
@@ -2199,22 +2210,59 @@ QString uGeneral::replaceCustomEmotes(const QString &message)
|
|||||||
|
|
||||||
void uGeneral::on_pushButton_2_clicked()
|
void uGeneral::on_pushButton_2_clicked()
|
||||||
{
|
{
|
||||||
if (ui->pushButton_2->text() != "Отключиться")
|
// Если кнопка в состоянии "Отключиться"
|
||||||
|
if (ui->pushButton_2->text() == "Отключиться")
|
||||||
{
|
{
|
||||||
QString oauthToken = "oauth:" + ui->edtBotToken->text();
|
disconnectFromTwitch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Попытка подключения
|
||||||
|
connectToTwitch();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uGeneral::connectToTwitch()
|
||||||
|
{
|
||||||
|
int botTokenDays = 0;
|
||||||
|
int streamerTokenDays = 0;
|
||||||
|
|
||||||
|
QString botToken = ui->edtBotToken->text();
|
||||||
|
QString streamerToken = ui->edtBotTokenStreamer->text();
|
||||||
|
|
||||||
|
// Проверка токенов
|
||||||
|
if (!twitchAPI->validateTwitchToken("Бот", botToken, botTokenDays))
|
||||||
|
{
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!twitchAPI->validateTwitchToken("Стример", streamerToken, streamerTokenDays))
|
||||||
|
{
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Подключение к чату Twitch
|
||||||
|
QString oauthToken = "oauth:" + botToken;
|
||||||
QString nickname = ui->edtBotName->text();
|
QString nickname = ui->edtBotName->text();
|
||||||
QString channel = ui->edtChannel->text();
|
QString channel = ui->edtChannel->text();
|
||||||
m_twitchClient->connectToTwitchChat(oauthToken, nickname, channel);
|
|
||||||
ui->pushButton_2->setText("Отключиться");
|
if (m_twitchClient->connectToTwitchChat(oauthToken, nickname, channel))
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
// Успешное подключение
|
||||||
|
ui->pushButton_2->setText("Отключиться");
|
||||||
|
ui->lbBotDays->setText(QString::number(botTokenDays));
|
||||||
|
ui->lbStreamerDays->setText(QString::number(streamerTokenDays));
|
||||||
|
setTwitchConnected(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uGeneral::disconnectFromTwitch()
|
||||||
|
{
|
||||||
m_twitchClient->disconnectFromServer();
|
m_twitchClient->disconnectFromServer();
|
||||||
m_userManager->clear();
|
m_userManager->clear();
|
||||||
ui->pushButton_2->setText("Подключиться");
|
ui->pushButton_2->setText("Подключиться");
|
||||||
setTwitchConnected(false);
|
setTwitchConnected(false);
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -3372,3 +3420,105 @@ void uGeneral::on_btnAUserName_clicked()
|
|||||||
cursor.insertText("[USERNAME]");
|
cursor.insertText("[USERNAME]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void uGeneral::on_btnRmWebService_clicked()
|
||||||
|
{
|
||||||
|
// Проверяем, выбрана ли строка в таблице
|
||||||
|
int currentRow = ui->sgWebServers->currentRow();
|
||||||
|
if (currentRow < 0) {
|
||||||
|
QMessageBox::warning(this, "Ошибка", "Выберите веб-сервис для удаления!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем данные из таблицы
|
||||||
|
QTableWidgetItem *nameItem = ui->sgWebServers->item(currentRow, 0);
|
||||||
|
QTableWidgetItem *typeItem = ui->sgWebServers->item(currentRow, 1);
|
||||||
|
QTableWidgetItem *portItem = ui->sgWebServers->item(currentRow, 2);
|
||||||
|
|
||||||
|
if (!nameItem || !typeItem || !portItem) {
|
||||||
|
QMessageBox::warning(this, "Ошибка", "Не удалось получить данные о сервисе!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString serviceName = nameItem->text();
|
||||||
|
QString serviceType = typeItem->text();
|
||||||
|
quint16 port = portItem->text().toUShort();
|
||||||
|
|
||||||
|
// Подтверждение удаления
|
||||||
|
int result = QMessageBox::question(this, "Подтверждение удаления",
|
||||||
|
QString("Вы уверены, что хотите удалить сервис '%1'?\n"
|
||||||
|
"Тип: %2\n"
|
||||||
|
"Порт: %3").arg(serviceName, serviceType, QString::number(port)),
|
||||||
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
|
if (result != QMessageBox::Yes) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем объект сервера из userData
|
||||||
|
QObject *serverObj = nameItem->data(Qt::UserRole).value<QObject*>();
|
||||||
|
|
||||||
|
bool deletedFromDB = false;
|
||||||
|
|
||||||
|
// Удаляем сервер в зависимости от типа
|
||||||
|
if (serviceType.toLower() == "чат" || serviceType.toLower() == "chat") {
|
||||||
|
// Обрабатываем чат-сервер
|
||||||
|
HttpServerChat *chatServer = qobject_cast<HttpServerChat*>(serverObj);
|
||||||
|
if (chatServer) {
|
||||||
|
// Останавливаем сервер
|
||||||
|
chatServer->stop();
|
||||||
|
|
||||||
|
// Удаляем из списка
|
||||||
|
int chatIndex = m_chatServers.indexOf(chatServer);
|
||||||
|
if (chatIndex >= 0) {
|
||||||
|
m_chatServers.removeAt(chatIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удаляем из базы данных
|
||||||
|
deletedFromDB = db->deleteChat(port);
|
||||||
|
|
||||||
|
// Удаляем объект
|
||||||
|
delete chatServer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (serviceType.toLower() == "уведомления" || serviceType.toLower() == "notification") {
|
||||||
|
// Обрабатываем сервер уведомлений
|
||||||
|
HttpServer *notifyServer = qobject_cast<HttpServer*>(serverObj);
|
||||||
|
if (notifyServer) {
|
||||||
|
// Останавливаем сервер
|
||||||
|
notifyServer->stop();
|
||||||
|
|
||||||
|
// Удаляем из списка
|
||||||
|
int notifyIndex = m_notificationServers.indexOf(notifyServer);
|
||||||
|
if (notifyIndex >= 0) {
|
||||||
|
m_notificationServers.removeAt(notifyIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удаляем из базы данных
|
||||||
|
deletedFromDB = db->deleteNotification(port);
|
||||||
|
|
||||||
|
// Удаляем объект
|
||||||
|
delete notifyServer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удаляем строку из таблицы
|
||||||
|
ui->sgWebServers->removeRow(currentRow);
|
||||||
|
|
||||||
|
// Логируем результат
|
||||||
|
if (deletedFromDB) {
|
||||||
|
LogManager::instance()->info("uGeneral", "on_btnRmWebService_clicked",
|
||||||
|
QString("Удален веб-сервис: %1 (тип: %2, порт: %3)")
|
||||||
|
.arg(serviceName, serviceType, QString::number(port)));
|
||||||
|
QMessageBox::information(this, "Успех",
|
||||||
|
QString("Сервис '%1' успешно удален!").arg(serviceName));
|
||||||
|
} else {
|
||||||
|
LogManager::instance()->warning("uGeneral", "on_btnRmWebService_clicked",
|
||||||
|
QString("Сервис удален из интерфейса, но возникли проблемы с БД: %1")
|
||||||
|
.arg(serviceName));
|
||||||
|
QMessageBox::warning(this, "Внимание",
|
||||||
|
QString("Сервис '%1' удален из интерфейса, но не удалось удалить его из базы данных!")
|
||||||
|
.arg(serviceName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -344,6 +344,8 @@ private slots:
|
|||||||
|
|
||||||
void on_btnAUserName_clicked();
|
void on_btnAUserName_clicked();
|
||||||
|
|
||||||
|
void on_btnRmWebService_clicked();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
// Установка статуса подключения к Twitch
|
// Установка статуса подключения к Twitch
|
||||||
void setTwitchConnected(bool connected);
|
void setTwitchConnected(bool connected);
|
||||||
@@ -464,7 +466,8 @@ private:
|
|||||||
// Загрузка эмодзи
|
// Загрузка эмодзи
|
||||||
void loadEmoties();
|
void loadEmoties();
|
||||||
void loadChatBadges();
|
void loadChatBadges();
|
||||||
|
void disconnectFromTwitch();
|
||||||
|
void connectToTwitch();
|
||||||
/**
|
/**
|
||||||
* @brief Инициализирует звуковые уведомления
|
* @brief Инициализирует звуковые уведомления
|
||||||
*/
|
*/
|
||||||
|
|||||||
+54
-1
@@ -36,7 +36,7 @@
|
|||||||
<enum>Qt::LeftToRight</enum>
|
<enum>Qt::LeftToRight</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>2</number>
|
<number>4</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="tabsClosable">
|
<property name="tabsClosable">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@@ -1273,6 +1273,19 @@
|
|||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btnRmWebService">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>350</y>
|
||||||
|
<width>101</width>
|
||||||
|
<height>24</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Удалить</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_6">
|
<widget class="QWidget" name="tab_6">
|
||||||
<property name="icon" stdset="0">
|
<property name="icon" stdset="0">
|
||||||
@@ -1833,6 +1846,46 @@
|
|||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="gridLayoutWidget_3">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>770</x>
|
||||||
|
<y>730</y>
|
||||||
|
<width>231</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_23">
|
||||||
|
<property name="text">
|
||||||
|
<string>Осталось дней токена стримера</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_22">
|
||||||
|
<property name="text">
|
||||||
|
<string>Осталось дней токена бота</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="lbBotDays">
|
||||||
|
<property name="text">
|
||||||
|
<string>0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="lbStreamerDays">
|
||||||
|
<property name="text">
|
||||||
|
<string>0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="statusbar"/>
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
|||||||
+2
-2
@@ -54,7 +54,7 @@ bool WebSocketClient::connectToServer(const QString &url)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketClient::connectToTwitchChat(const QString &oauthToken,
|
bool WebSocketClient::connectToTwitchChat(const QString &oauthToken,
|
||||||
const QString &nickname,
|
const QString &nickname,
|
||||||
const QString &channel)
|
const QString &channel)
|
||||||
{
|
{
|
||||||
@@ -65,7 +65,7 @@ void WebSocketClient::connectToTwitchChat(const QString &oauthToken,
|
|||||||
// URL для подключения к Twitch IRC через WebSocket
|
// URL для подключения к Twitch IRC через WebSocket
|
||||||
QString url = "wss://irc-ws.chat.twitch.tv:443";
|
QString url = "wss://irc-ws.chat.twitch.tv:443";
|
||||||
|
|
||||||
connectToServer(url);
|
return connectToServer(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketClient::onConnectedInternal()
|
void WebSocketClient::onConnectedInternal()
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ public:
|
|||||||
Q_INVOKABLE bool isConnected() const;
|
Q_INVOKABLE bool isConnected() const;
|
||||||
|
|
||||||
// Методы для Twitch чата
|
// Методы для Twitch чата
|
||||||
Q_INVOKABLE void connectToTwitchChat(const QString &oauthToken, const QString &nickname, const QString &channel);
|
Q_INVOKABLE bool connectToTwitchChat(const QString &oauthToken, const QString &nickname, const QString &channel);
|
||||||
Q_INVOKABLE void joinChannel(const QString &channel);
|
Q_INVOKABLE void joinChannel(const QString &channel);
|
||||||
Q_INVOKABLE void sendChatMessage(const QString &channel, const QString &message);
|
Q_INVOKABLE void sendChatMessage(const QString &channel, const QString &message);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user