نظام Event Flow

دليل محرر Event Flow

أنشئ أتمتة موثوقة لـ Social Stream Ninja. يشرح هذا الدليل الأساسيات والعقد المنطقية وتدفق الإشارات والحيل العملية التي يسأل عنها منشئو المحتوى كثيرًا (مثل تجنب صدى الدردشة ومعرفة متى تُجمَّع كتل AND وNOT).

العربية

0. نظرة سريعة

Event Flow محرر قائم على العقد. يحمل كل خط حمولة رسالة بالإضافة إلى حالة منطقية (true = متابعة، false = إيقاف). استخدم مصادر لإدخال أحداث، العقد المنطقية لترشيح القرارات، و إجراءات لتنفيذ عمليات (إرسال دردشة أو التحكم بالتراكبات أو ترحيل رسائل وغيرها).
هل تحتاج إلى تذكّر المشاركين أو فحص الأهلية لاحقًا أو إجراء سحب لمستخدمين فريدين أو مسح قائمة مسماة واحدة؟ افتح دليل ذاكرة المستخدم لنموذج الحالة المشتركة ولقطات الشاشة ومثال قابل للاستيراد.

ما هذا المحرر؟

محرر Event Flow هو طبقة «الأتمتة المتقدمة» في Social Stream Ninja. يعمل فوق مفاتيح التبديل البسيطة في النافذة المنبثقة ويتيح لك كتابة منطق التوجيه الخاص بك. استخدمه عندما تحتاج إلى:

  • مرّر الدردشة بين الخدمات مع مرشحات (مثل نسخ Twitch إلى Discord مع حظر الأوامر).
  • أنشئ أوامر قائمة على الولاء أو ألعاب كلمات مفتاحية أو بوابات للسحب باستخدام منطق AND/OR/NOT.
  • فعّل تراكبات مخصصة أو أصواتًا أو مشاهد OBS أو webhooks بناءً على البيانات التي تُثريها في التدفق.
  • امزج منصات متعددة داخل أتمتة واحدة (توجيه Kick وTwitch وYouTube عبر تدفق واحد).

اعتبر النافذة المنبثقة «إعدادات سريعة جاهزة»، وEvent Flow مجموعة أدوات لمسارات عمل مخصصة.

البدء والأساسيات

  • افتح محرر Event Flow من قائمة لوحة التحكم الرئيسية (في تطبيق سطح المكتب أو الإضافة).
  • يُحفظ كل مشروع محليًا إلى أن يُصدَّر. استخدم Export للنسخ الاحتياطي أو المشاركة.
  • اعمل داخل مساحات عمل تُسمى تدفقات. يمكن لكل تدفق الاشتراك في منصات متعددة في الوقت نفسه.

العقد في لمحة

  • المدخلات (المنافذ اليسرى) تتوقع سياق الرسالة.
  • المخرجات (المنافذ اليمنى) تُخرج السياق نفسه مع أي تعديلات.
  • قد تُخرج العقد المنطقية قناة true وقناة اختيارية false .

بنية الحمولة

تحمل كل رسالة كائن JSON. وتتبع المفاتيح الإلزامية docs/event-reference.html (platform وtype وchatname وchatmessage وغيرها). أرفق البيانات المخصصة ضمن meta.

يبدأ كل تدفق بمشغّل

لا تعمل عقد الإجراءات (الخضراء) من تلقاء نفسها — ولا تُنفَّذ إلا عندما تكون نتيجة عقدة مشغّل (زرقاء) سابقة لها true. يبدو التدفق المكوّن من إجراءات متسلسلة فقط صالحًا، لكنه يظل خاملًا لأن لا شيء يبدأ السلسلة. تصف أسماء العقد ما تفعله، وليس متى يحدث: إبراز الرسالة (Feature Message) يُبرز رسالة عندما يصل إليه التدفق — ولا يعمل عندما تُبرز رسالة في مكان آخر.

عقدتا إجراء موصولتان تسلسليًا دون عقدة مشغّل
❌ لا يعمل أبدًا. Feature Message وSpeak Text كلاهما إجراءات؛ فمن دون مشغّل في البداية، لا شيء يبدأ السلسلة.
مشغّل Any Message متصل بإجراءَي Feature Message وSpeak Text
✅ يعمل. مشغّل أي رسالة (Any Message) (أو Message Contains أو تعبير منتظم أو حدث تبرع أو غير ذلك) يبدأ السلسلة؛ ثم يعمل الإجراءان لكل رسالة مطابقة.

تراكب Flow Actions (خرج الإجراءات)

ابدأ بقالب تنبيه:

اختر تبرع: احتفال + كلام لحركة جاهزة ومقطع شكر اصطناعي، أو القالب المتقدم تبرع: حركة + صوت + مرشح OBS . تبدأ قوالب التنبيهات الجديدة معطلة لتتمكن من ضبطها واختبارها أولًا. لقالب OBS، اختر مصدرًا والمرشح نفسه الذي يكون معطلًا عادةً في إجراءَي المرشح.

تشغيل مقطع صوتي (Play Audio Clip) وMulti-Alerts يشتركان الآن في مكتبة من 17 صوتًا: تصفيق وقرع طبول واندفاع هواء وآلة نقود وتأثيرات أخرى، وأربع عبارات إنجليزية اصطناعية مسماة، وأصوات بسيطة. استماع / إيقاف (Listen / Stop) يعرض معاينة محلية مع حالة تشغيل ظاهرة. لا يزال بإمكانك رفع تسجيل أو اختيار ملف محلي للتطبيق. للأسماء أو الرسائل المتغيرة، استخدم الإجراء الموجود نطق النص (Speak Text) .

يشغّل Event Flow الصوت عبر Flow Actions كمصدر متصفح؛ ويشغّل Multi-Alerts الصوت عبر مصدر متصفح خاص به. أبقِ الصوت مفعّلًا في واحد فقط للحدث نفسه لتجنب التشغيل المزدوج. انتقل إلى عقدة تدفق بمفتاح Tab واضغط Enter أو المسافة لتحرير خصائصها.

العقد مثل تشغيل مقطع صوتي (Play Audio Clip), عرض تراكب وسائط (Display Media Overlay)، وعناصر تحكم OBS تحتاج إلى واجهة عرض. وهذه الواجهة هي صفحة تراكب Flow Actions المقدمة من actions.html. أبقِه يعمل في برنامج البث لديك (OBS أو لوحات متصفح Streamer.bot أو غيرها) حتى تجد إجراءات Event Flow موضعًا للظهور.

مشغّل Any Message متصل بإجراء Play Audio Clip
هذا التدفق مكتمل ويعمل مع كل رسالة — لكن الصوت يُشغَّل على صفحة تراكب Flow Actions، وليس في المحرر. يشغّل زر المعاينة في المحرر الصوت محليًا؛ أما التشغيل الفعلي فيتطلب فتح التراكب. إذا حظر المتصفح التشغيل التلقائي، فانقر على تفعيل الصوت في صفحة Flow Actions لإعادة محاولة آخر مقطع محظور. يتيح النقر في مكان آخر من تلك الصفحة التشغيل أيضًا. ويسمح مصدر متصفح OBS عادةً بالتشغيل التلقائي.
كيفية فتحه (من النافذة المنبثقة أو لوحة التحكم):
  1. افتح نافذة Social Stream Ninja المنبثقة الرئيسية (النافذة المحمّلة من popup.html أو أيقونة الإضافة).
  2. مرّر إلى بطاقة “Flow Actions”. استخدم [نسخ الرابط] أو انقر على الرابط داخل البطاقة.
  3. يبدو الرابط مثل https://socialstream.ninja/actions.html?session=YOURSESSION. الصقه في مصدر متصفح OBS (يُقترح 1920×1080) أو افتحه في أي متصفح للتراكبات.
استخدام وسائط محلية في التطبيق المستقل:
  1. في إجراء Play Audio Clip أو Display Media Overlay، انقر على اختيار ملف محلي (Choose Local File).
  2. انقر على نسخ رابط Flow Actions المحلي لـOBS ‏(Copy Local Flow Actions URL for OBS) واستخدم رابط localhost المُنشأ بدلًا من رابط Flow Actions المستضاف.
  3. أبقِ SSApp يعمل. إذا نُقل ملف محدد، فعُد إلى الإجراء وانقر على إعادة الربط (Relink).

لا تستطيع إضافة Chrome تقديم ملفات القرص بمفردها. استخدم Upload أو رابطًا مستضافًا عندما لا يتوفر مرافق سطح المكتب. راجع دليل ملفات الوسائط لـ Event Flow للإعداد الكامل.

بعد تحميل ذلك التراكب، يمكنه:

  • عرض GIPHY أو روابط وسائط مباشرة ونص وقصاصات احتفالية تُفعّلها تدفقاتك.
  • تشغيل الأصوات (TTS والمقاطع الصوتية) محليًا ليسمعها المشاهدون.
  • تواصل مع OBS عبر إعدادات WebSocket الموجودة ضمن قسم Flow Actions في النافذة المنبثقة (تبديل المشاهد وتبديل المصادر وتحديث نص GDI+/FreeType ومخزن الإعادة وغيرها).
أوضاع التحكم في OBS:
  • Browser Source API: متاح فقط عندما actions.html يعمل داخل مصدر متصفح OBS مع مستوى الوصول المتقدم (Advanced Access Level). يعمل تبديل المشاهد هنا، ويمكن لإجراءات التسجيل والبث ومخزن الإعادة استخدامه كبديل احتياطي.
  • OBS WebSocket: يُوصى به للتحكم المتسق. تستخدم Flow Actions في Social Stream Ninja واجهة OBS WebSocket v5 API من OBS 28 أو أحدث وتتوقع مجموعة الطلبات الحديثة على المنفذ 4455.
  • كلمة المرور: اختيارية. أضف فقط &obspw=... إلى رابط Flow Actions إذا كان خادم OBS مضبوطًا ليتطلب المصادقة.
  • تشخيص التراكب: أضف &obsdebug=1 إلى رابط actions.html إذا أردت شارة صغيرة مباشرة لاتصال OBS على التراكب أثناء استكشاف الأخطاء.
  • Set Text Source: يحدّث مُدخلات OBS Text (GDI+) وText (FreeType 2) مباشرة ويدعم متغيرات قوالب Event Flow مثل {counterValue} و {counterTarget}.
  • تثبيتات 4.x القديمة: إذا كنت لا تزال تستخدم obs-websocket 4.x أو المنفذ 4444، فلن تعمل إجراءات المصدر والمرشح والكتم والنص إلى أن تتم ترقية OBS أو obs-websocket.

راجع دليل التحكم في OBS المخصص للاطلاع على كل مشغّل وإجراء وخطوة إعداد ووصفة مختبرة.

مسار التشخيص الموصى به:
  1. افتح obs-websocket-test.html.
  2. تأكد من أن GetVersion, GetCurrentProgramScene، و GetSceneList تنجح.
  3. نفّذ فحص الإجراء المطابق هناك قبل اختبار أتمتة Event Flow كاملة.
أبقِ التراكب مفتوحًا. يؤدي إغلاق صفحة Flow Actions إلى إيقاف كل إجراءات التراكب والصوت وOBS في Event Flow مؤقتًا. أخفِها أو ضعها على شاشة منفصلة بدلًا من إغلاقها تمامًا.

1. ما الذي يمر عبر العقدة؟

تمرّر بيئة تشغيل Event Flow شيئين عبر كل سلك:

  1. الحمولة — كائن بيانات الحدث أو الرسالة.
  2. إشارة البوابة — قيمة true/false التي تخبر العقدة التالية بما إذا كان ينبغي تنفيذها.
إذا أخرجت عقدة false: تتوقف العقد اللاحقة عن التنفيذ ما لم تتلقَّ مدخلات عبر فرع منفصل (مثل منفذ false في عقدة Condition). يسهل ذلك بناء منطق احتياطي دون تكرار تدفقات كاملة.

متطلبات المدخلات

  • مصادر الأحداث (Twitch Message وTimers وManual Trigger وغيرها) تتجاهل المدخلات السابقة — فهي تنشئ حمولتها الخاصة وتُصدر دائمًا true إلا إذا حدث خطأ في العقدة نفسها.
  • عقد التحويل والمنطق تقرأ الحمولة وقد تعيد كتابة الحقول أو تضبط الحالة أو تقلب إشارة البوابة إلى false.
  • عقد الإجراءات لا تعمل إلا عندما تظل البوابة true. ويمكنها مع ذلك إخراج حمولة محدثة إذا أردت مواصلة سلسلة الإجراءات.

أنماط المخرجات

مخرج واحد

توفر معظم العقد مخرجًا واحدًا. كل ما يدخل (الحمولة والبوابة) يخرج دون تغيير ما لم تعدّله العقدة.

مخرجات true وfalse

تُخرج عقد Condition وCompare وRegex وLogic منفذين. صحيح (True) تستمر عبر المنفذ الأخضر؛ false تتوفر على المنفذ الرمادي أو الأحمر.

التمرير كما هو مقابل التجاوز

تعدّل بعض العقد (Set Variable وMath وText Replace) الحمولة لكنها تظل تمرّر true/false من مدخلاتها. وتعيد عقد أخرى (NOT وAND وOR) حساب القيمة المنطقية بنفسها.

2. مرجع سريع للعقد المنطقية

تجيب هذه الكتل عن أكثر الأسئلة شيوعًا حول معنى true وfalse.

NOT

  • المدخلات: قيمة منطقية واحدة (true/false) مشتقة من العقدة السابقة.
  • المخرجات: القيمة المنطقية المعكوسة بالإضافة إلى الحمولة دون تعديل.
  • السلوك الافتراضي: إذا لم يكن شيء موصولًا بمدخل NOT، فإن نتيجتها تكون false، لذا يكون الخرج true.
مثال: ضع NOT بعد "Contains Keyword" لتشغيل تنبيه عندما لا يستخدم المشاهد الكلمة المفتاحية.

AND

  • المدخلات: إشارتان منطقيتان أو أكثر (A وB و...). يمكنك ترك المنافذ الإضافية فارغة.
  • المخرجات: true فقط إذا كانت جميع المدخلات الموصولة تساوي true.
  • استخدم AND عندما يجب استيفاء شروط متعددة في الوقت نفسه («مشترك» و «رسالة الدردشة تحتوي على !raffle»).

OR

  • يصدر true إذا كان أيٌّ من المدخلات الموصولة يساوي true.
  • مفيد للمشغّلات متعددة المنصات: أوصل عقد رسائل Twitch وYouTube ببوابة OR واحدة، ثم وحّد الإجراء اللاحق.
هل أحتاج دائمًا إلى عقدة AND؟
لا. توفر عقد كثيرة بالفعل مرشحات شاملة (مثل “Filter User Level” مع “Contains Text”). استخدم AND فقط عندما لا تغطي الخيارات المدمجة تركيبتك، أو عندما تريد نقطة وصل منطقية قابلة لإعادة الاستخدام تشترك فيها فروع أخرى.
NOT والمدخلات الفارغة: ستظل عقدة NOT غير الموصولة تُخرج true. أبقِها موصولة بشيء ذي معنى أو عطّل العقدة حتى لا ترفع الحظر عن تدفق عن طريق الخطأ.

3. أمثلة تدفقات مصغرة

A. الرد التلقائي ما لم تكن الرسالة أمرًا

رسالة Twitch ──▶ مطابقة Regex "^!" ─┐ │ ├─false──▶ رد تلقائي («شكرًا للدردشة!») │ └─true──▶ لا تفعل شيئًا

هنا تُصدر عقدة Regex true عندما تكون الرسالة أمرًا. نوجّه منفذ false إلى ردنا، فيتلقى المشاركون العاديون إقرارًا بينما تمر الأوامر ببساطة.

B. اشتراط فحوص متعددة باستخدام AND

رسالة YouTube ──▶ تحتوي على “!queue” ─▶ AND ─▶ ترحيل إلى Discord عضوية مهداة ─▶ دور المستخدم = عضو ──▲

تضمن عقدة AND ترحيل رسائل الأعضاء الذين يستخدمون الكلمة المفتاحية الصحيحة فقط إلى Discord. يرسل الفرعان نتيجتهما المنطقية إلى عقدة AND؛ وتمرّ حمولة الفرع الأول إلى العقد اللاحقة.

C. عقدة NOT لمنع التنبيهات المتكررة

حمولة الحدث ─▶ فحص الحالة (isAlertMuted) └─false─▶ NOT ─▶ تشغيل احتفال

State Check يُخرج القيمة true عندما يكون التنبيه مكتومًا. بعكس تلك النتيجة، تضمن عقدة NOT تشغيل الاحتفال فقط عندما يكون العلم false.

D. تشغيل أحد صوتين عشوائيًا

تدفق يستخدم بوابات RANDOM وNOT وAND لتشغيل أحد مقطعين صوتيين عشوائيًا
اختيار عشوائي بنسبة 50/50 بين مقطعين صوتيين. تجري بوابة RANDOM اختيارًا واحدًا لكل رسالة مطابقة: عندما يمر الاختبار، يعمل الصوت A؛ وعندما يفشل، تعكس بوابة NOT النتيجة وتسمح بوابة AND بتشغيل الصوت B بدلًا منه.
مشغّل ──▶ RANDOM (50%) ──▶ تشغيل الصوت A │ └──▶ NOT ──▶ AND ──▶ تشغيل الصوت B مشغّل ──────────────────▲

بوابة AND ليست اختيارية. ستُخرج عقدة NOT وحدها true كلما كانت بوابة RANDOM خاملة، لذا سيعمل الصوت B مع كل رسالة دردشة لا تطابق المشغّل. توصيل المشغّل إلى AND كمدخل ثانٍ يقصر الصوت B على الرسائل المطابقة فقط. يعمل النمط نفسه مع أي زوج من الإجراءات البديلة، وليس الصوت وحده.

4. منع الصدى والحلقات والتغذية الراجعة للترحيل

ترحيل الدردشة بين الواجهات أداة قوية، لكنه قد يسبب صدى لا نهائيًا إذا استمعت إلى خرجك نفسه. اتبع هذه الاحتياطات:

ملاحظة وجهة YouTube Shorts:
تميّز المشغّلات الواردة ووجهات Relay Chat الصادرة بين youtube و youtubeshorts. استخدم إجراءَي ترحيل عندما ينبغي أن تصل الرسالة إلى كلا النوعين. راجع YouTube Shorts وEvent Flow.
يتخطى Relay Chat الرسائل المرتدة المعروفة تلقائيًا.
الرسالة المرتدة هي رسالة صادرة تُلتقط مجددًا من دردشة الوجهة. تتخطى إجراءات Relay Chat الحالية هذه الرسائل المرتدة المعروفة؛ ولا يوجد مربع اختيار منفصل باسم No Reflections. لإخفاء عرضها أو تقييده في لوحة الإرساء والتراكبات، استخدم مرشح الرسائل المرتدة (Reflection Filter) بالقيمة حظر الكل (Block All), السماح بالأولى (Allow First)، أو السماح بالكل (Allow All). يتحكم هذا في العرض عند إعادة الاستقبال، لا في الإرسال. اتبع شرح ترحيل Twitch وYouTube خطوة بخطوة لإعداد كامل.
  • تجنب أنظمة الترحيل المكررة. عطّل خيار Relay all العام عند استخدام مسارات Event Flow المكافئة، وتحقق من الخدمات الأخرى التي تربط الدردشات نفسها. لا يُضمن بقاء البيانات الوصفية المخصصة بعد المرور عبر دردشة منصة.
  • استخدم عقد Debounce أو Cooldown للتنبيهات التي ينبغي أن تعمل مرة واحدة فقط كل X ثانية.
  • اقطع الدورات عمدًا. إذا كان فرعان يغذي أحدهما الآخر، فأضف عقدة منطقية تفحص متغير حالة (“currentlyRelaying”) حتى يخرج التدفق مبكرًا عندما يكون العلم مفعّلًا.

5. المدخلات والمخرجات وأسئلة عملية

ما الذي يدخل إلى العقدة؟

  • حمولة الرسالة كاملة.
  • قيمة البوابة المنطقية (true/false).
  • سياق اختياري (متغيرات الحالة والمؤقتات) تطلبه العقدة صراحةً.

ما الذي يخرج من العقدة؟

  • الحمولة نفسها ما لم تعدّلها العقدة.
  • قيمة بوابة منطقية يُعاد حسابها (للعقد المنطقية) أو تُمرَّر كما هي (للإجراءات).
  • لا تغيّر معظم التأثيرات الجانبية (مثل إرسال الدردشة) الحمولة، لكن يمكن لإجراءات النقاط إرفاق حقول حالة مثل pointsTotal أو pointsSpendError للمنطق اللاحق.

متى تتفرع؟

كلما أردت الاستجابة بشكل مختلف لـ true مقابل false. اسحب سلكًا من المخرج الملون المطلوب (الأخضر = true، والرمادي أو الأحمر = false) إلى العقدة التالية.

تذكّر: إذا لم تفعل شيئًا بإشارة false ، ينتهي التدفق هناك ببساطة. وهذا مناسب للمرشحات («حظر كل ما يفشل في الفحص»)، لكن لا تنسَ توصيل مسار false إذا كنت تحتاج إلى بدائل احتياطية.

أسئلة وأجوبة شائعة

  • هل يجب استخدام AND لكل زوج من المرشحات؟ لا. تتضمن عقد كثيرة فحوصًا متعددة (مثل مرشح الرسائل الأساسي الذي يدعم كلمة مفتاحية ودورًا). استخدم AND للتركيبات المتقدمة فقط أو عند دمج إشارات من عقد مختلفة.
  • كيف تصل قيم true وfalse إلى عقدة NOT؟ أي عقدة ذات مخرج أخضر تُصدر true افتراضيًا. عندما يفشل شرط، تُصدر false. اربط ذلك السلك بـ NOT لعكس النتيجة.
  • هل تستطيع عقدة إخراج حمولة حتى إذا أرجعت false؟ نعم. تظل الحمولة تمر عبر مخرج false؛ ويعود إليك تحديد وجهة ذلك الفرع.
  • كيف أطابق أعضاء فريق TikTok؟ اختر عضو فريق TikTok (TikTok Team Member) في عقدة User Role. يتعرف على مستويات وشارات TikTok Fan Club أو الفريق في الرسالة الواردة ولا يعتمد على إعدادات Main Chat Overlay.
  • هل تستطيع كل عقدة Speak Text استخدام صوت مختلف؟ نعم. أدخل اسم صوت أو معرّفه المدعوم لدى الموفّر في تجاوز الصوت (Voice Override)، أو اتركه فارغًا لاستخدام إعداد TTS الافتراضي في Flow Actions.

6. مرجع متغيرات القوالب

تدعم عدة عقد إجراءات (Show Text وSet Text Source وSend Message وRelay Chat وTTS Speak وCall Webhook وPrint Thermal Label) متغيرات القوالب تُستبدل ببيانات الحدث وقت التشغيل. ضع أسماء المتغيرات بين أقواس معقوفة مثل {username}.

المتغيرات الأساسية (متوافقة مع الإصدارات السابقة)

المتغيرالاسم البديلالوصفمثال
{username}{chatname}اسم عرض المستخدمCoolViewer123
{message}{chatmessage}نص رسالة الدردشةمرحبًا بالجميع!
{source}-اسم المنصة (بحرف أول كبير)Twitch، YouTube
{type}-اسم المنصة (خام)twitch, youtube
{donation}{hasDonation}تسمية عرض التبرع أو الإكرامية$5.00، 500 bits

المتغيرات الموسعة

المتغيرالوصفمثال
{displayname}اسم العرض (حقل بديل)CoolViewer123
{donoValue}مكافئ التبرع بالدولار الأمريكي، المقدم أو المقدر؛ ويستمد Event Flow قيم العتبات من الحقل الموحّد hasDonation بصيغ مثل القيمة، $القيمة أو القيمة + الوحدة أو وحدة وقيمة بصيغة مختصرة. تستخدم الوحدات الافتراضية المسماة غير المعروفة معدل 100 وحدة = $0.01 USD؛ وتستخدم هدايا TikTok غير المسعّرة عملة واحدة لكل هدية ($0.01 لكل منها). {donationAmount} اسم بديل قديم5.00
{event}معرّف نوع الحدثcheer, raid, new_follower
{membership}حالة العضويةMEMBERSHIP, new_sponsor
{subtitle}سياق إضافيعضو منذ 3 أشهر
{userid}معرّف المستخدم في المنصة12345678
{chatimg}رابط الصورة الرمزية للمستخدمhttps://...
{contentimg}رابط الصورة المرفقةhttps://...
{rewardTitle}اسم المكافأة عندما يوفر المصدر حقل عنوان مكافأة في المستوى الأعلىأبرز رسالتي
{meta}بيانات حدث منظمة (JSON){"viewers":100}
{counterValue}قيمة العداد الحالية بعد خطوة Counter أو Check Counter12
{counterTarget}قيمة هدف العداد30
{counterRemaining}هدف العداد ناقص قيمته الحالية، بحد أدنى 018
مطابقة المتغيرات غير حساسة لحالة الأحرف. {USERNAME}, {Username}، و {username} تعمل كلها بالطريقة نفسها.
تعمل أيضًا الحقول التي يضيفها التدفق. إذا أضاف إجراء سابق قيمة في المستوى الأعلى إلى الرسالة، فيمكن للقوالب اللاحقة قراءتها مباشرة. بهذه الطريقة Check Counter يتيح {counterValue}, {counterTarget}، و {counterRemaining}.
JSON لإجراء Call Webhook: تعمل متغيرات القوالب داخل قيم السلاسل النصية في JSON عند أي مستوى تداخل للكائنات أو المصفوفات. لا تُطبَّق القوالب على مفاتيح الكائنات، ويُرسل المتن المخصص الخالي من العناصر النائبة دون تغيير.

قوالب أمثلة

  • Show Text: {username} just cheered {hasDonation}!
  • Set OBS Text Source: {username}: now {counterValue}, need {counterTarget}
  • Relay Chat: [{source}] {username}: {message}
  • TTS: {username} says {message}
  • تنبيه تبرع: {username} donated {donation} - {subtitle}
  • ملصق حراري: {username}، ثم سطر جديد، ثم {donation}. راجع دليل الطابعة الحرارية لإعداد الطابعة والملصقات ذات الحجم الثابت وتدفق كامل.
  • Call Webhook في Discord: {"content":"{message}","username":"{username}","avatar_url":"{chatimg}"}
تتحول المتغيرات المفقودة إلى سلاسل نصية فارغة. إذا لم يتضمن حدث حقلًا معينًا (مثل {donation} في رسالة دردشة عادية)، يُستبدل العنصر النائب بسلسلة نصية فارغة بدلًا من إظهار النص الحرفي {donation} .

7. قائمة أفضل الممارسات

  • سمِّ ولوِّن عقدك حتى تعرف مستقبلًا هوية كل فرع.
  • اختبر باستخدام المحاكي المدمج (Send Test Event) قبل تفعيل التدفق للاستخدام المباشر.
  • اجمع المنطق بالقرب من المصدر. رشّح في أبكر مرحلة ممكنة لتجنب معالجة إضافية لاحقًا.
  • خزّن التكرارات في عقد الحالة. استخدم العدادات ومفاتيح التبديل والطوابع الزمنية لتجنب التنبيهات المزدوجة.
  • وثّق حقول meta. عندما تضيف حقولًا مخصصة إلى meta ، فوثّقها حتى تظل التراكبات والعملاء البعيدون متوافقين.
احفظ نسخًا. صدّر تدفقك عند بلوغ كل مرحلة مهمة. الاستيراد هو أسهل طريقة للعودة إلى نسخة سابقة إذا فشلت تجربة.

8. استكشاف إضافي

تشغيل مسارات عمل مخصصة من Stream Deck أو API: مشغّلات مسماة وقالب بداية واكتشاف مسارات العمل وبيانات إضافية وأمثلة HTTP وWebSocket وP2P وإيماءات القرص.

هل أنت جاهز لمزيد من التفاصيل؟

  • استخدم عقد الحالة (State Nodes) (العدادات ومفاتيح التبديل والمؤقتات) لتتبع السياق بين الأحداث.
  • ادمج المتغيرات والمنطق لإنشاء أنظمة قوائم انتظار أو سحوبات أو محركات تسجيل نقاط.
  • اربط بـ النقاط والمكافآت حتى يتمكن المشاهدون من تفعيل التدفقات عمدًا.
  • هل تستخدم تطبيق SSApp لسطح المكتب؟ فعِّل عقد JavaScript المخصصة لأي منطق لا تغطيه عقدة مدمجة.
  • تحقق من مرجع الأحداث للوثائق التفصيلية عن الحمولات عبر جميع المنصات.

هذا الدليل مستقل عمدًا — انسخه محليًا، وكيّفه لفريقك، وواصل التجربة داخل المحرر.

9. JavaScript مخصص SSApp / سطح المكتب فقط

تتيح لك عقدتان في محرر Event Flow كتابة أي JavaScript لتُنفَّذ داخل مسار التدفق: شيفرة مخصصة (Custom Code) (مشغّل) و تنفيذ شيفرة مخصصة (Execute Custom Code) (إجراء). وهما الوسيلة المتاحة لكل ما لا تستطيع العقد المدمجة التعبير عنه.

يتطلب تطبيق سطح المكتب. عقد JavaScript المخصصة معطلة في إضافة المتصفح لأن سياسة أمان المحتوى في Manifest V3 لـ Chrome تحظر new Function() / eval(). افتح المحرر من خلال تطبيق SSApp لسطح المكتب لتفعيلها. في وضع الإضافة تظهر العقد بالرمادي مع التسمية «سطح المكتب فقط».
تحرير الشيفرة: حدد عقدة Custom Code وانقر على فتح محرر الشيفرة (Open Code Editor) لفتح نافذة تحرير كبيرة. حفظ وإغلاق (Save & Close) يتحقق من صياغة JavaScript ويحفظ التدفق بالكامل؛ Ctrl+S أو Cmd+S يفعل الشيء نفسه. يترك Cancel العقدة دون تغيير.
محرر Event Flow — الحالة الفارغة
محرر Event Flow. تسرد اللوحة اليسرى جميع العقد المتاحة؛ وتُنشئ التدفقات على مساحة العمل المنقطة؛ وتعرض اللوحة اليمنى خصائص العقدة المحددة.

Custom Code — عقدة مشغّل

اسحب شيفرة مخصصة (Custom Code) من متقدم (Advanced) في لوحة المحفزات إلى مساحة العمل. يعمل كبوابة: لا يستمر التدفق إلا عندما تُرجع شيفرتك true.

لوحة المشغّلات تعرض عقدة Custom Code ضمن مجموعة Advanced
يوجد Custom Code ضمن متقدم (Advanced) في لوحة المشغّلات.
لوحة خصائص مشغّل Custom Code تعرض محرر JavaScript
لوحة الخصائص بعد وضع المشغّل. اكتب أي تعبير يُرجع true أو false.
توقيع الدالة: تُنفَّذ شيفرتك بصيغة function(message) { ... }
يجب إرجاع: قيمة منطقية — true للسماح باستمرار التدفق، false لإيقافه.
المتاح: الكائن message (راجع واجهة API للرسائل أدناه)، بالإضافة إلى convertCurrency(value, targetCurrency, source) و convertToUSD(value, source).

Execute Custom Code — عقدة إجراء

اسحب تنفيذ شيفرة مخصصة (Execute Custom Code) من التكاملات (Integrations) في لوحة الإجراءات . ويمكنه تعديل الرسالة أو حظرها أو إرفاق بيانات وصفية تستطيع العقد اللاحقة قراءتها.

لوحة الإجراءات تعرض Execute Custom Code ضمن مجموعة Integrations
Execute Custom Code ضمن التكاملات (Integrations) في لوحة الإجراءات.
لوحة خصائص إجراء Execute Custom Code تعرض محرر الشيفرة
خصائص الإجراء. أرجع كائنًا لدمج التغييرات في نتيجة التدفق.
توقيع الدالة: تُنفَّذ شيفرتك بصيغة function(message, result) { ... }
ينبغي إرجاع: كائنًا أو Promise تُدمج في result— راجع واجهة API للنتيجة.
المتاح: message (حمولة الحدث)، result (حالة نتيجة التدفق الحالية)، printThermal(html, options)، بالإضافة إلى convertCurrency(value, targetCurrency, source) و convertToUSD(value, source).
الطباعة الحرارية في SSApp: اختر الطابعة وعاير عرض الورق والهوامش الآمنة ضمن التحكم في الطابعة (Printer Control)، ثم أرجع printThermal('<strong>' + message.chatname + '</strong>'). يضع SSApp المهمة في قائمة الانتظار بصمت عبر واجهة الطباعة الأصلية في Windows ويستخدم تلك الإعدادات المحفوظة. يمكن للتدفق تجاوزها بخيارات مثل { width: '58mm', marginLeft: '3mm', marginRight: '3mm', marginTop: '2mm', marginBottom: '2mm', feed: '3mm', marginType: 'printableArea' }. يتيح إرجاع Promise لـ Event Flow انتظار الإرسال والإبلاغ عن الأخطاء.
مساحة عمل تعرض مشغّل Custom Code وإجراء Execute Custom Code جنبًا إلى جنب
مشغّل Custom Code (أزرق) وإجراء Execute Custom Code (أخضر) موضوعان على مساحة العمل. اربط منفذ خرج المشغّل بمنفذ دخل الإجراء لتوصيلهما.

الكائن message

تستقبل العقدتان حمولة الحدث كاملة بوصفها message. الحقول أدناه متاحة دائمًا؛ وقد تتضمن أحداث المنصات حقولًا إضافية.

الحقلنوع البياناتالوصفمثال
message.chatmessageسلسلة نصيةنص رسالة الدردشة (قد يحتوي على HTML)"Hello stream!"
message.chatnameسلسلة نصيةاسم عرض المرسل"CoolViewer"
message.useridسلسلة نصيةمعرّف المستخدم في المنصة"12345678"
message.typeسلسلة نصيةمنصة المصدر (بحروف صغيرة)"twitch", "youtube", "kick"
message.hasDonationسلسلة نصيةسلسلة نصية منسقة للتبرع إن وُجدت"$5.00", "500 bits"
message.donoValueعدد / سلسلة نصيةمكافئ التبرع بالدولار الأمريكي عندما يوفره المصدر؛ وتُحترم القيم الصفرية الصالحة. يلجأ Event Flow إلى currency.js لتحويل التسميات الموحّدة في hasDonation لإجراء مقارنات العتبات، بما في ذلك 100 وحدة مسمّاة غير معروفة = $0.01 USD. ولا يحلل chatmessage لاستخراج قيم التبرعات.5
message.eventسلسلة نصيةمعرّف نوع الحدث"new_follower", "cheer", "raid"
message.membershipسلسلة نصيةحالة العضوية عند انطباقها"MEMBERSHIP"
message.subtitleسلسلة نصيةسطر سياق ثانوي"Member for 3 months"
message.modقيمة منطقيةالمرسل مشرفtrue
message.subscriberقيمة منطقيةالمرسل مشتركtrue
message.vipقيمة منطقيةلدى المرسل حالة VIPtrue
message.chatimgسلسلة نصيةرابط الصورة الرمزية للمستخدم"https://..."
message.metaكائنبيانات منظمة مخصصة مرفقة بالحدث{ viewers: 120 }
تحويل العملات: استخدم convertCurrency(message.hasDonation, 'EUR', message.type) لتحويل تسمية التبرع المنسقة إلى EUR. تُرجع رقمًا، أو null عندما تكون العملة المستهدفة المطلوبة غير مدعومة. يستخدم المحوّل أسعار Social Stream Ninja الداخلية التقريبية؛ ولا يتصل بخدمة صرف خارجية.

ما الذي يُرجعه الإجراء

أرجع كائنًا عاديًا من شيفرة الإجراء. تُدمج أي حقول تُضمّنها في كائن التدفق result ؛ وتحتفظ الحقول التي تحذفها من النتيجة بقيمها الحالية.

حقل الإرجاعنوع البياناتالتأثير
modifiedقيمة منطقيةاضبط true إذا غيّرت حقول message . يخبر العقد اللاحقة بأن الحمولة عُدّلت.
messageكائنأعِد تمرير الرسالة (التي ربما عُدّلت) حتى تستقبل العقد اللاحقة تغييراتك.
blockedقيمة منطقيةاضبط true لمنع عرض الرسالة أو ترحيلها.
أبسط قيمة إرجاع آمنة: return { modified: false, message };
حتى إذا لم تغيّر شيئًا، فإن إرجاع message يُبقيه يمر إلى العقدة التالية.

أمثلة مقاطع شيفرة

انسخ أيًا من هذه المقاطع إلى مساحة نص JavaScript Code في نوع العقدة المطابق.

مقاطع شيفرة المشغّلات — أرجع true لمتابعة التدفق

مطابقة كلمة مفتاحية (دون حساسية لحالة الأحرف)
تابع التدفق فقط عندما تحتوي الرسالة على كلمة أو عبارة محددة.
// Matches "!hello" anywhere in the message return (message.chatmessage || '').toLowerCase().includes('!hello');
اكتشاف الأوامر بتعبير منتظم
طابق الرسائل التي تبدأ بأمر من قائمة محددة (مثل !queue, !raffle, !enter).
return /^!(queue|raffle|enter)\b/i.test(message.chatmessage || '');
تبرع أعلى من حد معين
نفّذ فقط عندما يساوي التبرع مبلغًا أدنى أو يتجاوزه.
const amount = message.donoValue !== undefined && message.donoValue !== null && message.donoValue !== '' ? Number(message.donoValue) : (typeof convertToUSD === 'function' ? convertToUSD(message.hasDonation || '', message.type || '') : Number(String(message.hasDonation || '').replace(/[^0-9.]/g, '') || 0)); return amount >= 5;
YouTube Super Chat أو Super Sticker ضمن نطاق باليورو
حوّل تسمية تبرع YouTube القياسية إلى EUR، واستبعد Jewels/Gifts، واختر نطاقًا واحدًا للصوت أو التأثير المرئي.
var eventName = String(message.event || '').toLowerCase(); if (eventName !== 'superchat' && eventName !== 'supersticker') return false; var eurValue = convertCurrency(message.hasDonation || '', 'EUR', message.type || ''); if (typeof eurValue !== 'number' || !isFinite(eurValue)) return false; message.eurValue = eurValue; return eurValue >= 10 && eurValue < 25;
مرشح المنصة
معالجة أحداث منصات محددة فقط.
return ['twitch', 'youtube'].includes(message.type);
بوابة المشترك أو VIP أو المشرف
اسمح باستمرار التدفق للمستخدمين ذوي الصلاحيات فقط.
return !!(message.subscriber || message.vip || message.mod);
شروط متعددة — VIP وكلمة مفتاحية
اجمع فحص الدور ومحتوى الرسالة في تعبير واحد لا يغطيه أي مشغّل مدمج.
const isPrivileged = !!(message.subscriber || message.vip || message.mod); const isCommand = /^!feature\b/i.test(message.chatmessage || ''); return isPrivileged && isCommand;
بوابة طول الرسالة
معالجة الرسائل ذات المحتوى الكافي فقط (مفيد لـ TTS أو الترحيل لتجنب الإغراق برمز تعبيري واحد).
return (message.chatmessage || '').replace(/<[^>]+>/g, '').trim().length >= 20;

مقاطع شيفرة الإجراءات — أرجع { modified, message }

إلحاق شارة أو وسم بالرسالة
أضف مؤشرًا مرئيًا إلى نهاية كل رسالة تمر عبر هذا الإجراء.
message.chatmessage = (message.chatmessage || '').trimEnd() + ' ✅'; return { modified: true, message };
حظر الرسالة بشروط
افحص المحتوى وأسقط الرسالة بصمت عند مطابقة قاعدة — مفيد لأنماط الرسائل المزعجة التي لا يستطيع مرشح الكلمات المفتاحية التعبير عنها.
const text = (message.chatmessage || '').toLowerCase(); const spamPatterns = ['buy followers', 'free nitro', 'click here']; if (spamPatterns.some(p => text.includes(p))) { return { blocked: true, message }; } return { modified: false, message };
إزالة إشارات @mentions
أزِل جميع إشارات @username من الرسالة قبل ترحيلها إلى منصة أخرى.
message.chatmessage = (message.chatmessage || '').replace(/@\w+/g, '').trim(); return { modified: true, message };
تنسيق إعلان تبرع
أعِد كتابة chatmessage كسلسلة إعلان موحدة عند وجود تبرع.
const amount = parseFloat(message.donoValue || 0); if (amount > 0) { const note = (message.chatmessage || '').trim(); message.chatmessage = `💰 ${message.chatname} donated $${amount.toFixed(2)}!` + (note ? ` "${note}"` : ''); return { modified: true, message }; } return { modified: false, message };
إرفاق بيانات وصفية للتوجيه للعقد اللاحقة
وسِم الرسالة بحقل مخصص يمكن لإجراء لاحق من نوع تمرير الدردشة (Relay Chat) أو إرسال رسالة (Send Message) قراءته من متغير قالب ({meta}).
message.meta = message.meta || {}; // Assign a donation tier so the next node can use {meta} to decide overlay colour const amount = parseFloat(message.donoValue || 0); message.meta.donationTier = amount >= 20 ? 'gold' : amount >= 5 ? 'silver' : 'bronze'; return { modified: true, message };
بادئة رسالة تراعي المنصة
أضف تسمية المنصة في بداية الرسالة عند الترحيل بين المنصات حتى يعرف المشاهدون المصدر.
const labels = { twitch: '[Twitch]', youtube: '[YouTube]', kick: '[Kick]', tiktok: '[TikTok]', }; const label = labels[message.type] || `[${message.type || 'Chat'}]`; message.chatmessage = `${label} ${message.chatname}: ${message.chatmessage || ''}`; return { modified: true, message };

مثال كامل — بوت طلبات إضافة ميزات للمشاهدين المميزين (VIP)

يستمع هذا التدفق إلى !feature <text> من المشتركين أو المشاهدين المميزين (VIP) أو المشرفين، ويعيد تنسيقه كطلب إضافة ميزة، ثم يرحّله إلى وجهة ثانية (مثل Discord).

┌──────────────────────┐ ┌──────────────────────────┐ ┌──────────────────┐ │ مشغّل Custom Code │────▶│ إجراء Execute Custom Code │────▶│ Relay Chat │ │ │ │ │ │ (إلى Discord) │ │ بوابة: VIP/sub/mod │ │ إعادة تنسيق نص الرسالة │ │ │ │ + يبدأ بـ │ │ → "📋 طلب إضافة ميزة │ │ │ │ !feature │ │ من {name}: {text}" │ │ │ └──────────────────────┘ └──────────────────────────┘ └──────────────────┘

الخطوة 1 — مشغّل Custom Code (الصقه في حقل JavaScript Code للمشغّل):

// Only let VIPs, subscribers, and mods through, and only for !feature commands const isPrivileged = !!(message.subscriber || message.vip || message.mod); const isCommand = /^!feature\b/i.test((message.chatmessage || '').trim()); return isPrivileged && isCommand;

الخطوة 2 — إجراء Execute Custom Code (الصقه في حقل JavaScript Code للإجراء):

// Strip the "!feature" command word and format a clean announcement const featureText = (message.chatmessage || '') .replace(/^!feature\s*/i, '') .trim(); if (!featureText) { // No text after the command: block rather than relay an empty request return { blocked: true, message }; } message.chatmessage = `📋 Feature request from ${message.chatname}: ${featureText}`; return { modified: true, message };

الخطوة 3 — إجراء Relay Chat: أضف عقدة Relay Chat عادية بعد الإجراء واضبطها لتشير إلى وجهة Discord أو وجهة أخرى. لا حاجة إلى شيفرة مخصصة هنا — فالحقل المعاد تنسيقه message.chatmessage يمر تلقائيًا.

اختبار التدفق. انقر على الزر: اختبار التدفق (Test Flow) (أعلى يمين المحرر) لإرسال رسالة اصطناعية عبر المسار دون الحاجة إلى بث مباشر. عيّن chatname إلى اسم مشترك، وأضف رسالة مثل !feature dark mode support، وتأكد من أن وجهة Relay Chat تتلقى السلسلة النصية المعاد تنسيقها.
لوحة Test Flow لإرسال أحداث اختبار مصطنعة
لوحة Test Flow. املأ الحقول بما يطابق شروط المشغّل وانقر على تشغيل الاختبار (Run Test) للتحقق من المسار الكامل.

اعتبارات الأمان

تعمل الشيفرة المخصصة بصلاحيات عملية العرض. داخل SSApp، تتمتع الشيفرة في عقد Custom JS بوصول كامل إلى window وأي واجهات API تتيحها شيفرة التحميل المسبق (مثل window.ninjafy). تعامل مع ملفات التدفق المستوردة كشيفرة قابلة للتنفيذ — لا تستورد إلا تدفقات من مصادر تثق بها.
  • لا توجد بيئة عزل للشبكة. يمكن لشيفرة الإجراء استدعاء fetch(). إذا كنت تقبل تدفقات مشتركة من الآخرين، فراجع JavaScript قبل تفعيلها.
  • تُلتقط الأخطاء. يُرجع خطأ وقت التشغيل في شيفرتك false (للمشغّل) أو لا ينفّذ شيئًا (للإجراء)، ويسجّل الخطأ في وحدة تحكم DevTools — ولا يتعطل التدفق.
  • وأخطاء الصياغة أيضًا. خطأ من النوع SyntaxError وقت الترجمة يُلتقط بالطريقة نفسها. تحقق من DevTools ‏(F12) إذا بدت عقدة وكأنها لا تفعل شيئًا.