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_10_trips') { $app = $_POST['app'] ?? 'com.taxif.passenger'; $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' => 'Hashmi Al-Janoubi', 'lat' => 31.9350, 'lng' => 35.9350], ['name' => 'Al-Madina', 'lat' => 31.8500, 'lng' => 35.8000], ['name' => 'Sports City', 'lat' => 31.9820, 'lng' => 35.8880], ]; // 10 trip pairs with varied distances (~2km to ~17km) $tripPairs = [ [13, 5], // Sports City → Tla Al-Ali (~2km) [6, 0], // Shmeisani → Abdoun (~3km) [7, 1], // Um Uthaina → Jabal Amman (~4km) [3, 13], // Khalda → Sports City (~5km) [4, 2], // Al-Jubaiha → Sweileh (~5km) [0, 8], // Abdoun → Marj Al-Hamam (~6km) [1, 10], // Jabal Amman → Al-Qweismeh (~9km) [6, 9], // Shmeisani → Al-Muqabalain (~11km) [2, 12], // Sweileh → Al-Madina (~17km) [5, 11], // Tla Al-Ali → Hashmi (~5km) ]; $tasks = json_decode(file_get_contents(TASKS_FILE), true); $count = 0; foreach ($tripPairs as $i => $pair) { $start = $ammanLocations[$pair[0]]; $end = $ammanLocations[$pair[1]]; $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 standard tasks (one per trip) for TaxiF!"; } 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 10 Amman Trips

Queues 10 separate standard tasks (one per trip) with varied distances (2–17 km) for TaxiF. The bot processes each trip individually through normal polling.

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