#pragma once #include #include #include #include #include "android/xml/Node.h" class QJSEngine; namespace Black { class ScreenXmlParser; } namespace Scripting { // Лог из JS попадает в qDebug/qWarning с префиксом банка/скрипта. class LogBridge final : public QObject { Q_OBJECT public: LogBridge(QString tag, QObject *parent = nullptr) : QObject(parent), m_tag(std::move(tag)) {} public slots: void debug(const QString &message); void info(const QString &message); void warn(const QString &message); void error(const QString &message); private: QString m_tag; }; // Sleep + проверка interrupt (скрипт крутится в worker-потоке EventHandler'а). class TimerBridge final : public QObject { Q_OBJECT public: explicit TimerBridge(QObject *parent = nullptr) : QObject(parent) {} public slots: void sleep(int ms); // блокирующий, проверяет interrupt bool isInterrupted() const; // ручная проверка из JS }; // Прокси над AdbUtils. Все методы статические в C++ — здесь оборачиваем как Q_INVOKABLE, // чтобы JS видел их как host.adb.. class AdbBridge final : public QObject { Q_OBJECT public: explicit AdbBridge(QObject *parent = nullptr) : QObject(parent) {} public slots: QString getScreenDumpAsXml(const QString &deviceId, int idx); QString getRawScreenDumpAsXml(const QString &deviceId); bool makeTap(const QString &deviceId, int x, int y); bool makeSwipe(const QString &deviceId, int x1, int y1, int x2, int y2); bool makeSwipeWithDuration(const QString &deviceId, int x1, int y1, int x2, int y2, int durationMs); bool tryToStartApplication(const QString &deviceId, const QString &packageName); bool tryToKillApplication(const QString &deviceId, const QString &packageName); QString tryToGetRunningAppPid(const QString &deviceId, const QString &packageName); bool takeScreenshot(const QString &deviceId, const QString &name); bool inputText(const QString &deviceId, const QString &text); bool inputAdbIMEText(const QString &deviceId, const QString &text); bool enableAdbIMEKeyboard(const QString &deviceId); bool disableAdbIMEKeyboard(const QString &deviceId); bool hideKeyboard(const QString &deviceId); bool goBack(const QString &deviceId); void unlockScreen(const QString &deviceId, int screenWidth, int screenHeight); QString getDeviceTimezone(const QString &deviceId); QString captureScreenshotBase64(const QString &deviceId); }; // DAO-прокси: read для устройства/профиля/материалов, write для баланса/профиля. class DaoBridge final : public QObject { Q_OBJECT public: explicit DaoBridge(QObject *parent = nullptr) : QObject(parent) {} public slots: // DeviceDAO QVariantMap deviceGetById(const QString &id); QVariantMap deviceFindByAdbSerial(const QString &serial); // BankProfileDAO QVariantMap bankProfileGet(const QString &deviceId, const QString &appCode); bool bankProfileUpdateAmount(int profileId, double amount); bool bankProfileUpdateProfileInfo(int profileId, const QString &fullName, const QString &phone, const QString &email); bool bankProfileUpdateComment(int profileId, const QString &comment); // MaterialDAO QVariantList materialGetAccounts(const QString &deviceId, const QString &appCode); }; // Скоуп дампа задачи. JS-style API: begin/end вместо RAII (вешаем на try/finally). class DumpBridge final : public QObject { Q_OBJECT public: explicit DumpBridge(QObject *parent = nullptr) : QObject(parent) {} ~DumpBridge() override { endScope(QString()); } public slots: void beginScope(const QString &bank, const QString &taskKind, const QString &adbDeviceId, const QVariantMap &meta); void endScope(const QString &errorMessage); // пусто = success private: void *m_scope = nullptr; QString *m_errorPtr = nullptr; }; // Парсер экрана для банка Black. Каждый запуск скрипта получает свой инстанс, // поэтому m_xml/m_nodes не разделяются между задачами. class BlackParserBridge final : public QObject { Q_OBJECT public: explicit BlackParserBridge(QObject *parent = nullptr); ~BlackParserBridge() override; Black::ScreenXmlParser *parser() const { return m_parser; } public slots: void parseAndSaveXml(const QString &xml); bool isHomeScreen(); bool isSideMenu(); bool isPinCodeScreen(); bool isProfilePage(); bool isCVUScreen(); bool isTransactionLoadingScreen(); bool isTransactionListScreen(); bool isPayInputCardNumberScreen(); bool isPayTransferConfirmScreen(); bool isPayInputSumScreen(); bool isPayConfirmScreen(); bool isPaySuccessScreen(); QVariantMap findHolaButton(); QVariantMap findTextNode(const QString &text); QVariantMap findNodeByContentDesc(const QString &contentDesc); QVariantMap findNodeByContentDescContains(const QString &contentDesc); QVariantMap findButtonNode(const QString &text, bool contains); QVariantMap findFirstEditText(); QVariantMap findPinCodeEditText(); QVariantMap findVerMasAfterTuActividad(); QVariantMap findEditTextByHint(const QString &hint); QString parseUserNameFromHomeScreen(); double parseBalanceFromHomeScreen(); QString parseProfileNombre(); QString parseProfileApellido(); QString parseProfileEmail(); QString parseProfilePhone(); QString parseCVUNumber(); QString parseRecipientNameFromConfirm(); QString parsePaySuccessDateTime(); QString parsePaySuccessCoelsaId(); private: Black::ScreenXmlParser *m_parser; }; // Высокоуровневые операции, повторяющие методы Black::CommonScript: // runAppAndGoToHomeScreen, postAccountsData, createBankProfileIfNeeded. // Используют ТОТ ЖЕ парсер, что и BlackParserBridge — состояние (XML) общее. class BlackHelpersBridge final : public QObject { Q_OBJECT public: BlackHelpersBridge(BlackParserBridge *parser, QObject *parent = nullptr) : QObject(parent), m_parserBridge(parser) {} public slots: bool runAppAndGoToHomeScreen(const QString &deviceId, const QString &packageName, const QString &pinCode, int width, int height); void postAccountsData(const QVariantList &accountsWithEmptyMaterialId); void createBankProfileIfNeeded(const QString &deviceId, const QString &appCode, double parsedBalance); private: BlackParserBridge *m_parserBridge; }; // Утилиты конверсии Node ↔ QVariantMap. Объявлены здесь чтобы парсер-бридж // мог их использовать без зависимости от QJSEngine. QVariantMap nodeToVariantMap(const Node &node); } // namespace Scripting