241 lines
8.5 KiB
C++
241 lines
8.5 KiB
C++
//
|
||
// Created by Misterio on 24.04.2025.
|
||
//
|
||
|
||
#include "script_worker.h"
|
||
#include "adb_fun.h"
|
||
#include "xml_reader.h"
|
||
#include <regex>
|
||
#include <string>
|
||
#include <thread>
|
||
#include <chrono>
|
||
|
||
// Вспомогательные функции
|
||
|
||
void wait(const int milliseconds) {
|
||
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
|
||
}
|
||
|
||
// Функция для запуска скрипта с передачей параметров
|
||
void runScriptWorker(const std::string& pin, const std::string& last4digits) {
|
||
log("Запуск скрипта для ru.rshb.dbo");
|
||
|
||
if (!checkDevices()) {
|
||
log("ADB: Нет устройств");
|
||
qDebug("ADB: Нет устройств");
|
||
return;
|
||
}
|
||
|
||
if (!startApp("ru.rshb.dbo")) {
|
||
log("Не удалось запустить приложение");
|
||
qDebug("Не удалось запустить приложение");
|
||
return;
|
||
}
|
||
|
||
wait(4500);
|
||
dumpAndPullUiXml("ui_01.xml");
|
||
|
||
auto ui = parseUiDumpUsingQXml("ui_01.xml");
|
||
|
||
if (isPinScreen(ui)) {
|
||
log("Экран PIN-кода");
|
||
qDebug("Экран PIN-кода");
|
||
|
||
// Находим координаты цифр на экране и вводим ПИН
|
||
std::vector<UiElement> pinButtons = getPinButtons(ui);
|
||
for (size_t i = 0; i < pin.length(); ++i) {
|
||
char digit = pin[i];
|
||
for (const auto& el : pinButtons) {
|
||
if (el.text == std::string(1, digit)) {
|
||
tap((el.x1 + el.x2) / 2, (el.y1 + el.y2) / 2);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
wait(1000);
|
||
}
|
||
|
||
// Пост-логин баннеры — цикл для обработки разных состояний показов модальных окон
|
||
bool postLoginScreenFound = false;
|
||
int attempts = 5; // Максимальное количество попыток парсинга xml
|
||
while (attempts-- > 0) {
|
||
dumpAndPullUiXml("ui_02.xml");
|
||
auto ui2 = parseUiDumpUsingQXml("ui_02.xml");
|
||
|
||
// Закрытие баннеров или диалогов
|
||
if (handlePostLoginScreen(ui2)) {
|
||
postLoginScreenFound = true;
|
||
break;
|
||
}
|
||
|
||
// Проверка, если мы на главном экране
|
||
if (isMainScreen(ui2)) {
|
||
log("Главный экран подтверждён");
|
||
postLoginScreenFound = true;
|
||
break;
|
||
}
|
||
|
||
// Ждем немного перед следующим запросом дампа экрана
|
||
wait(1000);
|
||
}
|
||
|
||
if (!postLoginScreenFound) {
|
||
log("Не удалось определить пост-логин баннер.");
|
||
return;
|
||
}
|
||
|
||
// Пролистывание до кнопки "Все продукты"
|
||
swipe(1000, 2000, 1000, 1300);
|
||
wait(500);
|
||
|
||
// Нажимаем на кнопку "Все продукты"
|
||
dumpAndPullUiXml("ui_03.xml");
|
||
auto ui3 = parseUiDumpUsingQXml("ui_03.xml");
|
||
|
||
// Ищем кнопку "Все продукты" и нажимаем на неё
|
||
tapByText(ui3, "Все продукты");
|
||
wait(800);
|
||
|
||
// Шаг 6: Выбор карты на экране "Все продукты"
|
||
// Запрашиваем дамп UI для поиска карт
|
||
dumpAndPullUiXml("ui_04.xml");
|
||
auto ui4 = parseUiDumpUsingQXml("ui_04.xml");
|
||
|
||
// Определим, какую карту выбрать, например, с 4 цифрами "0823"
|
||
UiElement cardButton = findCardByLast4Digits(ui4, last4digits);
|
||
if (cardButton.text.isEmpty()) {
|
||
log("Не найдена карта с номером, содержащим " + last4digits);
|
||
return;
|
||
}
|
||
|
||
// Нажимаем на карту
|
||
tap((cardButton.x1 + cardButton.x2) / 2, (cardButton.y1 + cardButton.y2) / 2);
|
||
wait(1000);
|
||
|
||
// Нажимаем на кнопку "Оплатить"
|
||
// Запрашиваем дамп UI для поиска кнопки "Оплатить"
|
||
dumpAndPullUiXml("ui_05.xml");
|
||
auto ui5 = parseUiDumpUsingQXml("ui_05.xml");
|
||
|
||
// Ищем кнопку "Оплатить" и нажимаем на неё
|
||
UiElement payBtn = findPayButton(ui5);
|
||
if (payBtn.text.isEmpty()) {
|
||
log("Не найдена кнопка 'Оплатить'");
|
||
return;
|
||
}
|
||
|
||
// Нажимаем на кнопку "Оплатить"
|
||
tap((payBtn.x1 + payBtn.x2) / 2, (payBtn.y1 + payBtn.y2) / 2);
|
||
log("Нажата кнопка 'Оплатить'");
|
||
wait(1000);
|
||
}
|
||
|
||
// Функции для определения экранов и действий
|
||
|
||
bool isPinScreen(const std::vector<UiElement>& ui) {
|
||
for (const auto& el : ui) {
|
||
if (el.text == "Введите ПИН") {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
std::vector<UiElement> getPinButtons(const std::vector<UiElement>& ui) {
|
||
std::vector<UiElement> pinButtons;
|
||
for (const auto& el : ui) {
|
||
if (el.text.length() == 1 && std::isdigit(el.text[0].toLatin1())) {
|
||
pinButtons.push_back(el); // Собираем все элементы с цифрами
|
||
}
|
||
}
|
||
return pinButtons;
|
||
}
|
||
|
||
void tapByText(const std::vector<UiElement>& ui, const std::string& text) {
|
||
for (const auto& el : ui) {
|
||
if (el.text == QString::fromStdString(text)) {
|
||
tap((el.x1 + el.x2) / 2, (el.y1 + el.y2) / 2);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Тап по полю ввода
|
||
void tapInputField(const std::vector<UiElement>& ui, const std::string& fieldText) {
|
||
for (const auto& el : ui) {
|
||
if (el.text == QString::fromStdString(fieldText)) {
|
||
tap((el.x1 + el.x2) / 2, (el.y1 + el.y2) / 2);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Тап по кнопке "Далее"
|
||
void tapNextButton(const std::vector<UiElement>& ui) {
|
||
for (const auto& el : ui) {
|
||
if (el.text == "Войти" || el.text == "Далее" || el.text == "Продолжить") {
|
||
tap((el.x1 + el.x2) / 2, (el.y1 + el.y2) / 2);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
bool handlePostLoginScreen(const std::vector<UiElement>& ui) {
|
||
for (const auto& el : ui) {
|
||
// Ищем баннеры и модальные окна, которые нужно закрыть
|
||
if (el.text == "Получайте новости с помощью" || el.text == "Не пропускайте специальные предложения и рекомендации") {
|
||
// Тапаем по пустой области
|
||
tap((el.x1 + el.x2) / 2, (el.y1 + el.y2) / 2);
|
||
wait(900);
|
||
return true;
|
||
}
|
||
if (el.text == "Позже" || el.text == "Окей" || el.text == "Закрыть") {
|
||
// Тапаем по кнопке закрытия или кнопке "Позже"
|
||
tap((el.x1 + el.x2) / 2, (el.y1 + el.y2) / 2);
|
||
wait(900);
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
bool isMainScreen(const std::vector<UiElement>& ui) {
|
||
for (const auto& el : ui) {
|
||
if (el.text == "Счета и карты" || el.text == "Доступно баллов") {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
UiElement findCardByLast4Digits(const std::vector<UiElement>& ui, const std::string& last4digits) {
|
||
// Проходим по всем элементам UI, которые парсились из XML
|
||
for (const auto& el : ui) {
|
||
// Используем регулярное выражение для поиска 4 цифр в тексте
|
||
std::smatch m;
|
||
std::string str = el.text.toUtf8().constData(); // Преобразуем QString в std::string
|
||
|
||
// Если в тексте найдено совпадение с регулярным выражением для 4 цифр
|
||
if (std::regex_search(str, m, std::regex(R"(\*\*\s?(\d{4}))"))) {
|
||
// Проверяем, совпадают ли последние 4 цифры с переданными
|
||
if (m[1] == last4digits) {
|
||
// Если нашли совпадение, возвращаем элемент
|
||
return el;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Если карта с такими последними цифрами не найдена, возвращаем пустой элемент
|
||
return {};
|
||
}
|
||
|
||
UiElement findPayButton(const std::vector<UiElement>& ui) {
|
||
for (const auto& el : ui) {
|
||
if (el.text == "Оплатить") {
|
||
return el;
|
||
}
|
||
}
|
||
return {};
|
||
}
|
||
|