Загрузка данных


// ============================================================
//  ПОРТОВЫЙ БОТ + АВТОКЛИКЕР + РАСШИРЕННОЕ GUI
//  F6 - Вкл/Выкл защиту от админов | F7 - старт/стоп | F8 - запись маршрута | F9 - ТП | F10 - точка | F12 - выгрузка
// ============================================================

// в•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђ
//  GUI (взято из stroka_upd, адаптировано под порт)
// в•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђв•ђ

var guiBrowser = null;

var guiHTML = `<!DOCTYPE html>
<html><head><meta charset="utf-8"><style>
*{margin:0;padding:0;box-sizing:border-box;}
html,body{background:transparent;overflow:hidden;font-family:'Segoe UI',sans-serif;user-select:none;}
#panel{position:absolute;left:15px;top:15px;width:340px;
  background:linear-gradient(160deg,rgba(15,15,25,0.95),rgba(8,8,18,0.97));
  border-radius:12px;border:1px solid rgba(255,255,255,0.08);
  box-shadow:0 8px 32px rgba(0,0,0,0.6);overflow:hidden;cursor:move;}
.title{background:linear-gradient(90deg,rgba(0,180,80,0.25),rgba(80,0,200,0.25));
  padding:9px 12px;font-size:11px;font-weight:700;text-transform:uppercase;
  letter-spacing:1.5px;color:#fff;border-bottom:1px solid rgba(255,255,255,0.07);text-align:center;}
.tabs{display:flex;border-bottom:1px solid rgba(255,255,255,0.06);}
.tab{flex:1;padding:7px 4px;font-size:9px;font-weight:700;text-align:center;
  color:rgba(255,255,255,0.35);cursor:pointer;letter-spacing:.5px;text-transform:uppercase;
  transition:all .2s;border-bottom:2px solid transparent;}
.tab.active{color:#fff;border-bottom:2px solid #a78bfa;}
.tab:hover{color:rgba(255,255,255,0.7);}
.page{display:none;padding:10px 12px;}.page.active{display:block;}
.row{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;}
.row:last-child{margin-bottom:0;}
.lbl{font-size:10px;color:rgba(255,255,255,0.45);font-weight:600;text-transform:uppercase;letter-spacing:.4px;}
.val{font-size:11px;font-weight:700;color:#fff;text-align:right;
  background:rgba(255,255,255,0.07);padding:2px 8px;border-radius:5px;
  max-width:155px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.val.green{background:rgba(0,220,80,0.2);color:#00ff55;}
.val.blue{background:rgba(0,120,255,0.2);color:#4db8ff;}
.val.yellow{background:rgba(255,200,0,0.15);color:#ffe066;}
.val.red{background:rgba(255,50,50,0.2);color:#ff6666;}
.val.orange{background:rgba(255,140,0,0.2);color:#ffaa33;}
.val.purple{background:rgba(167,139,250,0.15);color:#a78bfa;}
.divider{height:1px;background:rgba(255,255,255,0.05);margin:6px 0;}
.stat-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:8px;}
.stat-cell{background:rgba(255,255,255,0.04);border-radius:7px;padding:7px 8px;text-align:center;}
.stat-cell .n{font-size:15px;font-weight:800;color:#00ff55;}
.stat-cell .l{font-size:8px;color:rgba(255,255,255,0.35);text-transform:uppercase;margin-top:2px;}
.inp-row{margin-bottom:8px;}
.inp-lbl{font-size:9px;color:rgba(255,255,255,0.45);text-transform:uppercase;letter-spacing:.4px;margin-bottom:4px;}
input[type=number]{width:100%;background:rgba(255,255,255,0.06);
  border:1px solid rgba(255,255,255,0.1);border-radius:5px;padding:5px 8px;color:#fff;font-size:11px;outline:none;}
select{width:100%;background:rgba(255,255,255,0.06);
  border:1px solid rgba(255,255,255,0.1);border-radius:5px;padding:6px 8px;color:#fff;font-size:11px;outline:none;}
select option{background:#11121d;color:#fff;}
input:focus,select:focus{border-color:rgba(167,139,250,0.5);}
.btn-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:6px;}
.ui-btn{width:100%;padding:7px 6px;border-radius:6px;text-align:center;cursor:pointer;
  background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.1);
  color:#fff;font-size:10px;font-weight:700;box-sizing:border-box;}
.ui-btn.green{background:rgba(0,220,80,0.15);border-color:rgba(0,220,80,0.3);color:#00ff55;}
.ui-btn.red{background:rgba(255,50,50,0.15);border-color:rgba(255,50,50,0.3);color:#ff6666;}
.ui-btn.yellow{background:rgba(255,200,0,0.15);border-color:rgba(255,200,0,0.25);color:#ffe066;}
.ui-btn.purple{background:rgba(167,139,250,0.2);border-color:rgba(167,139,250,0.3);color:#a78bfa;}
.hint{font-size:9px;color:rgba(255,255,255,0.35);line-height:1.35;margin-top:5px;}
.route-list{max-height:145px;overflow-y:auto;margin-top:7px;padding-right:2px;}
.route-item{width:100%;padding:7px 8px;margin-bottom:5px;border-radius:6px;cursor:pointer;
  background:rgba(255,255,255,0.045);border:1px solid rgba(255,255,255,0.08);
  color:rgba(255,255,255,0.74);font-size:10px;font-weight:700;box-sizing:border-box;}
.route-item:hover{background:rgba(255,255,255,0.08);color:#fff;}
.route-item.active{background:rgba(0,120,255,0.18);border-color:rgba(77,184,255,0.45);color:#4db8ff;}
.route-item.recorded{border-color:rgba(255,200,0,0.18);}
.reset-btn{width:100%;margin-top:8px;padding:6px;background:rgba(255,50,50,0.15);
  border:1px solid rgba(255,50,50,0.2);color:#ff6666;font-size:10px;font-weight:700;
  border-radius:5px;cursor:pointer;text-align:center;letter-spacing:.5px;}
.reset-btn:hover{background:rgba(255,50,50,0.25);}
</style></head><body>
<div id="panel">
  <div class="title">⚓ ПОРТОВЫЙ БОТ v2.0</div>
  <div class="tabs">
    <div class="tab" onclick="showTab('routes',this)">Routes</div>
    <div class="tab active" onclick="showTab('info',this)">📊 Инфо</div>
    <div class="tab" onclick="showTab('stats',this)">📈 Стат</div>
    <div class="tab" onclick="showTab('settings',this)">⚙️ Настр</div>
  </div>

  <div id="page-info" class="page active">
    <div class="row"><span class="lbl">Статус бота</span><span id="status" class="val red">Стоит</span></div>
    <div class="row"><span class="lbl">Автокликер</span><span id="clicker" class="val red">Выкл</span></div>
    <div class="divider"></div>
    <div id="bot-btn" onclick="toggleBot()" style="width:100%;padding:8px;margin-bottom:6px;border-radius:7px;text-align:center;cursor:pointer;background:rgba(0,220,80,0.15);border:1px solid rgba(0,220,80,0.3);color:#00ff55;font-size:11px;font-weight:700;letter-spacing:.5px;box-sizing:border-box;">▶ ЗАПУСТИТЬ БОТА</div>
    <div class="divider"></div>
    <div class="row"><span class="lbl">Текущий маршрут</span><span id="route-name" class="val blue">—</span></div>
    <div class="row"><span class="lbl">Прогресс</span><span id="route-progress" class="val">—</span></div>
    <div class="divider"></div>
    <div class="row"><span class="lbl">РђРґРјРёРЅС‹ &lt;40Рј</span><span id="admin-count" class="val green">0</span></div>
    <div class="divider"></div>
    <div class="row"><span class="lbl">TGK</span><span class="val purple">t.me/leet_community</span></div>
  </div>

  <div id="page-routes" class="page">
    <div class="inp-row">
      <div class="inp-lbl">Delivery routes pool</div>
      <select id="route-select" onchange="selectRoute()">
        <option value="auto">Auto - by state</option>
      </select>
      <div id="route-list" class="route-list"></div>
      <div class="hint">Pickup is fixed. After pickup the bot randomly chooses a built-in or custom delivery route.</div>
    </div>
    <div class="row"><span class="lbl">Selected</span><span id="selected-route-name" class="val blue">For delete</span></div>
    <div class="row"><span class="lbl">Recorded</span><span id="recorded-route-count" class="val yellow">0</span></div>
    <div class="row"><span class="lbl">Mode</span><span id="route-reverse-status" class="val purple">Random</span></div>
    <div class="divider"></div>
    <div class="btn-grid">
      <div class="ui-btn green" onclick="toggleBot()">F7 Start/Stop</div>
      <div class="ui-btn purple" onclick="clearCustomRoutes()">Clear Custom</div>
      <div class="ui-btn yellow record-route-btn" onclick="toggleRouteRecord()">F8 New Delivery</div>
      <div class="ui-btn yellow" onclick="forceRoutePoint()">F10 Start/Point</div>
      <div class="ui-btn" onclick="refreshRoutes()">Refresh</div>
      <div class="ui-btn red" onclick="deleteSelectedRoute()">Delete</div>
    </div>
  </div>

  <div id="page-stats" class="page">
    <div class="stat-grid">
      <div class="stat-cell"><div class="n" id="s-pk">0</div><div class="l">Обезбол</div></div>
      <div class="stat-cell"><div class="n" id="s-earned" style="color:#ffe066;">$0</div><div class="l">Заработано</div></div>
      <div class="stat-cell"><div class="n" id="s-pkval" style="color:#a78bfa;">$0</div><div class="l">Цена обезбол</div></div>
      <div class="stat-cell"><div class="n" id="s-pkrate">0</div><div class="l">Обезбол / час</div></div>
    </div>
    <div class="divider"></div>
    <div class="row"><span class="lbl">Время сессии</span><span id="s-session" class="val blue">00:00:00</span></div>
    <div class="row"><span class="lbl">$ / час</span><span id="s-earnrate" class="val yellow">—</span></div>
    <div class="row"><span class="lbl">Шанс обезбола</span><span id="s-chance" class="val">—</span></div>
    <div class="divider"></div>
    <div class="reset-btn" onclick="resetStats()">🗑 Сбросить статистику</div>
  </div>

  <div id="page-settings" class="page">
    <div class="inp-row">
      <div class="inp-lbl">Цена 1 обезбола ($)</div>
      <input type="number" id="cfg-pkprice" value="2900" oninput="saveCfg()">
    </div>
    <div class="inp-row">
      <div class="inp-lbl">Стоп при админе</div>
      <div id="admin-toggle" onclick="toggleAdminStop()" style="width:100%;padding:6px;border-radius:6px;text-align:center;cursor:pointer;background:rgba(0,220,80,0.15);border:1px solid rgba(0,220,80,0.3);color:#00ff55;font-size:10px;font-weight:700;box-sizing:border-box;">✅ Включено</div>
    </div>
    <div class="divider"></div>
    <div class="inp-row">
      <div class="inp-lbl">Телепорт на старт</div>
      <div onclick="teleportToStart()" style="width:100%;padding:6px;border-radius:6px;text-align:center;cursor:pointer;background:rgba(167,139,250,0.2);border:1px solid rgba(167,139,250,0.3);color:#a78bfa;font-size:10px;font-weight:700;box-sizing:border-box;">📍 F9 - Телепорт</div>
    </div>
    <div class="inp-row">
      <div class="inp-lbl">Запись маршрута</div>
      <div class="record-route-btn" onclick="toggleRouteRecord()" style="width:100%;padding:6px;border-radius:6px;text-align:center;cursor:pointer;background:rgba(255,200,0,0.15);border:1px solid rgba(255,200,0,0.25);color:#ffe066;font-size:10px;font-weight:700;box-sizing:border-box;">⏺ F8 - Начать запись</div>
    </div>
  </div>
</div>
<script>
  var panel = document.getElementById('panel');
  var drag = false, ox, oy;
  panel.onmousedown = function(e) {
    var tag = e.target.tagName;
    if (tag === 'INPUT' || tag === 'SELECT' || tag === 'OPTION' || e.target.classList.contains('ui-btn') || e.target.classList.contains('route-item')) return;
    drag = true;
    ox = e.clientX - panel.getBoundingClientRect().left;
    oy = e.clientY - panel.getBoundingClientRect().top;
    e.preventDefault();
  };
  document.onmousemove = function(e) { if (drag) { panel.style.left = (e.clientX - ox) + 'px'; panel.style.top = (e.clientY - oy) + 'px'; } };
  document.onmouseup = function() { drag = false; };

  function showTab(t, el) {
    document.querySelectorAll('.tab').forEach(x => x.classList.remove('active'));
    document.querySelectorAll('.page').forEach(x => x.classList.remove('active'));
    el.classList.add('active');
    document.getElementById('page-'+t).classList.add('active');
  }

  var settingsRecordBtn = document.querySelector('#page-settings .record-route-btn');
  if (settingsRecordBtn && settingsRecordBtn.parentNode) {
    settingsRecordBtn.parentNode.style.display = 'none';
  }

  var CFG = { pkprice: 2900 };
  var statsData = { pk: 0, startTime: Date.now() };
  var __persistLock = false;

  function persistCfg() {
    if (__persistLock) return;
    try { mp.trigger('gui:saveCfg', JSON.stringify(CFG)); } catch(e) {}
  }
  function persistStats() {
    if (__persistLock) return;
    try { mp.trigger('gui:saveStats', JSON.stringify(statsData)); } catch(e) {}
  }

  function loadPersistedCfg(cfg) {
    if (!cfg) return;
    __persistLock = true;
    try {
      var price = parseFloat(cfg.pkprice);
      if (!isNaN(price) && price >= 0) CFG.pkprice = price;
      var inp = document.getElementById('cfg-pkprice');
      if (inp) inp.value = CFG.pkprice;
    } catch(e) {}
    __persistLock = false;
    updateStats();
  }
  function loadPersistedStats(s) {
    if (!s) return;
    __persistLock = true;
    try {
      var pk = parseInt(s.pk, 10);
      statsData.pk = !isNaN(pk) && pk >= 0 ? pk : 0;
      var st = parseInt(s.startTime, 10);
      statsData.startTime = !isNaN(st) && st > 0 ? st : Date.now();
    } catch(e2) {}
    __persistLock = false;
    updateStats();
  }

  function saveCfg() {
    CFG.pkprice = parseFloat(document.getElementById('cfg-pkprice').value) || 0;
    updateStats();
    persistCfg();
    mp.trigger('gui:setPKPrice', CFG.pkprice);
  }
  function resetStats() {
    statsData = { pk: 0, startTime: Date.now() };
    updateStats();
    persistStats();
    mp.trigger('gui:resetStatsClient');
  }
  function addPK(count) {
    statsData.pk += (count || 1);
    updateStats();
    persistStats();
  }
  function updateStats() {
    var totalMoney = statsData.pk * CFG.pkprice;
    var elapsed = (Date.now() - statsData.startTime) / 3600000;
    var ratePerHour = elapsed > 0 ? (statsData.pk / elapsed).toFixed(1) : 0;
    var earnRate = elapsed > 0 ? Math.round(totalMoney / elapsed) : 0;
    var chance = statsData.pk > 0 ? '—' : '—'; // шанс не считаем, т.к. неизвестно кол-во действий
    document.getElementById('s-pk').innerText = statsData.pk;
    document.getElementById('s-earned').innerText = '$' + totalMoney.toLocaleString();
    document.getElementById('s-pkval').innerText = '$' + (statsData.pk * CFG.pkprice).toLocaleString();
    document.getElementById('s-pkrate').innerText = ratePerHour + ' / С‡';
    document.getElementById('s-earnrate').innerText = earnRate > 0 ? '$' + earnRate + ' / ч' : '—';
    document.getElementById('s-chance').innerText = chance;
  }

  var _adminStopEnabled = true;
  function toggleAdminStop() {
    _adminStopEnabled = !_adminStopEnabled;
    var btn = document.getElementById('admin-toggle');
    if (_adminStopEnabled) {
      btn.innerText = '✅ Включено';
      btn.style.background = 'rgba(0,220,80,0.15)';
      btn.style.borderColor = 'rgba(0,220,80,0.3)';
      btn.style.color = '#00ff55';
    } else {
      btn.innerText = '❌ Выключено';
      btn.style.background = 'rgba(255,50,50,0.15)';
      btn.style.borderColor = 'rgba(255,50,50,0.3)';
      btn.style.color = '#ff6666';
    }
    mp.trigger('gui:setAdminStop', _adminStopEnabled);
  }
  function teleportToStart() {
    mp.trigger('gui:teleportToStart');
  }
  function toggleBot() {
    mp.trigger('gui:toggleBot');
  }
  function toggleRouteRecord() {
    mp.trigger('gui:toggleRouteRecord');
  }
  function forceRoutePoint() {
    mp.trigger('gui:forceRoutePoint');
  }
  function refreshRoutes() {
    mp.trigger('gui:refreshRoutes');
  }
  function deleteSelectedRoute() {
    var sel = document.getElementById('route-select');
    if (sel) mp.trigger('gui:deleteRecordedRoute', sel.value);
  }
  function clearCustomRoutes() {
    mp.trigger('gui:clearCustomRoutes');
  }
  function toggleRouteReverse() {
    mp.trigger('gui:toggleRouteReverse');
  }
  function selectRoute() {
    var sel = document.getElementById('route-select');
    if (sel) mp.trigger('gui:setRouteSelection', sel.value);
  }
  function pickRoute(routeId) {
    var sel = document.getElementById('route-select');
    if (sel) sel.value = routeId;
    mp.trigger('gui:setRouteSelection', routeId);
  }
  function setRouteReverseStatus(enabled) {
    var el = document.getElementById('route-reverse-status');
    if (!el) return;
    el.innerText = 'Random';
    el.className = 'val purple';
  }
  function setRouteOptions(routes, selectedId) {
    var sel = document.getElementById('route-select');
    var list = document.getElementById('route-list');
    if (sel) sel.innerHTML = '';
    if (list) list.innerHTML = '';
    var recordedCount = 0;
    for (var i = 0; i < routes.length; i++) {
      if (sel) {
        var opt = document.createElement('option');
        opt.value = routes[i].id;
        opt.textContent = routes[i].name;
        sel.appendChild(opt);
      }
      if (list) {
        var item = document.createElement('div');
        item.className = 'route-item' + (routes[i].recorded ? ' recorded' : '') + (routes[i].id === (selectedId || 'auto') ? ' active' : '');
        item.textContent = routes[i].name;
        item.setAttribute('data-route-id', routes[i].id);
        item.onclick = function() { pickRoute(this.getAttribute('data-route-id')); };
        list.appendChild(item);
      }
      if (routes[i].recorded) recordedCount++;
    }
    if (sel) sel.value = selectedId || 'auto';
    var selected = null;
    for (var j = 0; j < routes.length; j++) {
      if (routes[j].id === sel.value) {
        selected = routes[j];
        break;
      }
    }
    var nameEl = document.getElementById('selected-route-name');
    if (nameEl) nameEl.innerText = selected ? selected.name : 'None';
    var countEl = document.getElementById('recorded-route-count');
    if (countEl) countEl.innerText = recordedCount;
  }
  function setBotBtn(running) {
    var btn = document.getElementById('bot-btn');
    if (!btn) return;
    if (running) {
      btn.innerText = '⏹ ОСТАНОВИТЬ БОТА';
      btn.style.background = 'rgba(255,50,50,0.15)';
      btn.style.borderColor = 'rgba(255,50,50,0.3)';
      btn.style.color = '#ff6666';
    } else {
      btn.innerText = '▶ ЗАПУСТИТЬ БОТА';
      btn.style.background = 'rgba(0,220,80,0.15)';
      btn.style.borderColor = 'rgba(0,220,80,0.3)';
      btn.style.color = '#00ff55';
    }
  }
  function setClickerStatus(status) {
    var el = document.getElementById('clicker');
    if (!el) return;
    el.innerText = status;
    el.className = 'val ' + (status === 'ON' ? 'green' : 'red');
  }
  function setStatus(status, route, progress) {
    var statusEl = document.getElementById('status');
    if (statusEl) {
      statusEl.innerText = status;
      if (status === 'Running') statusEl.className = 'val green';
      else if (status === 'AFK') statusEl.className = 'val red';
      else statusEl.className = 'val red';
    }
    var routeEl = document.getElementById('route-name');
    if (routeEl) routeEl.innerText = route || '—';
    var progEl = document.getElementById('route-progress');
    if (progEl) progEl.innerText = progress || '—';
  }
  function setAdminCount(count) {
    var el = document.getElementById('admin-count');
    if (!el) return;
    el.innerText = count;
    el.className = 'val ' + (count > 0 ? 'red' : 'green');
  }
  function setSessionTime(timeStr) {
    var el = document.getElementById('s-session');
    if (el) el.innerText = timeStr;
  }
  function setRouteRecordStatus(active, count) {
    var buttons = document.querySelectorAll('.record-route-btn');
    if (buttons.length) {
      for (var i = 0; i < buttons.length; i++) {
        var routeBtn = buttons[i];
        if (active) {
          routeBtn.innerText = 'F8