#include "GetProfileInfoScript.h" #include #include #include #include #include #include #include "adb/AdbUtils.h" #include "dao/MaterialDAO.h" #include "dao/BankProfileDAO.h" #include "dao/DeviceDAO.h" #include "net/NetworkService.h" #include "AppLogger.h" namespace Ozon { 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; } // Читаем текущий экран xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); // Закрываем рекламный bottom sheet, если открыт (home_ad_1) if (Node adNode = xmlScreenParser.tryToFindAdBanner(); !adNode.isEmpty()) { qDebug() << "[GetProfileInfo] Ad banner detected, closing..."; AdbUtils::makeTap(m_deviceId, adNode.x(), adNode.y()); QThread::msleep(1000); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); } // Свежий дамп перед проверкой домашнего экрана xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); // Если мы не на домашнем экране — перезапускаем приложение и вводим пин-код if (!xmlScreenParser.isHomeScreen()) { qDebug() << "[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: " + m_deviceId + " " + m_appCode; qWarning() << m_error; AdbUtils::tryToKillApplication(m_deviceId, app.package); emit finishedWithResult(m_error); return; } // После runAppAndGoToHomeScreen xml уже обновлён внутри метода, // но делаем свежий дамп, чтобы убедиться xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); } // Закрываем баннеры на главной, если есть tryToCloseAllBannersOnHomePage(m_deviceId, device.screenWidth, device.screenHeight); QThread::msleep(500); xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); // Находим имя пользователя в верхней части домашнего экрана и тапаем по нему Node userNameNode = xmlScreenParser.findUserNameOnHomeScreen(device.screenHeight); if (userNameNode.isEmpty()) { m_error = "Cannot find user name on home screen: " + m_deviceId; qWarning() << m_error; AdbUtils::tryToKillApplication(m_deviceId, app.package); emit finishedWithResult(m_error); return; } qDebug() << "[GetProfileInfo] Tapping on user name:" << userNameNode.text << "at" << userNameNode.x() << userNameNode.y(); AdbUtils::makeTap(m_deviceId, userNameNode.x(), userNameNode.y()); // Ждём загрузки страницы профиля QThread::msleep(2500); // Читаем XML профиля и проверяем что мы действительно там for (int attempt = 0; attempt < 5; ++attempt) { xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); if (xmlScreenParser.isProfileScreen()) { break; } QThread::msleep(1000); } if (!xmlScreenParser.isProfileScreen()) { m_error = "Profile screen not detected after tap: " + m_deviceId; qWarning() << m_error; AdbUtils::tryToKillApplication(m_deviceId, app.package); emit finishedWithResult(m_error); return; } // Извлекаем полное имя и телефон const QString fullName = xmlScreenParser.parseProfileFullName(); QString phone = xmlScreenParser.parseProfilePhone(); phone.remove(QRegularExpression(R"(\s+)")); // убираем все виды пробелов (включая \u00A0) qDebug() << "[GetProfileInfo] fullName:" << fullName << "phone:" << phone; if (!BankProfileDAO::updateProfileInfo(app.id, fullName, phone)) { m_error = "Failed to save profile info to DB: " + m_deviceId; qWarning() << m_error; } // Отправляем bank_profile на сервер const BankProfileInfo freshApp = BankProfileDAO::getApplication(device.id, m_appCode); const QMap currencyCodes = { {"RUB", 643}, {"USD", 840}, {"KRW", 410}, {"AZN", 944}, {"ARS", 32} }; const int currencyCode = currencyCodes.value(freshApp.currency.toUpper(), 643); const QStringList parts = fullName.split(' ', Qt::SkipEmptyParts); QJsonObject profileBody; profileBody["first_name"] = parts.value(0); profileBody["middle_name"] = parts.size() >= 3 ? parts.value(1) : ""; profileBody["last_name"] = parts.size() >= 3 ? parts.value(2) : parts.value(1); profileBody["bank_name"] = m_appCode; profileBody["phone_number"] = phone; profileBody["balance"] = QString::number(qRound64(freshApp.amount * 100)); profileBody["state"] = (freshApp.status == "active") ? "enabled" : "disabled"; profileBody["device_id"] = device.apiId; profileBody["currency"] = currencyCode; NetworkService ns; ns.setDeviceId(m_deviceId); ns.setPayload(QJsonDocument(profileBody).toJson()); if (freshApp.bankProfileId.isEmpty()) { ns.addExtra("app_id", freshApp.id); ns.postBankProfile(); const BankProfileInfo afterPost = BankProfileDAO::getApplication(device.id, m_appCode); if (afterPost.bankProfileId.isEmpty()) { const QString err = "postBankProfile failed for " + m_deviceId; qWarning() << "[GetProfileInfo]" << err; AppLogger::log("ozon/GetProfileInfo", m_deviceId, err, AdbUtils::captureScreenshotBytes(m_deviceId), "FETCH_PROFILE"); } else { qDebug() << "[GetProfileInfo] postBankProfile done"; } } else { ns.addExtra("bank_profile_id", freshApp.bankProfileId); ns.patchBankProfile(); qDebug() << "[GetProfileInfo] patchBankProfile done"; } // Отправляем данные аккаунтов на сервер если нет material_id const QList allAccounts = MaterialDAO::getAccounts(device.id, m_appCode); QList> accountsToPost; for (const auto &acc : allAccounts) { if (acc.materialId.isEmpty()) { accountsToPost.append({acc, Node()}); } } if (!accountsToPost.isEmpty()) { postAccountsData(accountsToPost); } AdbUtils::tryToKillApplication(m_deviceId, app.package); emit finishedWithResult(m_error); } } // namespace Ozon