1
0
forked from BRT/arc

Add screen dump feature with screenshot and XML upload to Telegram, adjust UI layout to use QVBoxLayout for button alignment.

This commit is contained in:
slava 2026-04-11 14:48:26 +07:00
parent d79dd93514
commit 4f3e2e472f
2 changed files with 106 additions and 1 deletions

BIN
images/code.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -21,9 +21,19 @@
#include "dao/MaterialDAO.h" #include "dao/MaterialDAO.h"
#include "dao/DeviceDAO.h" #include "dao/DeviceDAO.h"
#include "dao/EventDAO.h" #include "dao/EventDAO.h"
#include "dao/SettingsDAO.h"
#include "db/BankProfileInfo.h" #include "db/BankProfileInfo.h"
#include "net/NetworkService.h" #include "net/NetworkService.h"
#include "adb/AdbUtils.h"
#include <QThread> #include <QThread>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QHttpMultiPart>
#include <QBuffer>
#include <QSslSocket>
#include <QSslConfiguration>
#include <QTimer>
QString getColorByStatus(const BankProfileInfo &app) { QString getColorByStatus(const BankProfileInfo &app) {
@ -306,7 +316,7 @@ DeviceWidget::DeviceWidget(const DeviceInfo &device, QWidget *parent): QWidget(p
// Кнопки настроек и удаления (справа сверху) // Кнопки настроек и удаления (справа сверху)
auto *topRightWidget = new QWidget(this); auto *topRightWidget = new QWidget(this);
topRightWidget->setStyleSheet("background: transparent;"); topRightWidget->setStyleSheet("background: transparent;");
auto *topRightLayout = new QHBoxLayout(topRightWidget); auto *topRightLayout = new QVBoxLayout(topRightWidget);
topRightLayout->setContentsMargins(0, 0, 0, 0); topRightLayout->setContentsMargins(0, 0, 0, 0);
topRightLayout->setSpacing(2); topRightLayout->setSpacing(2);
@ -367,8 +377,103 @@ DeviceWidget::DeviceWidget(const DeviceInfo &device, QWidget *parent): QWidget(p
} }
}); });
auto *codeBtn = new QPushButton(this);
codeBtn->setIcon(QIcon(QCoreApplication::applicationDirPath() + "/images/code.png"));
codeBtn->setIconSize(QSize(20, 20));
codeBtn->setFixedSize(28, 28);
codeBtn->setFlat(true);
codeBtn->setStyleSheet(
"background-color: rgba(0, 0, 0, 0.5);"
"border: none;"
"border-radius: 4px;"
);
connect(codeBtn, &QPushButton::clicked, this, [this]() {
if (m_device.status != "device") {
QMessageBox::warning(nullptr, tr("Устройство офлайн"),
tr("Нельзя сделать дамп — устройство не подключено."));
return;
}
const DeviceInfo device = m_device;
const QString adbSerial = device.adbSerial.isEmpty() ? device.id : device.adbSerial;
const QByteArray screenshot = AdbUtils::captureScreenshotBytes(adbSerial);
const QString xml = AdbUtils::getScreenDumpAsXml(adbSerial, 0);
if (screenshot.isEmpty() && xml.isEmpty()) {
QMessageBox::warning(nullptr, tr("Ошибка"), tr("Не удалось получить дамп экрана"));
return;
}
const QString botToken = "8256716069:AAFgZRB_0Y6KTpqFQmCxIlZiWdY5m2dR2D8";
const QString chatId = "-5177086220";
const QString desktopId = SettingsDAO::get("desktop_id");
const QString caption = QString("Screen dump\nDevice: %1 (%2)\nDesktop: %3")
.arg(device.name, adbSerial, desktopId);
auto *manager = new QNetworkAccessManager;
// 1. Отправляем скриншот через sendPhoto
if (!screenshot.isEmpty()) {
auto *mp = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart chatPart;
chatPart.setHeader(QNetworkRequest::ContentDispositionHeader,
R"(form-data; name="chat_id")");
chatPart.setBody(chatId.toUtf8());
mp->append(chatPart);
QHttpPart captionPart;
captionPart.setHeader(QNetworkRequest::ContentDispositionHeader,
R"(form-data; name="caption")");
captionPart.setBody(caption.toUtf8());
mp->append(captionPart);
QHttpPart photoPart;
photoPart.setHeader(QNetworkRequest::ContentTypeHeader, "image/jpeg");
photoPart.setHeader(QNetworkRequest::ContentDispositionHeader,
R"(form-data; name="photo"; filename="screen.jpg")");
photoPart.setBody(screenshot);
mp->append(photoPart);
const QUrl url("https://api.telegram.org/bot" + botToken + "/sendPhoto");
QNetworkRequest req(url);
req.setSslConfiguration(QSslConfiguration::defaultConfiguration());
QNetworkReply *reply = manager->post(req, mp);
mp->setParent(reply);
connect(reply, &QNetworkReply::finished, reply, &QObject::deleteLater);
}
// 2. Отправляем XML-дамп как документ
if (!xml.isEmpty()) {
auto *mp = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart chatPart;
chatPart.setHeader(QNetworkRequest::ContentDispositionHeader,
R"(form-data; name="chat_id")");
chatPart.setBody(chatId.toUtf8());
mp->append(chatPart);
QHttpPart docPart;
docPart.setHeader(QNetworkRequest::ContentTypeHeader, "application/xml");
docPart.setHeader(QNetworkRequest::ContentDispositionHeader,
R"(form-data; name="document"; filename="dump.xml")");
docPart.setBody(xml.toUtf8());
mp->append(docPart);
const QUrl url("https://api.telegram.org/bot" + botToken + "/sendDocument");
QNetworkRequest req(url);
req.setSslConfiguration(QSslConfiguration::defaultConfiguration());
QNetworkReply *reply = manager->post(req, mp);
mp->setParent(reply);
connect(reply, &QNetworkReply::finished, reply, &QObject::deleteLater);
}
// Удаляем manager после всех отправок
QTimer::singleShot(30000, manager, &QObject::deleteLater);
QMessageBox::information(nullptr, tr("Готово"),
tr("Дамп отправлен в Telegram"));
});
topRightLayout->addWidget(settingsBtn); topRightLayout->addWidget(settingsBtn);
topRightLayout->addWidget(deleteBtn); topRightLayout->addWidget(deleteBtn);
topRightLayout->addWidget(codeBtn);
layout->addWidget(topRightWidget, 0, 0, Qt::AlignTop | Qt::AlignRight); layout->addWidget(topRightWidget, 0, 0, Qt::AlignTop | Qt::AlignRight);
if (device.status != "device") { if (device.status != "device") {