1
0
forked from BRT/arc
arc/scripts/black/get_profile_info.js
slava cae345cf61 Implement JS-based remote scripting framework for dynamic script updates:
- Add Proof of Concept (PoC) for executing JavaScript scripts fetched remotely.
- Integrate `Black::GetProfileInfoScript` logic into a JS version with fallback to C++ on errors.
- Extend `ScreenXmlParser` with additional JS-to-C++ bridge methods.
- Update `config.ini` for scripting configuration.
- Ensure scripts are securely fetched with SHA-256 validation and use an atomic caching mechanism.
- Add developer tools for debugging JS scripts and enable easier script updates without app re-deployment.
2026-05-13 15:42:10 +07:00

174 lines
6.9 KiB
JavaScript
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.

// black/get_profile_info.js
//
// JS-порт Black::GetProfileInfoScript. Логика 1:1 с C++ (см.
// android/black/GetProfileInfoScript.cpp), обращения к ADB/DAO/парсеру
// идут через host.*-мост.
//
// Контракт:
// params.deviceId — серийный или android_id
// params.appCode — "black"
// Возвращает:
// "" / null / undefined → success
// строку → бизнес-ошибка (попадёт в EventInfo.error)
// При выбросе исключения runtime сделает fallback на C++.
function run(host) {
var deviceId = host.params.deviceId;
var appCode = host.params.appCode;
var counter = 0;
// 1. Резолвим device (id может быть как android_id, так и adb serial).
var device = host.dao.deviceGetById(deviceId);
if (!device || !device.id) {
device = host.dao.deviceFindByAdbSerial(deviceId);
}
if (device && device.adbSerial) {
deviceId = device.adbSerial;
}
var app = host.dao.bankProfileGet(device.id, appCode);
if (!device || !device.id || !app || app.id < 0) {
var msg = "Device or app not found: " + deviceId + " " + appCode;
host.log.error(msg);
return msg;
}
host.dump.beginScope("black", "FETCH_PROFILE_INFO", deviceId, {});
try {
// 2. Читаем текущий экран
host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter));
// 3. Если не на домашнем экране — перезапускаем приложение
if (!host.parser.isHomeScreen()) {
host.log.debug("Not on home screen, restarting app...");
if (!host.helpers.runAppAndGoToHomeScreen(deviceId, app.package, app.pinCode,
device.screenWidth, device.screenHeight)) {
var err = "Cannot reach home screen: " + device.name + " (" + deviceId + ") " + appCode;
host.log.warn(err);
host.adb.tryToKillApplication(deviceId, app.package);
return err;
}
host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter));
}
// 4. Тапаем "¡Hola!"
var holaNode = host.parser.findHolaButton();
if (holaNode.isEmpty) {
var err2 = "Cannot find Hola button on home screen: " + deviceId;
host.log.warn(err2);
host.adb.tryToKillApplication(deviceId, app.package);
return err2;
}
// 5. Парсим имя и баланс с домашнего экрана
var fullName = host.parser.parseUserNameFromHomeScreen();
var balance = host.parser.parseBalanceFromHomeScreen();
host.log.debug("fullName from home: " + fullName + " balance: " + balance);
// Сохраняем баланс
host.dao.bankProfileUpdateAmount(app.id, balance);
host.adb.makeTap(deviceId, holaNode.x, holaNode.y);
host.timer.sleep(2000);
// 6. Ждём боковое меню
var sideMenuFound = false;
for (var i = 0; i < 5; ++i) {
host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter));
if (host.parser.isSideMenu()) {
sideMenuFound = true;
break;
}
host.timer.sleep(1000);
}
if (!sideMenuFound) {
var err3 = "Side menu not detected: " + deviceId;
host.log.warn(err3);
host.adb.tryToKillApplication(deviceId, app.package);
return err3;
}
// 7. Тапаем "Tu Información"
var tuInfoNode = host.parser.findNodeByContentDesc("Tu Información");
if (tuInfoNode.isEmpty) {
var err4 = "Cannot find Tu Información button: " + deviceId;
host.log.warn(err4);
host.adb.tryToKillApplication(deviceId, app.package);
return err4;
}
host.adb.makeTap(deviceId, tuInfoNode.x, tuInfoNode.y);
host.timer.sleep(2500);
// 8. Ждём страницу профиля
var profileFound = false;
for (var j = 0; j < 5; ++j) {
host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter));
if (host.parser.isProfilePage()) {
profileFound = true;
break;
}
host.timer.sleep(1000);
}
if (!profileFound) {
var err5 = "Profile page not detected: " + deviceId;
host.log.warn(err5);
host.adb.tryToKillApplication(deviceId, app.package);
return err5;
}
// 9. Парсим данные профиля
var nombre = host.parser.parseProfileNombre();
var apellido = host.parser.parseProfileApellido();
var email = host.parser.parseProfileEmail();
// 10. Скроллим вниз чтобы увидеть телефон
var x = Math.floor(device.screenWidth / 2);
var fromY = Math.floor(device.screenHeight * 3 / 4);
var toY = Math.floor(device.screenHeight / 4);
host.adb.makeSwipe(deviceId, x, fromY, x, toY);
host.timer.sleep(1500);
host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter));
var phone = host.parser.parseProfilePhone();
// Собираем полное имя
var parsedFullName;
if (nombre && apellido) {
parsedFullName = nombre + " " + apellido;
} else if (nombre) {
parsedFullName = nombre;
} else {
parsedFullName = fullName;
}
host.log.debug("nombre: " + nombre + " apellido: " + apellido
+ " email: " + email + " phone: " + phone
+ " fullName: " + parsedFullName);
// 11. Сохраняем профиль
if (!host.dao.bankProfileUpdateProfileInfo(app.id, parsedFullName, phone, email)) {
host.log.warn("Failed to save profile info to DB");
}
// 12. Создаём bank profile на сервере если нет
host.helpers.createBankProfileIfNeeded(deviceId, appCode, -1);
// 13. Отправляем аккаунты без material_id на сервер
var allAccounts = host.dao.materialGetAccounts(device.id, appCode);
var accountsToPost = [];
for (var k = 0; k < allAccounts.length; ++k) {
if (!allAccounts[k].materialId) accountsToPost.push(allAccounts[k]);
}
if (accountsToPost.length > 0) {
host.helpers.postAccountsData(accountsToPost);
}
host.dump.endScope("");
return ""; // success
} catch (e) {
// Любая JS-ошибка → engine error для runtime → fallback на C++.
host.dump.endScope(String(e));
throw e;
}
}