File size: 4,958 Bytes
976899c
35c2217
976899c
35c2217
 
 
976899c
35c2217
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
976899c
35c2217
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
---
title: '97'
sdk: docker
emoji: 🐨
colorFrom: pink
colorTo: gray
---
# إصلاحات مطلوبة — ملخص B / C / D

## B — عاصفة `start_sender()` ورمز 187
**المشكلة:** `tick()` / `drive_event()` كانت تستدعي `start_sender()` بلا شرط في أول الدورة، فتدفع `ffmpeg` إلى `rtmps://a.rtmps.youtube.com:443/live2` قبل أن يكون `liveBroadcast` مربوطًا وبحالة `ready/testing/live` → 7 إخفاقات 187 خلال 5 دقائق، بداية متأخرة 5:22 و ~116 ثانية ضائعة.

**الحل في `youtube_manager.py`:**
- `start_sender()` الآن تحرس نفسها:
  ```python
  if not ev.get('bound') or not ev.get('broadcast_id'): return
  if ev.get('youtube_status') in ('complete','revoked','created'): return
  ```
- `drive_event()` لم يعد يستدعيها فورًا بعد `ensure_broadcast()`. بدلًا من ذلك:
  1. بعد `ensure_broadcast()` نحدث `ev` ونَمسح الملاحظة العالقة ثم نسقط إلى **بوابة مشروطة**
  2. نقرأ `lifeCycleStatus` الحقيقي من `liveBroadcasts` (مع احترام كوتا 45 ث)
  3. نسمح بالإرسال فقط إذا كانت `life in ('ready','testing','live')`، وإلا نُوقف المرسل ونكتب `انتظار جاهزية الاستقبال`
  4. `life == 'live'` → نشغّل المرسل ثم `stream_health`، `ready/testing + streamStatus==active` → نطلب `transition` إلى `live`

النتيجة: لا دفع قبل وجود الـ ingest، لا عاصفة 187، ولا تأخير 5 دقائق.

---

## C — `youtube_api.py` بلا إعادة محاولة + الملاحظة لا تُمسح

**المشكلة 1:** `_request()` كانت تفعل `urlopen(timeout=25)` مرة واحدة. أي فشل TLS عابر → `SSLError / URLError` → تُرمى كـ `خطأ داخلي ... (SSLError)` وتكتبها `_event_error()` في `note` ولا شيء يمسحها → بقيت 40 دقيقة رغم أن البث سليم.

**الحل في `youtube_api.py`:**
- إضافة `import ssl`
- حلقة إعادة محاولة 3 مرات مع backoff أسي (1ث، 2ث، 4ث):
  - `HTTP 429/500/502/503/504` → إعادة محاولة مع `1.2*(attempt+1)` ث
  - `URLError, TimeoutError, OSError, ValueError, ssl.SSLError, SSLEOFError ...` → إعادة محاولة، ثم `APIError(None,'networkOrInvalidResponse')` فقط بعد نفاد المحاولات
- هذا يحول الفشل اللحظي لـ TLS من رسالة "حماية الأحداث" إلى نجاح صامت بعد ثانية.

**المشكلة 2:** `_event_error()` تكتب `note` ولا مسح عند التعافي.

**الحل في `youtube_manager.py`:**
- دالة جديدة `_clear_stale_error_note(key)` تمسح `note` إذا احتوت `حماية الأحداث` أو `خطأ داخلي` أو `networkOrInvalidResponse`
- تُستدعى في `drive_event()` في 4 نقاط تعافي:
  1. بداية الدورة بعد تأكد `obs status == live`
  2. بعد `ensure_stream()` ناجح
  3. بعد `ensure_broadcast()` ناجح
  4. بعد كل `remote('liveBroadcasts')` ناجح (التحقق الفعلي من الشبكة)

فإذا تعافت الشبكة، تختفي الملاحظة فورًا بدل 40 دقيقة.

---

## D — `Dockerfile.txt` في المستودع

**المشكلة:** رفعت `Dockerfile` باسم `Dockerfile.txt` (sha `89e0bc09` = نسختي السابقة) فتجاهله Docker وبنى من القديم بدون:
```
YOUTUBE_FORMAT_GUARD=off
YOUTUBE_FIFO_TIMESHIFT=10
YOUTUBE_HEALTH_INTERVAL=180
```
فبقي `timeshift=10` يعمل فقط من القيمة الافتراضية في `relay.py` (`ts = int(os.getenv('YOUTUBE_FIFO_TIMESHIFT','10'))`) ولم تكن واضحة في الـ image.

**الحل:**
- الملف المرفق `Dockerfile` هو النسخة الصحيحة (محتوى `Dockerfile.txt` السابق) — يحتوي كل متغيرات YouTube ingestion + التعليقات الكاملة.
- **احذف `Dockerfile.txt` من المستودع** (أو على الأقل لا ترفعه):
  ```bash
  git rm Dockerfile.txt
  git add Dockerfile youtube_api.py youtube_manager.py
  git commit -m "fix: gate start_sender (187 storm), retry youtube_api TLS, clear stale note, fix Dockerfile name"
  git push
  ```
- بعدها `docker build` سيقرأ `Dockerfile` الصحيح مباشرة، والقيم ستكون صريحة في الـ image وليس فقط default الكود.

---

## الملفات المرفقة
- `youtube_api.py` — مع retry
- `youtube_manager.py` — مع guard + مسح الملاحظة
- `Dockerfile` — النسخة الصحيحة (احذف Dockerfile.txt)

> كل الإصلاحات في الكود فقط كما طلبت، بلا تغيير سلوك الحالات السليمة، وباحترام كوتا YouTube (poll كل 45ث، health كل 180ث).