900) { return false; } // Generate the expected signature $expected_sig = hash_hmac('sha256', $device_id . $ts, $secret_key); // Secure comparison return hash_equals($expected_sig, $sig); } function jsonError($message, $code = 400) { http_response_code($code); echo json_encode(['status' => 'failure', 'message' => $message]); exit; } // ---------------------------------------------------------------------------- // API Request Routing // ---------------------------------------------------------------------------- $method = $_SERVER['REQUEST_METHOD']; $contentType = $_SERVER['CONTENT_TYPE'] ?? ''; // Check if request is API call from the Bot $isApiCall = false; $device_id = null; $ts = null; $sig = null; if ($method === 'GET' && isset($_GET['device_id'], $_GET['ts'], $_GET['sig'])) { $isApiCall = true; $device_id = $_GET['device_id']; $ts = intval($_GET['ts']); $sig = $_GET['sig']; } elseif ($method === 'POST') { // Check if JSON body has device credentials $rawInput = file_get_contents('php://input'); $input = json_decode($rawInput, true); if ($input && isset($input['device_id'], $input['ts'], $input['sig'])) { $isApiCall = true; $device_id = $input['device_id']; $ts = intval($input['ts']); $sig = $input['sig']; } } if ($isApiCall) { header('Content-Type: application/json; charset=UTF-8'); // Validate signature if (!validateSignature($device_id, $ts, $sig, SECRET_KEY)) { jsonError("Unauthorized device signature or expired timestamp. Device ID: $device_id, ts: $ts", 401); } if ($method === 'GET') { // Dequeue one task for this bot (FIFO) $tasks = json_decode(file_get_contents(TASKS_FILE), true); if (count($tasks) > 0) { $task = array_shift($tasks); file_put_contents(TASKS_FILE, json_encode($tasks, JSON_PRETTY_PRINT)); echo json_encode([ "status" => "success", "has_task" => true, "task" => $task ]); } else { echo json_encode([ "status" => "success", "has_task" => false ]); } exit; } elseif ($method === 'POST') { // Record Scrape result if (empty($input['task_id']) || empty($input['status'])) { jsonError("Missing required parameters in payload"); } $results = json_decode(file_get_contents(RESULTS_FILE), true); $newResult = [ 'task_id' => $input['task_id'], 'device_id' => $device_id, 'status' => $input['status'], // 'success' or 'failed' 'type' => $input['type'] ?? 'price_check', 'recorded_at' => date('Y-m-d H:i:s'), 'result_data' => $input['result_data'] ?? [] ]; array_unshift($results, $newResult); file_put_contents(RESULTS_FILE, json_encode($results, JSON_PRETTY_PRINT)); echo json_encode([ "status" => "success", "message" => "Result recorded successfully" ]); exit; } } // ---------------------------------------------------------------------------- // Admin Dashboard UI (Rendered on normal GET browser requests) // ---------------------------------------------------------------------------- // Handle Admin Actions $message = ''; $msgType = 'success'; if (isset($_POST['action'])) { if ($_POST['action'] === 'add_task') { $app = $_POST['app'] ?? ''; $start_loc = $_POST['start_location'] ?? ''; $end_loc = $_POST['end_location'] ?? ''; $start_lat = floatval($_POST['start_lat'] ?? 0.0); $start_lng = floatval($_POST['start_lng'] ?? 0.0); $end_lat = floatval($_POST['end_lat'] ?? 0.0); $end_lng = floatval($_POST['end_lng'] ?? 0.0); if ($app && $start_loc && $end_loc) { $tasks = json_decode(file_get_contents(TASKS_FILE), true); $taskId = "prc_" . uniqid(); $newTask = [ "task_id" => $taskId, "type" => "price_check", "app" => $app, "start_location" => $start_loc, "end_location" => $end_loc, "payload" => [ "start_lat" => $start_lat, "start_lng" => $start_lng, "end_lat" => $end_lat, "end_lng" => $end_lng ] ]; $tasks[] = $newTask; file_put_contents(TASKS_FILE, json_encode($tasks, JSON_PRETTY_PRINT)); $message = "Task successfully added and queued! Task ID: $taskId"; } else { $message = "Please fill in all required fields."; $msgType = 'error'; } } elseif ($_POST['action'] === 'generate_batch_trips' || $_POST['action'] === 'generate_10_trips') { $app = $_POST['app'] ?? 'com.taxif.passenger'; $numTrips = isset($_POST['num_trips']) ? (int)$_POST['num_trips'] : 30; $ammanLocations = [ ['name' => 'Abdoun', 'lat' => 31.9392, 'lng' => 35.8942], ['name' => 'Jabal Amman', 'lat' => 31.9511, 'lng' => 35.9189], ['name' => 'Sweileh', 'lat' => 32.0167, 'lng' => 35.8333], ['name' => 'Khalda', 'lat' => 31.9861, 'lng' => 35.8450], ['name' => 'Al-Jubaiha', 'lat' => 32.0194, 'lng' => 35.8753], ['name' => 'Tla Al-Ali', 'lat' => 31.9961, 'lng' => 35.8647], ['name' => 'Shmeisani', 'lat' => 31.9680, 'lng' => 35.9020], ['name' => 'Um Uthaina', 'lat' => 31.9610, 'lng' => 35.8770], ['name' => 'Marj Al-Hamam', 'lat' => 31.9000, 'lng' => 35.8500], ['name' => 'Al-Muqabalain', 'lat' => 31.8720, 'lng' => 35.8900], ['name' => 'Al-Qweismeh', 'lat' => 31.8900, 'lng' => 35.9200], ['name' => 'Al-Madina', 'lat' => 31.8500, 'lng' => 35.8000], ['name' => 'Sports City', 'lat' => 31.9820, 'lng' => 35.8880], ['name' => 'Tabarbour', 'lat' => 31.9960, 'lng' => 35.9520], ['name' => 'Marka', 'lat' => 31.9810, 'lng' => 35.9860], ['name' => 'Abu Nuseir', 'lat' => 32.0460, 'lng' => 35.8820], ['name' => 'Shafa Badran', 'lat' => 32.0430, 'lng' => 35.8950], ['name' => 'Al-Bayader', 'lat' => 31.9540, 'lng' => 35.8230], ['name' => 'Wadi Al-Seer', 'lat' => 31.9520, 'lng' => 35.8160], ['name' => 'Dahiyet Al-Rasheed','lat' => 32.0110, 'lng' => 35.8710], ['name' => 'Tariq', 'lat' => 32.0080, 'lng' => 35.9380], ['name' => 'Ras Al-Ain', 'lat' => 31.9420, 'lng' => 35.9270], ['name' => 'Al-Yarmouk', 'lat' => 31.9300, 'lng' => 35.9400], ]; $tasks = json_decode(file_get_contents(TASKS_FILE), true); $count = 0; for ($i = 0; $i < $numTrips; $i++) { $startIndex = array_rand($ammanLocations); do { $endIndex = array_rand($ammanLocations); } while ($endIndex === $startIndex); $start = $ammanLocations[$startIndex]; $end = $ammanLocations[$endIndex]; $taskId = "prc_" . uniqid(); $newTask = [ 'task_id' => $taskId, 'type' => 'price_check', 'app' => $app, 'start_location' => $start['name'], 'end_location' => $end['name'], 'payload' => [ 'start_lat' => $start['lat'], 'start_lng' => $start['lng'], 'end_lat' => $end['lat'], 'end_lng' => $end['lng'], ], ]; $tasks[] = $newTask; $count++; } file_put_contents(TASKS_FILE, json_encode($tasks, JSON_PRETTY_PRINT)); $message = "Generated $count random standard tasks for $app to map surge zones!"; } elseif ($_POST['action'] === 'clear_tasks') { file_put_contents(TASKS_FILE, json_encode([])); $message = "Task queue cleared successfully."; } elseif ($_POST['action'] === 'clear_results') { file_put_contents(RESULTS_FILE, json_encode([])); $message = "Scrape results history cleared successfully."; } } // Fetch stats and lists for display $currentTasks = json_decode(file_get_contents(TASKS_FILE), true); $scrapedResults = json_decode(file_get_contents(RESULTS_FILE), true); ?> Siro Bot - Standalone Server Control Panel

Siro Bot Control Center

Standalone API Endpoint & Simulation Controller Panel

Server Online

Task Generator

Generate Random Amman Trips

Queues random standard tasks (one per trip) with varied distances for the selected app to map surge zones.

Queued task list (Sent to bot via GET request) 0): ?>
No pending tasks. Queue some tasks using the form on the left!

Batch: ' . $tripCount . ' trips | First: ' . htmlspecialchars($firstTrip['start_location']) . '' . htmlspecialchars($firstTrip['end_location']) . '

'; } else { echo '

Route: ' . htmlspecialchars($task['start_location']) . '' . htmlspecialchars($task['end_location']) . '

'; } ?>
Pending
Results submitted by Bot via POST request 0): ?>
No scraping results recorded yet. Results will appear here when the Android bot submits them.

Task ID:

Device:

Distance: km | Time:

Scrape Failed