Prayer-Time-Bot / probe_live.py
Reoo88's picture
Sync full Tktktk engine (relay-v2.9-confirm) onto this Space.
9c10fcb
Raw History Blame Contribute Delete
8.43 kB
"""تشخيص مباشر لحالة مصدر تيك توك أثناء البث (يُشغَّل من داخل الحاوية أو محليًا).
الغرض: عندما يقول حدث يوتيوب «الجلسة مستمرة؛ انتظار المصدر المحدد للجودة» نريد أن نعرف
بالضبط أيُّ شكلٍ رجّعتْه تيك توك في تلك اللحظة، بدل تخمين سبب فقدان المرشّحات عند الدخول
إلى جولات PK أو الخروج منها. لا يكتب أي توكن ولا أي رابط كامل — فقط البنية والحالة.
الاستعمال:
python3 probe_live.py <username> [<username> ...]
python3 probe_live.py --relay [url] # طرف يوتيوب/المشرف من اللوحة نفسها
"""
import json, os, sys
def relay_state(url=None, user=None, password=None):
"""يطبع ما يراه المشرف من طرف يوتيوب: عمر آخر بايت، حدّ الحارس، سبب القفل، ونافذة التأجيل.
لا يستورد app ولا يلمس أي ملف: قراءة HTTP واحدة للوحة، بكلمة سرّ من البيئة فقط — حتى تُشغَّل
من داخل الحاوية (`python3 probe_live.py omarko89 --relay`) وهي تشخّص الطرفين في نفس الوقت.
"""
import base64, urllib.request
url = url or os.getenv('PROBE_RELAY_URL', 'http://127.0.0.1:7860/api/youtube')
user = user or os.getenv('USER_NAME', 'admin')
password = password or os.getenv('PASSWORD', '')
req = urllib.request.Request(url)
if password:
req.add_header('Authorization', 'Basic ' + base64.b64encode(('%s:%s' % (user, password)).encode()).decode())
try:
with urllib.request.urlopen(req, timeout=15) as resp:
d = json.loads(resp.read().decode('utf-8'))
except Exception as e:
print('\n=== relay | EXC %s: %s' % (type(e).__name__, str(e)[:150]))
return
print('\n=== طرف المشرف (يوتيوب) | send_mode=%s · %s' % (d.get('send_mode'), d.get('status')))
for ev in d.get('events') or []:
print(' @%s phase=%s yt=%s health=%s' % (ev.get('username'), ev.get('phase'),
ev.get('youtube_status'), ev.get('youtube_health')))
print(' مصدر: %s | خرج %.1f ث | آخر بايت %s ث | حدّ الحارس %s ث | صمت عند آخر قفل %s ث' % (
ev.get('source'), float(ev.get('output_seconds') or 0), ev.get('source_age_seconds'),
ev.get('source_stall_limit'), ev.get('source_gap')))
if ev.get('retry_in'):
print(' ⏳ إعادة الاتصال مؤجّلة %.0f ث (عقاب الوجهة) — إيقاف ثم تفعيل الأتمتة يُلغيها' % ev['retry_in'])
if ev.get('note'):
print(' note: %s' % str(ev['note'])[:140])
diag = list(ev.get('ffmpeg_diagnostics') or [])
raw = list(ev.get('ffmpeg_errors') or [])
if diag or raw:
# «لماذا أقفلت الوجهة؟» من فم FFmpeg نفسه، بعد إخفاء الرابط والمفتاح في relay.py
print(' تشخيص FFmpeg: %s' % (' | '.join(diag) if diag else 'سطر غير مصنَّف'))
if raw:
print(' آخر رسالة: %s' % str(raw[-1])[:160])
if not (d.get('events') or []):
print(' لا أحداث جارية (المذيع غير مباشر أو الأتمتة موقوفة)')
def brief(url):
if not isinstance(url, str):
return type(url).__name__
host = url.split('/', 3)[2] if url.startswith('http') else '(not-http)'
return '%s…%s len=%d' % (url[:14], host, len(url))
def shape(node, depth=0, path=''):
"""وصف مختصر للشجرة: المفاتيح وأنواعها، مع تفريغ ما يخصّ stream_data فقط."""
out = []
pad = ' ' * depth
if isinstance(node, dict):
for k in sorted(node.keys()):
v = node[k]
if isinstance(v, (dict, list)) and depth < 4:
out.append('%s%s: %s(%d)' % (pad, k, type(v).__name__, len(v)))
if k in ('stream_data', 'data', 'main', 'stream_url', 'pull_data', 'live_core_sdk_data', 'sdk_params'):
out += shape(v, depth + 1, path + '/' + k)
else:
t = type(v).__name__
if t == 'str' and len(v) > 60:
out.append('%s%s: url %s' % (pad, k, brief(v)))
elif t in ('str', 'int', 'float', 'bool') or v is None:
out.append('%s%s: %s=%r' % (pad, k, t, v if t != 'str' else v[:60]))
else:
out.append('%s%s: %s' % (pad, k, t))
elif isinstance(node, list):
out.append('%s[list of %d]' % (pad, len(node)))
if node:
out += shape(node[0], depth + 1, path + '[0]')
return out
def main():
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)) or '.')
from curl_cffi import requests
users = sys.argv[1:] or ['viggoo313']
for user in users:
tok = os.getenv('TIKTOK_SESSIONID_' + user.upper().replace('.', '_'), '') or os.getenv('TIKTOK_SESSIONID', '')
sid = tok.split(';')[0].strip()
sid = sid.split('=', 1)[1] if '=' in sid else sid
headers = {'Referer': 'https://www.tiktok.com/'}
if sid:
headers['Cookie'] = 'sessionid=%s; sessionid_ss=%s; sid_tt=%s' % (sid, sid, sid)
url = 'https://www.tiktok.com/api-live/user/room'
try:
r = requests.get(url, params={'aid': 1988, 'uniqueId': user, 'sourceType': 54, 'staleTime': 0},
impersonate='chrome', headers=headers, timeout=25)
print('\n=== %s | HTTP %s | bytes %d' % (user, r.status_code, len(r.content)))
if r.status_code != 200:
continue
j = r.json()
d = j.get('data', {}) or {}
live = d.get('liveRoom', {}) or {}
status = live.get('status')
person = d.get('user', {}) or {}
print(' liveRoom.status=%r roomId=%r title=%r' % (status, person.get('roomId'), str(live.get('title'))[:40]))
for key in ('streamData', 'hevcStreamData', 'pull_stream_url', 'live_core_sdk_data'):
blk = live.get(key)
if not isinstance(blk, dict):
print(' %-20s: %s' % (key, type(blk).__name__))
continue
sd = blk.get('pull_data', {}).get('stream_data')
if isinstance(sd, str):
try:
sd = json.loads(sd)
except Exception:
print(' %-20s: stream_data نص غير قابل للتحليل' % key)
continue
data = (sd or {}).get('data')
print(' %-20s: data=%s' % (key, type(data).__name__))
items = data.items() if isinstance(data, dict) else list(enumerate(data or []))
for label, item in items:
if not isinstance(item, dict):
print(' %s: %s' % (label, type(item).__name__))
continue
main = item.get('main', {}) or {}
keys = sorted(main.keys())
params = main.get('sdk_params') or {}
if isinstance(params, str):
try:
params = json.loads(params)
except Exception:
params = {}
print(' %-8s main=%s vcodec=%r res=%r fps=%r' % (
label, keys[:9], params.get('VCodec'), params.get('resolution'), params.get('expectedFps')))
for media in ('flv', 'hls', 'lls'):
if media in main:
print(' %s → %s' % (media, brief(main[media])))
except Exception as e:
print('\n=== %s | EXC %s: %s' % (user, type(e).__name__, str(e)[:160]))
def main_relay():
argv = [a for a in sys.argv[1:] if not a.startswith('--')]
relay_state(argv[0] if argv else None)
if __name__ == '__main__':
if '--relay' in sys.argv:
main_relay()
else:
main()