Spaces:
Paused
Paused
| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| import os | |
| import time | |
| import hashlib | |
| import gradio as gr | |
| from huggingface_hub import login | |
| # استيراد منطق الإدارة وقنوات الخزنة من الملف المنفصل | |
| import admin_panel | |
| # تسجيل الدخول وتأكيد السيادة | |
| TOKEN = os.getenv("AIOCR_KEY") | |
| if TOKEN: | |
| TOKEN = TOKEN.strip().split()[0] | |
| login(token=TOKEN) | |
| # دالة التحكم في ظهور زر التحقق بمجرد بدء كتابة الاسم | |
| def on_username_change(username): | |
| if username.strip(): | |
| return gr.update(visible=True) | |
| return gr.update(visible=False) | |
| # دالة التحقق من الاسم داخل الخزنة السحابية | |
| def check_user_in_vault(username): | |
| if not username.strip(): | |
| return ( | |
| gr.update(visible=False), | |
| gr.update(visible=False), | |
| gr.update(visible=False), | |
| "⚠️ يرجى إدخال الاسم أولاً لإجراء الفحص السيادي." | |
| ) | |
| registry = admin_panel.read_vault_file(admin_panel.USER_REGISTRY_FILE) or {} | |
| if username.strip() in registry: | |
| return ( | |
| gr.update(visible=False), | |
| gr.update(visible=False), | |
| gr.update(visible=True), | |
| f"🟢 مرحباً بعودتك يا {username}! تم التحقق من وجودك بالخزنة. يمكنك العبور الآن مباشرة." | |
| ) | |
| else: | |
| return ( | |
| gr.update(visible=True, value=""), | |
| gr.update(visible=True, value=False), | |
| gr.update(visible=False), | |
| "ℹ️ هذا الاسم غير مسجل سابقاً. يرجى إكمال إدخال الإيميل والموافقة على الشروط لإتمام التسجيل الأول." | |
| ) | |
| # دالة التحكم في ظهور زر البصمة بناءً على الموافقة على الشروط | |
| def toggle_gait_button(terms_accepted, email_val): | |
| if terms_accepted and email_val.strip(): | |
| return gr.update(visible=True) | |
| return gr.update(visible=False) | |
| # دالة التنقل من واجهة الأزرار الستة إلى واجهة التسجيل | |
| def navigate_to_registration(service_name): | |
| return ( | |
| gr.update(visible=False), | |
| gr.update(visible=True), | |
| f"🎯 الخدمة المحددة حالياً: {service_name}", | |
| service_name | |
| ) | |
| # 🎯 دالة موحّدة: تأخذ البصمة وتولّد رابط العبور وتعرضه فوراً في ضغطة واحدة | |
| # (دُمجت هنا خطوتا "navigate_to_gait_interface" و"generate_redirect_link" | |
| # القديمتين معاً، فلا حاجة لزر "إتمام عملية البصمة" المنفصل بعد الآن) | |
| def navigate_to_gait_interface(username, email, service): | |
| status_text = f"⚙️ تم ربط الجلسة بنجاح للمشترك: **{username}** | الخدمة المحددة: **{service}**" | |
| # دالة تشفير ثابتة (تأخذ الاسم والإيميل) لإنتاج نفس الرقم دائماً لكل مستخدم | |
| combined_string = f"{username.strip()}-{email.strip()}" | |
| hash_object = hashlib.md5(combined_string.encode('utf-8')) | |
| stable_numeric_id = str(int(hash_object.hexdigest(), 16) % 100000000).zfill(8) | |
| generated_device_token = f"SECURE-FPR-{stable_numeric_id}" | |
| # 🎯 التوجيه بحسب الخدمة المختارة: AI TTS تتجه لمساحة Radar تحديداً. | |
| # تنسيق رابط Hugging Face Space الرسمي: https://<username>-<space-name>.hf.space | |
| # (حروف صغيرة بالكامل + تحويل الشَّرطة السفلية "_" إلى شَرطة عادية "-") | |
| # Asem75/Aiocr_Radar → asem75-aiocr-radar | |
| if service == "AI_TTS": | |
| target_base = "https://asem75-aiocr-radar.hf.space" | |
| else: | |
| target_base = "https://asem75-aiocr-upload.hf.space" | |
| redirect_url = f"{target_base}/?user={username}&email={email}&device_token={generated_device_token}" | |
| html_output = f""" | |
| <div style="text-align:center; padding:20px; border: 2px solid #d4af37; background:#111827; border-radius:10px; margin-top:15px;"> | |
| <h4 style="color:#22c55e; margin:0 0 10px 0;">✅ تم إتمام ومطابقة البصمة بنجاح!</h4> | |
| <p style="color:#f3f4f6; font-size:15px; margin-bottom:15px;">اضغط على الرابط أدناه للعبور الآمن إلى بوابة الخدمة:</p> | |
| <a href="{redirect_url}" target="_blank" style="display:inline-block; padding:12px 25px; background:linear-gradient(135deg, #d4af37, #aa841a); color:#0f172a; font-weight:bold; font-size:16px; text-decoration:none; border-radius:8px; box-shadow: 0 0 15px #d4af37;">🔓 فتح بوابة العبور</a> | |
| </div> | |
| """ | |
| return ( | |
| gr.update(visible=False), # إخفاء طبقة التسجيل | |
| gr.update(visible=True), # إظهار طبقة العبور النهائية | |
| status_text, # نص معلومات الجلسة | |
| gr.update(visible=True, value=html_output), # إظهار رابط العبور فوراً | |
| ) | |
| # 🎯 دالة العودة السيادية إلى الصفحة الرئيسية لمنع أي نقص بالمعلومات | |
| def navigate_back_to_dashboard(): | |
| return ( | |
| gr.update(visible=True), # إظهار الأزرار الستة لخدمات المنصة | |
| gr.update(visible=False), # إخفاء طبقة البصمة | |
| "⚠️ يرجى الضغط على إحدى الأيقونات النشطة في الأعلى للبدء...", # تصفير مؤشر الخدمة | |
| gr.update(visible=False), # إخفاء زر العبور للتسجيل | |
| gr.update(visible=False) # إخفاء مخرجات رابط الرفع HTML | |
| ) | |
| def load_initial_about_data(): | |
| about_data = admin_panel.read_vault_file(admin_panel.ABOUT_APP_FILE) or {} | |
| info_val = about_data.get("info", "مرحباً بك في المنظومة الموحدة لخدمات الذكاء الاصطناعي السيادي.") | |
| version_val = about_data.get("version", "v3.0.0") | |
| return info_val, f"الإصدار الحالي المعتمد: {version_val}" | |
| COMBINED_CSS = """ | |
| body, .gradio-container { background-color: #0b0f19 !important; color: #f3f4f6 !important; font-family: 'Tajawal', sans-serif !important; } | |
| h1, h2, h3 { color: #d4af37 !important; text-align: center; } | |
| .custom-btn-card { font-size: 16px !important; font-weight: bold !important; height: 110px !important; border: 2px solid #38bdf8 !important; background: #1e293b !important; border-radius: 12px !important; cursor: pointer !important; transition: all 0.3s ease !important; } | |
| .custom-btn-card:hover { transform: translateY(-4px) !important; box-shadow: 0 0 15px #38bdf8 !important; } | |
| .custom-btn-disabled { font-size: 16px !important; font-weight: bold !important; height: 110px !important; border: 2px solid #475569 !important; background: #1e293b !important; opacity: 0.4 !important; border-radius: 12px !important; cursor: not-allowed !important; } | |
| button, .gr-button { background: linear-gradient(135deg, #d4af37, #aa841a) !important; color: #0f172a !important; font-weight: bold !important; border-radius: 8px !important; } | |
| .custom-gait-container { padding: 20px; border: 1px dashed #d4af37; background-color: #111827; border-radius: 10px; margin-bottom: 15px; } | |
| """ | |
| with gr.Blocks(title="بوابة توجيه المنظومة الموحدة") as demo: | |
| selected_service_state = gr.State("") | |
| gr.HTML(""" | |
| <div style="text-align:center; padding:20px; border-radius:10px; margin-bottom:15px;"> | |
| <h1 style="margin:0; font-size:2.2rem; filter:drop-shadow(0 0 10px #d4af37);">🔮 سديم المنظومة السيادية الموحدة</h1> | |
| <p style="color:#9ca3af; margin:5px 0 0 0; font-size:1.05rem;">بوابة العبور الذكية الموحدة للمساحات السيادية ومراقبة الرام</p> | |
| </div> | |
| """) | |
| with gr.Tabs(): | |
| with gr.Tab("📱 خدمات المنصة الرقمية"): | |
| with gr.Column(visible=True) as layer_1_icons: | |
| gr.HTML("<h3 style='text-align:right; margin-bottom:20px; color:#38bdf8;'>👋 خطوتك الأولى: اختر الخدمة الذكية التي تود تفعيلها من القائمة التالية:</h3>") | |
| with gr.Row(): | |
| btn_ocr = gr.Button("🔮\nAI OCR", elem_classes="custom-btn-card") | |
| btn_tts = gr.Button("🗣️\nAI TTS", elem_classes="custom-btn-card") | |
| btn_teacher = gr.Button("👨🏫\nMy Teacher", elem_classes="custom-btn-card") | |
| with gr.Row(): | |
| btn_explore = gr.Button("📚\nMy Courses", elem_classes="custom-btn-card") | |
| btn_editor_dis = gr.Button("📝\nAI Editor (قريباً)", elem_classes="custom-btn-disabled", interactive=False) | |
| btn_vault_dis = gr.Button("🛡️\nخزنة الحماية (قريباً)", elem_classes="custom-btn-disabled", interactive=False) | |
| service_indicator = gr.Markdown("⚠️ يرجى الضغط على إحدى الأيقونات النشطة في الأعلى للبدء...", elem_id="serv-ind") | |
| next_to_reg_btn = gr.Button("🚪 ادخل للتسجيل وتأكيد الهوية", variant="primary", visible=False) | |
| with gr.Column(visible=False) as layer_2_registration: | |
| gr.HTML("<h3 style='text-align:right; color:#d4af37;'>📝 خطوتك الثانية: تسجيل الهوية والعبور الآمن للبصمة</h3>") | |
| with gr.Tabs(): | |
| with gr.Tab("🔐 بوابة العبور والتسجيل"): | |
| with gr.Row(): | |
| client_name = gr.Textbox(label="👤 الاسم الكامل", placeholder="اكتب اسمك الثلاثي هنا لتأكيد البصمة...") | |
| verify_user_btn = gr.Button("🔍 فحص والتحقق من الاسم في الخزنة السحابية", variant="secondary", visible=False) | |
| status_check_output = gr.Markdown("📌 بانتظار إدخال الاسم وضغط زر التحقق...") | |
| with gr.Row(): | |
| client_email = gr.Textbox(label="📧 البريد الإلكتروني المعتمد", placeholder="اكتب بريدك الإلكتروني هنا...", visible=False) | |
| terms_checkbox = gr.Checkbox(label="📜 أوافق بالكامل على شروط وأحكام العبور السيادية واستخدام المنظومة الموحدة", value=False, visible=False) | |
| go_to_static_btn = gr.Button("🔗 الانتقال إلى فحص البصمة والتوجيه النهائي", variant="primary", visible=False) | |
| with gr.Tab("ℹ️ حول التطبيق والوثيقة الاستراتيجية"): | |
| about_text_box = gr.Markdown("جاري جلب وثيقة التعريف السحابية...") | |
| version_box = gr.Markdown("الإصدار: جاري الفحص...") | |
| # ────────────────────────────────────────────────────────── | |
| # طبقة العبور النهائية: أصبحت الآن تعرض رابط العبور مباشرة | |
| # بمجرد الوصول إليها (تم حذف شاشة "الوقوف أمام الكاميرا" | |
| # وزر "إتمام عملية البصمة" المنفصل بناءً على طلبك) | |
| # ────────────────────────────────────────────────────────── | |
| with gr.Column(visible=False) as layer_4_gait: | |
| gr.HTML("<h3 style='text-align:center; color:#38bdf8;'>👣 بوابة العبور النهائية</h3>") | |
| gait_session_info = gr.Markdown("⚙️ جاري تحميل بيانات الجلسة المشفرة...") | |
| redirect_link_output = gr.HTML(visible=False) | |
| back_to_services_btn = gr.Button("🔄 العودة إلى القائمة الرئيسية للخدمات", variant="secondary") | |
| with gr.Tab("👑 قمرة القيادة (خاص بالأدمن)"): | |
| with gr.Row(): | |
| admin_pwd_input = gr.Textbox(label="🔑 أدخل رمز العبور السيادي للأدمن", type="password", placeholder="اكتب كلمة مرور الإدارة لوصول كامل...") | |
| verify_pwd_btn = gr.Button("🔓 فحص وتفعيل الصلاحيات") | |
| admin_auth_status = gr.Markdown("🔒 بانتظار إدخال رمز العبور السيادي...") | |
| with gr.Column(visible=False) as layer_3_admin_panel: | |
| about_info_input = gr.Textbox(label="📝 نص وثيقة التعريف الاستراتيجية بالمنظومة", lines=5, visible=False) | |
| about_version_input = gr.Textbox(label="🔢 رقم الإصدار المعتمد سيادياً", visible=False) | |
| adm_refresh_msg, adm_msg_tbl, adm_refresh_usr, adm_usr_tbl = admin_panel.build_admin_ui(about_info_input, about_version_input) | |
| # ================= خريطة تفاعلات الأحداث ================= | |
| btn_ocr.click(fn=lambda: ("AI_OCR", "🟢 تم اختيار خدمة: **AI OCR** بنجاح. يمكنك الآن الدخول للتسجيل.", gr.update(visible=True)), outputs=[selected_service_state, service_indicator, next_to_reg_btn]) | |
| btn_tts.click(fn=lambda: ("AI_TTS", "🟢 تم اختيار خدمة: **AI TTS** بنجاح. يمكنك الآن الدخول للتسجيل.", gr.update(visible=True)), outputs=[selected_service_state, service_indicator, next_to_reg_btn]) | |
| btn_teacher.click(fn=lambda: ("My_Teacher", "🟢 تم اختيار خدمة: **My Teacher** بنجاح. يمكنك الآن الدخول للتسجيل.", gr.update(visible=True)), outputs=[selected_service_state, service_indicator, next_to_reg_btn]) | |
| btn_explore.click(fn=lambda: ("My_Courses", "🟢 تم اختيار خدمة: **My Courses** بنجاح. يمكنك الآن الدخول للتسجيل.", gr.update(visible=True)), outputs=[selected_service_state, service_indicator, next_to_reg_btn]) | |
| next_to_reg_btn.click( | |
| fn=navigate_to_registration, | |
| inputs=[selected_service_state], | |
| outputs=[layer_1_icons, layer_2_registration, service_indicator, selected_service_state] | |
| ) | |
| client_name.change(fn=on_username_change, inputs=[client_name], outputs=[verify_user_btn]) | |
| verify_user_btn.click( | |
| fn=check_user_in_vault, | |
| inputs=[client_name], | |
| outputs=[client_email, terms_checkbox, go_to_static_btn, status_check_output] | |
| ) | |
| terms_checkbox.change(fn=toggle_gait_button, inputs=[terms_checkbox, client_email], outputs=[go_to_static_btn]) | |
| client_email.change(fn=toggle_gait_button, inputs=[terms_checkbox, client_email], outputs=[go_to_static_btn]) | |
| # ضغطة واحدة فقط: تنتقل لطبقة العبور وتولّد رابط التحويل وتعرضه مباشرة | |
| go_to_static_btn.click( | |
| fn=navigate_to_gait_interface, | |
| inputs=[client_name, client_email, selected_service_state], | |
| outputs=[layer_2_registration, layer_4_gait, gait_session_info, redirect_link_output] | |
| ) | |
| back_to_services_btn.click( | |
| fn=navigate_back_to_dashboard, | |
| outputs=[layer_1_icons, layer_4_gait, service_indicator, next_to_reg_btn, redirect_link_output] | |
| ) | |
| def unlock_admin_panel(password): | |
| if password == "asem2026": | |
| return gr.update(visible=True), gr.update(value="🔓 تم التحقق بنجاح! قمرة القيادة نشطة الآن.") | |
| return gr.update(visible=False), gr.update(value="❌ كلمة المرور غير صحيحة. الوصول مرفوض.") | |
| verify_pwd_btn.click(fn=unlock_admin_panel, inputs=[admin_pwd_input], outputs=[layer_3_admin_panel, admin_auth_status]) | |
| demo.load(fn=load_initial_about_data, outputs=[about_text_box, version_box]) | |
| demo.load(admin_panel.load_messages_grid, outputs=[adm_msg_tbl]) | |
| demo.load(admin_panel.get_users_table, outputs=[adm_usr_tbl]) | |
| if __name__ == "__main__": | |
| demo.launch(server_name="0.0.0.0", theme=gr.themes.Soft(), css=COMBINED_CSS) | |