167 lines
7.9 KiB
JavaScript
167 lines
7.9 KiB
JavaScript
// ozon/get_profile_info.js
|
||
//
|
||
// JS-порт Ozon::GetProfileInfoScript. Логика 1:1 с C++ (см.
|
||
// android/ozon/GetProfileInfoScript.cpp). Все ADB/DAO/парсер-вызовы идут
|
||
// через host.*-мост, состояние парсера общее с host.helpers.
|
||
//
|
||
// Контракт:
|
||
// params.deviceId — серийный или android_id
|
||
// params.appCode — "ozon"
|
||
// Возвращает:
|
||
// "" / null / undefined → success
|
||
// строка → бизнес-ошибка (попадёт в EventInfo.error
|
||
// и в BankSetupWizard.humanReadableError)
|
||
// При throw runtime сделает fallback на C++.
|
||
//
|
||
// Сообщения об ошибках в этом файле ДОЛЖНЫ совпадать с подстроками из
|
||
// views/bank/BankSetupWizard.cpp:659 (humanReadableError), иначе мастер
|
||
// покажет "Произошла непредвиденная ошибка" вместо конкретной диагностики.
|
||
|
||
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("ozon", "FETCH_PROFILE_INFO", deviceId, {});
|
||
|
||
try {
|
||
// 2. Читаем текущий экран
|
||
host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter));
|
||
|
||
// 3. Закрываем рекламный bottom sheet, если открыт (home_ad_1)
|
||
var adNode = host.parser.tryToFindAdBanner();
|
||
if (!adNode.isEmpty) {
|
||
host.log.debug("Ad banner detected, closing...");
|
||
host.adb.makeTap(deviceId, adNode.x, adNode.y);
|
||
host.timer.sleep(1000);
|
||
host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter));
|
||
}
|
||
|
||
// 4. Свежий дамп перед проверкой домашнего экрана
|
||
host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter));
|
||
|
||
// 5. Если не на домашнем экране — перезапускаем приложение и вводим пин-код
|
||
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));
|
||
}
|
||
|
||
// 6. Закрываем баннеры на главной, если есть
|
||
host.helpers.tryToCloseAllBannersOnHomePage(deviceId, device.screenWidth, device.screenHeight);
|
||
host.timer.sleep(500);
|
||
host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter));
|
||
|
||
// 7. Парсим баланс с домашнего экрана
|
||
var parsedCards = host.parser.parseCardsOnHomeScreen();
|
||
var parsedBalance = parsedCards.length > 0 ? parsedCards[0].amount : 0.0;
|
||
host.log.debug("parseCardsOnHomeScreen returned " + parsedCards.length
|
||
+ " cards, balance: " + parsedBalance);
|
||
|
||
// 8. Fallback: если парсинг не нашёл баланс, берём из materials
|
||
if (parsedBalance <= 0.0) {
|
||
var accounts = host.dao.materialGetAccounts(device.id, appCode);
|
||
for (var i = 0; i < accounts.length; ++i) {
|
||
if (accounts[i].amount > 0.0) {
|
||
parsedBalance = accounts[i].amount;
|
||
break;
|
||
}
|
||
}
|
||
host.log.debug("Fallback balance from materials: " + parsedBalance);
|
||
}
|
||
if (parsedBalance > 0.0) {
|
||
host.dao.bankProfileUpdateAmount(app.id, parsedBalance);
|
||
}
|
||
|
||
// 9. Находим имя пользователя в верхней части и тапаем по нему
|
||
var userNameNode = host.parser.findUserNameOnHomeScreen(device.screenHeight);
|
||
if (userNameNode.isEmpty) {
|
||
var err2 = "Cannot find user name on home screen: " + deviceId;
|
||
host.log.warn(err2);
|
||
host.adb.tryToKillApplication(deviceId, app.package);
|
||
return err2;
|
||
}
|
||
host.log.debug("Tapping on user name: " + userNameNode.text
|
||
+ " at " + userNameNode.x + " " + userNameNode.y);
|
||
host.adb.makeTap(deviceId, userNameNode.x, userNameNode.y);
|
||
|
||
// 10. Ждём загрузки страницы профиля
|
||
host.timer.sleep(2500);
|
||
|
||
// 11. Проверяем что мы действительно на экране профиля (с retry)
|
||
var profileFound = false;
|
||
for (var j = 0; j < 5; ++j) {
|
||
host.parser.parseAndSaveXml(host.adb.getScreenDumpAsXml(deviceId, ++counter));
|
||
host.helpers.closeGooglePlayBannerIfVisible(deviceId, device.screenWidth, device.screenHeight);
|
||
if (host.parser.isProfileScreen()) {
|
||
profileFound = true;
|
||
break;
|
||
}
|
||
host.timer.sleep(1000);
|
||
}
|
||
if (!profileFound) {
|
||
var err3 = "Profile screen not detected after tap: " + deviceId;
|
||
host.log.warn(err3);
|
||
host.adb.tryToKillApplication(deviceId, app.package);
|
||
return err3;
|
||
}
|
||
|
||
// 12. Извлекаем полное имя и телефон. Telephone из Ozon XML может
|
||
// содержать неразрывные пробелы (U+00A0) и обычные — чистим оба.
|
||
var fullName = host.parser.parseProfileFullName();
|
||
var phone = host.parser.parseProfilePhone().replace(/[\s ]/g, '');
|
||
|
||
host.log.debug("fullName: " + fullName + " phone: " + phone);
|
||
|
||
// 13. Сохраняем профиль (email Ozon не отдаёт — передаём пустую строку)
|
||
if (!host.dao.bankProfileUpdateProfileInfo(app.id, fullName, phone, "")) {
|
||
host.log.warn("Failed to save profile info to DB: " + deviceId);
|
||
}
|
||
|
||
// 14. Регистрируем/обновляем bank profile на сервере. Хелпер сам
|
||
// перечитывает свежий профиль из БД и шлёт POST/PATCH по наличию bankProfileId.
|
||
host.helpers.createBankProfileIfNeeded(deviceId, appCode, parsedBalance);
|
||
|
||
// 15. Отправляем аккаунты без 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);
|
||
}
|
||
|
||
// 16. Возвращаемся на домашний экран
|
||
host.adb.goBack(deviceId);
|
||
host.timer.sleep(1000);
|
||
|
||
host.dump.endScope("");
|
||
return ""; // success
|
||
} catch (e) {
|
||
host.dump.endScope(String(e));
|
||
throw e;
|
||
}
|
||
}
|