From 89ccb7fa6349a322fb350c771b8c15e27c688277 Mon Sep 17 00:00:00 2001 From: viktor138irk <78488229+viktor138irk@users.noreply.github.com> Date: Fri, 11 Jul 2025 22:17:56 +0900 Subject: [PATCH] Add files via upload --- README | 27 + admin.php | 164 +++ adminLogic.php | 291 +++++ assets/css/style.css | 180 +++ assets/js/main.js | 125 +++ check_unique.php | 58 + db.json | 2513 +++++++++++++++++++++++++++++++++++++++++ dmrid.dat | 228 ++++ index.php | 71 ++ register.php | 195 ++++ savedata/admin.php | 405 +++++++ savedata/db.json | 2557 ++++++++++++++++++++++++++++++++++++++++++ savedata/dmrid.dat | 224 ++++ savedata/logic.php | 227 ++++ 14 files changed, 7265 insertions(+) create mode 100644 README create mode 100644 admin.php create mode 100644 adminLogic.php create mode 100644 assets/css/style.css create mode 100644 assets/js/main.js create mode 100644 check_unique.php create mode 100644 db.json create mode 100644 dmrid.dat create mode 100644 index.php create mode 100644 register.php create mode 100644 savedata/admin.php create mode 100644 savedata/db.json create mode 100644 savedata/dmrid.dat create mode 100644 savedata/logic.php diff --git a/README b/README new file mode 100644 index 0000000..707fbee --- /dev/null +++ b/README @@ -0,0 +1,27 @@ +# Структура проекта + +index.php - Главная страница со ссылками на адмнику и базы данных +register.php - Форма регистрации для новых пользователей +admin.php - Админка, для управления пользователями +db.json,dmrid.dat - Базы данных +savedata - Папка, в которую можно сохранять старое в случае изменений + +## Админка +admin.php + Основной файл, html со вставками php, логика и стили импортируются из других файлов. + Тут можно редактировать основную структуру страницы + +adminLogic.php + Файл, с кодом для основной логики, обрабатывает удаление, добавление, блокировку + пользователей, вызванные из admin.php + Импортируются в admin.php в первой строчке проекта + Методы - sync, delete, block, confirm, post + Переменные - данные о пользователях, данные о пользователях с пагинацией + +/assets/... + Папка со стилем и js-кодом (для валидации имени в форме создания). + Импортируется в админку в теге
и перед последним тегом + +## Структура данных +db.json - {"count": 4, "results":[{},{}]} +dmrid.dat - ID;CALLSIGN; diff --git a/admin.php b/admin.php new file mode 100644 index 0000000..7992889 --- /dev/null +++ b/admin.php @@ -0,0 +1,164 @@ + + + + + + + Админка DMR + + + + +
Панель администратора DMR ID +НАЗАД +
+ +
+ +
+

Кореcпонденты:

+
+
+ + +
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + ✏️ + 🗑️ + ✖️ +
+ + 1): ?> + + +
+ +
+

Добавить кореспондента

+ +
+ + +
+ + +
+ + +
+ + + + + + + + + +
+ +
+ +
+

Ожидают подтверждения

+ + + + + +
+
+
+ + + diff --git a/adminLogic.php b/adminLogic.php new file mode 100644 index 0000000..ef82ef5 --- /dev/null +++ b/adminLogic.php @@ -0,0 +1,291 @@ + 0, 'results' => []]; +$data = $json['results']; + +//Запрос, который отправляется сервером на форму создания +if (isset($_GET['ajax_check'])) { + $id = $_GET['id'] ?? ''; + $callsign = strtoupper(trim($_GET['callsign'] ?? '')); + $response = [ + 'idInvalid' => !preg_match('/^\d{6,7}$/', $id), + 'idExists' => false, + 'callsignInvalid' => !preg_match('/^[A-Z0-9]{4,7}$/', $callsign), + 'callsignExists' => false + ]; + //Проверяет id и callsign на существование + foreach ($data as $row) { + if ($row['id'] == $id) $response['idExists'] = true; + if (strtoupper($row['callsign']) === $callsign) $response['callsignExists'] = true; + } + header('Content-Type: application/json'); + echo json_encode($response); + exit; +} + +//Метод синхронизации +if (isset($_GET['sync'])) { + $lines = []; + + //Читает json - берет из него id, callsign в нужном формате и добавляет в строки + foreach ($data as $item) { + if (!empty($item['confirmed'])) { + $id = trim($item['id']); + $callsign = strtoupper(trim($item['callsign'])); + $lines[] = "{$id};{$callsign};"; + } + } + + //Перезаписывем файл + file_put_contents($datFile, implode(PHP_EOL, $lines) . PHP_EOL); + + //Совершаем перенаправление на страницу админки + header("Location: admin.php"); + exit; +} + +//Редактирование +if (isset($_GET['edit'])) { + //Отправляем не в форме а в json запросе, поэтому сначала должны получить формат + $rawData = file_get_contents("php://input"); + $postData = json_decode($rawData, true); + + $edit_id = (int)$postData['id']; + $callsign = strtoupper(trim($postData['callsign'])); + $fname = trim($postData['fname'] ?? ''); + $surname = trim($postData['surname'] ?? ''); + $city = trim($postData['city'] ?? ''); + $state = trim($postData['state'] ?? ''); + $country = trim($postData['country'] ?? ''); + $remarks = trim($postData['remarks'] ?? ''); + + //Ищем среди данных по айди то поле, которое редактировали + foreach ($data as &$item) { + if ($item['id'] == $edit_id) { + $entry = "{$item['id']};{$item['callsign']};"; + $item['callsign'] = $callsign; + $item['fname'] = $fname; + $item['surname'] = $surname; + $item['city'] = $city; + $item['state'] = $state; + $item['country'] = $country; + $item['remarks'] = $remarks; + //$entry присвоена до редактирования - фильтруем и удаляем, после - добавляем (FILE_APPEND) + $lines = file($datFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $filtered = array_filter($lines, function($line) use ($entry) { + return trim($line) !== $entry; + }); + + file_put_contents($datFile, implode(PHP_EOL, $filtered) . PHP_EOL); + + $entry = "{$item['id']};{$item['callsign']};"; + file_put_contents($datFile, $entry . PHP_EOL, FILE_APPEND); + } + } + + //Так очищается переменная, чтоб использовать ее дальше. После записываем все в json + unset($item); + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + + file_put_contents($datFile, implode(PHP_EOL, array_map(fn($r) => "{$r['id']};{$r['callsign']};", $data)) . PHP_EOL); + + header("Location: admin.php"); + exit; +} + + +//Подтверждение. GET - без формы и json, просто ищем запись по id +if (isset($_GET['confirm'])) { + $confirmId = (int)$_GET['confirm']; + + foreach ($data as &$item) { + if ($item['id'] === $confirmId) { + $item['confirmed'] = true; + + $lines = file($datFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $entry = "{$item['id']};{$item['callsign']};"; + //нет необходимости удалять - до подтверждения записи не было + if (!in_array($entry, $lines)) { + file_put_contents($datFile, $entry . PHP_EOL, FILE_APPEND); + } + + break; + } + } + unset($item); + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + header("Location: admin.php"); + exit; +} + +//Блокировка. Аналогично одобрению, меняем на false +if (isset($_GET['block'])) { + $confirmId = (int)$_GET['block']; + + foreach ($data as &$item) { + if ($item['id'] === $confirmId) { + $item['confirmed'] = false; + + $lines = file($datFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $entry = "{$item['id']};{$item['callsign']};"; + + $filtered = array_filter($lines, function($line) use ($entry) { + return trim($line) !== $entry; + }); + + file_put_contents($datFile, implode(PHP_EOL, $filtered) . PHP_EOL); + + break; + } + } + unset($item); + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + header("Location: admin.php"); + exit; +} + +//Удаление +if (isset($_GET['delete'])) { + $deleteId = (int)$_GET['delete']; + + $callsign = null; + + foreach ($data as $index => $item) { + if ($item['id'] === $deleteId) { + //Получаем позывной для строки в фильтре и очищаем json от найденной переменной + $callsign = $item['callsign']; + unset($data[$index]); + break; + } + } + + $data = array_values($data); + + if ($callsign === null) { + header("Location: admin.php"); + exit; + } + + //Перезаписываем + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + + $lines = file($datFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $filtered = array_filter($lines, function($line) use ($deleteId, $callsign) { + return trim($line) !== "{$deleteId};{$callsign};"; + }); + + file_put_contents($datFile, implode(PHP_EOL, $filtered) . PHP_EOL); + header("Location: admin.php"); + exit; +} + +//Переменная - используется в форме добавления. Аналогично редактированию, на есть форма - не надо доставать json +$form_error = ''; +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add'])) { + $new_id = (int)$_POST['new_id']; + $callsign = strtoupper(trim($_POST['new_callsign'])); + $fname = trim($_POST['fname'] ?? ''); + $surname = trim($_POST['surname'] ?? ''); + $city = trim($_POST['city'] ?? ''); + $state = trim($_POST['state'] ?? ''); + $country = trim($_POST['country'] ?? ''); + $remarks = trim($_POST['remarks'] ?? ''); + + if ($new_id < 100000 || $new_id > 9999999) { + $form_error = 'ID должен быть 6–7 цифр.'; + } elseif (!preg_match('/^[A-Z0-9]{4,7}$/', $callsign)) { + $form_error = 'Позывной: 4–7 латинских символов/цифр.'; + } elseif (array_filter($data, fn($r) => $r['id'] == $new_id || strtoupper($r['callsign']) === $callsign)) { + $form_error = 'Такой ID или позывной уже существует.'; + } elseif (preg_match('/[^a-zA-Z\s]/', $fname . $surname . $city . $state . $country)) { + $form_error = 'Дополнительные поля должны содержать только латиницу.'; + } else { + $data[] = [ + 'id' => $new_id, + 'callsign' => $callsign, + 'fname' => $fname, + 'surname' => $surname, + 'city' => $city, + 'state' => $state, + 'country' => $country, + 'remarks' => $remarks, + 'confirmed' => true + ]; + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + + $dat_line = "{$new_id};{$callsign};" . PHP_EOL; + file_put_contents($datFile, $dat_line, FILE_APPEND); + + header("Location: admin.php"); + exit; + } +} + +//Дальше идут поля, которые используются для пагинации в таблице. +//Сначала идет поиск и фильтрация на подтвержденных +$searchQuery = trim($_GET['search'] ?? ''); + +$confirmed = array_values(array_filter($data, fn($d) => !empty($d['confirmed']))); + +if ($searchQuery !== '') { + $confirmed = array_filter($confirmed, function($row) use ($searchQuery) { + foreach (['id', 'callsign', 'fname', 'surname', 'city', 'state', 'country', 'remarks'] as $field) { + if (stripos((string)($row[$field] ?? ''), $searchQuery) !== false) { + return true; + } + } + return false; + }); +} + +//Среди подтвержденных полей идет сортировка +$validSortKeys = ['id', 'callsign', 'fname', 'surname', 'city', 'state', 'country', 'remarks']; +$sortKey = $_GET['sort'] ?? 'id'; +$sortOrder = $_GET['order'] ?? 'asc'; + +if (!in_array($sortKey, $validSortKeys)) { + $sortKey = 'id'; +} + +usort($confirmed, function($a, $b) use ($sortKey, $sortOrder) { + $valA = $a[$sortKey] ?? ''; + $valB = $b[$sortKey] ?? ''; + + $result = is_numeric($valA) && is_numeric($valB) + ? $valA <=> $valB + : strcasecmp((string)$valA, (string)$valB); + //asc - desc : направление сортировки + return $sortOrder === 'desc' ? -$result : $result; +}); + +//Пагинация +$page = max(1, (int)($_GET['page'] ?? 1)); +$perPage = 15; +$total = count($confirmed); +$totalPages = ceil($total / $perPage); +$offset = ($page - 1) * $perPage; +//$confirmed - сортированный массив; $offset - на сколько сдвинуть от начала; $perPage - сколько на странице +$currentPageData = array_slice($confirmed, $offset, $perPage); + +//Используем, чтоб сохранить пагинацию и сортировку - используется на главной странице +function sortLink(string $key, string $label): string { + $currentSort = $_GET['sort'] ?? 'id'; + $currentOrder = $_GET['order'] ?? 'asc'; + $nextOrder = ($currentSort === $key && $currentOrder === 'asc') ? 'desc' : 'asc'; + $page = $_GET['page'] ?? 1; + + return "$label"; +} +?> diff --git a/assets/css/style.css b/assets/css/style.css new file mode 100644 index 0000000..6e9c89f --- /dev/null +++ b/assets/css/style.css @@ -0,0 +1,180 @@ +* { box-sizing: border-box; } + body { + font-family: Arial, sans-serif; + background: #f3f4f6; + margin: 0; + padding: 0; + } + header { + background: #1f2937; + color: #fff; + padding: 15px 30px; + font-size: 20px; + font-weight: bold; + } + .container { + display: flex; + padding: 30px; + gap: 30px; + align-items: flex-start; + } + .left-section { flex: 3; } + .right-section { + flex: 1; + position: sticky; + top: 30px; + background: #fff; + border-radius: 10px; + padding: 20px; + box-shadow: 0 0 10px rgba(0,0,0,0.05); + } + .user-table { + width: 100%; + background: #fff; + border-collapse: collapse; + margin-top: 1em; + } + + .user-table th, .user-table td { + border: 1px solid #ccc; + padding: 8px 8px; + text-align: left; + vertical-align: center; + } + + .user-table th { + background-color: #f4f4f4; + } + .user-table th:last-child, + .user-table td.button-group { + width: 90px; + text-align: center; + white-space: nowrap; + } + .unconfirmed-card { + background: #fff; + padding: 5px; + margin-bottom: 1px; + border-radius: 8px; + box-shadow: 0 0 4px rgba(0,0,0,0.05); + display: flex; + justify-content: space-between; + align-items: center; + } + .card-space { + display: flex; + justify-content: space-between; + align-items: center; + } + .card { + background: #fff; + padding: 15px; + margin-bottom: 10px; + border-radius: 8px; + box-shadow: 0 0 4px rgba(0,0,0,0.05); + display: flex; + justify-content: space-between; + align-items: center; + } + .card span { font-size: 14px; } + + .button-group {white-space: nowrap; + text-align: center; + flex-direction: row; + padding: 4px;} + .card a, .button-group a { display: inline-block; + padding: 4px 8px; + margin: 0 2px; + font-size: 0.9em; + background-color: #f4f4f4; color: white; + border: 1px solid #ccc; + text-decoration: none; + transition: background-color 0.3s ease; + border-radius: 4px;} + .card a:hover { background-color: #f4f4f4; color:#1f2937; font-weight:bold;} + .button-group a:hover { background-color: #d7d7d7; color:#1f2937;} + .confirm { color: #10b981; font-weight: bold; text-decoration: none; } + .delete { color: #ef4444; text-decoration: none; } + .add-form input { + padding: 10px; + margin-bottom: 10px; + width: 100%; + border-radius: 5px; + border: 1px solid #ccc; + } + .add-form button { + transition: background-color 0.3s ease; + padding: 10px; + background: #1f2937; + color: white; + border: none; + border-radius: 5px; + font-weight: bold; + width: 100%; + cursor: pointer; + } + .add-form button:hover { + padding: 10px; + background: #f4f4f4; + color: #1f2937; + border: none; + border-radius: 5px; + font-weight: bold; + width: 100%; + cursor: pointer; + } + .form-error { + color: red; + font-size: 13px; + margin-top: -8px; + margin-bottom: 10px; + } + .sync-button { + transition: background-color 0.3s ease; + background: #ccc; + color: #1f2937; + border: none; + padding: 8px 14px; + font-size: 14px; + border-radius: 5px; + cursor: pointer; + } + .sync-button:hover { + background: white; + color: black; + font-weight: bold; + border: none; + padding: 8px 14px; + font-size: 14px; + border-radius: 5px; + cursor: pointer; + } + .search-form { + margin-bottom: 1rem; + font-weight: bold; + } + .search-form input { + padding: 6px; + font-size: 1rem; + } + .search-form button { + padding: 6px 10px; + border-radius: 5px; + font-weight: bold; + font-size: 1rem; + cursor: pointer; + transition: background-color 0.2s ease; + } + .search-form button:hover {background-color: #1f2937; color: white; border-radius: 5px;} + .pagination { margin-top: 15px; text-align: center; } + .pagination a {padding: 6px 12px; border: 1px solid #ccc; border-radius: 4px; background-color: #f2f2f2; color: #333; text-decoration: none; transition: background-color 0.2s ease;} + a { color: black; text-decoration: none;} + + a:hover, + a:focus, + a:visited, + a:active { + text-decoration: none; + } + .pagination .current { background: #1f2937; color: #fff; } + h2, h3 { margin-top: 0; } diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..9041240 --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,125 @@ +//Две функции в файле - добавление и редактирование. Загружаются при загрузке странице, +//ищут переменные по id или имени, добавляются к переменным через EventListener +document.addEventListener("DOMContentLoaded", () => { + const idInput = document.querySelector('input[name="new_id"]'); + const csInput = document.querySelector('input[name="new_callsign"]'); + const submitBtn = document.getElementById('submit-btn'); + const idError = document.getElementById('id-error'); + const csError = document.getElementById('callsign-error'); + const latinError = document.getElementById('latin-error'); + const optionalInputs = document.querySelectorAll('.add-form input[type="text"]:not([name="new_callsign"]):not([name="remarks"])'); + + async function check() { + const id = idInput.value.trim(); + const callsign = csInput.value.trim(); + idError.textContent = ''; + csError.textContent = ''; + latinError.textContent = ''; + submitBtn.disabled = false; + //Вызываем метод из логики на валидацию + const res = await fetch(`?ajax_check=1&id=${encodeURIComponent(id)}&callsign=${encodeURIComponent(callsign)}`); + const json = await res.json(); + + if (json.idInvalid) { + idError.textContent = 'ID должен быть 6–7 цифр.'; + } else if (json.idExists) { + idError.textContent = 'Такой ID уже существует.'; + } + + if (json.callsignInvalid) { + csError.textContent = 'Позывной: 4–7 латинских символов/цифр.'; + } else if (json.callsignExists) { + csError.textContent = 'Такой позывной уже существует.'; + } + + if (json.idInvalid || json.idExists || json.callsignInvalid || json.callsignExists) { + submitBtn.disabled = true; + } + + for (const input of optionalInputs) { + if (input.value && !/^[a-zA-Z\s]*$/.test(input.value)) { + latinError.textContent = 'Дополнительные поля должны содержать только латиницу.'; + submitBtn.disabled = true; + break; + } + } + } + //Добавляем функцию на ввод + idInput.addEventListener('input', check); + csInput.addEventListener('input', check); + optionalInputs.forEach(input => input.addEventListener('input', check)); +}); + +//Редактирование +document.addEventListener('DOMContentLoaded', function () { + //По клику получаем ближайшую ячеку и строку + document.querySelectorAll('.edit-btn').forEach(btn => { + btn.addEventListener('click', function (e) { + e.preventDefault(); + const td = btn.closest('td'); + const tr = td.closest('tr'); + const id = tr.cells[0].innerText; + + if (tr.classList.contains('editing')) return; + + tr.classList.add('editing'); + const cells = tr.querySelectorAll('td'); + const headers = ['id', 'callsign', 'fname', 'surname', 'city', 'state', 'country', 'remarks']; + //Проходимся по ячейкам и меняем то, что внутри, ограничиваем позывной и телеграм + for (let i = 1; i < cells.length - 1; i++) { + const field = headers[i]; + const value = cells[i].textContent.trim(); + console.log(field); + let inputHTML = ``; + cells[i].innerHTML = inputHTML; + + const input = cells[i].querySelector('input'); + input.addEventListener('input', () => { + input.value = input.value.replace(/[^A-Za-z0-9]/g, ''); + }); + + } else if (field === 'remarks') { + inputHTML += ` maxlength="32">`; + cells[i].innerHTML = inputHTML; + + const input = cells[i].querySelector('input'); + input.addEventListener('input', () => { + input.value = input.value.replace(/[^A-Za-z0-9_]/g, ''); + }); + + } else { + inputHTML += '>'; + cells[i].innerHTML = inputHTML; + } + } + + //Меняем внутреннее содержимое ячейки + td.innerHTML = ` + + + `; + //Отправляем в класс с логикой + td.querySelector('.save-btn').addEventListener('click', () => { + const data = { "id": id}; + console.log('click on test'); + for (let i = 1; i < cells.length - 1; i++) { + const input = cells[i].querySelector('input'); + data[headers[i]] = input.value; + } + + fetch('?edit=1', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }).then(res => {location.reload();}); + }); + //Просто перезагружаем страницу - ничего не отправляем + td.querySelector('.cancel-btn').addEventListener('click', () => location.reload()); + }); + }); +}); diff --git a/check_unique.php b/check_unique.php new file mode 100644 index 0000000..b3b9327 --- /dev/null +++ b/check_unique.php @@ -0,0 +1,58 @@ + false, + 'callsignExists' => false, + 'idInvalid' => false, + 'callsignInvalid' => false, +]; + +// Валидация ID +if (!preg_match('/^\d{6,7}$/', $new_id)) { + $response['idInvalid'] = true; +} + +// Валидация позывного +if (!preg_match('/^[A-Z0-9]{4,7}$/', $new_callsign)) { + $response['callsignInvalid'] = true; +} + +// Проверка в db.json +$dbPath = __DIR__ . '/db.json'; +if (file_exists($dbPath)) { + $json = json_decode(file_get_contents($dbPath), true); + foreach ($json as $entry) { + if (isset($entry['id']) && $entry['id'] == $new_id) { + $response['idExists'] = true; + } + if (isset($entry['callsign']) && strcasecmp($entry['callsign'], $new_callsign) === 0) { + $response['callsignExists'] = true; + } + } +} + +// Проверка в dmrid.dat +$dmrPath = __DIR__ . '/dmrid.dat'; +if (file_exists($dmrPath)) { + $lines = file($dmrPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + foreach ($lines as $line) { + $parts = explode(';', $line); + if (count($parts) >= 2) { + $id = trim($parts[0]); + $cs = trim($parts[1]); + + if ($id === $new_id) { + $response['idExists'] = true; + } + if (strcasecmp($cs, $new_callsign) === 0) { + $response['callsignExists'] = true; + } + } + } +} + +echo json_encode($response); diff --git a/db.json b/db.json new file mode 100644 index 0000000..faabbc8 --- /dev/null +++ b/db.json @@ -0,0 +1,2513 @@ +{ + "count": 228, + "results": [ + { + "id": 1400001, + "callsign": "PHOENIX", + "fname": "ADMIN", + "surname": "", + "city": "Aldan", + "state": "YAKUTIA", + "country": "Russia", + "remarks": "DMRYKT", + "confirmed": true + }, + { + "id": 1030095, + "callsign": "EVGEN", + "fname": "EVGENY", + "surname": "", + "city": "Smolensk", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 6700001, + "callsign": "SEVER", + "fname": "EVGENY", + "surname": "", + "city": "Smolensk", + "state": "", + "country": "Russia", + "remarks": "XLXSMK", + "confirmed": true + }, + { + "id": 140001, + "callsign": "XLXSMK", + "fname": "", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 140004, + "callsign": "XLXPDS", + "fname": "", + "surname": "", + "city": "Podolsk", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 140005, + "callsign": "ECHO", + "fname": "ECHOTEST", + "surname": "", + "city": "", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 1030217, + "callsign": "PHOENIX", + "fname": "Viktor", + "surname": "", + "city": "Aldan", + "state": "Yakutia", + "country": "Russia", + "remarks": "viktor14R", + "confirmed": true + }, + { + "id": 6700002, + "callsign": "DVSB", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6700003, + "callsign": "DVSF", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030176, + "callsign": "KASKAD", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1400077, + "callsign": "DYNAMIT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030174, + "callsign": "LEKTRON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501655, + "callsign": "ICEBERG", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030169, + "callsign": "RAMON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030171, + "callsign": "ZELLO", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030170, + "callsign": "FRNLINK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030167, + "callsign": "LESHIY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030166, + "callsign": "FAGOT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030165, + "callsign": "STALKER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501501, + "callsign": "IRON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030152, + "callsign": "USER1", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030153, + "callsign": "USER2", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030154, + "callsign": "USER3", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030155, + "callsign": "USER4", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030156, + "callsign": "USER5", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030157, + "callsign": "BARMI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030158, + "callsign": "USER7", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030159, + "callsign": "USER8", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030160, + "callsign": "USER9", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030161, + "callsign": "USER10", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500460, + "callsign": "RYBAK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500779, + "callsign": "R7KAY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7801620, + "callsign": "MUTABOR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030148, + "callsign": "JUPITER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 5000941, + "callsign": "KIRPICH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030144, + "callsign": "EGERY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2840338, + "callsign": "HBLINK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030136, + "callsign": "RYBACH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030137, + "callsign": "LUDZA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030138, + "callsign": "BUY27", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030139, + "callsign": "DEMBI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030140, + "callsign": "KOLDA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030141, + "callsign": "GRAS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030142, + "callsign": "GRAS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030143, + "callsign": "KOPPI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501513, + "callsign": "SWIFT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030134, + "callsign": "REGION", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030133, + "callsign": "VOLNA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030132, + "callsign": "SUMRAK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501517, + "callsign": "R2BRI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7804951, + "callsign": "DUNAY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030129, + "callsign": "RUBEZH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2503228, + "callsign": "KARDAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030127, + "callsign": "HAUX", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030126, + "callsign": "NEBO2", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030125, + "callsign": "LUCKY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550059, + "callsign": "GITARIST", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030123, + "callsign": "DIZEL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030122, + "callsign": "AKRA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2503128, + "callsign": "SIMBA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7807808, + "callsign": "YKCYC", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 2501250, + "callsign": "ADVOKAT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030118, + "callsign": "KARAT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2509132, + "callsign": "BARISTA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030106, + "callsign": "CHAMBAR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501316, + "callsign": "NARCISS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550001, + "callsign": "ARENDAT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550002, + "callsign": "UMBRELA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550003, + "callsign": "MIHA111", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550004, + "callsign": "KAREL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550006, + "callsign": "ZS6DLK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550008, + "callsign": "ZS6RES", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550009, + "callsign": "EVGEN", + "fname": "EVGENY", + "surname": "", + "city": "Smolensk", + "state": "", + "country": "Russia", + "remarks": "XLXSMK", + "confirmed": true + }, + { + "id": 6550010, + "callsign": "MAGUS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030104, + "callsign": "ARENDAT", + "fname": "Anatoly", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 2500352, + "callsign": "EGORYCH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2570200, + "callsign": "STRELA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030103, + "callsign": "MALOY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501349, + "callsign": "FOXMAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030098, + "callsign": "NARCIS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030097, + "callsign": "SHTURMN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501301, + "callsign": "GRACH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030040, + "callsign": "ARKTEST", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030096, + "callsign": "BARMI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030092, + "callsign": "ALEXBUT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030091, + "callsign": "MASHUK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030088, + "callsign": "AKCENT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030086, + "callsign": "NET1", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6555027, + "callsign": "BOGDAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030084, + "callsign": "BOGDAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030083, + "callsign": "KARAS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501190, + "callsign": "IGORH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030081, + "callsign": "AZGARD", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030080, + "callsign": "MORSKOY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501231, + "callsign": "PENZA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030078, + "callsign": "VORON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030077, + "callsign": "AZART", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030100, + "callsign": "DOCTOR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2864293, + "callsign": "MIHA111", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2508125, + "callsign": "MEHANIK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030074, + "callsign": "GRANIT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501366, + "callsign": "SASHKO", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030072, + "callsign": "FRNLINK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 2518001, + "callsign": "KORUS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030070, + "callsign": "SLITER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 4700830, + "callsign": "FDR830", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030068, + "callsign": "ALEX203", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2502228, + "callsign": "PRORAB", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030066, + "callsign": "PRORAB", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501099, + "callsign": "KIPARIS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7800056, + "callsign": "AYVENGO", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6700067, + "callsign": "VIRAJ", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030061, + "callsign": "SAN428", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501182, + "callsign": "POOH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030059, + "callsign": "DVINA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2570193, + "callsign": "KANAPA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030057, + "callsign": "AYDAR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030003, + "callsign": "MIHA111", + "fname": "Mihail", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 1030056, + "callsign": "GNOM", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500358, + "callsign": "NAIL44", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1230311, + "callsign": "YUG311", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500780, + "callsign": "MAX03", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500945, + "callsign": "DIMGRAD", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030178, + "callsign": "RYAZAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030049, + "callsign": "LEXUS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500944, + "callsign": "KALASH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7700023, + "callsign": "BARON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030002, + "callsign": "UMBREL", + "fname": "Ivan", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 1030046, + "callsign": "VETER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030004, + "callsign": "VOSTOK", + "fname": "Dmitriy", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 1030005, + "callsign": "ELISTA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030006, + "callsign": "ARTEK", + "fname": "Slavik", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 1030007, + "callsign": "VLAD770", + "fname": "Vlad", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 1030008, + "callsign": "GITARIS", + "fname": "Mihail", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 1030009, + "callsign": "TRI333", + "fname": "Nikolay", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 1030011, + "callsign": "URAL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030013, + "callsign": "AYAKS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500263, + "callsign": "NOVAK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030016, + "callsign": "DMITROV", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030012, + "callsign": "VOST555", + "fname": "zxvxz", + "surname": "zxcxzc", + "city": "zxczxc", + "state": "zxczxc", + "country": "zxczx", + "remarks": "", + "confirmed": true + }, + { + "id": 1030018, + "callsign": "SENATOR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030030, + "callsign": "STELS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030021, + "callsign": "DANTIST", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2502181, + "callsign": "DMIT920", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2570148, + "callsign": "MASTER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500887, + "callsign": "ALEX", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030027, + "callsign": "KARE", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2502168, + "callsign": "BUMER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2506145, + "callsign": "GURZA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030032, + "callsign": "ARTEM48", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030033, + "callsign": "LESNIK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 5973777, + "callsign": "SOKOL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500222, + "callsign": "VOLKIS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6555016, + "callsign": "URAL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 4600403, + "callsign": "ARTEK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550007, + "callsign": "VLAD770", + "fname": "Vlad", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 6555008, + "callsign": "NAVIRUS", + "fname": "Serega", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 2503316, + "callsign": "GITARIS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500247, + "callsign": "SOKOL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030038, + "callsign": "MAZAY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2502072, + "callsign": "GRANIT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030001, + "callsign": "NAVIRUS", + "fname": "Serega", + "surname": "", + "city": "Moscow", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 2501668, + "callsign": "NEMOI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1400841, + "callsign": "YAKUT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500893, + "callsign": "BOREY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501457, + "callsign": "ALEX77", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030182, + "callsign": "BRONIX", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030183, + "callsign": "KALITKA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030184, + "callsign": "0350", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 5600001, + "callsign": "VLAD46", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501726, + "callsign": "PATRIOT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2509122, + "callsign": "DOMINIK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030188, + "callsign": "AVER89", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030189, + "callsign": "MAGNAT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030191, + "callsign": "TERIKON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030192, + "callsign": "OCTOBER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501757, + "callsign": "TRIDVA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030194, + "callsign": "LIMAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1111777, + "callsign": "TRAKTOR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030196, + "callsign": "UDM697", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500773, + "callsign": "ITMAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500500, + "callsign": "PORU4IK", + "fname": "Alexandr", + "surname": "", + "city": "Podolsk", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 2501815, + "callsign": "KAREL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7900001, + "callsign": "DIMA55", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030201, + "callsign": "ANTIK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501712, + "callsign": "KLIM45", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030203, + "callsign": "DENKENG", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030204, + "callsign": "1908", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030205, + "callsign": "NUMARK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030207, + "callsign": "IGOR377", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500866, + "callsign": "PRAD0SC", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501222, + "callsign": "ENOT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030212, + "callsign": "RUSSIA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030214, + "callsign": "GROZA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501263, + "callsign": "REDDI77", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030216, + "callsign": "BOTCHI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501789, + "callsign": "BURAN88", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500810, + "callsign": "SLON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 5500055, + "callsign": "ROSTIK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030230, + "callsign": "DANAG", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501891, + "callsign": "MEXAHNK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030232, + "callsign": "ZEZERON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030233, + "callsign": "PEAKTOP", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030234, + "callsign": "ZATON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030235, + "callsign": "ROKOT40", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501931, + "callsign": "ENGINER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030239, + "callsign": "DENNM", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030240, + "callsign": "FDMA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030241, + "callsign": "GAGIN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501918, + "callsign": "IRTISH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 4000001, + "callsign": "AVIATOR", + "fname": "Dmitriy", + "surname": "", + "city": "Kaluga", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 2502062, + "callsign": "TRUBACH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2506090, + "callsign": "KAVKAZ", + "fname": "Alexandr", + "surname": "", + "city": "Maykop", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 1030249, + "callsign": "AMUR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1419867, + "callsign": "JDJDDJ", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1415260, + "callsign": "123123", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2508021, + "callsign": "KORUS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500591, + "callsign": "VLAD", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2506134, + "callsign": "KAVKAZ", + "fname": "Alexandr", + "surname": "", + "city": "Maykop", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 2501956, + "callsign": "MARCUS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7900002, + "callsign": "SHULTZ", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6401088, + "callsign": "MITRA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 140003, + "callsign": "XLXARK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 140000, + "callsign": "XLXYKT", + "fname": "BRIDGE", + "surname": "", + "city": "Aldan", + "state": "Yakutia", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 2506105, + "callsign": "PHOENIX", + "fname": "Viktor", + "surname": "", + "city": "Aldan", + "state": "Yakutia", + "country": "Russia", + "remarks": "viktor14R", + "confirmed": true + }, + { + "id": 2506217, + "callsign": "KASKAD", + "fname": "Roma", + "surname": "", + "city": "Maikop", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 141000, + "callsign": "HBLINK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 145001, + "callsign": "PISTAR1", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + } + ] +} \ No newline at end of file diff --git a/dmrid.dat b/dmrid.dat new file mode 100644 index 0000000..a2b7e7e --- /dev/null +++ b/dmrid.dat @@ -0,0 +1,228 @@ +1400001;PHOENIX; +1030095;EVGEN; +6700001;SEVER; +140001;XLXSMK; +140004;XLXPDS; +140005;ECHO; +1030217;PHOENIX; +6700002;DVSB; +6700003;DVSF; +1030176;KASKAD; +1400077;DYNAMIT; +1030174;LEKTRON; +2501655;ICEBERG; +1030171;ZELLO; +1030170;FRNLINK; +1030167;LESHIY; +1030166;FAGOT; +1030165;STALKER; +2501501;IRON; +1030152;USER1; +1030153;USER2; +1030154;USER3; +1030155;USER4; +1030156;USER5; +1030157;BARMI; +1030158;USER7; +1030159;USER8; +1030160;USER9; +1030161;USER10; +2500460;RYBAK; +2500779;R7KAY; +7801620;MUTABOR; +1030148;JUPITER; +5000941;KIRPICH; +1030144;EGERY; +2840338;HBLINK; +1030136;RYBACH; +1030137;LUDZA; +1030138;BUY27; +1030139;DEMBI; +1030140;KOLDA; +1030141;GRAS; +1030142;GRAS; +1030143;KOPPI; +2501513;SWIFT; +1030134;REGION; +1030133;VOLNA; +1030132;SUMRAK; +2501517;R2BRI; +7804951;DUNAY; +1030129;RUBEZH; +2503228;KARDAN; +1030127;HAUX; +1030126;NEBO2; +1030125;LUCKY; +6550059;GITARIST; +1030123;DIZEL; +1030122;AKRA; +2503128;SIMBA; +7807808;YKCYC; +2501250;ADVOKAT; +1030118;KARAT; +2509132;BARISTA; +1030106;CHAMBAR; +2501316;NARCISS; +6550001;ARENDAT; +6550002;UMBRELA; +6550003;MIHA111; +6550004;KAREL; +6550006;ZS6DLK; +6550008;ZS6RES; +6550009;EVGEN; +6550010;MAGUS; +1030104;ARENDAT; +2500352;EGORYCH; +2570200;STRELA; +1030103;MALOY; +2501349;FOXMAN; +1030098;NARCIS; +1030097;SHTURMN; +2501301;GRACH; +1030040;ARKTEST; +1030096;BARMI; +1030092;ALEXBUT; +1030091;MASHUK; +1030088;AKCENT; +1030086;NET1; +6555027;BOGDAN; +1030084;BOGDAN; +1030083;KARAS; +2501190;IGORH; +1030081;AZGARD; +1030080;MORSKOY; +2501231;PENZA; +1030078;VORON; +1030077;AZART; +1030100;DOCTOR; +2864293;MIHA111; +2508125;MEHANIK; +1030074;GRANIT; +2501366;SASHKO; +1030072;FRNLINK; +2518001;KORUS; +1030070;SLITER; +4700830;FDR830; +1030068;ALEX203; +2502228;PRORAB; +1030066;PRORAB; +2501099;KIPARIS; +7800056;AYVENGO; +6700067;VIRAJ; +1030061;SAN428; +2501182;POOH; +1030059;DVINA; +2570193;KANAPA; +1030057;AYDAR; +1030003;MIHA111; +1030056;GNOM; +2500358;NAIL44; +1230311;YUG311; +2500780;MAX03; +2500945;DIMGRAD; +1030178;RYAZAN; +1030049;LEXUS; +2500944;KALASH; +7700023;BARON; +1030002;UMBREL; +1030046;VETER; +1030004;VOSTOK; +1030005;ELISTA; +1030006;ARTEK; +1030007;VLAD770; +1030008;GITARIS; +1030009;TRI333; +1030011;URAL; +1030013;AYAKS; +2500263;NOVAK; +1030016;DMITROV; +1030012;VOST555; +1030018;SENATOR; +1030030;STELS; +1030021;DANTIST; +2502181;DMIT920; +2570148;MASTER; +2500887;ALEX; +1030027;KARE; +2502168;BUMER; +2506145;GURZA; +1030032;ARTEM48; +1030033;LESNIK; +5973777;SOKOL; +2500222;VOLKIS; +6555016;URAL; +4600403;ARTEK; +6550007;VLAD770; +6555008;NAVIRUS; +2503316;GITARIS; +2500247;SOKOL; +1030038;MAZAY; +2502072;GRANIT; +1030001;NAVIRUS; +2501668;NEMOI; +1400841;YAKUT; +2500893;BOREY; +2501457;ALEX77; +1030182;BRONIX; +1030183;KALITKA; +1030184;0350; +5600001;VLAD46; +2501726;PATRIOT; +2509122;DOMINIK; +1030188;AVER89; +1030189;MAGNAT; +1030191;TERIKON; +1030192;OCTOBER; +2501757;TRIDVA; +1030194;LIMAN; +1111777;TRAKTOR; +1030196;UDM697; +2500773;ITMAN; +2500500;PORU4IK; +2501815;KAREL; +7900001;DIMA55; +1030201;ANTIK; +2501712;KLIM45; +1030203;DENKENG; +1030204;1908; +1030205;NUMARK; +1030207;IGOR377; +2500866;PRAD0SC; +2501222;ENOT; +1030212;RUSSIA; +1030214;GROZA; +2501263;REDDI77; +1030216;BOTCHI; +2501789;BURAN88; +2500810;SLON; +5500055;ROSTIK; +1030230;DANAG; +2501891;MEXAHNK; +1030232;ZEZERON; +1030233;PEAKTOP; +1030234;ZATON; +1030235;ROKOT40; +2501931;ENGINER; +1030239;DENNM; +1030240;FDMA; +1030241;GAGIN; +2501918;IRTISH; +4000001;AVIATOR; +2502062;TRUBACH; +2506090;KAVKAZ; +1030249;AMUR; +1419867;JDJDDJ; +1415260;123123; +2508021;KORUS; +2500591;VLAD; +2506134;KAVKAZ; +2501956;MARCUS; +7900002;SHULTZ; +6401088;MITRA; +140003;XLXARK; +140000;XLXYKT; +2506105;PHOENIX; +2506217;KASKAD; +141000;HBLINK; +145001;PISTAR1; +1030169;RAMON; diff --git a/index.php b/index.php new file mode 100644 index 0000000..7c2d56a --- /dev/null +++ b/index.php @@ -0,0 +1,71 @@ + 'Админка', + 'https://xlx.dmrykt.ru/' => 'XLX Сервер', + 'db.json' => 'Файл базы данных для HBLink', + 'dmrid.dat' => 'Файл базы данных для XLX', + 'https://xlx.dmrykt.ru/pistar/DMRIdsYKT.dat' => 'Файл базы данных для Pi-star', +]; +?> + + + + + DMR ID Панель + + + +
+

Панель управления DMR ID

+ $label): ?> + + +
+ + diff --git a/register.php b/register.php new file mode 100644 index 0000000..46ad397 --- /dev/null +++ b/register.php @@ -0,0 +1,195 @@ + 0, 'results' => []]; + $data = $json['results']; + + foreach ($data as $row) { + if (strcasecmp($row['callsign'], $callsign) === 0) { + $errorMessage = "Такой позывной уже существует!"; + break; + } + } + + if (!$errorMessage) { + do { + $newId = rand(1410000, 1419999); + $used = false; + foreach ($data as $row) { + if ($row['id'] == $newId) { + $used = true; + break; + } + } + } while ($used); + + $data[] = [ + "id" => $newId, + "callsign" => $callsign, + "fname" => $_POST['fname'] ?? "", + "surname" => $_POST['surname'] ?? "", + "city" => $_POST['city'] ?? "", + "state" => $_POST['state'] ?? "", + "country" => $_POST['country'] ?? "", + "remarks" => $_POST['remarks'] ?? "", + "confirmed" => false + ]; + + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + + header("Location: register.php?success=1"); + exit; + } + } +} +if (isset($_GET['success'])) { + $successMessage = "Заявка отправлена! Ожидайте подтверждения."; +} +?> + + + + + Регистрация DMR + + + + +

Заявка на DMR ID

+ + +

+ + + +

+ + +
+ +
Позывной должен содержать только латинские буквы и цифры (4–7 символов)
+ +
Telegram Обязательное поле, только латинские буквы и цифры.
+ + + + + +
Дополнительные поля должны содержать только латиницу (A-Z).
+ + +
+ + + + + diff --git a/savedata/admin.php b/savedata/admin.php new file mode 100644 index 0000000..04bf8f8 --- /dev/null +++ b/savedata/admin.php @@ -0,0 +1,405 @@ + 0, 'results' => []]; +$data = $json['results']; + +if (isset($_GET['ajax_check'])) { + $id = $_GET['id'] ?? ''; + $callsign = strtoupper(trim($_GET['callsign'] ?? '')); + $response = [ + 'idInvalid' => !preg_match('/^\d{6,7}$/', $id), + 'idExists' => false, + 'callsignInvalid' => !preg_match('/^[A-Z0-9]{4,7}$/', $callsign), + 'callsignExists' => false + ]; + foreach ($data as $row) { + if ($row['id'] == $id) $response['idExists'] = true; + if (strtoupper($row['callsign']) === $callsign) $response['callsignExists'] = true; + } + header('Content-Type: application/json'); + echo json_encode($response); + exit; +} + +if (isset($_GET['sync'])) { + $confirmed = []; + foreach ($data as $item) { + if (!empty($item['confirmed'])) { + $confirmed["{$item['id']};{$item['callsign']};"] = true; + } + } + + $lines = file($datFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $filtered = array_filter($lines, function($line) use ($confirmed) { + return isset($confirmed[trim($line)]); + }); + + $existingLines = array_flip(array_map('trim', $lines)); + foreach ($confirmed as $entry => $val) { + if (!isset($existingLines[$entry])) { + $filtered[] = $entry; + } + } + + file_put_contents($datFile, implode(PHP_EOL, $filtered) . PHP_EOL); + + header("Location: " . strtok($_SERVER["REQUEST_URI"], '?')); + exit; +} + +if (isset($_GET['confirm'])) { + $confirmId = (int)$_GET['confirm']; + + foreach ($data as &$item) { + if ($item['id'] === $confirmId) { + $item['confirmed'] = true; + + $lines = file($datFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $entry = "{$item['id']};{$item['callsign']};"; + + if (!in_array($entry, $lines)) { + file_put_contents($datFile, $entry . PHP_EOL, FILE_APPEND); + } + + break; + } + } + unset($item); + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + header("Location: " . strtok($_SERVER["REQUEST_URI"], '?')); + exit; +} + +if (isset($_GET['block'])) { + $confirmId = (int)$_GET['block']; + + foreach ($data as &$item) { + if ($item['id'] === $confirmId) { + $item['confirmed'] = false; + + $lines = file($datFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $entry = "{$item['id']};{$item['callsign']};"; + + $filtered = array_filter($lines, function($line) use ($entry) { + return trim($line) !== $entry; + }); + + file_put_contents($datFile, implode(PHP_EOL, $filtered) . PHP_EOL); + + break; + } + } + unset($item); + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + header("Location: " . strtok($_SERVER["REQUEST_URI"], '?')); + exit; +} + +if (isset($_GET['delete'])) { + $deleteId = (int)$_GET['delete']; + + $callsign = null; + + foreach ($data as $index => $item) { + if ($item['id'] === $deleteId) { + $callsign = $item['callsign']; + unset($data[$index]); + break; + } + } + + $data = array_values($data); + + if ($callsign === null) { + header("Location: " . strtok($_SERVER["REQUEST_URI"], '?')); + exit; + } + + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + + $lines = file($datFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $filtered = array_filter($lines, function($line) use ($deleteId, $callsign) { + return trim($line) !== "{$deleteId};{$callsign};"; + }); + + file_put_contents($datFile, implode(PHP_EOL, $filtered) . PHP_EOL); + header("Location: " . strtok($_SERVER["REQUEST_URI"], '?')); + exit; +} + +$form_error = ''; +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $new_id = (int)$_POST['new_id']; + $callsign = strtoupper(trim($_POST['new_callsign'])); + $fname = trim($_POST['fname'] ?? ''); + $surname = trim($_POST['surname'] ?? ''); + $city = trim($_POST['city'] ?? ''); + $state = trim($_POST['state'] ?? ''); + $country = trim($_POST['country'] ?? ''); + $remarks = trim($_POST['remarks'] ?? ''); + + if ($new_id < 100000 || $new_id > 9999999) { + $form_error = 'ID должен быть 6–7 цифр.'; + } elseif (!preg_match('/^[A-Z0-9]{4,7}$/', $callsign)) { + $form_error = 'Позывной: 4–7 латинских символов/цифр.'; + } elseif (array_filter($data, fn($r) => $r['id'] == $new_id || strtoupper($r['callsign']) === $callsign)) { + $form_error = 'Такой ID или позывной уже существует.'; + } elseif (preg_match('/[^a-zA-Z\s]/', $fname . $surname . $city . $state . $country . $remarks)) { + $form_error = 'Дополнительные поля должны содержать только латиницу.'; + } else { + $data[] = [ + 'id' => $new_id, + 'callsign' => $callsign, + 'fname' => $fname, + 'surname' => $surname, + 'city' => $city, + 'state' => $state, + 'country' => $country, + 'remarks' => $remarks, + 'confirmed' => true + ]; + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + + $dat_line = "{$new_id};{$callsign};" . PHP_EOL; + file_put_contents($datFile, $dat_line, FILE_APPEND); + + header("Location: admin.php"); + exit; + } +} +$confirmed = array_values(array_filter($data, fn($d) => !empty($d['confirmed']))); +$page = max(1, (int)($_GET['page'] ?? 1)); +$perPage = 15; +$total = count($confirmed); +$totalPages = ceil($total / $perPage); +$offset = ($page - 1) * $perPage; +$currentPageData = array_slice($confirmed, $offset, $perPage); +?> + + + + + + Админка DMR + + + + +
Панель администратора DMR +
+ + +
+
+ +
+
+

Заявки

+
+ +
+ ID:
+ Позывной:
+ Имя:
+ Фамилия:
+ Город:
+ Регион:
+ Страна:
+ Примечание:
+
+ + Удалить + Заблокировать + +
+ +
+ 1): ?> + + +
+ +
+

Добавить вручную

+ +
+ +
+ +
+ + +
+ + + + + + + +
+ +
+ +
+

Ожидают подтверждения

+ + + + + +
+
+
+ + + + + diff --git a/savedata/db.json b/savedata/db.json new file mode 100644 index 0000000..6086529 --- /dev/null +++ b/savedata/db.json @@ -0,0 +1,2557 @@ +{ + "count": 232, + "results": [ + { + "id": 1400001, + "callsign": "ADMIN", + "fname": "ADMIN", + "surname": "YKT", + "city": "Aldan", + "state": "YAKUTIA", + "country": "Russia", + "remarks": "TG: @DMRYKT", + "confirmed": true + }, + { + "id": 1030095, + "callsign": "EVGEN", + "fname": "EVGENY", + "surname": "Smolensk", + "city": "Smolensk", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 6700001, + "callsign": "SEVER", + "fname": "EVGENY", + "surname": "Smolensk", + "city": "Smolensk", + "state": "", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 140001, + "callsign": "XLXSMK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 140002, + "callsign": "XLXYKT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 140003, + "callsign": "XLXARK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 140004, + "callsign": "XLXPDS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 140005, + "callsign": "ECHO", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030217, + "callsign": "PHOENIX", + "fname": "Viktor", + "surname": "Yakutia", + "city": "Aldan", + "state": "Yakutia", + "country": "Russia", + "remarks": "", + "confirmed": true + }, + { + "id": 1412262, + "callsign": "SEVERY", + "fname": "ssk", + "surname": "ddjjks", + "city": "joiio", + "state": "jnjnkj", + "country": "jnnj", + "remarks": "jnjnj", + "confirmed": true + }, + { + "id": 1410461, + "callsign": "TESTI", + "fname": "dksjdjk", + "surname": "dcs", + "city": "cds", + "state": "sd", + "country": "dsc", + "remarks": "idc", + "confirmed": true + }, + { + "id": 670001, + "callsign": "XLXB", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 670003, + "callsign": "PODOLSK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6700002, + "callsign": "DVSB", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6700003, + "callsign": "DVSF", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030176, + "callsign": "KASKAD", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1400077, + "callsign": "DYNAMIT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030174, + "callsign": "LEKTRON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501655, + "callsign": "ICEBERG", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030169, + "callsign": "RAMON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030171, + "callsign": "ZELLO", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030170, + "callsign": "FRNLINK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030167, + "callsign": "LESHIY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030166, + "callsign": "FAGOT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030165, + "callsign": "STALKER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030164, + "callsign": "NIRVANA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501501, + "callsign": "IRON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030152, + "callsign": "USER1", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030153, + "callsign": "USER2", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030154, + "callsign": "USER3", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030155, + "callsign": "USER4", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030156, + "callsign": "USER5", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030157, + "callsign": "BARMI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030158, + "callsign": "USER7", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030159, + "callsign": "USER8", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030160, + "callsign": "USER9", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030161, + "callsign": "USER10", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500460, + "callsign": "RYBAK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500779, + "callsign": "R7KAY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7801620, + "callsign": "MUTABOR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030148, + "callsign": "JUPITER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 5000941, + "callsign": "KIRPICH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030144, + "callsign": "EGERY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2840338, + "callsign": "HBLINK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030136, + "callsign": "RYBACH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030137, + "callsign": "LUDZA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030138, + "callsign": "BUY27", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030139, + "callsign": "DEMBI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030140, + "callsign": "KOLDA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030141, + "callsign": "GRAS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030142, + "callsign": "GRAS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030143, + "callsign": "KOPPI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501513, + "callsign": "SWIFT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030134, + "callsign": "REGION", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030133, + "callsign": "VOLNA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030132, + "callsign": "SUMRAK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501517, + "callsign": "R2BRI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7804951, + "callsign": "DUNAY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030129, + "callsign": "RUBEZH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2503228, + "callsign": "KARDAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030127, + "callsign": "HAUX", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030126, + "callsign": "NEBO2", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030125, + "callsign": "LUCKY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550059, + "callsign": "GITARIST", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030123, + "callsign": "DIZEL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030122, + "callsign": "AKRA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2503128, + "callsign": "SIMBA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7807808, + "callsign": "YKCYC", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501250, + "callsign": "ADVOKAT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030118, + "callsign": "KARAT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2509132, + "callsign": "BARISTA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030106, + "callsign": "CHAMBAR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501316, + "callsign": "NARCISS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550001, + "callsign": "ARENDAT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550002, + "callsign": "UMBRELA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550003, + "callsign": "MIHA111", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550004, + "callsign": "KAREL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550006, + "callsign": "ZS6DLK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550008, + "callsign": "ZS6RES", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550009, + "callsign": "EVGEN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550010, + "callsign": "MAGUS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030104, + "callsign": "ARENDAT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500352, + "callsign": "EGORYCH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2570200, + "callsign": "STRELA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030103, + "callsign": "MALOY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501349, + "callsign": "FOXMAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030098, + "callsign": "NARCIS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030097, + "callsign": "SHTURMN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501301, + "callsign": "GRACH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030040, + "callsign": "ARKTEST", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030096, + "callsign": "BARMI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030092, + "callsign": "ALEXBUT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030091, + "callsign": "MASHUK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030088, + "callsign": "AKCENT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1000780, + "callsign": "P25", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030086, + "callsign": "NET1", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030087, + "callsign": "NET2", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6555027, + "callsign": "BOGDAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030084, + "callsign": "BOGDAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030083, + "callsign": "KARAS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501190, + "callsign": "IGORH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030081, + "callsign": "AZGARD", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030080, + "callsign": "MORSKOY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501231, + "callsign": "PENZA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030078, + "callsign": "VORON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030077, + "callsign": "AZART", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030100, + "callsign": "DOCTOR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2864293, + "callsign": "MIHA111", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2508125, + "callsign": "MEHANIK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030074, + "callsign": "GRANIT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501366, + "callsign": "SASHKO", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030072, + "callsign": "FRNLINK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2518001, + "callsign": "KORUS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030070, + "callsign": "SLITER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 4700830, + "callsign": "FDR830", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030068, + "callsign": "ALEX203", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2502228, + "callsign": "PRORAB", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030066, + "callsign": "PRORAB", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501099, + "callsign": "KIPARIS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7800056, + "callsign": "AYVENGO", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6700067, + "callsign": "VIRAJ", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030061, + "callsign": "SAN428", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501182, + "callsign": "POOH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030059, + "callsign": "DVINA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2570193, + "callsign": "KANAPA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030057, + "callsign": "AYDAR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030003, + "callsign": "MIHA111", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030056, + "callsign": "GNOM", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500358, + "callsign": "NAIL44", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1230311, + "callsign": "YUG311", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500780, + "callsign": "MAX03", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500945, + "callsign": "DIMGRAD", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030178, + "callsign": "RYAZAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030049, + "callsign": "LEXUS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500944, + "callsign": "KALASH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7700023, + "callsign": "BARON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030002, + "callsign": "UMBREL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030046, + "callsign": "VETER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030004, + "callsign": "VOSTOK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030005, + "callsign": "ELISTA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030006, + "callsign": "ARTEK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030007, + "callsign": "VLAD770", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030008, + "callsign": "GITARIS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030009, + "callsign": "TRI333", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030011, + "callsign": "URAL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030013, + "callsign": "AYAKS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500263, + "callsign": "NOVAK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030016, + "callsign": "DMITROV", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030012, + "callsign": "VOST555", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030018, + "callsign": "SENATOR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030030, + "callsign": "STELS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030021, + "callsign": "DANTIST", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2502181, + "callsign": "DMIT920", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2570148, + "callsign": "MASTER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500887, + "callsign": "ALEX", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030027, + "callsign": "KARE", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2502168, + "callsign": "BUMER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2506145, + "callsign": "GURZA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030032, + "callsign": "ARTEM48", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030033, + "callsign": "LESNIK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 5973777, + "callsign": "SOKOL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500222, + "callsign": "VOLKIS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6555016, + "callsign": "URAL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 4600403, + "callsign": "ARTEK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6550007, + "callsign": "VLAD770", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 6555008, + "callsign": "NAVIRUS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2503316, + "callsign": "GITARIS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500247, + "callsign": "SOKOL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030038, + "callsign": "MAZAY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2502072, + "callsign": "GRANIT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030001, + "callsign": "NAVIRUS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501668, + "callsign": "NEMOI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1400841, + "callsign": "YAKUT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500893, + "callsign": "BOREY", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501457, + "callsign": "ALEX77", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030182, + "callsign": "BRONIX", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030183, + "callsign": "KALITKA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030184, + "callsign": "0350", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 5600001, + "callsign": "VLAD46", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501726, + "callsign": "PATRIOT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2509122, + "callsign": "DOMINIK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030188, + "callsign": "AVER89", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030189, + "callsign": "MAGNAT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030191, + "callsign": "TERIKON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030192, + "callsign": "OCTOBER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501757, + "callsign": "TRIDVA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030194, + "callsign": "LIMAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1111777, + "callsign": "TRAKTOR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030196, + "callsign": "UDM697", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500773, + "callsign": "ITMAN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500500, + "callsign": "PORU4IK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501815, + "callsign": "KAREL", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7900001, + "callsign": "DIMA55", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030201, + "callsign": "ANTIK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501712, + "callsign": "KLIM45", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030203, + "callsign": "DENKENG", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030204, + "callsign": "1908", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030205, + "callsign": "NUMARK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030207, + "callsign": "IGOR377", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500866, + "callsign": "PRAD0SC", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501222, + "callsign": "ENOT", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030212, + "callsign": "RUSSIA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030214, + "callsign": "GROZA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501263, + "callsign": "REDDI77", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030216, + "callsign": "BOTCHI", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501789, + "callsign": "BURAN88", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500810, + "callsign": "SLON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 5500055, + "callsign": "ROSTIK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030230, + "callsign": "DANAG", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501891, + "callsign": "MEXAHNK", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030232, + "callsign": "ZEZERON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030233, + "callsign": "PEAKTOP", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030234, + "callsign": "ZATON", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030235, + "callsign": "ROKOT40", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501931, + "callsign": "ENGINER", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030239, + "callsign": "DENNM", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030240, + "callsign": "FDMA", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030241, + "callsign": "GAGIN", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501918, + "callsign": "IRTISH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 4000001, + "callsign": "AVIATOR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2502062, + "callsign": "TRUBACH", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2506090, + "callsign": "KAVKAZ", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1030249, + "callsign": "AMUR", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1419867, + "callsign": "JDJDDJ", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 1415260, + "callsign": "123123", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2508021, + "callsign": "KORUS1", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2508009, + "callsign": "KORUS2", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2500591, + "callsign": "VLAD", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2506134, + "callsign": "KAVKAZ", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 670002, + "callsign": "ECHO1", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 2501956, + "callsign": "MARCUS", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + }, + { + "id": 7900002, + "callsign": "SHULTZ", + "fname": "", + "surname": "", + "city": "", + "state": "", + "country": "", + "remarks": "", + "confirmed": true + } + ] +} \ No newline at end of file diff --git a/savedata/dmrid.dat b/savedata/dmrid.dat new file mode 100644 index 0000000..4f0bdc7 --- /dev/null +++ b/savedata/dmrid.dat @@ -0,0 +1,224 @@ +1400001;ADMIN; +140002;XLXYKT; +140003;XLXARK; +140004;XLXPDS; +1412262;SEVERY; +1410461;TESTI; +670001;XLXB; +670003;PODOLSK; +6700002;DVSB; +6700003;DVSF; +1030176;KASKAD; +1400077;DYNAMIT; +1030174;LEKTRON; +2501655;ICEBERG; +1030169;RAMON; +1030171;ZELLO; +1030170;FRNLINK; +1030167;LESHIY; +1030166;FAGOT; +1030165;STALKER; +1030164;NIRVANA; +2501501;IRON; +1030153;USER2; +1030154;USER3; +1030155;USER4; +1030156;USER5; +1030157;BARMI; +1030158;USER7; +1030159;USER8; +1030160;USER9; +1030161;USER10; +2500460;RYBAK; +2500779;R7KAY; +7801620;MUTABOR; +1030148;JUPITER; +5000941;KIRPICH; +1030144;EGERY; +2840338;HBLINK; +1030136;RYBACH; +1030137;LUDZA; +1030138;BUY27; +1030139;DEMBI; +1030140;KOLDA; +1030141;GRAS; +1030142;GRAS; +1030143;KOPPI; +2501513;SWIFT; +1030134;REGION; +1030133;VOLNA; +1030132;SUMRAK; +2501517;R2BRI; +7804951;DUNAY; +1030129;RUBEZH; +2503228;KARDAN; +1030127;HAUX; +1030126;NEBO2; +1030125;LUCKY; +6550059;GITARIST; +1030123;DIZEL; +1030122;AKRA; +2503128;SIMBA; +7807808;YKCYC; +2501250;ADVOKAT; +1030118;KARAT; +2509132;BARISTA; +1030106;CHAMBAR; +2501316;NARCISS; +6550001;ARENDAT; +6550002;UMBRELA; +6550003;MIHA111; +6550004;KAREL; +6550006;ZS6DLK; +6550008;ZS6RES; +6550009;EVGEN; +6550010;MAGUS; +1030104;ARENDAT; +2500352;EGORYCH; +2570200;STRELA; +1030103;MALOY; +2501349;FOXMAN; +1030098;NARCIS; +1030097;SHTURMN; +2501301;GRACH; +1030040;ARKTEST; +1030096;BARMI; +1030092;ALEXBUT; +1030091;MASHUK; +1030088;AKCENT; +1000780;P25; +1030086;NET1; +1030087;NET2; +6555027;BOGDAN; +1030084;BOGDAN; +1030083;KARAS; +2501190;IGORH; +1030081;AZGARD; +1030080;MORSKOY; +2501231;PENZA; +1030078;VORON; +1030100;DOCTOR; +2864293;MIHA111; +2508125;MEHANIK; +1030074;GRANIT; +2501366;SASHKO; +1030072;FRNLINK; +2518001;KORUS; +1030070;SLITER; +4700830;FDR830; +1030068;ALEX203; +2502228;PRORAB; +1030066;PRORAB; +2501099;KIPARIS; +7800056;AYVENGO; +6700067;VIRAJ; +1030061;SAN428; +2501182;POOH; +1030059;DVINA; +2570193;KANAPA; +1030057;AYDAR; +1030003;MIHA111; +1030056;GNOM; +2500358;NAIL44; +1230311;YUG311; +2500780;MAX03; +2500945;DIMGRAD; +1030178;RYAZAN; +1030049;LEXUS; +2500944;KALASH; +7700023;BARON; +1030002;UMBREL; +1030046;VETER; +1030004;VOSTOK; +1030005;ELISTA; +1030006;ARTEK; +1030007;VLAD770; +1030008;GITARIS; +1030009;TRI333; +1030011;URAL; +1030013;AYAKS; +2500263;NOVAK; +1030016;DMITROV; +1030012;VOST555; +1030018;SENATOR; +1030030;STELS; +1030021;DANTIST; +2502181;DMIT920; +2570148;MASTER; +2500887;ALEX; +1030027;KARE; +2502168;BUMER; +2506145;GURZA; +1030032;ARTEM48; +1030033;LESNIK; +5973777;SOKOL; +2500222;VOLKIS; +6555016;URAL; +4600403;ARTEK; +6550007;VLAD770; +6555008;NAVIRUS; +2503316;GITARIS; +2500247;SOKOL; +1030038;MAZAY; +2502072;GRANIT; +1030001;NAVIRUS; +2501668;NEMOI; +1400841;YAKUT; +2500893;BOREY; +2501457;ALEX77; +1030182;BRONIX; +1030183;KALITKA; +1030184;0350; +5600001;VLAD46; +2501726;PATRIOT; +2509122;DOMINIK; +1030188;AVER89; +1030189;MAGNAT; +1030192;OCTOBER; +2501757;TRIDVA; +1030194;LIMAN; +1111777;TRAKTOR; +1030196;UDM697; +2500773;ITMAN; +2500500;PORU4IK; +2501815;KAREL; +7900001;DIMA55; +1030201;ANTIK; +2501712;KLIM45; +1030203;DENKENG; +1030204;1908; +1030205;NUMARK; +1030207;IGOR377; +2500866;PRAD0SC; +2501222;ENOT; +1030212;RUSSIA; +1030214;GROZA; +2501263;REDDI77; +1030216;BOTCHI; +2501789;BURAN88; +2500810;SLON; +5500055;ROSTIK; +1030230;DANAG; +2501891;MEXAHNK; +1030232;ZEZERON; +1030233;PEAKTOP; +1030234;ZATON; +1030235;ROKOT40; +2501931;ENGINER; +1030239;DENNM; +1030240;FDMA; +1030241;GAGIN; +2501918;IRTISH; +4000001;AVIATOR; +2502062;TRUBACH; +1030249;AMUR; +123123;SDDD; +2508009;KORUS2; +2500591;VLAD; +1419867;JDJDDJ; +1419418;TESTTES; +1417126;TESTTE1; +1416712;TESTTE1; +670002;ECHO1; +2501956;MARCUS; +7900002;SHULTZ; diff --git a/savedata/logic.php b/savedata/logic.php new file mode 100644 index 0000000..0f8c359 --- /dev/null +++ b/savedata/logic.php @@ -0,0 +1,227 @@ + 0, 'results' => []]; +$data = $json['results']; + +if (isset($_GET['ajax_check'])) { + $callsign = strtoupper(trim($_GET['callsign'] ?? '')); + $response = [ + 'callsignInvalid' => !preg_match('/^[A-Z0-9]{4,7}$/', $callsign), + 'callsignExists' => false + ]; + foreach ($data as $row) { + if (strtoupper($row['callsign']) === $callsign) $response['callsignExists'] = true; + } + header('Content-Type: application/json'); + echo json_encode($response); + exit; +} + +if (isset($_GET['sync'])) { + $lines = []; + + foreach ($data as $item) { + if (!empty($item['confirmed'])) { + $id = trim($item['id']); + $callsign = strtoupper(trim($item['callsign'])); + $lines[] = "{$id};{$callsign};"; + } + } + + file_put_contents($datFile, implode(PHP_EOL, $lines) . PHP_EOL); + + header("Location: admin.php"); + exit; +} + +if (isset($_GET['confirm'])) { + $confirmId = (int)$_GET['confirm']; + + foreach ($data as &$item) { + if ($item['id'] === $confirmId) { + $item['confirmed'] = true; + + $lines = file($datFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $entry = "{$item['id']};{$item['callsign']};"; + + if (!in_array($entry, $lines)) { + file_put_contents($datFile, $entry . PHP_EOL, FILE_APPEND); + } + + break; + } + } + unset($item); + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + header("Location: admin.php"); + exit; +} + +if (isset($_GET['block'])) { + $confirmId = (int)$_GET['block']; + + foreach ($data as &$item) { + if ($item['id'] === $confirmId) { + $item['confirmed'] = false; + + $lines = file($datFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $entry = "{$item['id']};{$item['callsign']};"; + + $filtered = array_filter($lines, function($line) use ($entry) { + return trim($line) !== $entry; + }); + + file_put_contents($datFile, implode(PHP_EOL, $filtered) . PHP_EOL); + + break; + } + } + unset($item); + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + header("Location: admin.php"); + exit; +} + +if (isset($_GET['delete'])) { + $deleteId = (int)$_GET['delete']; + + $callsign = null; + + foreach ($data as $index => $item) { + if ($item['id'] === $deleteId) { + $callsign = $item['callsign']; + unset($data[$index]); + break; + } + } + + $data = array_values($data); + + if ($callsign === null) { + header("Location: admin.php"); + exit; + } + + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + + $lines = file($datFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $filtered = array_filter($lines, function($line) use ($deleteId, $callsign) { + return trim($line) !== "{$deleteId};{$callsign};"; + }); + + file_put_contents($datFile, implode(PHP_EOL, $filtered) . PHP_EOL); + header("Location: admin.php"); + exit; +} + +$form_error = ''; +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $new_id = (int)$_POST['new_id']; + do { + $new_id = rand(1410000, 1419999); + $used = false; + foreach ($data as $row) { + if ($row['id'] == $newId) { + $used = true; + break; + } + } + } while ($used); + $callsign = strtoupper(trim($_POST['new_callsign'])); + $fname = trim($_POST['fname'] ?? ''); + $surname = trim($_POST['surname'] ?? ''); + $city = trim($_POST['city'] ?? ''); + $state = trim($_POST['state'] ?? ''); + $country = trim($_POST['country'] ?? ''); + $remarks = trim($_POST['remarks'] ?? ''); + + if ($new_id < 100000 || $new_id > 9999999) { + $form_error = 'ID должен быть 6–7 цифр.'; + } elseif (!preg_match('/^[A-Z0-9]{4,7}$/', $callsign)) { + $form_error = 'Позывной: 4–7 латинских символов/цифр.'; + } elseif (array_filter($data, fn($r) => $r['id'] == $new_id || strtoupper($r['callsign']) === $callsign)) { + $form_error = 'Такой ID или позывной уже существует.'; + } elseif (preg_match('/[^a-zA-Z\s]/', $fname . $surname . $city . $state . $country . $remarks)) { + $form_error = 'Дополнительные поля должны содержать только латиницу.'; + } else { + $data[] = [ + 'id' => $new_id, + 'callsign' => $callsign, + 'fname' => $fname, + 'surname' => $surname, + 'city' => $city, + 'state' => $state, + 'country' => $country, + 'remarks' => $remarks, + 'confirmed' => true + ]; + $json['results'] = $data; + $json['count'] = count($data); + file_put_contents($file, json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); + + $dat_line = "{$new_id};{$callsign};" . PHP_EOL; + file_put_contents($datFile, $dat_line, FILE_APPEND); + + header("Location: admin.php"); + exit; + } +} + +$searchQuery = trim($_GET['search'] ?? ''); + +$confirmed = array_values(array_filter($data, fn($d) => !empty($d['confirmed']))); + +if ($searchQuery !== '') { + $confirmed = array_filter($confirmed, function($row) use ($searchQuery) { + foreach (['id', 'callsign', 'fname', 'surname', 'city', 'state', 'country', 'remarks'] as $field) { + if (stripos((string)($row[$field] ?? ''), $searchQuery) !== false) { + return true; + } + } + return false; + }); +} + +$validSortKeys = ['id', 'callsign', 'fname', 'surname', 'city', 'state', 'country', 'remarks']; +$sortKey = $_GET['sort'] ?? 'id'; +$sortOrder = $_GET['order'] ?? 'asc'; + +if (!in_array($sortKey, $validSortKeys)) { + $sortKey = 'id'; +} + +usort($confirmed, function($a, $b) use ($sortKey, $sortOrder) { + $valA = $a[$sortKey] ?? ''; + $valB = $b[$sortKey] ?? ''; + + $result = is_numeric($valA) && is_numeric($valB) + ? $valA <=> $valB + : strcasecmp((string)$valA, (string)$valB); + + return $sortOrder === 'desc' ? -$result : $result; +}); + +$page = max(1, (int)($_GET['page'] ?? 1)); +$perPage = 15; +$total = count($confirmed); +$totalPages = ceil($total / $perPage); +$offset = ($page - 1) * $perPage; +$currentPageData = array_slice($confirmed, $offset, $perPage); + +function sortLink(string $key, string $label): string { + + $currentSort = $_GET['sort'] ?? 'id'; + $currentOrder = $_GET['order'] ?? 'asc'; + $nextOrder = ($currentSort === $key && $currentOrder === 'asc') ? 'desc' : 'asc'; + $page = $_GET['page'] ?? 1; + + return "$label"; +} +?>