From 299132b5059cfccb2c56691408e479e4e48a0d91 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Mon, 29 Jun 2026 23:45:06 +0300 Subject: [PATCH] Update: 2026-06-29 23:45:06 --- .../executionHistory/executionHistory.bin | Bin 629561 -> 849017 bytes .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .../.gradle/8.13/fileHashes/fileHashes.bin | Bin 71865 -> 72065 bytes .../.gradle/8.13/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../8.13/fileHashes/resourceHashesCache.bin | Bin 18973 -> 19143 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../buildOutputCleanup/outputFiles.bin | Bin 22097 -> 22151 bytes android_bot/.gradle/file-system.probe | Bin 8 -> 8 bytes .../siro/android_bot/service/AppLauncher.kt | 10 +- .../service/ScraperAccessibilityService.kt | 146 +++++++++++++++++- backend/bot/generate_price_tasks.php | 107 ++++++++----- backend/bot/standalone_worker.php | 51 +++++- loction_server/locationDB.sql | 17 +- 13 files changed, 278 insertions(+), 53 deletions(-) diff --git a/android_bot/.gradle/8.13/executionHistory/executionHistory.bin b/android_bot/.gradle/8.13/executionHistory/executionHistory.bin index 040e87c36e220b7531e06a6e662b2c1b277b95b0..5a7b19ea1698ffa9dd14008c0a2c5d9fb0eaba3c 100644 GIT binary patch delta 3953 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 delta 1319 zcmZWodrVVT9KN^hy%bu)Ef4!*2&Ht9vGS+{HzH6FMVYw$F`Z=VAPUk^29yaHClI^R zk!pZ8*+Cc#7*HIQ4Uyh3pfEr{zz1WJN+rT%DT@=))bSY8-M0Q?caksXM!T$rzoWaW@a+qkxsb&*T@i~I7` zxLfn=vuk_*owS{XAniTvVRkDSX%=apvp*rbj2zH@$T>}h+H50CCNTFE8chk1YNPusf?4tlTtZ2 zyMru#hYVq+jWscxH&+sPp0|r%`5OavY?2F$b7T;vR%;l0ca=TK=P%#l6&C#AXjK~u zq}d1`GkR(jjK*{Q%OhiTSx4hv;Jt2i5&|Slaui8+!tN!|a(m~Qq6bqk2`@yFL)T@} zHWKDc+0Cd3GXyBOKMSc4Is5>^4C?wAgxXHE516LJfNE*Os%pB z3lguzD7QM(Oz)K~W0H6LG(q)k9+Me@TI8z1fpTu$wPp&?Q|bPAuoPK>OAlraG(En4 zLE72n^A@m9NI`6L#}?GdhWj1a`e(cfcco}4e=sQ~q(rDc zwK%%m{Mg>jVgy;)NDyYtIheb!uyUtmdM)L0-17;%J{xIc+59FI#^*20TL)qVw6G27 zw1NUdBv~HLkRjdq9%Kc?_sDt_siA~gnuqJDFh&W6!8JS8j&>T3N9W*=Jqj}$0k=2hv|X$sI7&X z3ClN&9kzF=20{v|XUa8-t9}7D#2dI`SLQFL~j^viy)ju$2^(ZYv zL5||jIx^u0O7;*z5S94eR973oFJ7oGuU^M49e1ag*Q-*7lKXoad6+W;U=HdF;`$JG zoQk4X5OAb{8U*HP=q1cq3sBI}NtQFK)Z66i`~jnd$^z%yQH)z|r<7zO`NpQ>Q{^8C zC9@G_T*-ILIlSE+UHih3wz->IgFFfAST#3n*IEMJH(Z1hS(X zY8ni}%TdGs)KtEvhN&Xd7<;D)fhwDtMYT^#bo=VoQexB_n-8mJRq-m6fC~XC9yd?ZUZ)iLHHDq)-whYnn0`w!U9R%D;+oGbzVHi*KWY06TSedqaP><1OhCRCH+UG2 z&-Z`|=e@e0a0slBf$i+%i;=?hlUT$)1lhU2|5DyBq#)7?HS7;W4dYQDjpkpKppdxV zvt`3#vOfix<~RF8bo_{i=x|ttse{L&_S#|{hAFkGs_C2R*nuGf3ez8PARQUNAacOe zqV%-BwCU9Q!c8aY=V_c0+J~%#f#LFQOdU8Z=>e()0s)7~6I+ERw{;1D;`&GL=DA%J zj0!mPEQ9MY?NJ4)mrp%BIlkvnP^;2o)4O-iUeh=(&6|?2ni1?M`CMhNa`qr*AdMDQ zxevM|#f=@BLK|0@UQFC&2+@)A5MqJXe^6A(Cpx=%P4xHc{y6hD%kn;`np{qZ8oLXV zkM@=+eCKk#*86(xOrvkByQSLmx}jFrKoq_FJh^bT@Z`KcA$y=}bL%0Zj4OaNnuCNl zUYoLIJC6|4178vQ$@40p=F~xSsNI~rzwcK460d~ABDM8*ZY_*@ZQjD+2UIlg)m7y= z5Jf^eFpXViK8@>1-$dqHHuG{e-uGw(8!NQG9HN6AzK+&9W1UeHc|YPrS2GoS&Ed(Q#f=Ik0hz5<53*e$iy)H$J`a`U%Td zP{G%e-?}zzKKWIeiLrB|Vu#4~xjc+AJd;_o`RiZ%?!Cjm_5GH^jEkJMEM5qOtWXN!0|&tUwZ&ko7#Ooi(*eq$ShR3BE!uT>UfjNW WN)t8rEIsD|an|?aP)m-0ECB!y3})s4 delta 989 zcmZqN%(8PM%LWq(M(NF_5)1h@zf*h9y!opZGY8|$$+`FEY)&;6lwzIt@=NB8$<@BP zVAlP~Ykj4Hq8>4IZk{83H*;2$T*ao#-V6+k^Im?syq5tCc-{diJ!2rD3B-yZEKvQw zXi`j?$>kzl=N|n^@jqZ4U$TAyC4qonZL*}_3We_ONrJYT4etw8o}5!ED}IWqNPO1j zhki*S3Z7|u7rs5(leuoAsP^V%X@^ZF(H5aZak0BJP8e0=0Q zIZ-L;v9oTzqIai`EyU<-1&9vDm6Io=*d-`E>OGM2*8l zAdO~f(WK^0a*8J%f3*Jo@}>2~9aJ3x>XRq73J1;*^Utrly5|1vjIFKD52&K5xx9;5 zQ?Ic?+yOCla$A=WFmgX#W7|BptAbGhyGyP?Ljv01~6dS4*)d`1q}cI literal 17 VcmZQpDUVz8=j>v01~6cn3IH_X1mgez diff --git a/android_bot/.gradle/8.13/fileHashes/resourceHashesCache.bin b/android_bot/.gradle/8.13/fileHashes/resourceHashesCache.bin index 669b0552c5eeb6a0cd3183a580daad5015dcfec5..f8949c41a20cfe2821f15479b50847faec4c2bde 100644 GIT binary patch delta 343 zcmbO`h4J`Q#tkMCn!@c%(zbFn6{azOfhX^OC|IZ!I(zme|I-k0uf)l&5*8YF-rBU! z(o67$3ND2yW)-+1F5jm&11c^%xm3bJfJ3p%t-kd9I;ddt zs$%B$eG329&i|g`|4!a_rrCK+6;d_V6{MJTWqajcn)0`XzQ;m2vJA#tkMCf_&{u(zbFn6{azOfhX_eSP6^CM}`40sQ42+2z6@Q3t NG}s}w+0o+;BLEgs8Y%z) diff --git a/android_bot/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/android_bot/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 8c1fd746b03d74fb7f71f7de490d881e947b0c8f..302125bb10e17ee8c772da64da7ceccb404b6488 100644 GIT binary patch literal 17 VcmZSn@TkOm3HOb23}C=G6#zaH1#AES literal 17 VcmZSn@TkOm3HOb23}C>R3;;dh1v&r# diff --git a/android_bot/.gradle/buildOutputCleanup/outputFiles.bin b/android_bot/.gradle/buildOutputCleanup/outputFiles.bin index 2d8ab2c13b8dd62d520a5658dba0fa7d7e4ae2ba..7bccaed8a74d69e9844a2534d535cd63fd8cbf35 100644 GIT binary patch delta 99 zcmcb(hOvDu;|3E6#?zZkB?4LaPpnLsc;T`Z0~mw_ZmyMiz$xJ1`>*mf!~R83(bCDG rY8C=coWW&G=gx#f1(P?os#UQt2}^EN{2{*3fOWH@hXCK?^S)*PW+xvk delta 46 zcmV+}0MY-4tpU-j0kAX}0m!p87*PbXo*dT+lZ_@Yv(+YY1OgJ#u_5>uu`oylvq4A@ E4yYs%0{{R3 diff --git a/android_bot/.gradle/file-system.probe b/android_bot/.gradle/file-system.probe index 31d1f58f2e78b231f1be8e324b6cae2921f24a7f..964ca61fac2c1fb9478ecdd8c41ad0937e3a7a08 100644 GIT binary patch literal 8 PcmZQzV4N>1_vJ4D2D}2r literal 8 PcmZQzV4U~z)0sm63-|;H diff --git a/android_bot/app/src/main/java/com/siro/android_bot/service/AppLauncher.kt b/android_bot/app/src/main/java/com/siro/android_bot/service/AppLauncher.kt index 08c71f63..99d0faa2 100644 --- a/android_bot/app/src/main/java/com/siro/android_bot/service/AppLauncher.kt +++ b/android_bot/app/src/main/java/com/siro/android_bot/service/AppLauncher.kt @@ -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 { diff --git a/android_bot/app/src/main/java/com/siro/android_bot/service/ScraperAccessibilityService.kt b/android_bot/app/src/main/java/com/siro/android_bot/service/ScraperAccessibilityService.kt index 1d7ae8b2..5c20d3cd 100644 --- a/android_bot/app/src/main/java/com/siro/android_bot/service/ScraperAccessibilityService.kt +++ b/android_bot/app/src/main/java/com/siro/android_bot/service/ScraperAccessibilityService.kt @@ -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") } diff --git a/backend/bot/generate_price_tasks.php b/backend/bot/generate_price_tasks.php index dc079ac8..34423a28 100644 --- a/backend/bot/generate_price_tasks.php +++ b/backend/bot/generate_price_tasks.php @@ -34,22 +34,40 @@ CREATE TABLE IF NOT EXISTS competitor_prices ( "; $con->exec($sql); -// 2. Ten Key Regions in Damascus -$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], - ['name' => 'Kafersouseh', 'lat' => 33.4981, 'lng' => 36.2730], - ['name' => 'Al-Midan', 'lat' => 33.4947, 'lng' => 36.2995], - ['name' => 'Bab Tuma', 'lat' => 33.5126, 'lng' => 36.3150], - ['name' => 'Rukneddine', 'lat' => 33.5350, 'lng' => 36.2950], - ['name' => 'Dummar', 'lat' => 33.5385, 'lng' => 36.2250], - ['name' => 'Baramkeh', 'lat' => 33.5100, 'lng' => 36.2885], - ['name' => 'Muhajireen', 'lat' => 33.5320, 'lng' => 36.2720], +// 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], + ['name' => 'Kafersouseh', 'lat' => 33.4981, 'lng' => 36.2730], + ['name' => 'Al-Midan', 'lat' => 33.4947, 'lng' => 36.2995], + ['name' => 'Bab Tuma', 'lat' => 33.5126, 'lng' => 36.3150], + ['name' => 'Rukneddine', 'lat' => 33.5350, 'lng' => 36.2950], + ['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,39 +90,44 @@ function generateRandomPoint($lat, $lng, $radius) { $tasksCreated = 0; -foreach ($regions as $region) { - // A. Generate Start Point (within 2km of region center) - $start = generateRandomPoint($region['lat'], $region['lng'], 2); +foreach ($countriesConfig as $countryCode => $config) { + $competitors = $config['competitors']; + $regions = $config['regions']; - // B. Generate Short Trip (2-5 km from start) - $shortDist = rand(20, 50) / 10.0; - $shortEnd = generateRandomPoint($start['lat'], $start['lng'], $shortDist); + foreach ($regions as $region) { + // A. Generate Start Point (within 2km of region center) + $start = generateRandomPoint($region['lat'], $region['lng'], 2); - // C. Generate Long Trip (10-15 km from start) - $longDist = rand(100, 150) / 10.0; - $longEnd = generateRandomPoint($start['lat'], $start['lng'], $longDist); + // B. Generate Short Trip (2-5 km from start) + $shortDist = rand(20, 50) / 10.0; + $shortEnd = generateRandomPoint($start['lat'], $start['lng'], $shortDist); - $trips = [$shortEnd, $longEnd]; + // C. Generate Long Trip (10-15 km from start) + $longDist = rand(100, 150) / 10.0; + $longEnd = generateRandomPoint($start['lat'], $start['lng'], $longDist); - foreach ($trips as $end) { - foreach ($competitors as $app) { - $taskId = "prc_" . uniqid(); - - $taskData = [ - "task_id" => $taskId, - "type" => "price_check", - "app" => $app, - "payload" => [ - "start_lat" => $start['lat'], - "start_lng" => $start['lng'], - "end_lat" => $end['lat'], - "end_lng" => $end['lng'] - ] - ]; + $trips = [$shortEnd, $longEnd]; - // Push to Redis Queue - $redis->lpush('queue:bot:tasks', json_encode($taskData)); - $tasksCreated++; + foreach ($trips as $end) { + foreach ($competitors as $app) { + $taskId = "prc_" . uniqid(); + + $taskData = [ + "task_id" => $taskId, + "type" => "price_check", + "app" => $app, + "payload" => [ + "start_lat" => $start['lat'], + "start_lng" => $start['lng'], + "end_lat" => $end['lat'], + "end_lng" => $end['lng'] + ] + ]; + + // Push to Redis Queue + $redis->lpush('queue:bot:tasks', json_encode($taskData)); + $tasksCreated++; + } } } } diff --git a/backend/bot/standalone_worker.php b/backend/bot/standalone_worker.php index fd03db7d..b772caec 100644 --- a/backend/bot/standalone_worker.php +++ b/backend/bot/standalone_worker.php @@ -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); + + + + @@ -664,7 +672,24 @@ $scrapedResults = json_decode(file_get_contents(RESULTS_FILE), true);
No pending tasks. Queue some tasks using the form on the left!
@@ -702,7 +727,23 @@ $scrapedResults = json_decode(file_get_contents(RESULTS_FILE), true);
- SYP + Scrape Failed diff --git a/loction_server/locationDB.sql b/loction_server/locationDB.sql index c81cb6d4..ed5bf19d 100644 --- a/loction_server/locationDB.sql +++ b/loction_server/locationDB.sql @@ -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`