import 'dart:convert'; import 'dart:io'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:jwt_decoder/jwt_decoder.dart'; import 'package:secure_string_operations/secure_string_operations.dart'; import '../../constant/api_key.dart'; import '../../constant/box_name.dart'; import '../../constant/char_map.dart'; import '../../constant/info.dart'; import '../../constant/links.dart'; import '../../env/env.dart'; import '../../main.dart'; import '../../print.dart'; import 'device_info.dart'; import 'encrypt_decrypt.dart'; import 'security_checks.dart'; class CRUD { var dev = ''; getJWT() async { // إذا كان الأدمن مسجل دخوله بالفعل، لا تقم بتوليد توكن "ضيف" قديم if (box.read(BoxName.driverID) != null) { Log.print('Admin session active. Skipping guest JWT.'); return; } dev = Platform.isAndroid ? 'android' : 'ios'; var payload = { 'id': 'admin', 'password': AK.passnpassenger, 'aud': '${AK.allowed}$dev', }; Log.print('payload: ${payload}'); var response1 = await http.post( Uri.parse(AppLink.loginJwtDriver), body: payload, ); if (response1.statusCode == 200) { final decodedResponse1 = jsonDecode(response1.body); final jwt = decodedResponse1['jwt']; Log.print('jwt: ${jwt}'); await box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs)); // await AppInitializer().getKey(); } } Future get({ required String link, Map? payload, }) async { String token = ''; var rawJwt = box.read(BoxName.jwt); if (rawJwt == null) { await getJWT(); rawJwt = box.read(BoxName.jwt); } if (rawJwt != null) { token = r(rawJwt.toString()).split(AppInformation.addd)[0]; try { if (JwtDecoder.isExpired(token)) { // If we have an admin ID, we should probably re-login or refresh, // but for now let's just fall back to guest JWT if needed. if (box.read(BoxName.driverID) == null) { await getJWT(); token = r(box.read(BoxName.jwt).toString()) .split(AppInformation.addd)[0]; } } } catch (e) { print('❌ JWT Decode Error: $e'); // If decryption failed, try using raw (maybe it was saved plain) token = rawJwt.toString().split(AppInformation.addd)[0]; } } var url = Uri.parse(link); Log.print('--- [CRUD GET] ---'); Log.print('URL: $link'); Log.print('Payload: $payload'); var response = await http.post( url, body: payload, headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Bearer $token', 'X-Device-FP': box.read(BoxName.fingerPrint) ?? '', }, ); Log.print('Status Code: ${response.statusCode}'); Log.print('Response Body: ${response.body}'); Log.print('------------------'); if (response.statusCode == 200) { try { var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'success') { return response.body; } return jsonData['status'] ?? 'failure'; } catch (e) { return 'failure'; } } else if (response.statusCode == 401) { return 'token_expired'; } else { return 'failure'; } } Future post( {required String link, Map? payload}) async { var url = Uri.parse(link); try { String token = ''; var rawJwt = box.read(BoxName.jwt); if (rawJwt != null) { token = r(rawJwt.toString()).split(AppInformation.addd)[0]; try { if (JwtDecoder.isExpired(token)) { if (box.read(BoxName.driverID) == null) { await getJWT(); token = r(box.read(BoxName.jwt).toString()) .split(AppInformation.addd)[0]; } } } catch (e) { token = rawJwt.toString().split(AppInformation.addd)[0]; } } Log.print('--- [CRUD POST] ---'); Log.print('URL: $link'); Log.print('Payload: $payload'); var response = await http.post( url, body: payload, headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Bearer $token', 'X-Device-FP': box.read(BoxName.fingerPrint) ?? '', }, ); Log.print('Status Code: ${response.statusCode}'); Log.print('Response Body: ${response.body}'); Log.print('-------------------'); if (response.statusCode == 200) { try { var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'success') { return jsonData; } else { return jsonData['status']; } } catch (e) { return 'failure'; } } else if (response.statusCode == 401) { return 'token_expired'; } else { return 'failure'; } } catch (e) { // addError('HTTP request error: $e', 'crud().post - HTTP'); return 'failure'; } } getJwtWallet() async { // 1. فحص التوكن المخزن أولاً (Caching) لتقليل طلبات الـ SSO var cachedWalletJwt = box.read('wallet_jwt'); var cachedWalletExpiry = box.read('wallet_jwt_expiry'); if (cachedWalletJwt != null && cachedWalletExpiry != null) { int expiryMs = int.tryParse(cachedWalletExpiry.toString()) ?? 0; // إذا لم ينته بعد (مع هامش أمان 60 ثانية) if (DateTime.now().millisecondsSinceEpoch < expiryMs - 60000) { Log.print( 'Using cached Wallet JWT. Expiry: ${DateTime.fromMillisecondsSinceEpoch(expiryMs)}'); return cachedWalletJwt.toString(); } } String fingerPrint = await DeviceHelper.getDeviceFingerprint(); final mainTokenEnc = box.read(BoxName.jwt); if (mainTokenEnc == null) return null; String mainToken = mainTokenEnc.toString(); // فك تشفير التوكن بنفس طريقة دالة get() التي تعمل بنجاح try { mainToken = r(mainTokenEnc.toString()).split(AppInformation.addd)[0]; } catch (e) { // إذا فشل فك التشفير، نستخدم القيمة كما هي (ربما مخزنة بدون تشفير) mainToken = mainTokenEnc.toString().split(AppInformation.addd)[0]; } Log.print('Wallet SSO mainToken length: ${mainToken.length}'); Log.print( 'Wallet SSO token starts with: ${mainToken.substring(0, mainToken.length > 10 ? 10 : mainToken.length)}'); // استخدام الـ SSO للسيرفر الرئيسي إذا كان الأدمن مسجل دخوله var response1 = await http.post( Uri.parse(AppLink.loginWalletAdminV3), headers: { 'Authorization': 'Bearer $mainToken', 'X-Device-FP': fingerPrint, }, ); Log.print('Wallet SSO login status: ${response1.statusCode}'); if (response1.statusCode == 200) { final decoded = jsonDecode(response1.body); final msg = decoded['message']; String? jwt; String? hmac; if (msg is Map) { jwt = msg['jwt']; hmac = msg['hmac']; } else { jwt = decoded['jwt']; hmac = decoded['hmac']; } if (hmac != null) await box.write(BoxName.hmac, hmac); // تخزين التوكن الجديد في الكاش لمدة 10 دقائق (600 ثانية) if (jwt != null) { await box.write('wallet_jwt', jwt); await box.write('wallet_jwt_expiry', (DateTime.now().millisecondsSinceEpoch + (600 * 1000)).toString()); Log.print('Wallet JWT cached successfully.'); } return jwt?.toString(); } else { // Fallback: المحاولة بالطريقة القديمة إذا فشل الـ SSO var payload = { 'id': box.read(BoxName.driverID) ?? '1', 'password': AK.passnpassenger, 'aud': '${Env.allowedWallet}${Platform.isAndroid ? 'android' : 'ios'}', 'fingerPrint': fingerPrint }; var fallbackRes = await http.post( Uri.parse(AppLink.loginWalletAdmin), body: payload, ); if (fallbackRes.statusCode == 200) { final decoded = jsonDecode(fallbackRes.body); if (decoded['jwt'] != null) return decoded['jwt'].toString(); } } return null; } Future getWallet({ required String link, Map? payload, bool isRetry = false, }) async { var s = await getJwtWallet(); final hmac = box.read(BoxName.hmac); var url = Uri.parse(link); Log.print('--- getWallet Execution ---'); Log.print('URL: $url'); Log.print('JWT: $s'); Log.print('HMAC: $hmac'); Log.print('Is Retry: $isRetry'); Log.print('Payload: $payload'); if (payload != null && hmac != null) { payload['hmac'] = hmac.toString(); } try { var response = await http.post( url, body: payload, headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Bearer $s', 'X-HMAC-Auth': hmac.toString(), 'X-Device-FP': box.read(BoxName.fingerPrint) ?? '', }, ); Log.print('Status Code: ${response.statusCode}'); Log.print('Response Body: ${response.body}'); if (response.statusCode == 200) { try { var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'success') { return jsonData; } Log.print('Logic Error: Status is not success. Data: $jsonData'); return jsonData['status'] ?? 'failure'; } catch (e) { Log.print('JSON Decode Error in getWallet: $e'); return 'failure'; } } else if (response.statusCode == 401 && !isRetry) { Log.print('Token expired (401). Clearing cache and retrying...'); await box.remove('wallet_jwt'); await box.remove('wallet_jwt_expiry'); return await getWallet(link: link, payload: payload, isRetry: true); } else { Log.print('HTTP Error in getWallet. Status: ${response.statusCode}'); return 'failure'; } } catch (e) { Log.print('HTTP Request Exception in getWallet: $e'); return 'failure'; } } Future postWallet( {required String link, Map? payload}) async { var s = await getJwtWallet(); Log.print('jwt: ${s}'); final hmac = box.read(BoxName.hmac); Log.print('hmac: ${hmac}'); var url = Uri.parse(link); Log.print('url: ${url}'); // إضافة الـ HMAC للـ payload لزيادة التوافقية if (payload != null && hmac != null) { payload['hmac'] = hmac.toString(); } try { // await LoginDriverController().getJWT(); var response = await http.post( url, body: payload, headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Bearer $s', 'X-HMAC-Auth': hmac.toString(), 'X-Device-FP': box.read(BoxName.fingerPrint) ?? '', }, ); // Log.print('response.request:${response.request}'); // Log.print('response.body: ${response.body}'); // Log.print('payload:$payload'); if (response.statusCode == 200) { try { var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'success') { return jsonData; } return jsonData['status'] ?? 'failure'; } catch (e) { return 'failure'; } } else if (response.statusCode == 401) { await getJwtWallet(); return 'token_expired'; } else { return 'failure'; } } catch (e) { // addError('HTTP request error: $e', 'crud().post - HTTP'); return 'failure'; } } // } Future sendWhatsAppAuth(String to, message) async { var res = await CRUD().post( link: AppLink.send_whatsapp_message, payload: {'receiver': to, 'message': message}); if (res != 'failure') { Get.snackbar('Success', 'Message sent successfully'); } else { Get.snackbar('Error', 'Failed to send message'); } } Future getAgoraToken({ required String channelName, required String uid, }) async { var uid = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver); var res = await http.get( Uri.parse( 'https://repulsive-pig-rugby-shirt.cyclic.app/token?channelName=$channelName'), headers: {'Authorization': 'Bearer ${AK.agoraAppCertificate}'}); if (res.statusCode == 200) { var response = jsonDecode(res.body); return response['token']; } else {} } Future getLlama({ required String link, required String payload, required String prompt, }) async { var url = Uri.parse( link, ); var headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer LL-X5lJ0Px9CzKK0HTuVZ3u2u4v3tGWkImLTG7okGRk4t25zrsLqJ0qNoUzZ2x4ciPy' // 'Authorization': 'Bearer ${Env.llamaKey}' }; var data = json.encode({ "model": "Llama-3-70b-Inst-FW", // "model": "llama-13b-chat", "messages": [ { "role": "user", "content": "Extract the desired information from the following passage as json decoded like $prompt just in this:\n\n$payload" } ], "temperature": 0.9 }); var response = await http.post( url, body: data, headers: headers, ); if (response.statusCode == 200) { return response.body; } return response.statusCode; } Future allMethodForAI(String prompt, driverID, imagePath) async { // await ImageController().choosImage(linkPHP, imagePath); Future.delayed(const Duration(seconds: 2)); var extractedString = await arabicTextExtractByVisionAndAI( imagePath: imagePath, driverID: driverID); var json = jsonDecode(extractedString); var textValues = getAllTextValuesWithLineNumbers(json); // List textValues = getAllTextValues(json); // await AI().geminiAiExtraction(prompt, textValues); } Map>> getAllTextValuesWithLineNumbers( Map json) { Map>> output = {}; int lineNumber = 1; if (json.containsKey('regions')) { List regions = json['regions']; for (Map region in regions) { if (region.containsKey('lines')) { List lines = region['lines']; List> linesWithText = []; for (Map line in lines) { if (line.containsKey('words')) { List words = line['words']; String lineText = ""; for (Map word in words) { if (word.containsKey('text')) { lineText += word['text'] + " "; } } lineText = lineText.trim(); linesWithText.add( {"line_number": lineNumber.toString(), "text": lineText}); lineNumber++; } } output["region_${region.hashCode}"] = linesWithText; } } } return output; } // List getAllTextValues(Map json) { // List textValues = []; // if (json.containsKey('regions')) { // List regions = json['regions']; // for (Map region in regions) { // if (region.containsKey('lines')) { // List lines = region['lines']; // for (Map line in lines) { // if (line.containsKey('words')) { // List words = line['words']; // for (Map word in words) { // if (word.containsKey('text')) { // textValues.add(word['text']); // } // } // } // } // } // } // } // return textValues; // } Future arabicTextExtractByVisionAndAI({ required String imagePath, required String driverID, }) async { var headers = { 'Content-Type': 'application/json', 'Ocp-Apim-Subscription-Key': AK.ocpApimSubscriptionKey }; String imagePathFull = '${AppLink.server}/card_image/$imagePath-$driverID.jpg'; var request = http.Request( 'POST', Uri.parse( 'https://eastus.api.cognitive.microsoft.com/computervision/imageanalysis:analyze?features=caption,read&model-version=latest&language=en&api-version=2024-02-01')); request.body = json.encode({"url": imagePathFull}); request.headers.addAll(headers); http.StreamedResponse response = await request.send(); if (response.statusCode == 200) { return await response.stream.bytesToString(); } else {} } Future getChatGPT({ required String link, required String payload, }) async { var url = Uri.parse( link, ); var headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer ${Env.chatGPTkeySeferNew}' }; var data = json.encode({ "model": "gpt-3.5-turbo", "messages": [ { "role": "user", "content": "Extract the desired information from the following passage as json decoded like vin,make,made,year,expiration_date,color,owner,registration_date just in this:\n\n$payload" } ], "temperature": 0.9 }); var response = await http.post( url, body: data, headers: headers, ); if (response.statusCode == 200) { return response.body; } return response.statusCode; } Future postStripe({ required String link, Map? payload, }) async { // String? secretKey = await storage.read(key: BoxName.secretKey); var url = Uri.parse( link, ); var response = await http.post( url, body: payload, headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Bearer ${AK.secretKey}', }, ); if (response.statusCode == 200) { return response.body; } else {} } Future kazumiSMS({ required String link, Map? payload, }) async { var url = Uri.parse( link, ); var headers = {'Content-Type': 'application/json'}; var request = http.Request('POST', url); request.body = json.encode({ "username": "Sefer", "password": AK.smsPasswordEgypt, }); request.headers.addAll(headers); http.StreamedResponse response = await request.send(); if (response.statusCode == 200) { var responseBody = await response.stream.bytesToString(); var data = json.decode(responseBody); return data; } else {} } Future sendSmsEgypt(String phone, otp) async { // String sender = await getSender(); var headers = {'Content-Type': 'application/json'}; var body = jsonEncode({ "username": "Sefer", "password": "E)Pu=an/@Z", "message": otp, "language": "e", "sender": "Sefer Egy", "receiver": phone }); var res = await http.post( Uri.parse(AppLink.sendSms), body: body, headers: headers, ); } Future postPayMob({ required String link, Map? payload, }) async { // String? basicAuthCredentials = // await storage.read(key: BoxName.basicAuthCredentials); var url = Uri.parse( link, ); var response = await http.post(url, body: payload, headers: {'Content-Type': 'application/json'}); var jsonData = jsonDecode(response.body); if (response.statusCode == 200) { if (jsonData['status'] == 'success') { return response.body; } else { return (jsonData['status']); } } else { return response.statusCode; } } sendEmail( String link, Map? payload, ) async { var headers = { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', }; var request = http.Request('POST', Uri.parse(link)); request.bodyFields = payload!; request.headers.addAll(headers); http.StreamedResponse response = await request.send(); if (response.statusCode == 200) { } else {} } Future postFromDialogue({ required String link, Map? payload, }) async { // String? basicAuthCredentials = // await storage.read(key: BoxName.basicAuthCredentials); var url = Uri.parse( link, ); var response = await http.post( url, body: payload, headers: { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', }, ); if (response.body.isNotEmpty) { var jsonData = jsonDecode(response.body); if (response.statusCode == 200) { if (jsonData['status'] == 'success') { Get.back(); // Get.snackbar( // jsonData['status'], // jsonData['message'], // ); return response.body; } } return (jsonData['status']); } } Future sendVerificationRequest(String phoneNumber) async { final accountSid = AK.accountSIDTwillo; final authToken = AK.authTokenTwillo; final verifySid = AK.twilloRecoveryCode; final Uri verificationUri = Uri.parse( 'https://verify.twilio.com/v2/Services/$verifySid/Verifications'); // Send the verification request final response = await http.post( verificationUri, headers: { 'Authorization': 'Basic ${base64Encode(utf8.encode('$accountSid:$authToken'))}', 'Content-Type': 'application/x-www-form-urlencoded', }, body: { 'To': phoneNumber, 'Channel': 'sms', }, ); if (response.statusCode == 201) { } else {} // Prompt the user to enter the OTP const otpCode = "123456"; // Replace with user input // Check the verification code final checkUri = Uri.parse( 'https://verify.twilio.com/v2/Services/$verifySid/VerificationCheck'); final checkResponse = await http.post( checkUri, headers: { 'Authorization': 'Basic ${base64Encode(utf8.encode('$accountSid:$authToken'))}', 'Content-Type': 'application/x-www-form-urlencoded', }, body: { 'To': phoneNumber, 'Code': otpCode, }, ); if (checkResponse.statusCode == 201) { } else {} } Future getGoogleApi({ required String link, Map? payload, }) async { var url = Uri.parse( link, ); var response = await http.post( url, body: payload, ); var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'OK') { return jsonData; } return (jsonData['status']); } Future update({ required String endpoint, required Map data, required String id, }) async { // String? basicAuthCredentials = // await storage.read(key: BoxName.basicAuthCredentials); var url = Uri.parse('$endpoint/$id'); var response = await http.put( url, body: json.encode(data), headers: { 'Authorization': 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', }, ); return json.decode(response.body); } Future delete({ required String endpoint, required String id, }) async { // String? basicAuthCredentials = // await storage.read(key: BoxName.basicAuthCredentials); var url = Uri.parse('$endpoint/$id'); var response = await http.delete( url, headers: { 'Authorization': 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', }, ); return json.decode(response.body); } List phoneDriversTest = [ 201023248456, 201023248456, ]; }