THEZYZSTUDIO commited on
Commit
9490d6d
·
verified ·
1 Parent(s): b1f94a7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +49 -10
app.py CHANGED
@@ -511,9 +511,9 @@ def _capture_via_import_pipe(display: str):
511
 
512
  def _capture_via_xlib_direct(display: str):
513
  """
514
- خط الدفاع الثاني والأخير: قراءة X11 framebuffer مباشرة عبر
515
- python-xlib، بدون subprocess إطلاقاً (أسرع من أي أداة خارجية،
516
- ويعمل حتى لو ImageMagick غير مثبّت على السيرفر).
517
  """
518
  from PIL import Image
519
  try:
@@ -531,17 +531,56 @@ def _capture_via_xlib_direct(display: str):
531
  return None, 0, 0
532
 
533
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
534
  def _capture_raw(display: str) -> tuple:
535
  """
536
  يلتقط الشاشة بأسرع طريقة موثوقة: import-pipe أولاً (سريعة جداً)،
537
- وعند فشلها فقط xlib-direct كبديل واحد. بحد أقصى محاولتين سريعتين
538
- لكل طريقة (وليس 9 محاولات كالسابق) — لأن كلا الطريقتين إما تنجحان
539
- فوراً أو تفشلان لسبب دائم، وإعادة المحاولة أكثر من مرتين لا تُغيّر
540
- النتيجة، فقط تُبطئ الاستجابة.
 
 
541
  """
542
  for method_name, method in (
543
  ("import-pipe", _capture_via_import_pipe),
544
  ("xlib-direct", _capture_via_xlib_direct),
 
545
  ):
546
  for attempt in range(2):
547
  try:
@@ -555,14 +594,14 @@ def _capture_raw(display: str) -> tuple:
555
  if attempt == 0:
556
  time.sleep(0.3)
557
 
558
- print(f"[cap:{display}] ⚠️ All methods failed — placeholder")
559
  from PIL import Image as PILImg, ImageDraw
560
  sw, sh = _get_screen_size(display)
561
  img = PILImg.new("RGB", (sw or 1280, sh or 800), (15, 20, 40))
562
  draw = ImageDraw.Draw(img)
563
  draw.rectangle([(0, 0), (sw, 55)], fill=(30, 40, 80))
564
  draw.text((10, 10), f"⚠️ Screenshot failed — DISPLAY={display}", fill=(255, 120, 80))
565
- draw.text((10, 32), "Methods tried: import-pipe, xlib-direct", fill=(130, 130, 150))
566
  return img, sw or 1280, sh or 800
567
 
568
 
@@ -1505,7 +1544,7 @@ async def health():
1505
 
1506
  async def _cleanup_tmp():
1507
  """ينظّف /tmp كل 5 دقائق. ملاحظة v13: محرك الالتقاط
1508
- الجديد (import-pipe/xlib-direct) لا يكتب أي ملفات zss_* على الإطلاق (كلشيء
1509
  في الذاكرة عبر pipe)، فهذه الدالة أصبحت غير ضرورية فعلياً للقطات
1510
  الشاشة، لكنها تُرك كشبكة أمان إضافية (مثلاً لو أضيف كود مستقبلاً
1511
  يكتب ملفات مؤقتة بنفس البادئة)."""
 
511
 
512
  def _capture_via_xlib_direct(display: str):
513
  """
514
+ خط الدفاع الثاني: قراءة X11 framebuffer مباشرة عبر python-xlib،
515
+ بدون subprocess إطلاقاً (أسرع من أي أداة خارجية، ويعمل حتى لو
516
+ ImageMagick غير مثبّت على السيرفر).
517
  """
518
  from PIL import Image
519
  try:
 
531
  return None, 0, 0
532
 
533
 
534
+ def _capture_via_xwd(display: str):
535
+ """
536
+ خط الدفاع الثالث — طريقة جديدة تماماً، مستقلة كلياً عن الطريقتين
537
+ السابقتين في مسارها البرمجي: `xwd` (X Window Dump) هي أداة أصلية من
538
+ حزمة x11-apps الأساسية نفسها (وليست ImageMagick مثل `import`، ولا
539
+ مكتبة python-xlib عبر اتصال socket مباشر مثل الطريقة الثانية) —
540
+ فإذا كان سبب فشل الطريقتين الأخريين متعلقاً تحديداً بـ ImageMagick
541
+ (مفقود/معطوب) أو بمكتبة python-xlib نفسها (تعارض إصدار، اتصال عالق)،
542
+ فإن xwd تسلك مساراً مختلفاً بالكامل في النواة قد ينجح حين تفشل الطريقتان
543
+ الأخريان. تكتب xwd تنسيق XWD الخام إلى stdout مباشرة (بدون ملف مؤقت على
544
+ القرص، بنفس فلسفة import-pipe)، ثم نحوّله عبر PIL.
545
+ """
546
+ from PIL import Image
547
+ env = {**os.environ, "DISPLAY": display}
548
+ try:
549
+ r = subprocess.run(
550
+ ["xwd", "-root", "-display", display, "-silent"],
551
+ env=env, timeout=6, capture_output=True
552
+ )
553
+ if r.returncode != 0 or not r.stdout or len(r.stdout) < 500:
554
+ return None, 0, 0
555
+ # PIL يدعم قراءة تنسيق XWD مباشرة (plugin XVThumb/XWD مدمج)
556
+ img = Image.open(io.BytesIO(r.stdout))
557
+ img = img.convert("RGB")
558
+ w, h = img.size
559
+ if w < 100 or h < 100:
560
+ return None, 0, 0
561
+ return img, w, h
562
+ except FileNotFoundError:
563
+ print(f"[cap:{display}] xwd not installed")
564
+ return None, 0, 0
565
+ except Exception as e:
566
+ print(f"[cap:{display}] xwd: {e}")
567
+ return None, 0, 0
568
+
569
+
570
  def _capture_raw(display: str) -> tuple:
571
  """
572
  يلتقط الشاشة بأسرع طريقة موثوقة: import-pipe أولاً (سريعة جداً)،
573
+ ثم xlib-direct، وأخيراً xwd كخط دفاع ثالث جديد كلياً بمسار برمجي
574
+ مختلف تماماً عن الطريقتين الأوليين (أداة X11 أصلية أخرى غير
575
+ ImageMagick وغير python-xlib) — هذا يضمن أن فشل مصدر واحد (مثل
576
+ ImageMagick معطوب أو تعارض في مكتبة xlib) لا يعني فشل الالتقاط
577
+ بالكامل، لأن xwd تسلك مساراً مستقلاً تماماً وقد تنجح حين تفشل الأخريان.
578
+ بحد أقصى محاولتين سريعتين لكل طريقة.
579
  """
580
  for method_name, method in (
581
  ("import-pipe", _capture_via_import_pipe),
582
  ("xlib-direct", _capture_via_xlib_direct),
583
+ ("xwd", _capture_via_xwd),
584
  ):
585
  for attempt in range(2):
586
  try:
 
594
  if attempt == 0:
595
  time.sleep(0.3)
596
 
597
+ print(f"[cap:{display}] ⚠️ All methods failed (import-pipe, xlib-direct, xwd) — placeholder")
598
  from PIL import Image as PILImg, ImageDraw
599
  sw, sh = _get_screen_size(display)
600
  img = PILImg.new("RGB", (sw or 1280, sh or 800), (15, 20, 40))
601
  draw = ImageDraw.Draw(img)
602
  draw.rectangle([(0, 0), (sw, 55)], fill=(30, 40, 80))
603
  draw.text((10, 10), f"⚠️ Screenshot failed — DISPLAY={display}", fill=(255, 120, 80))
604
+ draw.text((10, 32), "Methods tried: import-pipe, xlib-direct, xwd", fill=(130, 130, 150))
605
  return img, sw or 1280, sh or 800
606
 
607
 
 
1544
 
1545
  async def _cleanup_tmp():
1546
  """ينظّف /tmp كل 5 دقائق. ملاحظة v13: محرك الالتقاط
1547
+ الجديد (import-pipe/xlib-direct/xwd) لا يكتب أي ملفات zss_* على الإطلاق (كلشيء
1548
  في الذاكرة عبر pipe)، فهذه الدالة أصبحت غير ضرورية فعلياً للقطات
1549
  الشاشة، لكنها تُرك كشبكة أمان إضافية (مثلاً لو أضيف كود مستقبلاً
1550
  يكتب ملفات مؤقتة بنفس البادئة)."""