1
0
forked from BRT/arc
arc/android/black/GetLastTransactionsScript.cpp
slava 8ed25698e8 Add GetLastTransactionsScript and PayByCardScript implementations for Black app
Implemented `GetLastTransactionsScript` for automated retrieval of transactions, handling home screen navigation, "Ver más" button detection, and transaction list parsing with database storage. Introduced `PayByCardScript` for automated card payments, covering recipient selection, amount input, payment confirmation, and transaction logging. Added XML assets and updates to support these workflows.
2026-03-12 18:42:38 +07:00

169 lines
6.9 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 "GetLastTransactionsScript.h"
#include <QThread>
#include <QTimeZone>
#include "adb/AdbUtils.h"
#include "dao/AccountDAO.h"
#include "dao/ApplicationDAO.h"
#include "dao/DeviceDAO.h"
#include "dao/TransactionDAO.h"
#include "AppLogger.h"
namespace Black {
GetLastTransactionsScript::GetLastTransactionsScript(
QString deviceId,
QString appCode,
QObject *parent
) : CommonScript(parent),
m_deviceId(std::move(deviceId)), m_appCode(std::move(appCode)) {
}
GetLastTransactionsScript::~GetLastTransactionsScript() = default;
void GetLastTransactionsScript::doStart() {
const DeviceInfo device = DeviceDAO::getDeviceById(m_deviceId);
const ApplicationInfo app = ApplicationDAO::getApplication(m_deviceId, 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));
// Если не на домашнем экране — перезапускаем приложение
if (!xmlScreenParser.isHomeScreen()) {
qDebug() << "[Black::GetLastTransactions] Not on home screen, restarting app...";
if (!runAppAndGoToHomeScreen(device.id, app.package, app.pinCode,
device.screenWidth, device.screenHeight)) {
m_error = "Cannot reach home screen: " + m_deviceId;
qWarning() << m_error;
AppLogger::log("black/GetLastTransactions", m_deviceId, m_error,
AdbUtils::captureScreenshotBytes(m_deviceId),
"FETCH_TRANSACTIONS");
AdbUtils::tryToKillApplication(m_deviceId, app.package);
emit finishedWithResult(m_error);
return;
}
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
}
// Тапаем "Ver más" рядом с "Tu actividad" для перехода на экран транзакций
Node verMasBtn = xmlScreenParser.findVerMasAfterTuActividad();
if (verMasBtn.isEmpty()) {
// Попробуем проскроллить вниз чтобы увидеть "Tu actividad" + "Ver más"
for (int i = 0; i < 5; ++i) {
const int x = device.screenWidth / 2;
const int offset = device.screenHeight / 4;
AdbUtils::makeSwipe(m_deviceId, x, device.screenHeight - offset, x, offset);
QThread::msleep(1000);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
verMasBtn = xmlScreenParser.findVerMasAfterTuActividad();
if (!verMasBtn.isEmpty()) break;
}
}
if (verMasBtn.isEmpty()) {
m_error = "Button 'Ver más' not found: " + m_deviceId;
qWarning() << m_error;
emit finishedWithResult(m_error);
return;
}
qDebug() << "[Black::GetLastTransactions] Tapping 'Ver más' at" << verMasBtn.x() << verMasBtn.y();
AdbUtils::makeTap(m_deviceId, verMasBtn.x(), verMasBtn.y());
QThread::msleep(2000);
// Ждём загрузки экрана транзакций
// Сперва появляется экран загрузки (Tu Actividad без транзакций),
// затем подгружаются транзакции
bool loaded = false;
for (int attempt = 0; attempt < 15; ++attempt) {
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
if (xmlScreenParser.isTransactionListScreen()) {
loaded = true;
break;
}
if (xmlScreenParser.isTransactionLoadingScreen()) {
qDebug() << "[Black::GetLastTransactions] Loading screen detected, waiting for transactions, attempt" << attempt + 1 << "/ 15";
} else {
qDebug() << "[Black::GetLastTransactions] Waiting for transaction screen, attempt" << attempt + 1 << "/ 15";
}
QThread::msleep(1500);
}
if (!loaded) {
// Проверяем: если экран загрузки есть, но транзакций нет — это нормально (пустой аккаунт)
if (xmlScreenParser.isTransactionLoadingScreen()) {
qDebug() << "[Black::GetLastTransactions] No transactions found (empty account)";
AdbUtils::goBack(m_deviceId);
QThread::msleep(1000);
emit finishedWithResult(m_error);
return;
}
m_error = "Transaction list screen not loaded: " + m_deviceId;
qWarning() << m_error;
emit finishedWithResult(m_error);
return;
}
// Находим accountId для сохранения транзакций
int accountId = -1;
const QList<AccountInfo> accounts = AccountDAO::getAccounts(m_deviceId, m_appCode);
if (!accounts.isEmpty()) {
accountId = accounts.first().id;
qDebug() << "[Black::GetLastTransactions] Using accountId:" << accountId;
} else {
qWarning() << "[Black::GetLastTransactions] No account found for" << m_deviceId << m_appCode;
}
// Берём все транзакции что видны на экране
const QTimeZone argTz("America/Argentina/Buenos_Aires");
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
QList<TransactionInfo> pageItems = xmlScreenParser.parseTransactionItems();
qDebug() << "[Black::GetLastTransactions] Found" << pageItems.size() << "transactions on screen";
for (const TransactionInfo &tx : pageItems) {
TransactionInfo saveTx = tx;
saveTx.bankName = "black";
saveTx.status = TransactionStatus::Complete;
saveTx.timestamp = QDateTime::currentDateTimeUtc();
// Парсим дату из bankTime: "21 de febrero de 2026 - 09:39"
QDateTime parsed = xmlScreenParser.parseSpanishDate(saveTx.bankTime);
if (parsed.isValid()) {
parsed.setTimeZone(argTz);
saveTx.completeTime = parsed;
}
qDebug() << "[Black::GetLastTransactions]"
<< "date:" << saveTx.bankTime
<< "desc:" << saveTx.description
<< "name:" << saveTx.name
<< "amount:" << (saveTx.amount >= 0 ? "+" : "") + QString::number(saveTx.amount, 'f', 2);
// Сохраняем в БД
if (accountId != -1) {
saveTx.accountId = accountId;
if (TransactionDAO::insertTransactionIfNotExists(saveTx)) {
qDebug() << "[Black::GetLastTransactions] Saved transaction to DB";
}
}
}
qDebug() << "[Black::GetLastTransactions] Total transactions:" << pageItems.size();
// Возвращаемся на домашний экран
AdbUtils::goBack(m_deviceId);
QThread::msleep(1000);
emit finishedWithResult(m_error);
}
} // namespace Black