🛠️ IDE Configuration Complete — Cursor · Windsurf · Antigravity (2026-06-12 ~05:20 GMT+2)
د. وائل أكمل ربط آخر 3 IDEs على اللابتوب (WAELGPD) بالترسانة + الموديلات. كل خطوة مؤكّدة بصرياً (screenshots).
النتيجة النهائية (مُتحقّقة حياً عبر screenshots):
| IDE | MCP wael-arsenal | الموديل المختار | |---|---|---| | 🟦 Cursor (Pro Plan) | ✅ 8/8 أخضر | Opus 4.8 ⭐ (+ Golden Chain كله مفعّل: GPT-5.5, Sonnet 4.6, Gemini 3.1 Pro, Codex 5.3) | | 🟪 Windsurf (Pro Plan) | ✅ 8/8 أخضر | Claude Opus 4.8 Medium ⭐ | | 🟢 Antigravity (Google) | ✅ 8/8 (إجمالي 70 tools) | Claude Opus 4.6 Thinking (أقوى متاح في خطته) |الطريقة المعتمدة (الأسرع — نجحت):
- Cursor + Windsurf: أمر PowerShell واحد كتب MCP في الملفين مباشرة:
%USERPROFILE%\.cursor\mcp.json
- Windsurf: %USERPROFILE%\.codeium\windsurf\mcp_config.json
- Antigravity: المسار
~/.antigravity\mcp.jsonلم يُقرأ تلقائياً. الطريقة الصحيحة = من الواجهة: Agent panel → "MCP Servers" → "View raw config" → دمج wael-arsenal داخل نفس كتلة mcpServers مع datacloud.
الدروس (مهمة):
1. mojibake في PowerShell: التعليقات العربية في .ps1 تتشفّر خطأ عند فك zip على ويندوز → قوس) داخل تعليق عربي خرّب الـ parser. القاعدة: سكربتات .ps1 للابتوب = ASCII فقط (تعليقات إنجليزية)، صفر عربي.
2. Antigravity MCP لا يُقرأ من ملف خارجي (~/.antigravity/mcp.json) — يُضاف فقط من واجهة الـ Agent (View raw config). JSON واحد بـ mcpServers واحدة تجمع الكل (مفتاحان mcpServers = الثاني يُتجاهل).
3. خطأ ${REGION}: أدوات Google الافتراضية (alloydb + dataproc) فيها متغير ${REGION} غير مُعبّأ → "invalid character '{' in host name". الحل: حذفهما (غير مستخدمين). bigquery/spanner/cloud-sql/knowledge_catalog/notebooks/visualization تبقى.الحالة: اللابتوب مربوط بالترسانة عبر 8 أدوات كاملة:
Cursor · Windsurf · Antigravity · Claude Code · Codex · Continue · Kilo · Gemini — كلها MCP wael-arsenal (8 tools) + Golden Chain models.ملفات أُنشئت:
- projects/laptop-arsenal/ide-config/{cursor_mcp,windsurf_mcp_config,antigravity_mcp}.json
- projects/laptop-arsenal/ide-config/{SETUP_GUIDE.md, MERGE_IDE_MCP.ps1 (ASCII-only), RUN_MERGE_IDE.bat, IDE_SETUP_bundle.zip}
🛟 Full Recovery Snapshot built (2026-06-12 05:40 GMT+2 — د. وائل طلب)
- بُني سكربت
scripts/full_recovery_snapshot.sh— نقطة استرجاع كاملة 1:1 → R2 (bucket kiloclaw, remote r2:). - يلتقط: كامل /data/.openclaw (config + secrets/vault + identity device-auth + telegram credentials + skill-workshop + logs) + workspace (memory بلا snapshots, skills, scripts, projects بلا venv/node_modules, .git history). يستثني المتجدد الضخم.
- النسخة الأولى:
recovery-20260612-033829.tar.zst— 2.1GB zstd — 29,717 ملف — SHA256 da1a5143… — VERIFIED (read-after-write + re-download sha OK). - R2:
r2:kiloclaw/recovery-points/20260612-033829/+/latest/(archive+MANIFEST+RECOVER.md). - إيميل أُرسل لـ wayrk76@gmail.com (msgid 19eb9ebf6b510e7d) بكل URLs + أوامر الاسترجاع + RECOVER.md/MANIFEST مرفقين.
- Cron أسبوعي: الأحد 04:00 الكويت (id 10d01e87-a00b-4b4c-9ab5-1ca70a12848e, haiku, announce لـ 195448437).
- درس: latest/ يحتاج delete-before-copy (rclone copy لا يستبدل) — أُصلح في السكربت.
- ملاحظة tar_rc=2 = تحذير "Removing leading /" غير حرج (8966→29717 entry + sha سليم = اكتمال مؤكّد).
📺 Unified Entertainment Search built (2026-06-12 ~06:00 GMT+2 — د. وائل طلب)
- ملف:
projects/entertainment-hub/unified_search.py— يبحث query عبر كل اشتراكات Xtream IPTV الـ12 (live+vod+series) بالتوازي. - يرجّع: اسم القناة/الفيلم/المسلسل + في أي اشتراك + رابط مباشر .m3u8/movie/series (مع user/pass).
--proxyيلفّ الرابط عبر hub https proxy (public_url.txt) → قابل للمشاركة يفتح من أي مكان.- يتخطى الاشتراكات الميتة (auth!=1) تلقائياً. root-owned creds → يُشغّل بـ sudo.
- مُختبَر حياً: «الكويت» → 5 قنوات في Lion (KW Kuwait TV1/2/Sports/Arabi). «MBC» → 40 نتيجة عبر اشتراكات.
- الاشتراكات الـ12: xiptv·github·iptv.llc·Supreme·Adam gold·MH new·Bazoka·Cartoon·Adam vip new·Lion·Maven·K8.
- الاستخدام: د. وائل يقول "أعطني قناة X / فيلم Y" → أشغّل
sudo python3 unified_search.py "X" [--kind live] [--proxy]وأرجّع الرابط. - hub شغّال: https://bowling-census-dice-halifax.trycloudflare.com (trycloudflare — يتغير عند restart).
🎮 Hub games tab fix + tunnel health-guard (2026-06-12 ~06:00 GMT+2)
- شكوى: قسم الألعاب المجانية لا يعمل عند الضغط.
- تشخيص (3 طبقات): epic_free() يعمل (لعبتان)؛ localhost:8899/api/games = HTTP 200 0.014s؛ لكن الرابط العام = HTTP 000.
- جذر: نفق trycloudflare (PID 112660) العملية حية لكن الـ URL منتهي/ميت → الواجهة لا تجلب /api/games (ولا أي محتوى عبر الرابط العام).
- إصلاح: قتل النفق الميت + إعادة بناء → رابط جديد https://hundreds-businesses-moving-need.trycloudflare.com (HTTP 200 مُتحقَّق: home + games + 10/12 subs).
- جذري: daemons_keepalive حارس النفق كان يفحص process فقط → حدّثته ليفحص الصحة الحية (curl /api/games == 200)؛ لو الـ URL مات يعيد بناء النفق ويحدّث public_url.txt. يمنع التكرار.
- درس: trycloudflare quick-tunnel ينتهي دورياً بينما العملية تبقى = نوع "alive-but-dead" (مثل M-032 لكن للنفق). الحل = health-probe لا pgrep.
📡 Unified Search EXPANDED → all sources (2026-06-12 ~06:00 GMT+2 — د. وائل طلب)
- وسّعت unified_search.py ليبحث عبر: 12 اشتراك Xtream + الترسانة المجانية الافتراضية (IPTV-org آلاف القنوات الحرة + Archive.org أفلام/كرتون public-domain).
- متوازي (14 workers). يرتّب: اشتراكات أولاً (HD مدفوع) + يحجز حتى 20 خانة للمصادر المجانية (لا تُزحم).
- العنوان يعرض التقسيم: «الاشتراكات: N · الترسانة المجانية: M».
- flags: --kind live/vod/series/all · --proxy (https share) · --no-free · --json · --limit.
- مُختبَر حياً: BBC→44 (IPTV-org) · Popeye→20 (Archive.org) · Kuwait→60 (اشتراكات). Kuwait حرة=0 في IPTV-org (الكتالوج العام لا يملكها — طبيعي، الاشتراكات تغطّيها).
- الاستخدام: د. وائل يطلب أي قناة/فيلم/مسلسل/كرتون → أشغّل البحث الشامل وأرجّع كل الأماكن (عندك default + كل الاشتراكات) + روابط.
🎮 Entertainment Arsenal — Games Hub Completed (2026-06-12 ~06:30 GMT+2)
استكملنا الجزء الناقص من ترسانة الترفيه بعد /new (طلب د. وائل: إكمال البحث الذكي + الألعاب + تحديث الهاب).
ما كان جاهزاً (تحقّقنا منه):
- Smart unified search (live/vod/series عبر 12 اشتراك + Free Pluto/Archive) ✅
- IPTV subscriptions tab, library (Internet Archive), channels (IPTV-org), free streaming, adult gate ✅
- HLS/MPEG-TS/MP4 player + stream proxy (يحل mixed-content http→https) ✅
ما بنيناه اليوم (Games — تشغيل مباشر):
projects/entertainment-hub/games_hub.py— 3 طبقات قانونية:
- Routes في app.py:
/api/games/playable/api/games/epic/api/games/info+/games/xo(لعبتنا المحلية تُخدَم من xo-game). - Frontend (index.html): تبويب ألعاب بـ 3 sub-views + genre filter + launchGame() مع iframe player داخل المودال.
- iframe verification: اختبرنا X-Frame-Options/CSP لكل لعبة فعلياً؛ صحّحنا embed flags (play2048→gabrielecirulli, lichess/snake/pong/krunker→new-tab).
- اختبار حي: 2048 تُشغّل داخل الهاب مباشرة (screenshot مؤكّد).
🐛 Bug مهم أُصلح (creds permission):
iptv_subscriptions.jsonكان0600 root:rootلكن الهاب يعمل user=node(flask مثبّت لـ node فقط في /data/.local، root بلا flask) →/api/searchكان يرمي 500 PermissionError.- الحل:
chown node:nodeللملف (يبقى 0600، خاص بـ node — الأمان محفوظ؛ الدير أصلاً node-owned 0700). الآن search=80 hits، subs=10 active. - درس: الهاب يجب أن يعمل user=node (flask). أي ملف secrets يقرأه الهاب يجب أن يكون node-readable.
الحالة:
- public URL: hundreds-businesses-moving-need.trycloudflare.com (200)
- keepalive daemon (cron 31398c3f) يحرس الهاب port-based — يعيد التشغيل إن سقط.
- SKILL.md محدّث بقسم Games Hub.
🔥 Entertainment Arsenal — Enhancement Wave (2026-06-12 ~06:40 GMT+2)
د. وائل طلب تطوير وتقوية الترسانة لأقصى حد + اختبار 100% + تثبيت نهائي على البورتال.
التحسينات المنفّذة (كلها مُختبرة حياً عبر البورتال):
1. ⚡ Performance — TTL cache في unified_search.py: -_cached_content (كتالوجات الاشتراكات، TTL 15د) + alive() cache (10د).
- VOD search: 14-18s → ~4s warm | live: 2.6s → 0.96s warm.
- Background pre-warm thread في app.py (يسخّن الكتالوجات + trending بعد 8s من الإقلاع) → أول بحث سريع.
2. 🔥 Discover tab جديد (discover.py): مصادر مجانية بلا مفتاح:
- الأكثر رواجاً (TVMaze weight+rating) · يُعرض اليوم (schedule) · بحث مسلسل (+الحلقة القادمة).
- OMDB enrichment (مفتاح 245cde94): IMDb + Rotten Tomatoes لأي عنوان (Oppenheimer 8.2/93%).
- الضغط على عنوان → يقفز للبحث الشامل ليجده في الاشتراكات/المجاني.
- Routes: /api/discover/trending|airing|show|rating.
3. 🐛 fixed key= trap: سطر OMDB في discover.py تسرّب فيه placeholder → 400/None. أُصلح بـ string concat (نفس الفخ الموثّق في الذاكرة).
4. 🔒 استقرار: أضفت HUB_SECRET ثابت في env.sh (الحارسان في keepalive يستخدمانه الآن → sessions تبقى عبر restart). الهاب user=node + creds node:node 0600.الحالة النهائية (12/12 endpoint + 3 kinds search = 100%):
home·library·free·channels(arabic/kids/science/world)·discover(trending/airing/rating)·games(playable18/epic/info/xo)·iptv-subs(10)·search(live80/vod80/series80) — كلها 200 وعاملة.- keepalive (cron 31398c3f) يحرس الهاب port+URL-based — يعيد بناء التنل إن انتهت صلاحية trycloudflare.
- public: hundreds-businesses-moving-need.trycloudflare.com
- SKILL.md محدّث (Discover + Performance).
🕹️ Entertainment Arsenal — Retro Emulation + DVR Wave (2026-06-12 ~07:00 GMT+2)
د. وائل طلب: محاكيات ألعاب ريترو (Atari/Sega/Nintendo/PlayStation) أونلاين embedded + تسجيل/snapshot من القنوات + تأكيد كل المشغّلات تعمل embedded بلا تعطّل + أفكار إبداعية.
1) 🕹️ Retro Emulation (retro.py + emu.html):
- محرك
EJS_threads=false للتوافق الأوسع + فحص WebGL برسالة واضحة.2) 🔴 DVR — تسجيل + snapshot من القنوات (recorder.py):
- ffmpeg server-side: snapshot JPEG أو تسجيل MP4 مؤقت (5ث–1ساعة).
الحالة (كل endpoint مُختبر حياً عبر البورتال = 100%):
home·retro(library 3/14 systems·homebrew 24·emu·roms)·rec(jobs)·discover(40)·games(18)·channels(120)·iptv-subs(10)·search-live(80). كلها 200.دروس:
source 2>/dev/null في nested bash ضاع المفاتيح مجدداً — استخدم /usr/bin/python3 مباشرة للاختبارات.
المتبقّي للأفكار الإبداعية (لم يُنفّذ بعد):
- جدولة تسجيل (record لاحقاً في وقت محدد)
- favorites/مفضلة عبر المحتوى
- watch history
📺 Entertainment Arsenal — EPG Guide Search Wave (2026-06-12 ~07:15 GMT+2)
د. وائل: فكرة إبداعية — بحث في الـ EPG (دليل البرامج) عبر كل القنوات: أقول "مباراة بين كذا" أو اسم برنامج (عربي/إنجليزي) → يبحث في جداول البرامج → يقول في أي قناة يُعرض + رابط مباشر.
المنفّذ (epg.py + UI tab):
- جلب XMLTV (
xmltv.php) لكل اشتراك + parse (ElementTree) + فهرسة البرامج. - ربط channel→stream_id عبر epg_channel_id (3496/3520 قناة مربوطة بـ stream قابل للتشغيل).
- بحث AR+EN (normalize) + فلتر 🔴 يُعرض الآن + ترتيب (now أولاً ثم upcoming).
- النتيجة: برنامج → اسم القناة → رابط تشغيل مباشر (proxied).
الاشتراكات التي توفر EPG (تحقّق حي):
✅ Adam vip new (171,294 برنامج) · K8 (204,848) · Supreme (7389 ch) · xiptv. ❌ بلا EPG: MH/Bazoka/Cartoon/Lion/Maven/Adam gold (xmltv فارغ).الأداء + الكاش:
- cold ~25s (جلب 130MB guides أول مرة) · warm 0.2-0.4s ⚡ (cache TTL 30د + pre-warm thread في الخلفية).
🐛 درس مهم (Flask template caching):
TEMPLATES_AUTO_RELOAD=True + jinja_env.auto_reload=True في app.py → تعديلات القوالب تظهر فوراً بلا restart.
الحالة النهائية (100%):
EPG(bein 52/news 80/sport 80/مباراة 5) · retro(3) · rec(jobs) · discover(40) · games(18) · search-live(80) · iptv-subs(10). كلها عاملة عبر البورتال.🚀 Portal Update — ربط ترسانة الترفيه بالبورتال (2026-06-12 ~07:25 GMT+2)
د. وائل: أضف كل التحديثات والروابط المحدّثة على صفحة البورتال.
المنفّذ:
الروابط النهائية الحيّة:
- 🚀
ملاحظة بنيوية:
- Portal يقرأ الـ hub URL ديناميكياً → لو تغيّر tunnel الهاب (انتهت صلاحية trycloudflare)، الـ keepalive يحدّث public_url.txt والـ Portal يلتقطه تلقائياً. لا روابط ميتة.
⏰ Scheduled Recording + Downloads Page (2026-06-12 ~07:25 GMT+2)
د. وائل: أضف تسجيل مجدول (في أوقات معينة) + تخزين في folder على السيرفر + صفحة تنزيلات تعرضها مع روابط تحميل.
المنفّذ (recorder.py + UI):
1. جدولة زمنية:schedule_add(url,name,start_ts,duration,repeat) + scheduler thread يفحص كل 20s ويُطلق عند الوقت. repeat: once/daily/weekly. يبدأ تلقائياً عند import (في الهاب).
2. صفحة 📁 التنزيلات (تبويب جديد): كل ملفات recordings/ مع ▶ عرض (inline player/img) + ⬇ تحميل + قسم المجدولة (إلغاء).
3. زر ⏰ جدولة في DVR bar داخل مشغّل القناة الحية (datetime-local + مدة + تكرار).مُختبر حياً (100%):
- جدولت تسجيل 12s بعد 40s → scheduler أطلقه في وقته بالضبط → أنتج sched_demo_
Routes:
/api/rec/schedule (when=ISO local + tzoff + duration + repeat) · /api/rec/scheduled · /api/rec/schedule/cancel/<id> · /api/rec/downloads.Portal:
أُضيف رابط "📁 التسجيلات والتنزيلات" لبطاقة الترسانة في البورتال.الحالة: كل الميزات حية 100% — Portal 200 · Hub 200 · downloads/scheduled routes تعمل · scheduler thread حي.
📡 DVR على كل محتوى الاشتراكات (2026-06-12 ~07:30 GMT+2)
د. وائل أكّد: التسجيل/الجدولة/التنزيلات يجب أن تعمل على اشتراكاته بكل محتوياتها (قنوات + أفلام + مسلسلات).
التحقق + التفعيل:
- Backend كان يدعم vod/series أصلاً (_resolve_record_url + xt_url يبنيان live/vod/series URLs).
- فعّلت DVR bar في UI لكل الأنواع: playIptv الآن يعرض أزرار snapshot/record/schedule على live + vod + series (كان live فقط). + playSearch يعرضها لنتائج البحث (raw url عبر ?u=).
- مُختبر حياً (تسجيل فعلي):
/series/.../{sid}.mp4 = container وليس حلقة قابلة للتشغيل.ملاحظة صادقة (series limitation):
- المسلسلات في Xtream إبيزودية — تحتاج episode picker (get_series_info → episode_id) للتشغيل/التسجيل.
- الأهم يعمل 100%: القنوات الحية (المباريات) + الأفلام (VOD) — يغطي "مباراة فلانية" + "فيلم فلاني".
- TODO مستقبلي: episode picker للمسلسلات (تشغيل + تسجيل حلقة محددة).
الحالة: Portal 200 · Hub 200 · DVR live+vod ✅ · downloads/scheduled تعمل · hub stable.
🔧 إصلاح جذري: تشغيل المسلسلات + MKV في المتصفح (2026-06-12 ~07:35 GMT+2)
د. وائل: المحتوى (مثل مسلسل المحقق كونان) يعطي "تعذّر تشغيل هذا الرابط" في المتصفح رغم أنه يعمل على Xtream. أصلح جذرياً + ضع كل المشغّلات/plugins embedded.
التشخيص الحي (السبب الجذري — سببان):
1. المسلسلات: Xtream يحتاجepisode_id لا series_id. الرابط /series/.../{series_id}.mp4 يرجع HTTP 422. لازم get_series_info → seasons → episodes → episode_id.
2. الحاوية MKV: الحلقات بصيغة .mkv (video/x-matroska). المتصفح لا يشغّل MKV في <video> رغم أن الكوديك h264+aac متوافق. (نفس المشكلة لبعض أفلام VOD بصيغة mkv/avi).الإصلاح (app.py):
1.xt_series_info + /api/iptv/series/<sub>/<sid>: يحلّل المسلسل لمواسم+حلقات، كل حلقة برابطها الصحيح (episode_id + ext الحقيقي).
2. /api/iptv/episode/<sub>/<eid>/<ext>: رابط تشغيل الحلقة المحددة.
3. _playable_url + /api/remux: أي حاوية غير native (mkv/avi/flv) → ffmpeg remux on-the-fly إلى fragmented MP4 (copy codecs، بلا re-encode = سريع) → تشغّل مباشرة في المتصفح.
4. search VOD/series يستخدم _playable_url (remux للـ mkv).UI (index.html):
- مختار حلقات للمسلسلات: فتح مسلسل → اختيار الموسم → قائمة الحلقات → تشغيل الحلقة (مع DVR + تحميل).
- يعمل من تبويب «اشتراكاتي» ومن «بحث شامل» (series hit يفتح المختار تلقائياً).
مُختبر حياً 100% (في <video> حقيقي بالمتصفح):
- DETECTIVE CONAN → 25 موسم، 28 حلقة في S1.
- حلقة S01E01 (mkv) → /api/remux → video 720×400، readyState=4 (يشغّل فعلاً) ✅.
- المسلسل الذي فشل عند د. وائل = يعمل الآن.
درس:
- المتصفح لا يشغّل MKV/AVI حتى لو الكوديك متوافق — الحل remux للحاوية (سريع، بلا re-encode).
- Xtream series = إبيزودي، يحتاج episode resolution دائماً.
🔧 Entertainment Hub — حل جذري لـ "خطأ في التحميل" (2026-06-12 ~20:00)
المشكلة: البحث/الاشتراكات كانت تستعلم كل 10 اشتراكات Xtream حياً (synchronous, timeout 18s) → أي مزوّد بطيء/معطّل = "خطأ في التحميل" + توقف البحث.
الحل (genius — كما طلب د. وائل):
indexer.py— يفهرس كل القنوات/الأفلام/المسلسلات (1,076,141 عنصر) من كل الاشتراكات إلى SQLite FTS5 (catalog.db, 240MB) في 33s. atomic swap (لا يمسح فهرس جيد بفارغ).catalog_search.py— بحث فوري من DB (0.2-1ms) AR+EN synonyms. lanes منفصلة: live / movies(vod+series) / all.- app.py endpoints جديدة:
/api/catalog/search?kind=live|movies·/api/catalog/subs(فوري) ·/api/catalog/content/<sub>/<kind>·/api/catalog/resolve/<sub>/<sid>(VOD lazy) ·/api/catalog/series/<sub>/<sid>·/api/catalog/status·/api/catalog/reindex.
- UI: تبويبان منفصلان «📡 بحث قنوات» + «🎬 بحث أفلام/مسلسلات» + «📺 برامج تُعرض (EPG)» منفصل. الاشتراكات تقرأ من DB فوراً.
playHit()يعالج deferred resolve. - Cron يومي 04:00 الكويت (
a52c22e6-9b94-4cd9-a2c7-34f5ea029350, isolated, gemini-2.5-flash, delivery=none) لإعادة الفهرسة.
الأرقام: live=168,354 · series=188,680 · vod=719,107 قناة/فيلم/مسلسل مفهرسة.
📺 EPG (live schedule) — الطبقة الثانية من الحل (2026-06-12 ~20:40)
سؤال د. وائل الذكي: القنوات/الأفلام static (فهرسة 24h تكفي)، لكن EPG/البرامج التي تُعرض = زمنية متغيرة. كيف نتعامل معها؟
الحل (hybrid genius):
- EPG ليس live-ping — هو جدول مستقبلي (XMLTV يغطي عدة أيام). فنفهرسه دورياً كـ static، لكن نحسب «يُعرض الآن / قادم» حياً وقت البحث من start/stop المخزّنة.
indexer.py --epg— يحلّل XMLTV لكل اشتراك → جدولprogrammes(title/channel/start/stop) + FTS5pfts. فهرس 574,286 برنامجاً في 62s (من K8/Supreme/Adam vip new/xiptv — البقية لا تخدم XMLTV = قيد المزوّد).catalog_search.epg_search()— بحث فوري من DB (10-83ms)؛on_now/upcomingتُحسب منint(time.time())لحظة الاستعلام → دقيق دائماً رغم أن البيانات مخزّنة./api/epg/searchيستخدم DB أولاً (source:db) + fallback live إن لم يوجد فهرس./api/epg/channelكذلك./api/catalog/statusيعرضepg_ready+epg_age_h.- Cron EPG كل 3 ساعات (
c0ff96fb-aad8-4e7b-b093-3fabdd18ada7, isolated, gemini-2.5-flash) — أكثر تواتراً من الكتالوج (الجدول يتدحرج). الكتالوج يومي 04:00.
الخلاصة المعمارية (نوعان من البيانات، استراتيجيتان): 1. static (قنوات/أفلام/مسلسلات) → فهرس + 24h refresh. 2. time-based (EPG) → فهرس الجدول كل 3h + حساب on-now حياً وقت الاستعلام.
⚡ Hub Enhancements + ضبط نهائي (2026-06-12 ~21:10)
تأكيد فهم د. وائل (صحيح): البحث في الأسماء (قنوات + أفلام/مسلسلات) من كل الاشتراكات؛ الـ EPG (البرامج الحية) من الاشتراكات الكبيرة التي تدعم XMLTV فقط.
التحسينات المطبّقة + verified حياً:
1. مؤشر حالة الفهرس في الهيدر — 🟢 الفهرس حديث · EPG حديث 🔄 (loadIdxStatus من /api/catalog/status كل 5min) + ضغطه = reindex فوري (reindexNow → /api/catalog/reindex).
2. subs_summary precomputed في meta — /api/catalog/subs صار 440ms→23ms (19×). يُحدّث في كل reindex + populated يدوياً للفهرس الحالي.
3. /api/catalog/unified — بحث واحد فوري يجمع قنوات+أفلام+EPG بالتوازي من DB (75ms): ch=30 mv=40 epg=20.
4. EPG hint محدّث (أزلت "أول بحث قد يأخذ لحظات" — صار فورياً) + ملاحظة "متوفر من الاشتراكات التي تدعم EPG".
التحقق الحي (browser على hub.drwaelalkishawi.com): الهيدر يظهر 🟢 الفهرس حديث · EPG حديث؛ 3 تبويبات منفصلة (بحث قنوات / أفلام-مسلسلات / EPG) تعمل.
الحالة: hub+portal+catalog+EPG كلها HTTP 200 + حديثة. cron: catalog يومي 04:00 + EPG كل 3h. كلاهما isolated gemini-flash delivery=none.
🚀 Hub Enhancements Round 2 — functionality + الأداء (2026-06-12 ~21:30)
د. وائل طلب تطوير الـ functionality + الأداء/السرعة معاً. طبّقت + verified حياً:
الأداء:
- DB tuning في
_con(): cache_size=-20000 (20MB) + mmap_size=256MB + temp_store=MEMORY + query_only. - LRU query cache (TTL 120s, max 400) في catalog_search → بحث متكرر 38ms→8.5ms.
@app.after_requestيضيفCache-Control: public, max-age=60لـ search/unified/subs/epg → الجهاز يكاش النتائج 60s.
- Search-as-you-type debounced 280ms (Enter=فوري) في كل التبويبات — نتائج تظهر أثناء الكتابة.
- ⭐ المفضّلة + 🕒 شوهد مؤخراً — تبويب جديد، تُحفظ localStorage على الجهاز (لكل جهاز). ⭐ على كل بطاقة بحث + playHit يسجّل recently-watched تلقائياً.
مؤجّل (اختياري، عند الطلب): تجميع القنوات حسب الدولة/الفئة تلقائياً · توحيد التبويبات في «بحث ذكي واحد» (unified endpoint جاهز).