Update: 2026-06-29 23:45:06
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -15,7 +15,15 @@ object AppLauncher {
|
||||
"zaken" to "com.zakinn.app",
|
||||
"com.zakinn.app" to "com.zakinn.app",
|
||||
"tufaddal" to "com.bis.taxi",
|
||||
"com.bis.taxi" to "com.bis.taxi"
|
||||
"com.bis.taxi" to "com.bis.taxi",
|
||||
"careem" to "com.careem.acma",
|
||||
"com.careem.acma" to "com.careem.acma",
|
||||
"uber" to "com.ubercab",
|
||||
"com.ubercab" to "com.ubercab",
|
||||
"taxif" to "com.taxif.passenger",
|
||||
"com.taxif.passenger" to "com.taxif.passenger",
|
||||
"jeeny" to "me.com.easytaxi",
|
||||
"me.com.easytaxi" to "me.com.easytaxi"
|
||||
)
|
||||
|
||||
fun launchApp(context: Context, appName: String): Boolean {
|
||||
|
||||
@@ -98,6 +98,10 @@ class ScraperAccessibilityService : AccessibilityService() {
|
||||
"ae.com.yalla.go.dubai.client" -> handleYallaGoAutomation(rootNode)
|
||||
"com.zakinn.app" -> handleZakinnAutomation(rootNode)
|
||||
"com.bis.taxi" -> handleTfadalAutomation(rootNode)
|
||||
"com.careem.acma" -> handleCareemAutomation(rootNode)
|
||||
"com.ubercab" -> handleUberAutomation(rootNode)
|
||||
"com.taxif.passenger" -> handleTaxiFAutomation(rootNode)
|
||||
"me.com.easytaxi" -> handleJeenyAutomation(rootNode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,7 +326,7 @@ class ScraperAccessibilityService : AccessibilityService() {
|
||||
private fun searchPriceByCurrency(node: android.view.accessibility.AccessibilityNodeInfo?) {
|
||||
if (node == null) return
|
||||
val text = node.text?.toString() ?: ""
|
||||
if (text.contains("ل.س") || text.contains("SYP") || text.contains("AED") || text.contains("SP") || text.contains("SP.")) {
|
||||
if (text.contains("ل.س") || text.contains("SYP") || text.contains("AED") || text.contains("SP") || text.contains("SP.") || text.contains("JOD") || text.contains("د.أ") || text.contains("JD")) {
|
||||
Log.i(TAG, "Found price pattern dynamically: $text")
|
||||
submitPriceToServer(text)
|
||||
return
|
||||
@@ -385,6 +389,146 @@ class ScraperAccessibilityService : AccessibilityService() {
|
||||
return r * c
|
||||
}
|
||||
|
||||
private fun handleCareemAutomation(rootNode: android.view.accessibility.AccessibilityNodeInfo) {
|
||||
val task = currentTask ?: return
|
||||
Log.d(TAG, "Careem Automation event. State: $currentState")
|
||||
when (currentState) {
|
||||
BotState.SEARCHING_START -> {
|
||||
val pickupEdit = findEditableNode(rootNode)
|
||||
if (pickupEdit != null) {
|
||||
val startLoc = task.optString("start_location", "Amman")
|
||||
val arguments = android.os.Bundle().apply {
|
||||
putCharSequence(android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, startLoc)
|
||||
}
|
||||
pickupEdit.performAction(android.view.accessibility.AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
||||
Log.i(TAG, "Careem: Entered start: $startLoc")
|
||||
currentState = BotState.SEARCHING_END
|
||||
}
|
||||
}
|
||||
BotState.SEARCHING_END -> {
|
||||
val destEdit = findEditableNode(rootNode)
|
||||
if (destEdit != null) {
|
||||
val endLoc = task.optString("end_location", "Airport")
|
||||
val arguments = android.os.Bundle().apply {
|
||||
putCharSequence(android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, endLoc)
|
||||
}
|
||||
destEdit.performAction(android.view.accessibility.AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
||||
Log.i(TAG, "Careem: Entered end: $endLoc")
|
||||
currentState = BotState.READING_PRICE
|
||||
}
|
||||
}
|
||||
BotState.READING_PRICE -> {
|
||||
searchPriceByCurrency(rootNode)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleUberAutomation(rootNode: android.view.accessibility.AccessibilityNodeInfo) {
|
||||
val task = currentTask ?: return
|
||||
Log.d(TAG, "Uber Automation event. State: $currentState")
|
||||
when (currentState) {
|
||||
BotState.SEARCHING_START -> {
|
||||
val pickupEdit = findEditableNode(rootNode)
|
||||
if (pickupEdit != null) {
|
||||
val startLoc = task.optString("start_location", "Amman")
|
||||
val arguments = android.os.Bundle().apply {
|
||||
putCharSequence(android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, startLoc)
|
||||
}
|
||||
pickupEdit.performAction(android.view.accessibility.AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
||||
Log.i(TAG, "Uber: Entered start: $startLoc")
|
||||
currentState = BotState.SEARCHING_END
|
||||
}
|
||||
}
|
||||
BotState.SEARCHING_END -> {
|
||||
val destEdit = findEditableNode(rootNode)
|
||||
if (destEdit != null) {
|
||||
val endLoc = task.optString("end_location", "Airport")
|
||||
val arguments = android.os.Bundle().apply {
|
||||
putCharSequence(android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, endLoc)
|
||||
}
|
||||
destEdit.performAction(android.view.accessibility.AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
||||
Log.i(TAG, "Uber: Entered end: $endLoc")
|
||||
currentState = BotState.READING_PRICE
|
||||
}
|
||||
}
|
||||
BotState.READING_PRICE -> {
|
||||
searchPriceByCurrency(rootNode)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleTaxiFAutomation(rootNode: android.view.accessibility.AccessibilityNodeInfo) {
|
||||
val task = currentTask ?: return
|
||||
Log.d(TAG, "TaxiF Automation event. State: $currentState")
|
||||
when (currentState) {
|
||||
BotState.SEARCHING_START -> {
|
||||
val pickupEdit = findEditableNode(rootNode)
|
||||
if (pickupEdit != null) {
|
||||
val startLoc = task.optString("start_location", "Amman")
|
||||
val arguments = android.os.Bundle().apply {
|
||||
putCharSequence(android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, startLoc)
|
||||
}
|
||||
pickupEdit.performAction(android.view.accessibility.AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
||||
Log.i(TAG, "TaxiF: Entered start: $startLoc")
|
||||
currentState = BotState.SEARCHING_END
|
||||
}
|
||||
}
|
||||
BotState.SEARCHING_END -> {
|
||||
val destEdit = findEditableNode(rootNode)
|
||||
if (destEdit != null) {
|
||||
val endLoc = task.optString("end_location", "Airport")
|
||||
val arguments = android.os.Bundle().apply {
|
||||
putCharSequence(android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, endLoc)
|
||||
}
|
||||
destEdit.performAction(android.view.accessibility.AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
||||
Log.i(TAG, "TaxiF: Entered end: $endLoc")
|
||||
currentState = BotState.READING_PRICE
|
||||
}
|
||||
}
|
||||
BotState.READING_PRICE -> {
|
||||
searchPriceByCurrency(rootNode)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleJeenyAutomation(rootNode: android.view.accessibility.AccessibilityNodeInfo) {
|
||||
val task = currentTask ?: return
|
||||
Log.d(TAG, "Jeeny Automation event. State: $currentState")
|
||||
when (currentState) {
|
||||
BotState.SEARCHING_START -> {
|
||||
val pickupEdit = findEditableNode(rootNode)
|
||||
if (pickupEdit != null) {
|
||||
val startLoc = task.optString("start_location", "Amman")
|
||||
val arguments = android.os.Bundle().apply {
|
||||
putCharSequence(android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, startLoc)
|
||||
}
|
||||
pickupEdit.performAction(android.view.accessibility.AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
||||
Log.i(TAG, "Jeeny: Entered start: $startLoc")
|
||||
currentState = BotState.SEARCHING_END
|
||||
}
|
||||
}
|
||||
BotState.SEARCHING_END -> {
|
||||
val destEdit = findEditableNode(rootNode)
|
||||
if (destEdit != null) {
|
||||
val endLoc = task.optString("end_location", "Airport")
|
||||
val arguments = android.os.Bundle().apply {
|
||||
putCharSequence(android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, endLoc)
|
||||
}
|
||||
destEdit.performAction(android.view.accessibility.AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
|
||||
Log.i(TAG, "Jeeny: Entered end: $endLoc")
|
||||
currentState = BotState.READING_PRICE
|
||||
}
|
||||
}
|
||||
BotState.READING_PRICE -> {
|
||||
searchPriceByCurrency(rootNode)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onInterrupt() {
|
||||
Log.w(TAG, "Accessibility Service Interrupted")
|
||||
}
|
||||
|
||||
@@ -34,8 +34,11 @@ CREATE TABLE IF NOT EXISTS competitor_prices (
|
||||
";
|
||||
$con->exec($sql);
|
||||
|
||||
// 2. Ten Key Regions in Damascus
|
||||
$regions = [
|
||||
// 2. Ten Key Regions in Damascus (Syria) and Amman (Jordan)
|
||||
$countriesConfig = [
|
||||
'SY' => [
|
||||
'competitors' => ['yallago', 'zaken', 'tufaddal'],
|
||||
'regions' => [
|
||||
['name' => 'Umayyad Square', 'lat' => 33.5138, 'lng' => 36.2765],
|
||||
['name' => 'Mezzeh', 'lat' => 33.5074, 'lng' => 36.2530],
|
||||
['name' => 'Malki', 'lat' => 33.5220, 'lng' => 36.2840],
|
||||
@@ -46,10 +49,25 @@ $regions = [
|
||||
['name' => 'Dummar', 'lat' => 33.5385, 'lng' => 36.2250],
|
||||
['name' => 'Baramkeh', 'lat' => 33.5100, 'lng' => 36.2885],
|
||||
['name' => 'Muhajireen', 'lat' => 33.5320, 'lng' => 36.2720],
|
||||
]
|
||||
],
|
||||
'JO' => [
|
||||
'competitors' => ['com.careem.acma', 'com.ubercab', 'com.taxif.passenger', 'me.com.easytaxi'],
|
||||
'regions' => [
|
||||
['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' => 'Jabal Al-Weibdeh', 'lat' => 31.9560, 'lng' => 35.9220],
|
||||
['name' => 'Marj Al-Hamam', 'lat' => 31.9000, 'lng' => 35.8500],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$competitors = ['yallago', 'zaken', 'tufaddal'];
|
||||
|
||||
// Helper to generate a random point within a radius (in km)
|
||||
function generateRandomPoint($lat, $lng, $radius) {
|
||||
$radiusInDegrees = $radius / 111.0; // 1 degree is ~111km
|
||||
@@ -72,7 +90,11 @@ function generateRandomPoint($lat, $lng, $radius) {
|
||||
|
||||
$tasksCreated = 0;
|
||||
|
||||
foreach ($regions as $region) {
|
||||
foreach ($countriesConfig as $countryCode => $config) {
|
||||
$competitors = $config['competitors'];
|
||||
$regions = $config['regions'];
|
||||
|
||||
foreach ($regions as $region) {
|
||||
// A. Generate Start Point (within 2km of region center)
|
||||
$start = generateRandomPoint($region['lat'], $region['lng'], 2);
|
||||
|
||||
@@ -107,6 +129,7 @@ foreach ($regions as $region) {
|
||||
$tasksCreated++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "Successfully generated and queued $tasksCreated pricing tasks.\n";
|
||||
|
||||
@@ -506,6 +506,10 @@ $scrapedResults = json_decode(file_get_contents(RESULTS_FILE), true);
|
||||
.app-yallago { background: rgba(59, 130, 246, 0.15); color: #60a5fa; border: 1px solid rgba(59, 130, 246, 0.3); }
|
||||
.app-zaken { background: rgba(16, 185, 129, 0.15); color: #34d399; border: 1px solid rgba(16, 185, 129, 0.3); }
|
||||
.app-tufaddal { background: rgba(245, 158, 11, 0.15); color: #fbbf24; border: 1px solid rgba(245, 158, 11, 0.3); }
|
||||
.app-careem { background: rgba(16, 185, 129, 0.15); color: #34d399; border: 1px solid rgba(16, 185, 129, 0.3); }
|
||||
.app-uber { background: rgba(255, 255, 255, 0.1); color: #f3f4f6; border: 1px solid rgba(255, 255, 255, 0.2); }
|
||||
.app-taxif { background: rgba(239, 68, 68, 0.15); color: #f87171; border: 1px solid rgba(239, 68, 68, 0.3); }
|
||||
.app-jeeny { background: rgba(139, 92, 246, 0.15); color: #a78bfa; border: 1px solid rgba(139, 92, 246, 0.3); }
|
||||
|
||||
.time-badge {
|
||||
font-size: 0.80rem;
|
||||
@@ -601,6 +605,10 @@ $scrapedResults = json_decode(file_get_contents(RESULTS_FILE), true);
|
||||
<option value="ae.com.yalla.go.dubai.client">YallaGo (ae.com.yalla.go.dubai.client)</option>
|
||||
<option value="com.zakinn.app">Zaken / Zakinn (com.zakinn.app)</option>
|
||||
<option value="com.bis.taxi">Tfadal (com.bis.taxi)</option>
|
||||
<option value="com.careem.acma">Careem (com.careem.acma)</option>
|
||||
<option value="com.ubercab">Uber (com.ubercab)</option>
|
||||
<option value="com.taxif.passenger">TaxiF (com.taxif.passenger)</option>
|
||||
<option value="me.com.easytaxi">Jeeny (me.com.easytaxi)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -664,7 +672,24 @@ $scrapedResults = json_decode(file_get_contents(RESULTS_FILE), true);
|
||||
<div class="empty-state">No pending tasks. Queue some tasks using the form on the left!</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($currentTasks as $task):
|
||||
$appLabel = ($task['app'] === 'ae.com.yalla.go.dubai.client') ? 'yallago' : (($task['app'] === 'com.zakinn.app') ? 'zaken' : 'tufaddal');
|
||||
$app = $task['app'] ?? '';
|
||||
if ($app === 'ae.com.yalla.go.dubai.client') {
|
||||
$appLabel = 'yallago';
|
||||
} elseif ($app === 'com.zakinn.app') {
|
||||
$appLabel = 'zaken';
|
||||
} elseif ($app === 'com.bis.taxi') {
|
||||
$appLabel = 'tufaddal';
|
||||
} elseif ($app === 'com.careem.acma') {
|
||||
$appLabel = 'careem';
|
||||
} elseif ($app === 'com.ubercab') {
|
||||
$appLabel = 'uber';
|
||||
} elseif ($app === 'com.taxif.passenger') {
|
||||
$appLabel = 'taxif';
|
||||
} elseif ($app === 'me.com.easytaxi') {
|
||||
$appLabel = 'jeeny';
|
||||
} else {
|
||||
$appLabel = 'unknown';
|
||||
}
|
||||
?>
|
||||
<div class="list-item">
|
||||
<div class="task-info">
|
||||
@@ -702,7 +727,23 @@ $scrapedResults = json_decode(file_get_contents(RESULTS_FILE), true);
|
||||
<?php foreach ($scrapedResults as $res):
|
||||
$data = $res['result_data'];
|
||||
$app = $data['app'] ?? 'unknown';
|
||||
$appLabel = (strpos($app, 'yalla') !== false) ? 'yallago' : ((strpos($app, 'zakinn') !== false || strpos($app, 'zaken') !== false) ? 'zaken' : 'tufaddal');
|
||||
if (strpos($app, 'yalla') !== false) {
|
||||
$appLabel = 'yallago';
|
||||
} elseif (strpos($app, 'zakinn') !== false || strpos($app, 'zaken') !== false) {
|
||||
$appLabel = 'zaken';
|
||||
} elseif (strpos($app, 'bis.taxi') !== false || strpos($app, 'tufaddal') !== false) {
|
||||
$appLabel = 'tufaddal';
|
||||
} elseif (strpos($app, 'careem') !== false) {
|
||||
$appLabel = 'careem';
|
||||
} elseif (strpos($app, 'ubercab') !== false || strpos($app, 'uber') !== false) {
|
||||
$appLabel = 'uber';
|
||||
} elseif (strpos($app, 'taxif') !== false) {
|
||||
$appLabel = 'taxif';
|
||||
} elseif (strpos($app, 'easytaxi') !== false || strpos($app, 'jeeny') !== false) {
|
||||
$appLabel = 'jeeny';
|
||||
} else {
|
||||
$appLabel = 'unknown';
|
||||
}
|
||||
$isSuccess = ($res['status'] === 'success');
|
||||
$price = $data['price'] ?? 0;
|
||||
$dist = $data['distance_km'] ?? 0;
|
||||
@@ -718,7 +759,11 @@ $scrapedResults = json_decode(file_get_contents(RESULTS_FILE), true);
|
||||
</div>
|
||||
<div class="price-text">
|
||||
<?php if ($isSuccess): ?>
|
||||
<?php echo number_format($price, 0); ?> SYP
|
||||
<?php
|
||||
$currency = (in_array($appLabel, ['careem', 'uber', 'taxif', 'jeeny'])) ? 'JOD' : 'SYP';
|
||||
$decimals = ($currency === 'JOD') ? 2 : 0;
|
||||
echo number_format($price, $decimals) . ' ' . $currency;
|
||||
?>
|
||||
<?php else: ?>
|
||||
<span style="color:var(--error-color); font-size:0.9rem;">Scrape Failed</span>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -220,7 +220,9 @@ ALTER TABLE `car_tracks`
|
||||
-- Indexes for table `driver_behavior`
|
||||
--
|
||||
ALTER TABLE `driver_behavior`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `idx_driver_id` (`driver_id`),
|
||||
ADD KEY `idx_trip_id` (`trip_id`);
|
||||
|
||||
--
|
||||
-- Indexes for table `driver_daily_summary`
|
||||
@@ -233,26 +235,29 @@ ALTER TABLE `driver_daily_summary`
|
||||
-- Indexes for table `driver_daily_work`
|
||||
--
|
||||
ALTER TABLE `driver_daily_work`
|
||||
ADD PRIMARY KEY (`driver_id`,`work_date`),
|
||||
ADD KEY `idx_driver_date` (`driver_id`,`work_date`);
|
||||
ADD PRIMARY KEY (`driver_id`,`work_date`);
|
||||
|
||||
--
|
||||
-- Indexes for table `driver_orders`
|
||||
--
|
||||
ALTER TABLE `driver_orders`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `idx_driver_id` (`driver_id`),
|
||||
ADD KEY `idx_order_id` (`order_id`);
|
||||
|
||||
--
|
||||
-- Indexes for table `login_attempts`
|
||||
--
|
||||
ALTER TABLE `login_attempts`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `idx_ip_time` (`ip_address`,`attempt_time`);
|
||||
|
||||
--
|
||||
-- Indexes for table `login_attempts_drivers`
|
||||
--
|
||||
ALTER TABLE `login_attempts_drivers`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `idx_ip_time` (`ip_address`,`attempt_time`);
|
||||
|
||||
--
|
||||
-- Indexes for table `places`
|
||||
|
||||
Reference in New Issue
Block a user