CoolFace
Apppublic

Mariamsayed17/first-aid-api

sourceHugging Faceapache-2.0updated 4mo agoView on Hugging Face
0likes
main.py764 linesDownload Raw Back to root
1import os2 3import io4import json5import numpy as np6import joblib7import tensorflow as tf8from PIL import Image9import cv210from fastapi import FastAPI, File, UploadFile, Query11from fastapi.middleware.cors import CORSMiddleware12from pydantic import BaseModel13from database import save_user, save_prediction14 15 16# =========================17# 🔧 FIX KERAS ERROR18 19from keras.layers import InputLayer20 21def custom_input_layer(*args, **kwargs):22    if "batch_shape" in kwargs:23        batch_shape = kwargs.pop("batch_shape")24        kwargs["shape"] = batch_shape[1:]25 26    kwargs.pop("optional", None)27 28    return InputLayer(*args, **kwargs)29 30 31# =========================32# 🚀 APP33# =========================34app = FastAPI(title="Esafny AI Unified")35 36app.add_middleware(37    CORSMiddleware,38    allow_origins=["*"],39    allow_credentials=True,40    allow_methods=["*"],41    allow_headers=["*"],42)43 44 45class User(BaseModel):46    name: str47    email: str48    password: str49 50 51@app.get("/")52def home():53    return {"message": "API is working 🚀"}54 55 56# 🧪 test insert57@app.get("/test-insert")58def test_insert():59    res = save_prediction(1, "test_case")60 61    if res:62        return {"status": "Insert Success ✅"}63    else:64        return {"status": "Insert Failed ❌"}65 66# =========================67# 💬 CHAT MODEL68# =========================69class ChatRequest(BaseModel):70    message: str71 72 73# =========================74# 🧠 IMAGE MODELS75# =========================76import keras77from keras.layers import Dense78 79_old_init = Dense.__init__80 81def new_init(self, *args, **kwargs):82    kwargs.pop("quantization_config", None)83    _old_init(self, *args, **kwargs)84 85Dense.__init__ = new_init86extractor = tf.keras.models.load_model(87    "wound_extractor_model.h5",88    compile=False,89    custom_objects={90        "InputLayer": custom_input_layer91    }92)93ensemble = joblib.load("wound_ensemble_model.pkl")94 95with open("class_indices.json", "r") as f:96    labels = list(json.load(f).keys())97 98 99# =========================100# 🧠 DETECT FROM TEXT101# =========================102def detect_injury(message: str):103    msg = message.lower()104 105    mapping = {106        "headache": ["صداع", "headache"],107        "fever": ["حمى", "fever"],108        "abdominal_pain": ["مغص", "stomach"],109        "diarrhea": ["اسهال", "diarrhea"],110        "vomiting": ["قيء", "vomit"],111        "cough": ["سعال", "cough"],112        "choking": ["اختناق", "choking"],113        "wound": ["جرح", "wound"],114        "bleeding": ["نزيف", "bleeding"],115        "burn": ["حرق", "burn"],116        "bruise": ["كدمة", "bruise"],117        "allergy": ["حساسية", "allergy"],118        "fracture": ["كسر", "fracture"],119        "dizziness": ["دوخة", "dizziness"],120        "cut": ["cut", "جرح"],121        "abrasion": ["abrasion", "سحجات"],122        "laceration": ["laceration", "جرح عميق"],123        "normal skin": ["جلد طبيعي"],124        "poisoning":["poisoning", "تسمم"],125        "diabetic_emergencies":["diabetic_emergencies"," السكري"],126        "seizures":["seizures", "تشنج"]127    }128 129    for k, v in mapping.items():130        if any(i in msg for i in v):131            return k132 133    return "unknown"134 135 136# =========================137# 🧠 SEVERITY138# =========================139def analyze_image_severity(img, injury):140 141    image = np.array(img)142    gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)143 144    if injury in ["cut", "wound", "laceration"]:145 146        edges = cv2.Canny(gray, 50, 150)147        wound_pixels = np.sum(edges > 0)148 149        if wound_pixels > 4000:150            return "شديدة"151        elif wound_pixels > 1500:152            return "متوسطة"153        else:154            return "بسيطة"155 156    elif injury == "burn":157 158        hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)159 160        red_mask = cv2.inRange(161            hsv,162            np.array([0, 50, 50]),163            np.array([20, 255, 255])164        )165 166        burn_area = np.sum(red_mask > 0)167 168        if burn_area > 20000:169            return "شديدة"170        elif burn_area > 8000:171            return "متوسطة"172        else:173            return "بسيطة"174 175    elif injury == "bruise":176 177        dark_pixels = np.sum(gray < 80)178 179        if dark_pixels > 15000:180            return "شديدة"181        elif dark_pixels > 7000:182            return "متوسطة"183        else:184            return "بسيطة"185 186    elif injury in [187        "fracture",188        "seizures",189        "poisoning",190        "choking",191        "diabetic_emergencies"192    ]:193        return "شديدة"194 195    return "بسيطة"196 197# =========================198# 🧠 FIRST AID199# =========================200def get_first_aid(injury, severity):201    data = {"burn": {202            "بسيطة": {203                "explanation": "حرق من الدرجة الأولى يصيب البشرة فقط؛ يظهر كاحمرار وألم بسيط دون فقاعات.",204                "steps": [205                    "أبعد المصاب عن مصدر الحرق فوراً.",206                    "ضع المنطقة تحت ماء جاري فاتر (15-20 دقيقة) وتجنب الثلج مباشرة.",207                    "انزع أي إكسسوارات (خواتم/ساعات) قبل حدوث تورم.",208                    "جفف المنطقة بلطف وادهن كريماً مرطباً.",209                    "تغطية بسيطة بشاش معقم إذا لزم الأمر."210                ],211                "medicine": ["Panthenol Cream", "Bepanthen Plus", "Aloe Vera Gel", "MEBO (مرطب جروح)"],212                "hospital_trigger": False213            },214            "متوسطة": {215                "explanation": "حرق من الدرجة الثانية؛ يسبب فقاعات سوائل (Blisters) وألماً شديداً جداً وتورم.",216                "steps": [217                    "تبريد المنطقة بالماء الفاتر فوراً.",218                    "ممنوع ثقب أو فتح الفقاعات نهائياً لتجنب التلوث والعدوى.",219                    "تغطية الحرق بشاش معقم غير لاصق (Vaseline Gauze).",220                    "رفع الطرف المصاب لتقليل التورم."221                ],222                "medicine": ["MEBO Ointment", "Fucidin Cream (مضاد حيوي)", "Silver Sulfadiazine", "Ibuprofen (مسكن ألم)"],223                "hospital_trigger": True,224                "hospital_note": "في حالة الحروق المتوسطة، اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى لتجنب التلوث."225            },226            "شديدة": {227                "explanation": "حرق من الدرجة الثالثة؛ يتلف الجلد بعمق وقد يبدو متفحماً أو أبيض اللون، وغالباً لا يشعر المصاب بالألم لتلف الأعصاب.",228                "steps": [229                    "لا تضع أي سوائل أو كريمات أو مواد منزلية.",230                    "غطِّ المنطقة المحروقة بقطعة قماش معقمة وجافة تماماً.",231                    "تأكد من علامات التنفس لدى المصاب.",232                    "التوجه للطوارئ فوراً أو طلب الإسعاف."233                ],234                "medicine": ["إجراءات المستشفى فقط (IV Fluids, Morphine)"],235                "hospital_trigger": True,236                "hospital_note": "الحالة حرجة جداً! اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى فوراً."237            }238        },"fracture": {239            "بسيطة": {240                "explanation": "كسر مغلق بسيط أو شعري؛ لا يوجد تشوه واضح في شكل العضو.",241                "steps": [242                    "تثبيت العضو المصاب بجبيرة مؤقتة (خشب أو كرتون) لمنع الحركة.",243                    "وضع كمادات باردة لتقليل الورم.",244                    "رفع العضو المصاب قليلاً."245                ],246                "medicine": ["Panadol (Paracetamol)", "Advil (Ibuprofen)", "Catafast (عند الحاجة)"],247                "hospital_trigger": True,248                "hospital_note": "لعمل الأشعة والجبيرة، اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى."249            },250            "شديدة": {251                "explanation": "كسر مضاعف (مفتوح) يبرز منه العظم، أو كسر في العمود الفقري/الجمجمة.",252                "steps": [253                    "ممنوع تحريك المصاب نهائياً في حالات كسر الظهر أو الرقبة.",254                    "في الكسر المفتوح: غطِّ العظم البارز بشاش معقم ولا تحاول إرجاعه مكانه.",255                    "السيطرة على النزيف بالضغط حول منطقة الكسر.",256                    "اطلب الإسعاف فوراً."257                ],258                "medicine": ["مسكنات وريدية بالمستشفى"],259                "hospital_trigger": True,260                "hospital_note": "خطر النزيف أو الشلل! اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى فوراً."261            }262        },"bleeding": {263            "بسيطة": {264                "explanation": "نزيف سطحي ناتج عن خدوش بسيطة.",265                "steps": ["غسل الجرح وتطهيره.", "الضغط المباشر لمدة 5 دقائق.", "استخدام لاصق جروح."],266                "medicine": ["Betadine", "Fucidin", "Dettol (مخفف)"],267                "hospital_trigger": False268            },269            "شديدة": {270                "explanation": "نزيف شرياني غزير لا يتوقف بالضغط العادي.",271                "steps": ["ضغط شديد ومستمر بقطعة قماش سميكة ونظيفة.",272                    "رفع العضو فوق مستوى القلب.",273                    "استخدام رباط ضاغط (Tourniquet) في حالات البتر أو النزيف الذي يهدد الحياة."274                ],275                "medicine": ["Hemo-stop", "Kapron (بإشراف طبي)"],276                "hospital_trigger": True,277                "hospital_note": "خطر هبوط الدورة الدموية! اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى فوراً."278            }279        },"choking": {280            "بسيطة": {281                "explanation": "انسداد جزئي لمجرى الهواء (المصاب يسعل).",282                "steps": ["شجع المصاب على السعال بقوة.", "ابقَ بجانبه وراقبه."],283                "medicine": ["Oplex"],284                "hospital_trigger": False285            },286            "شديدة": {287                "explanation": "انسداد كامل؛ المصاب لا يستطيع التنفس أو الكلام ولون وجهه يتغير للأزرق.",288                "steps": [289                    "نفذ مناورة هيمليك (ضغطات قوية على البطن فوق السرة).",290                    "إذا فقد المصاب وعيه، ابدأ الإنعاش القلبي الرئوي (CPR).",291                    "اطلب الإسعاف فوراً."292                ],293                "medicine": ["أكسجين طوارئ"],294                "hospital_trigger": True,295                "hospital_note": "حالة اختناق! اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى فوراً."296            }297        },"diabetic_emergencies": {298            "متوسطة": {299                "explanation": "هبوط سكري؛ انخفاض حاد في السكر؛ تشوش، عرق بارد، ورعشة.",300            301                "steps": [302                    "إعطاء المصاب الواعي نصف كوب عصير أو 3 ملاعق سكر مذابة.",303                    "الانتظار 15 دقيقة وإعادة القياس.",304                    "إعطاء وجبة خفيفة بعد الإفاقة."305                ],306                "medicine": ["Glucolin Tablets", "Dextrose Gel"],307                "hospital_trigger": False308            },309            "شديدة": {310                "explanation": "غيبوبة_كاملة؛ فقدان وعي تام لمريض السكر .",311                "steps": [312                    "ممنوع وضع أي شيء في الفم (خطر الاختناق).",313                    "وضع المصاب في وضعية الإفاقة (على جانبه).",314                    "طلب الإسعاف فوراً."315                ],316                "medicine": ["GlucaGen HypoKit (حقنة طوارئ)"],317                "hospital_trigger": True,318                "hospital_note": "اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى فوراً."319            }320        }, "abdominal_pain": {321            "بسيطة": {322                "explanation": "مغص ناتج عن غازات أو سوء هضم.",323                "steps": ["شرب سوائل دافئة.", "تدليك البطن.", "الراحة."],324                "medicine": ["Buscopan", "Visceral", "Gast-Reg", "Spasmo-digestin"],325                "hospital_trigger": False326            },327            "شديدة": {328                "explanation": "ألم حاد مفاجئ (اشتباه زائدة دودية أو حصوات).",329                "steps": [330                    "ممنوع تناول الطعام أو الشراب.",331                    "ممنوع أخذ مسكنات قوية قبل التشخيص.",332                    "التوجه للطوارئ فوراً."333                ],334                "medicine": ["لا يؤخذ دواء قبل التشخيص"],335                "hospital_trigger": True,336                "hospital_note": "قد تحتاج لتدخل جراحي! اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى فوراً."337            }338        },"seizures": {339            "شديدة": {340                "explanation": "نوبة تشنجات وفقدان وعي.",341                "steps": [342                    "تأمين المكان حول المصاب من الأجسام الحادة.",343                    "وضع وسادة تحت الرأس.",344                    "ممنوع وضع أي شيء في الفم أو تقييد الحركة.",345                    "بعد النوبة، ضعه على جنبه (وضعية الإفاقة)."346                ],347                "medicine": ["Depakine", "Epanutin (للمتابعة)"],348                "hospital_trigger": True,349                "hospital_note": "إذا استمرت النوبة > 5 دقائق، اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى."350            }351        },"allergy": {352            "بسيطة": {353                "explanation": "حكة أو احمرار بسيط.",354                "steps": [355                    "غسل المنطقة بماء بارد.", "الابتعاد عن المسبب."356                    ],357                "medicine": ["Fenistil Gel", "Zyrtec", "Allerid"],358                "hospital_trigger": False359            },360            "شديدة": {361                "explanation": "صدمة تحسسية؛ تورم اللسان وضيق تنفس حاد.",362                "steps": [363                    "استخدام حقنة EpiPen إن وجدت.", "النقل الفوري للمستشفى."364                ],365                "medicine": ["Adrenaline (Epinephrine)", "Telfast"],366                "hospital_trigger": True,367                "hospital_note": "حالة حياة أو موت! اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى فوراً."368            }369        },"poisoning": {370            "شديدة": {371                "explanation": "بلع مواد كيميائية أو جرعات أدوية زائدة.",372                "steps": [373                    "تحديد المادة وكميتها.",374                    "ممنوع إجبار المصاب على القيء (خاصة مع المنظفات).",375                    "الاتصال بمركز السموم فوراً."376                ],377                "medicine": ["Activated Charcoal (فحم نشط)"],378                "hospital_trigger": True,379                "hospital_note": "اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى فوراً."380            }381        },"headache": {382            "بسيطة": {383               "explanation": "صداع توتري أو ناتج عن إجهاد عام.",384                "steps": [385                    "الراحة في غرفة مظلمة", "شرب كمية كافية من الماء" 386                ],387                "medicine": ["Panadol ", "Abimol ", "Advil "],388                "hospital_trigger": False,389            },390            "شديدة": {391                "explanation": "صداع حاد ومفاجئ قد يكون مؤشراً لارتفاع شديد في ضغط الدم أو مشاكل وعائية.",392                "steps": [393                    "قياس ضغط الدم فوراً", "تجنب الحركة المفاجئة" 394                ],395                "medicine": ["Cataflam ", "Excedrin "],396                "hospital_trigger": True,397                "hospital_note": "خطر! هذا النوع من الصداع يتطلب فحصاً عصبياً فورياً لاستبعاد النزيف أو الجلطة. اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى فوراً."398            }399        },"fever": {400            "بسيطة":{401                "explanation": "ارتفاع طفيف في درجة الحرارة (أقل من 38.5).",402                "steps": [403                    "الإكثار من السوائل", "تخفيف الملابس"404                ],405                "medicine": ["Panadol ", "Cetal "],406                "hospital_trigger": False,407            },   408            "متوسطة":{409               "explanation": "حرارة متوسطة ناتجة عن التهاب محتمل (38.5 - 39.5).",410                "steps": [411                    "عمل كمادات ماء فاتر", "الراحة التامة"412                ],413               "medicine": ["Brufen ", "Voltaren Supp "],414               "hospital_trigger": False,415            },  416            "شديدة": {417                "explanation": "حمى شديدة (فوق 39.5) تهدد وظائف الجسم الحيوية.",418                "steps": [419                    "كمادات فورية تحت الإبط وبين الفخذين", "عدم استخدام الماء المثلج"420                ],421                "medicine": ["Perfalgan (حقن وريدية بالمستشفى)"],422                "hospital_trigger": True,423                "hospital_note": "اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى."424            }425        },"bruise": {426            "بسيطة":{427                "explanation": "تجمع دموي سطحي نتيجة اصطدام.",428                "clinical_steps": [429                    "كمادات باردة لمدة 15 دقيقة", "رفع العضو المصاب"430                ],431                "prescribed_meds": ["Reparil Gel", "Hirudoid"],432                "hospital_trigger": False,433            },434            "متوسطة": {435                "explanation": "تجمع دموي واسع مع ألم عند اللمس وتورم ملحوظ.",436                "steps": [437                    "استخدام كمادات باردة في أول يومين", "ثم كمادات دافئة بعد 48 ساعة"438                ],439                "medicine": ["Alpha-Chymotrypsin ", "Ibuprofen"],440                "hospital_trigger": False,441            },442            "شديدة": {443                "explanation": "كدمة واسعة مع اشتباه نزيف داخليأو كسر.",444                "steps": [445                    "تثبيت العضو تماماً", "عمل أشعة X-Ray"446                ],447                "hospital_trigger": True,448                "hospital_note": "اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى."449            }450        },"dizziness": {451            "بسيطة": {452                "explanation": "دوار ناتج عن هبوط طفيف في ضغط الدم أو نقص سكر.",453                "steps": [454                    "الاستلقاء مع رفع القدمين", "تناول وجبة خفيفة سكرية"455                ],456                "medicine": ["Effortil (إيفورتيل لرفع الضغط)", "شرب سوائل مملحة"],457                "hospital_trigger": False,458           },  459            "شديدة": {460                "explanation": "دوار دهليزي حاد أو فقدان توازن يمنع الحركة.",461                "steps": [462                    "تثبيت الرأس في وضعية مريحة", "تجنب الإضاءة القوية"463                ],464                "medicine": ["Betaserc ", "Stugeron "],465                "hospital_trigger": True,466                "hospital_note": "قد يشير الدوار الشديد لمشكلة في الأذن الداخلية أو تدفق الدم للمخ. اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى"467            }468        },"vomiting": {469            "بسيطة": {470                "explanation": "اضطراب بسيط في المعدة أو غثيان عارض.",471                "steps": [472                    "التوقف عن الأكل لمدة ساعتين", "رشفات صغيرة من الماء"473                ],474                "medicine": ["Motilium (موتيليوم)", "Emetrex (إيميتريكس)"],475                "hospital_trigger": False,476            },477           478            "شديدة": {479                "explanation": "قيء قهري مستمر يمنع الاحتفاظ بأي سوائل داخل الجسم.",480                "steps": [481                    "مراقبة علامات الجفاف (جفاف اللسان/قلة التبول)"482                ],483                "medicine": ["Primperan ", "Zofran "],484                "hospital_trigger": True,485                "hospital_note": "تحتاج لتعويض السوائل عن طريق المحاليل الوريدية فوراً. اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى"486            }487        },"diarrhea": {488            "بسيطة": {489                "explanation": "نزلات معوية بسيطة أو سوء هضم.",490                "steps": [491                 "شرب محلول الجفاف بعد كل مرة إسهال", "تناول الزبادي والبطاطس المسلوقة"492                ],493                "medicine": ["Smecta ", "ORS (محلول جفاف)"],494                "hospital_trigger": False, 495            },496            "شديدة": {497                "explanation": "إسهال حاد (أكثر من 10 مرات يومياً) أو وجود دم بالبراز.",498                "steps": [499                    "جمع عينة للتحليل إذا أمكن", "مراقبة درجة الحرارة"500                ],501                "medicine": ["Antinal ", "Streptoquin "],502                "hospital_trigger": True,503                "hospital_note": "اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى."504            }505        },506        "cut": {507            "بسيطة": {508                "explanation": "جرح قطعي سطحي لا يتجاوز الطبقة الخارجية للجلد والنزيف يتوقف سريعاً.",509                "steps": [510                    "غسل الجرح بماء نظيف وصابون", "الضغط المباشر بقطعة شاش معقمة"511                ],512                "medicine": ["Betadine", "Fucidin (مضاد حيوي موضعى)", "لاصق جروح"],513                "hospital_trigger": False,514            },515          "متوسطة": {516              "explanation": "جرح أعمق قليلاً، النزيف يحتاج لضغط مستمر وقد يحتاج لغرز بسيطة.",517              "steps": [518                 "تطهير حول الجرح وليس داخله", "استخدام رباط ضاغط خفيف"519               ],520              "medicine": ["Fucicort Cream", "Garamycin Ointment"],521              "hospital_trigger": True,522              "hospital_note": "قد يحتاج الجرح لغرز طبية (Sutures). اضغط على 'مستشفيات' للتقييم الجراحي وللحصول على عنوان أقرب مستشفي."523            },524            "شديدة": {525                "explanation": "جرح قطعي غائر مع نزيف شرياني أو ظهور أنسجة داخلية.",526                "steps": [527                    "ضغط شديد جداً فوق النزيف", "رفع العضو فوق مستوى القلب", "عدم إزالة الشاش إذا تشبع بالدم بل أضف فوقه"528                    ],529                "medicine": ["حقنة تيتانوس (Tetanus Toxoid) في المستشفى"],530                "hospital_trigger": True,531                "hospital_note": "خطر النزيف الحاد! توجه لأقرب قسم طوارئ فوراً من خلال قائمة المستشفيات للحصول على عنوان أقرب مستشفي"532            }533        },534        "cough": {535            "بسيطة":{536                "explanation": "كحة جافة ناتجة عن حساسية أو تهيج بسيط.",537                "steps": [538                    "شرب سوائل دافئة", "ترطيب هواء الغرفة"539                ],540                "medicine": ["Guaifenesin", "Notuss"],541                "hospital_trigger": False,542            },543            "شديدة": {544                "explanation": "كحة حادة مع نهجان، زرقة في الشفاه، أو خروج دم.",545                "steps": [546                    "الجلوس بوضع قائم", "محاولة التنفس بهدوء"547                ],548                "medicine": ["Bronchicum", "Selgon "],549                "hospital_trigger": True,550                "hospital_note": "اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى."551            }552        },"laceration": {553            "بسيطة": {554                "explanation": "جرح قطعي سطحي.",555                "steps": ["تطهير بماء وملح", "ضغط لوقف النزيف"556                ],557                "medicine": ["Betadine", "Fucidin"],558                "hospital_trigger": False,559            },560            "متوسطة": {561                "explanation": "تمزق جلدي غير منتظم مع تلوث بالأتربة أو أجسام غريبة.",562                "steps": [563                    "غسل مكثف بمحلول ملح (Saline)", "محاولة إيقاف النزيف بقطع معقمة"564                ],565                "medicine": ["Augmentin (مضاد حيوي بالفم)", "Betadine Solution"],566                "hospital_trigger": True,567                "hospital_note": "الجرح المتهتك عرضة للتلوث. اضغط على 'مستشفيات' للتنظيف الجراحي والحصول على عنوان أقرب مستشفي."568            },569            "شديدة": {570                "explanation": "جرح عميق متهتك مع نزيف مستمر.",571                "steps":[572                    "ضغط مباشر وقوي", "رفع العضو للأعلى"573                ],574                "medicine": ["Tetanus Shot (Clinic)"],575                "hospital_trigger": True,576                "hospital_note": "اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى."577            }578        },"abrasion": {579            "بسيطة": {580                 "explanation": "سحجات جلدية سطحية.",581                "steps":[582                    "غسل بمحلول مطهر", "وضع كريم مرطب"583                ],584                "medicine": ["Betadine", "Bepanthen"],585                "hospital_trigger": False,586            },587            "متوسطة": {588                "explanation": "سحجة واسعة تغطي منطقة كبيرة من الجسم (مثل سحجات حوادث الدراجات).",589                "steps": [590                    "تنظيف بلطف لإزالة الأتربة", "وضع طبقة رقيقة من ميبو (Mebo)"591                ],592                "medicine": ["Mebo Ointment", "Flamazine Cream"],593                "hospital_trigger": False,594            },595            "شديدة":{596                 "explanation": "سحجات واسعة ملوثة بأجسام غريبة.",597                "steps":[598                    "تنظيف جراحي هادئ", "مضاد حيوي واسع المدى"599                ],600                "medicine": ["Mebo", "Fucicort"],601                "hospital_trigger": True,602                "hospital_note": "اضغط على 'مستشفيات' من القائمة للحصول على عنوان أقرب مستشفى."603            }604        }, "normal_skin": {605            "بسيطة": {606                "explanation": "الجلد سليم، لا توجد إصابة واضحة.",607                "steps": ["لا يحتاج"],608                "medicine": ["لا يحتاج"]609            }610        }611    }612    return data.get(injury, {}).get(severity, {})613# =========================614# 🧾 RESPONSE615# =========================616def format_response(injury, severity, data):617    if isinstance(data, list):618        data = {619            "explanation": "",620            "steps": [],621            "medicine": data,622            "hospital_trigger": False623        }624 625    if injury in ["normal skin", "normal_skin"]:626        return {627            "injury": "normal_skin",628            "severity": "لا يوجد",629            "explanation": data.get(630                "explanation",631                "الجلد سليم، لا توجد إصابة واضحة."632            ),633            "steps": ["لا يحتاج إلى إسعافات أولية"],634            "medicine": ["لا يحتاج إلى أدوية"],635            "hospital_trigger": False,636            "hospital_note": "لا يحتاج إلى اي شئ سليم معافي"637        }638 639    return {640        "injury": injury,641        "severity": severity,642        "explanation": data.get("explanation", ""),643        "steps": data.get("steps", []),644        "medicine": data.get("medicine", []),645        "hospital_trigger": data.get("hospital_trigger", False),646        "hospital_note": data.get("hospital_note", "")647    }648 649 650# =========================651# 💬 CHAT API652# =========================653@app.post("/chat")654async def chat(data: ChatRequest):655 656    message = data.message657 658    injury = detect_injury(message)659 660    print("injury =", injury)661 662    if injury == "unknown":663        return {664            "bot_response": "❗️ مش قادر أحدد الحالة، ممكن توضحي أكتر؟"665        }666 667    severity = "بسيطة"668 669    result = get_first_aid(injury, severity)670 671    formatted = format_response(672    injury,673    severity,674    result675    )676 677    return {678    "bot_response": formatted679    }680    # =========================681# 🖼 IMAGE API682# =========================683def predict_image(img):684    img = img.resize((224, 224))685    x = np.array(img)686    x = np.expand_dims(x, axis=0)687    x = tf.keras.applications.efficientnet.preprocess_input(x.astype("float32"))688    689    features = extractor.predict(x, verbose=0)690    probs = ensemble.predict_proba(features)[0]691    idx = np.argmax(probs)692    confidence = float(probs[idx])693    injury = labels[idx]694    695    # تحويل المسافة لـ Underscore لتجنب أخطاء القاموس696    if injury == "normal skin":697        injury = "normal_skin"698        699    severity = analyze_image_severity(img, injury)700    data = get_first_aid(injury, severity)701    702    return format_response(injury, severity, data)703 704 705@app.post("/predict")706async def predict(user_id: int = Query(...), file: UploadFile = File(...)):707    try:708        print("========== NEW REQUEST ==========")709        print("user_id =", user_id)710        print("filename =", file.filename)711        712        content = await file.read()713        if not content:714            return {"bot_response": "❌ الملف فارغ"}715 716        # فحص برمجياً هل الملف صورة؟717        try:718            img = Image.open(io.BytesIO(content))719            img.verify()720        except Exception as e:721            print("INVALID IMAGE:", e)722            return {"bot_response": "❌ الملف المرسل ليس صورة صحيحة"}723 724        # إعادة فتح الصورة بعد الـ verify725        img = Image.open(io.BytesIO(content)).convert("RGB")726        727        # تشغيل موديل الذكاء الاصطناعي728        result = predict_image(img)729        print("RESULT =", result)730 731        # استخراج نوع الإصابة لحفظها في قاعدة البيانات732        injury_type = "unknown"733        if result:734            try:735                injury_type = result.split("\n")[0].replace("الحالة: ", "")736            except:737                injury_type = "unknown"738 739        # حفظ في قاعدة البيانات740        save_prediction(user_id, injury_type)741 742        return {743            "type": "image",744            "bot_response": result745        }746    except Exception as e:747        print("ERROR =", str(e))748        return {"bot_response": f"❌ خطأ في السيرفر: {str(e)}"}749        750@app.post("/register")751def register(user: User):752 753    result = save_user(user.name, user.email, user.password)754 755    if isinstance(result, dict) and "error" in result:756        return result757 758    # 👇 دي أهم حاجة759    user_id = result["data"][0]["id"]760 761    return {762        "success": True,763        "user_id": user_id764    }