This commit is contained in:
Hamza-Ayed
2026-05-14 18:24:32 +03:00
commit 8272065938
646 changed files with 50360 additions and 0 deletions

4
backend/.env Normal file
View File

@@ -0,0 +1,4 @@
DB_HOST=localhost
DB_NAME=jordanBotDb
DB_USER=jordanBotUser
DB_PASS=nfKvcF576lFFxCNy82tB

11
backend/README.md Normal file
View File

@@ -0,0 +1,11 @@
# Jordan Bot - PHP Backend API
هذا هو الخادم (Backend) الخاص ببوت الأردن، مبني بلغة PHP الخالصة ليكون خفيفاً وسهلاً في الاستضافة على أي خادم (Shared Hosting) بدون تعقيدات Node.js.
## الهيكل:
- `config/db.php`: ملف إعدادات قاعدة البيانات (PDO). يمكنك لاحقاً وضع بيانات الـ MySQL فيه.
- `api/rides.php`: يستقبل كل طلب رحلة يصله البوت لحفظ البيانات (السعر، المسافة، التطبيق) لغايات الدراسة الاقتصادية وتحديد أوقات الذروة.
- `api/location.php`: يستقبل تحديثات مواقع السائقين. **طريقة العمل:** يقوم تطبيق الأندرويد بجمع موقع السائق كل 3 ثوانٍ ويحفظها مؤقتاً في الذاكرة. كل 5 دقائق، يقوم التطبيق بإرسال "دفعة واحدة" (Bulk Upload) تحتوي على كل النقاط السابقة لتقليل استهلاك البطارية والإنترنت.
## معرف الجهاز (Fingerprint):
يتم استخدام بصمة الجهاز (Android ID) لتمييز السائقين بدون الحاجة لتسجيل الدخول، مما يساعد في تتبع الاشتراكات مستقبلاً وبناء خريطة دقيقة لكل سائق.

70
backend/api/location.php Normal file
View File

@@ -0,0 +1,70 @@
<?php
// backend/api/location.php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
require_once '../config/db.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'message' => 'Method Not Allowed']);
exit;
}
$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, true);
if (!$input || !isset($input['fingerprint']) || !isset($input['locations'])) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Invalid data structure. Fingerprint and locations required.']);
exit;
}
$fingerprint = $input['fingerprint'];
$locations = $input['locations'];
try {
$pdo->beginTransaction();
$sql = "INSERT INTO driver_locations (fingerprint, latitude, longitude, speed, recorded_at, uploaded_at)
VALUES (:fingerprint, :latitude, :longitude, :speed, :recorded_at, NOW())";
$stmt = $pdo->prepare($sql);
$insertedCount = 0;
foreach ($locations as $loc) {
$latitude = $loc['latitude'] ?? null;
$longitude = $loc['longitude'] ?? null;
$speed = $loc['speed'] ?? 0;
$timestamp = $loc['timestamp'] ?? null;
if ($latitude !== null && $longitude !== null && $timestamp !== null) {
$stmt->execute([
':fingerprint' => $fingerprint,
':latitude' => $latitude,
':longitude' => $longitude,
':speed' => $speed,
':recorded_at' => date('Y-m-d H:i:s', $timestamp / 1000)
]);
$insertedCount++;
}
}
$pdo->commit();
http_response_code(201);
echo json_encode([
'success' => true,
'message' => "Bulk location sync successful",
'synced_count' => $insertedCount
]);
} catch (PDOException $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Database error: ' . $e->getMessage()]);
}
?>

61
backend/api/rides.php Normal file
View File

@@ -0,0 +1,61 @@
<?php
// backend/api/rides.php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
require_once '../config/db.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'message' => 'Method Not Allowed']);
exit;
}
$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, true);
if (!$input) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Invalid JSON input']);
exit;
}
$platform = $input['platform'] ?? 'Unknown';
$price = $input['price'] ?? 0.0;
$pickupDistance = $input['pickupDistance'] ?? 'Unknown';
$dropoffDistance = $input['dropoffDistance'] ?? 'Unknown';
$timeToPickup = $input['timeToPickup'] ?? 'Unknown';
$isAccepted = isset($input['isAccepted']) ? (int)$input['isAccepted'] : 0;
$rawText = $input['rawText'] ?? '';
$fingerprint = $input['fingerprint'] ?? 'UNKNOWN_DEVICE';
try {
$sql = "INSERT INTO rides (fingerprint, platform, price, pickup_distance, dropoff_distance, time_to_pickup, is_accepted, raw_text, created_at)
VALUES (:fingerprint, :platform, :price, :pickup_distance, :dropoff_distance, :time_to_pickup, :is_accepted, :raw_text, NOW())";
$stmt = $pdo->prepare($sql);
$stmt->execute([
':fingerprint' => $fingerprint,
':platform' => $platform,
':price' => $price,
':pickup_distance' => $pickupDistance,
':dropoff_distance' => $dropoffDistance,
':time_to_pickup' => $timeToPickup,
':is_accepted' => $isAccepted,
':raw_text' => $rawText
]);
http_response_code(201);
echo json_encode([
'success' => true,
'message' => 'Ride record created successfully',
'ride_id' => $pdo->lastInsertId()
]);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Database error: ' . $e->getMessage()]);
}
?>

5
backend/composer.json Normal file
View File

@@ -0,0 +1,5 @@
{
"require": {
"vlucas/phpdotenv": "^5.5"
}
}

27
backend/config/db.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
// backend/config/db.php
require_once __DIR__ . '/../vendor/autoload.php';
use Dotenv\Dotenv;
// Load environment variables from .env
$dotenv = Dotenv::createImmutable(__DIR__ . '/..');
$dotenv->load();
$host = $_ENV['DB_HOST'] ?? 'localhost';
$dbname = $_ENV['DB_NAME'] ?? 'jordan_bot_db';
$username = $_ENV['DB_USER'] ?? 'root';
$password = $_ENV['DB_PASS'] ?? '';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch (PDOException $e) {
// In production, you should log this error and show a generic message
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Database connection failed']);
exit;
}
?>

33
backend/schema.sql Normal file
View File

@@ -0,0 +1,33 @@
-- Jordan Bot Database Schema
CREATE DATABASE IF NOT EXISTS jordan_bot_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE jordan_bot_db;
-- Table to store ride requests for data mining
CREATE TABLE IF NOT EXISTS rides (
id INT AUTO_INCREMENT PRIMARY KEY,
fingerprint VARCHAR(255) NOT NULL,
platform ENUM('Uber', 'Careem', 'Jeeny', 'Petra Ride', 'TaxiF', 'Unknown') DEFAULT 'Unknown',
price DECIMAL(10, 2) DEFAULT 0.00,
pickup_distance VARCHAR(50),
dropoff_distance VARCHAR(50),
time_to_pickup VARCHAR(50),
is_accepted TINYINT(1) DEFAULT 0,
raw_text TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX (fingerprint),
INDEX (platform)
) ENGINE=InnoDB;
-- Table to store driver locations for map updating
CREATE TABLE IF NOT EXISTS driver_locations (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
fingerprint VARCHAR(255) NOT NULL,
latitude DOUBLE NOT NULL,
longitude DOUBLE NOT NULL,
speed FLOAT DEFAULT 0,
recorded_at TIMESTAMP NULL,
uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX (fingerprint),
INDEX (recorded_at)
) ENGINE=InnoDB;