1
0
forked from BRT/arc
arc/android/ozon/GetProfileInfoScript.cpp

184 lines
7.7 KiB
C++

#include "GetProfileInfoScript.h"
#include <QJsonDocument>
#include <QRegularExpression>
#include <QJsonObject>
#include <QMap>
#include <QtGlobal>
#include <QThread>
#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<QString, int> currencyCodes = {
{"RUB", 643}, {"USD", 840}, {"KRW", 410}, {"AZN", 944}, {"ARS", 32}, {"TJS", 972}
};
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<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);
}
// Возвращаемся на домашний экран
AdbUtils::goBack(m_deviceId);
QThread::msleep(1000);
emit finishedWithResult(m_error);
}
} // namespace Ozon