Spaces:
Running on Zero
Running on Zero
| # admin_office_app_patch.py | |
| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| """ | |
| Divid Teacher — Bridge لمكتب الإدارة V10. | |
| الإصدار: | |
| admin_office_app_patch_v5_admin_office_v10_unified_diagnostics | |
| المهام: | |
| - استخدام admin_access_manager لتسجيل دخول owner / manager_1 / manager_2. | |
| - تركيب admin_office_ui.py داخل admin_panel الحالي. | |
| - تمرير حقل كلمة مرور المدير نفسه حتى يفحص كل زر الصلاحية على السيرفر. | |
| - إبقاء مكونات الفحص القديمة في الخلف للتوافق مع callbacks القديمة، | |
| بينما الفحوص المرئية أصبحت مجتمعة داخل تبويب «الفحص» في Admin Office V10. | |
| - لا يحتاج تعديل app.py يدويًا طالما أن app.py يستدعي apply_admin_office_patch(). | |
| """ | |
| from __future__ import annotations | |
| import re | |
| VERSION = "admin_office_app_patch_v5_admin_office_v10_unified_diagnostics" | |
| REQUIRED_ADMIN_OFFICE_VERSION = ( | |
| "admin_office_ui_v10_repository_browser_" | |
| "flexible_audit_unified_diagnostics" | |
| ) | |
| def _patch_admin_login(source: str) -> str: | |
| new_login = r'''def ui_admin_login(password): | |
| password = str(password or "").strip() | |
| try: | |
| from admin_access_manager import get_manager as get_admin_access_manager | |
| access = get_admin_access_manager() | |
| result = access.authenticate(password) | |
| except Exception as exc: | |
| return ( | |
| markdown_error(f"تعذر تحميل نظام صلاحيات المدراء: {exc}"), | |
| gr.update(visible=False), | |
| ) | |
| if isinstance(result, dict) and result.get("success"): | |
| display_name = str(result.get("display_name") or "المدير").strip() | |
| admin_id = str(result.get("admin_id") or "").strip() | |
| return ( | |
| markdown_success( | |
| f"تم فتح لوحة المدير: {display_name}" | |
| + (f" — {admin_id}" if admin_id else "") | |
| ), | |
| gr.update(visible=True), | |
| ) | |
| message = ( | |
| str(result.get("message") or "كلمة مرور المدير غير صحيحة.") | |
| if isinstance(result, dict) | |
| else "كلمة مرور المدير غير صحيحة." | |
| ) | |
| return ( | |
| markdown_error(message), | |
| gr.update(visible=False), | |
| )''' | |
| pattern = r'''def ui_admin_login\(password\):.*?(?=\n\ndef ui_admin_list_students\()''' | |
| patched, count = re.subn( | |
| pattern, | |
| new_login, | |
| source, | |
| count=1, | |
| flags=re.DOTALL, | |
| ) | |
| if count != 1: | |
| raise RuntimeError( | |
| "لم أجد دالة ui_admin_login الحالية بصورة آمنة؛ " | |
| "لم يتم تطبيق Patch حتى لا نكسر التطبيق." | |
| ) | |
| return patched | |
| def _hide_legacy_admin_tools(source: str) -> str: | |
| """ | |
| لا يحذف الوظائف القديمة ولا callbacks الخاصة بها. | |
| يخفي واجهتها فقط لأن Admin Office V10 يعرض الفحوص في تبويب واحد. | |
| """ | |
| replacements = { | |
| ' gr.Markdown("## أدوات المدير والفحص")': | |
| ' gr.Markdown("## أدوات المدير والفحص القديمة - نُقلت إلى تبويب الفحص", visible=False)', | |
| ' check = gr.Button("فحص النظام")': | |
| ' check = gr.Button("فحص النظام", visible=False)', | |
| ' queue_center_btn = gr.Button("عرض الحصص العلاجية")': | |
| ' queue_center_btn = gr.Button("عرض الحصص العلاجية", visible=False)', | |
| ' process_task_btn = gr.Button("معالجة مهمة واحدة")': | |
| ' process_task_btn = gr.Button("معالجة مهمة واحدة", visible=False)', | |
| ' queue_test_btn = gr.Button("اختبار نظام الحصص المؤجلة")': | |
| ' queue_test_btn = gr.Button("اختبار نظام الحصص المؤجلة", visible=False)', | |
| ' media_test_btn = gr.Button("اختبار فيديو الحصة العلاجية")': | |
| ' media_test_btn = gr.Button("اختبار فيديو الحصة العلاجية", visible=False)', | |
| ' admin_media_html = gr.HTML("")': | |
| ' admin_media_html = gr.HTML("", visible=False)', | |
| ' admin_out = gr.Markdown("")': | |
| ' admin_out = gr.Markdown("", visible=False)', | |
| ' with gr.Accordion("فحص دخول الطالب", open=False):': | |
| ' with gr.Accordion("فحص دخول الطالب", open=False, visible=False):', | |
| } | |
| for old, new in replacements.items(): | |
| if old in source: | |
| source = source.replace(old, new, 1) | |
| return source | |
| def apply_admin_office_patch(source: str) -> str: | |
| if not isinstance(source, str) or not source.strip(): | |
| raise RuntimeError("مصدر app.py فارغ.") | |
| source = _patch_admin_login(source) | |
| source = _hide_legacy_admin_tools(source) | |
| marker = ' with gr.Accordion("إدارة تسجيل الطلاب", open=True):' | |
| if marker in source: | |
| indent = " " | |
| else: | |
| marker = 'with gr.Accordion("إدارة تسجيل الطلاب", open=True):' | |
| if marker not in source: | |
| raise RuntimeError( | |
| "لم أجد واجهة إدارة تسجيل الطلاب القديمة داخل المصدر. " | |
| "لم يتم تطبيق Patch حتى لا نكسر التطبيق." | |
| ) | |
| pos = source.find(marker) | |
| indent = source[source.rfind("\n", 0, pos) + 1:pos] | |
| replacement = ( | |
| indent + "# مكتب الإدارة V10 متعدد المديرين والصلاحيات والفحص الموحد\n" | |
| + indent + "try:\n" | |
| + indent + " from admin_office_ui import build_admin_office\n" | |
| + indent + " _ADMIN_OFFICE_COMPONENTS = build_admin_office(\n" | |
| + indent + " get_admin_manager=get_admin_manager,\n" | |
| + indent + " get_student_manager=get_student_manager,\n" | |
| + indent + " admin_key=ADMIN_PANEL_KEY,\n" | |
| + indent + " admin_password_component=admin_password,\n" | |
| + indent + " )\n" | |
| + indent + "except Exception as _admin_office_error:\n" | |
| + indent + " gr.Markdown(\n" | |
| + indent + ' "### تعذر تحميل Admin Office V10\\n\\n"\n' | |
| + indent + " + str(_admin_office_error)\n" | |
| + indent + " )\n\n" | |
| + indent + "# واجهة التسجيل القديمة مخفية للتوافق فقط\n" | |
| + indent + 'with gr.Accordion("إدارة تسجيل الطلاب القديمة - توافق", open=False, visible=False):' | |
| ) | |
| patched = source.replace(marker, replacement, 1) | |
| required = [ | |
| "from admin_access_manager import get_manager as get_admin_access_manager", | |
| "from admin_office_ui import build_admin_office", | |
| "admin_password_component=admin_password", | |
| "_ADMIN_OFFICE_COMPONENTS = build_admin_office(", | |
| "Admin Office V10", | |
| ] | |
| missing = [item for item in required if item not in patched] | |
| if missing: | |
| raise RuntimeError( | |
| "فشل التحقق من Patch مكتب الإدارة V10: " + repr(missing) | |
| ) | |
| # إذا كان مصدر التطبيق كاملاً وصالحًا، نتحقق من الصياغة قبل التنفيذ. | |
| compile(patched, "<patched_app_admin_office_v10>", "exec") | |
| return patched | |
| def summary(): | |
| return { | |
| "success": True, | |
| "ready": True, | |
| "version": VERSION, | |
| "admin_office_required_version": REQUIRED_ADMIN_OFFICE_VERSION, | |
| "multi_admin": True, | |
| "unified_diagnostics": True, | |
| "legacy_diagnostics_deleted": False, | |
| "legacy_diagnostics_hidden_for_compatibility": True, | |
| "app_py_manual_change_required": False, | |
| } | |