189 lines
7.0 KiB
C++
189 lines
7.0 KiB
C++
#include "GetProfileInfoScript.h"
|
||
|
||
#include <QJsonDocument>
|
||
#include <QJsonObject>
|
||
#include <QThread>
|
||
|
||
#include "adb/AdbUtils.h"
|
||
#include "dao/MaterialDAO.h"
|
||
#include "dao/BankProfileDAO.h"
|
||
#include "dao/DeviceDAO.h"
|
||
#include "dump/TaskDumpRecorder.h"
|
||
#include "net/NetworkService.h"
|
||
|
||
namespace Black {
|
||
|
||
GetProfileInfoScript::GetProfileInfoScript(
|
||
QString deviceId,
|
||
QString appCode,
|
||
QObject *parent
|
||
) : CommonScript(parent),
|
||
m_deviceId(std::move(deviceId)),
|
||
m_appCode(std::move(appCode)) {
|
||
}
|
||
|
||
GetProfileInfoScript::~GetProfileInfoScript() = default;
|
||
|
||
void GetProfileInfoScript::doStart() {
|
||
DeviceInfo device = DeviceDAO::getDeviceById(m_deviceId); if (device.id.isEmpty()) device = DeviceDAO::findByAdbSerial(m_deviceId); if (!device.adbSerial.isEmpty()) m_deviceId = device.adbSerial;
|
||
const BankProfileInfo app = BankProfileDAO::getApplication(device.id, m_appCode);
|
||
|
||
if (device.id.isEmpty() || app.id == -1) {
|
||
m_error = "Device or app not found: " + m_deviceId + " " + m_appCode;
|
||
qCritical() << m_error;
|
||
emit finishedWithResult(m_error);
|
||
return;
|
||
}
|
||
|
||
const TaskDumpMeta dumpMeta{};
|
||
TaskDumpRecorder::Scope dumpScope("black", "FETCH_PROFILE_INFO", m_deviceId, dumpMeta, &m_error);
|
||
|
||
// Читаем текущий экран
|
||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||
|
||
// Если не на домашнем экране — перезапускаем
|
||
if (!xmlScreenParser.isHomeScreen()) {
|
||
qDebug() << "[Black::GetProfileInfo] Not on home screen, restarting app...";
|
||
if (!runAppAndGoToHomeScreen(m_deviceId, app.package, app.pinCode,
|
||
device.screenWidth, device.screenHeight)) {
|
||
m_error = "Cannot reach home screen: " + device.name + " (" + m_deviceId + ") " + m_appCode;
|
||
qWarning() << m_error;
|
||
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||
emit finishedWithResult(m_error);
|
||
return;
|
||
}
|
||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||
}
|
||
|
||
// 1. Тапаем по кнопке "¡Hola!" (аватар с именем) на домашнем экране
|
||
Node holaNode = xmlScreenParser.findHolaButton();
|
||
if (holaNode.isEmpty()) {
|
||
m_error = "Cannot find Hola button on home screen: " + m_deviceId;
|
||
qWarning() << m_error;
|
||
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||
emit finishedWithResult(m_error);
|
||
return;
|
||
}
|
||
|
||
// Парсим имя и баланс с домашнего экрана
|
||
const QString fullName = xmlScreenParser.parseUserNameFromHomeScreen();
|
||
const double balance = xmlScreenParser.parseBalanceFromHomeScreen();
|
||
qDebug() << "[Black::GetProfileInfo] fullName from home:" << fullName << "balance:" << balance;
|
||
|
||
// Сохраняем баланс
|
||
BankProfileDAO::updateAmount(app.id, balance);
|
||
|
||
AdbUtils::makeTap(m_deviceId, holaNode.x(), holaNode.y());
|
||
QThread::msleep(2000);
|
||
|
||
// 2. Ждём боковое меню
|
||
bool sideMenuFound = false;
|
||
for (int attempt = 0; attempt < 5; ++attempt) {
|
||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||
if (xmlScreenParser.isSideMenu()) {
|
||
sideMenuFound = true;
|
||
break;
|
||
}
|
||
QThread::msleep(1000);
|
||
}
|
||
|
||
if (!sideMenuFound) {
|
||
m_error = "Side menu not detected: " + m_deviceId;
|
||
qWarning() << m_error;
|
||
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||
emit finishedWithResult(m_error);
|
||
return;
|
||
}
|
||
|
||
// 3. Тапаем "Tu Información"
|
||
Node tuInfoNode = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Tu Información"));
|
||
if (tuInfoNode.isEmpty()) {
|
||
m_error = "Cannot find Tu Información button: " + m_deviceId;
|
||
qWarning() << m_error;
|
||
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||
emit finishedWithResult(m_error);
|
||
return;
|
||
}
|
||
|
||
AdbUtils::makeTap(m_deviceId, tuInfoNode.x(), tuInfoNode.y());
|
||
QThread::msleep(2500);
|
||
|
||
// 4. Ждём страницу профиля "Tu información"
|
||
bool profileFound = false;
|
||
for (int attempt = 0; attempt < 5; ++attempt) {
|
||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||
if (xmlScreenParser.isProfilePage()) {
|
||
profileFound = true;
|
||
break;
|
||
}
|
||
QThread::msleep(1000);
|
||
}
|
||
|
||
if (!profileFound) {
|
||
m_error = "Profile page not detected: " + m_deviceId;
|
||
qWarning() << m_error;
|
||
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||
emit finishedWithResult(m_error);
|
||
return;
|
||
}
|
||
|
||
// 5. Парсим данные профиля (первый экран: nombre, apellido, email)
|
||
const QString nombre = xmlScreenParser.parseProfileNombre();
|
||
const QString apellido = xmlScreenParser.parseProfileApellido();
|
||
const QString email = xmlScreenParser.parseProfileEmail();
|
||
|
||
// 6. Скроллим вниз чтобы увидеть телефон
|
||
const int x = device.screenWidth / 2;
|
||
const int fromY = device.screenHeight * 3 / 4;
|
||
const int toY = device.screenHeight / 4;
|
||
AdbUtils::makeSwipe(m_deviceId, x, fromY, x, toY);
|
||
QThread::msleep(1500);
|
||
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||
|
||
const QString phone = xmlScreenParser.parseProfilePhone();
|
||
|
||
// Собираем полное имя: "имя фамилия"
|
||
QString parsedFullName;
|
||
if (!nombre.isEmpty() && !apellido.isEmpty()) {
|
||
parsedFullName = nombre + " " + apellido;
|
||
} else if (!nombre.isEmpty()) {
|
||
parsedFullName = nombre;
|
||
} else {
|
||
parsedFullName = fullName; // fallback с домашнего экрана
|
||
}
|
||
|
||
qDebug() << "[Black::GetProfileInfo] nombre:" << nombre
|
||
<< "apellido:" << apellido
|
||
<< "email:" << email
|
||
<< "phone:" << phone
|
||
<< "fullName:" << parsedFullName;
|
||
|
||
// 7. Сохраняем в БД
|
||
if (!BankProfileDAO::updateProfileInfo(app.id, parsedFullName, phone, email)) {
|
||
qWarning() << "[Black::GetProfileInfo] Failed to save profile info to DB";
|
||
}
|
||
|
||
// 7. Создаём bank profile если нет
|
||
if (const QString err = createBankProfileIfNeeded(m_deviceId, m_appCode); !err.isEmpty()) {
|
||
m_error = err;
|
||
emit finishedWithResult(m_error);
|
||
return;
|
||
}
|
||
|
||
// 8. Отправляем данные аккаунтов на сервер если нет material_id
|
||
const QList<MaterialInfo> allAccounts = MaterialDAO::getAccounts(device.id, m_appCode);
|
||
QList<QPair<MaterialInfo, Node>> accountsToPost;
|
||
for (const auto &acc : allAccounts) {
|
||
if (acc.materialId.isEmpty()) {
|
||
accountsToPost.append({acc, Node()});
|
||
}
|
||
}
|
||
if (!accountsToPost.isEmpty()) {
|
||
postAccountsData(accountsToPost);
|
||
}
|
||
|
||
emit finishedWithResult(m_error);
|
||
}
|
||
|
||
} // namespace Black
|