1
0
forked from BRT/arc
arc/android/rshb/CommonScript.cpp
slava 8a3c1c5196 Refactor scripts to improve modularity and add transaction handling.
Enhanced `CommonScript` and `PayByPhoneScript` functionalities by restructuring functions for better readability and parameterization (e.g., device-specific inputs). Included a new transaction handling process and database updates for tracking payment details and statuses.
2025-05-07 19:16:08 +07:00

205 lines
7.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "CommonScript.h"
#include <QRandomGenerator>
#include <QThread>
#include "adb/AdbUtils.h"
CommonScript::CommonScript(QObject *parent)
: QObject(parent) {
}
CommonScript::~CommonScript() = default;
void CommonScript::start() {
doStart();
emit finished();
}
Node CommonScript::swipeToButton(
const QString &deviceId,
const QString &text, int &counter, const int width, const int height
) {
for (int i = 0; i < 10; ++i) {
if (Node button = xmlScreenParser.findButtonNode(text, true); button.x() > 0 && button.y() > 0) {
return button;
}
const int x = width / 2;
const int offset = height / 4;
AdbUtils::makeSwipe(deviceId, x, height - offset, x, offset);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++counter));
}
return {};
}
bool CommonScript::inputPinCode(const QString &deviceId, const QList<Node> &pincode) {
for (const Node &node: pincode) {
const bool completePincode = AdbUtils::makeTap(deviceId, node.x(), node.y());
if (!completePincode) {
return false;
}
QThread::msleep(QRandomGenerator::global()->bounded(100, 901));
}
return true;
}
bool CommonScript::runAppAndGoToHomeScreen(
const QString &deviceId,
const QString &packageName,
const QString &pinCode,
const int width,
const int height
) {
// Запустить устройство
if (const QString pid = AdbUtils::tryToGetRunningAppPid(deviceId, packageName); !pid.isEmpty()) {
qDebug() << "Process already running, pid: " << pid;
AdbUtils::getScreenDumpAsXml(deviceId, 1000);
AdbUtils::tryToKillApplication(deviceId, packageName);
}
if (!AdbUtils::tryToStartApplication(deviceId, packageName)) {
AdbUtils::takeScreenshot(deviceId, "run_app_error");
qWarning() << "Process has not started";
return false;
}
// Даем минимальное время на запуск
QThread::msleep(4500);
int counter = 0;
int restarted = 0;
int totalCounter = 0;
bool findAndInputPincode = false;
while (true) {
counter++;
totalCounter++;
// 3 раза уже перезапускали приложение, завершаем попытки
if (restarted > 2) {
AdbUtils::takeScreenshot(deviceId, "3_times_try_start");
return false;
}
// Если более 30 секунд мы пытаемся перейти на домашнюю, перезапускаем
if (counter > 30) {
AdbUtils::tryToKillApplication(deviceId, packageName);
QThread::msleep(4500);
++restarted;
counter = 0;
}
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
if (xmlScreenParser.isHomeScreen()) {
return true;
}
// Проверяем на банеры после пин-кодом
Node closeBannerOrDialogNode = xmlScreenParser.tryToFindBannerOrDialog(width, height);
if (closeBannerOrDialogNode.x() != -1 && closeBannerOrDialogNode.y() != -1) {
AdbUtils::makeTap(deviceId, closeBannerOrDialogNode.x(), closeBannerOrDialogNode.y());
QThread::msleep(1000);
continue;
}
// Проверяем на банеры перед пин-кодом
Node closeBannerNode = xmlScreenParser.tryToFindSecurityBanner();
if (!closeBannerNode.isEmpty()) {
AdbUtils::makeTap(deviceId, closeBannerNode.x(), closeBannerNode.y());
QThread::msleep(1000);
continue;
}
// Проверяем, что это экран ввода пин-кода
if (!findAndInputPincode) {
if (const QList<Node> pincode = xmlScreenParser.tryToFindPinCode(pinCode, "Введите ПИН");
pincode.size() == 4) {
inputPinCode(deviceId, pincode);
// После ввода пин-код нужно сделать задержку, пока подгрузка идет, чтобы снова не спарсить
findAndInputPincode = true;
QThread::msleep(3000);
continue;
}
}
QThread::msleep(1000);
// Если что-то пойдет не по плану...
if (totalCounter > 100) {
AdbUtils::takeScreenshot(deviceId, "too_many_attempts");
return false;
}
}
}
bool CommonScript::tryToCloseAllBannersOnHomePage(const QString &deviceId, const int width, const int height) {
Node closeBannerOrDialogNode = xmlScreenParser.tryToFindBannerOrDialog(width, height);
if (closeBannerOrDialogNode.x() != -1 && closeBannerOrDialogNode.y() != -1) {
AdbUtils::makeTap(deviceId, closeBannerOrDialogNode.x(), closeBannerOrDialogNode.y());
return true;
}
// TODO тут все другие банеры попробовать закрыть
return false;
}
bool CommonScript::goToAllProducts(
const QString &deviceId,
const int width,
const int height
) {
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, m_counter));
if (tryToCloseAllBannersOnHomePage(deviceId, width, height)) {
QThread::msleep(500);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
}
if (xmlScreenParser.isHomeScreen()) {
// идем на экран "Все продукты"
if (Node allCardTitle = xmlScreenParser.findTextNode("Счета и карты"); !allCardTitle.isEmpty()) {
// 1. Если нет кнопки видимой, свайпаем. Кликаем на "Все продукты"
for (int i = 0; i < 5; ++i) {
Node allProductsBtn = xmlScreenParser.findButtonNode("Все продукты", false);
if (allProductsBtn.x() > 0 && allProductsBtn.y() > 0) {
AdbUtils::makeTap(deviceId, allProductsBtn.x(), allProductsBtn.y());
QThread::msleep(1000);
break;
}
AdbUtils::makeSwipe(deviceId,
allCardTitle.x(), allCardTitle.y(),
allCardTitle.x(), allCardTitle.y() - 200);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
}
for (int i = 0; i < 5; ++i) {
Node allProductsTitle = xmlScreenParser.findTextNode("Все продукты");
// Проверяем что вверху заголовок
if (!allProductsTitle.isEmpty() && allProductsTitle.y() < 300) {
return true;
}
QThread::msleep(1000);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
}
} else {
// FIXME пишем в БД, что не дошли до домашней страницы, и завершаемся
// сохраняем скрин приложения
// дделаем алерт
}
} else {
// FIXME
qDebug() << "Not home screen...";
}
return false;
}
bool CommonScript::readTransactionData() {
return false;
}
// 1. топаем на домашнюю
// 2. распарсить мои карты и вернуть данные
// 3. синхронизировать историю транзакций (с домашней)
void CommonScript::stop() {
m_running = false;
}