القنوات
تجلب القنوات محادثات الفريق إلى Libre WebUI: غرف عامة وخاصة ورسائل مباشرة، مع
سلاسل ردود وتفاعلات وتثبيت وتتبع غير المقروء ومرفقات وردود @model، وكل ذلك على
الأسس الدائمة والمشفّرة نفسها المستخدمة في المحادثات.
أنواع القنوات والعضوية
| النوع | من يستطيع رؤيتها | من ينضم إليها |
|---|---|---|
public | يستطيع الجميع تصفحها | ينضم أي شخص بنفسه |
private | الأعضاء فقط | يدعو المالك الأعضاء |
dm | المشاركان فقط | تُفتح تلقائيًا؛ ودائمًا بين شخصين بالضبط |
العضوية هي السلطة الوحيدة على محتوى القناة: تتحقق كل قراءة وكتابة — بما فيها تنزيل المرفقات وتسليم الأحداث مباشرة — من عضوية المستدعي أولًا، ويتلقى غير الأعضاء خطأ 404 لا يكشف وجود المورد. ولا يمنح دور المسؤول العام أي وصول إلى محتوى القنوات عمدًا.
منشئ القناة العامة أو الخاصة هو مالكها. يستطيع المالكون إعادة التسمية والأرشفة والدعوة (في القنوات الخاصة) وإزالة الأعضاء والإشراف على الرسائل وحذف القناة؛ ويغادر المالك بحذف القناة، لا بالتخلي عنها. تُزال الرسائل المباشرة المكررة لكل زوج: يؤدي فتح DM مع الشخص نفسه دائمًا إلى المحادثة نفسها.
المخطط الزمني
تشكّل الرسائل مخططًا زمنيًا دائمًا ومرتبًا، يُقرأ في الاتجاهين بمؤشرات قائمة على
المفاتيح (created_at مع معرّف الرسالة)، فلا تتخطى الصفحات إدخالات أو تكررها.
- منشورات آمنة عند التكرار. يقدّم العميل هوية الرسالة؛ ويصل الطلب المعاد إلى الإدخال نفسه في المخطط مرة واحدة بالضبط.
- حذف بعلامة. يمحو حذف الرسالة محتواها، لكنه يبقي إدخالها في المخطط، فلا تصبح سلاسل الردود معلقة ولا يتغير الترتيب. يحذف المؤلفون رسائلهم، ويمكن لمالكي القناة الإشراف على أي رسالة.
- التعديلات للمؤلف وحده، وتحمل علامة
editedAt. - سلاسل الردود ذات مستوى واحد. يمكن لأي رسالة جذر استضافة سلسلة؛ وتُرفض الردود على الردود. تحمل الرسائل الجذر عدد الردود مباشرة.
- التفاعلات خاصة بكل مستخدم ولكل رمز تعبيري، وتُحسب بلا تكرار.
- التثبيتات يديرها الأعضاء وتُعرض لكل قناة.
تُشفّر أسماء القنوات وأوصافها ومحتوى الرسائل عند التخزين وفق الحدود نفسها لرسائل المحادثة.
حالة عدم القراءة
تحمل كل عضوية مؤشر قراءة متزايدًا فقط. يحسب الخادم أعداد غير المقروء لكل قناة
(رسائلك لا تكون غير مقروءة أبدًا)، ويقدّم POST /api/channels/:channelId/read
المؤشر ولا يعيده إلى الخلف، فلا يستطيع عميل قديم إحياء رسائل مقروءة.
التسليم الآني
يُضاف كل تغيير في المخطط إلى تدفق الأحداث الدائم channel:<id>، ويُوزع عبر
GET /api/channels/:channelId/events (SSE). تُعاد مراجعة العضوية قبل كل تسليم، لذا
يؤدي حذف عضو إلى إغلاق تدفقه المباشر بطريقة آمنة. يبقى المخطط الزمني في SQL المرجع
الحاسم: يعيد المشترك الذي فوّت أحداثًا قراءة المخطط ببساطة؛ فالسجل وسيلة تسليم، لا
مصدر الحقيقة.
المرفقات
تُرفع الملفات أولًا (POST /api/channels/:channelId/attachments)، وتنتظر مؤقتًا في
ذاكرة ارتباط مشتركة، ثم تُرفق عند نشر الرسالة. لا يُستخدم ارتباط الرفع إلا مرة
واحدة، وتنتهي صلاحيته من دون استخدام بعد 15 دقيقة. تنتمي بايتات blob إلى الرافع
(وتدخل في حصته)، وتُعاد مراجعة عضوية القناة عند كل تنزيل.
ردود @model
يستطيع محرر الرسائل توجيه رسالة إلى نموذج. يظهر الرد فورًا كرسالة معلقة منسوبة إلى النموذج، وتكمله مهمة دائمة تعمل بدقة تحت هوية العضو المستدعي: وصوله إلى النماذج وبيانات اعتماد موفّره وتوجيهه هو، لا بيانات مالك القناة أو عضو آخر. لا يستطيع عضو أُزيل بينما إشارته في الطابور إبقاءها حية: تعيد المهمة التحقق من العضوية قبل التوليد وتسجل فشلًا ظاهرًا بدلًا منها. تظهر أعطال النموذج على الرد نفسه بدل أن تختفي في طابور.
تستخدم ردود النموذج محادثة القناة الحديثة (حتى 30 رسالة) كسياق. وتعمل كإكمالات لمرة واحدة: لم تُربط بعد أدوات المحادثة واسترجاع المعرفة والبحث على الويب بإشارات القنوات.
الحدود
| الحد | القيمة |
|---|---|
| القنوات المنشأة لكل مستخدم | 50 |
| الأعضاء لكل قناة | 200 |
| الرسائل لكل قناة | 50,000 |
| طول الرسالة | 8,000 حرف |
| المرفقات لكل رسالة | 5 × 10 MB |
| التفاعلات لكل رسالة | 200 |
القيود
- لم تُنفذ مؤشرات الحضور وحالة الكتابة.
- يتبع تصدير محتوى القنوات وسياسات الاحتفاظ بها آلية النسخ الاحتياطي للمثيل؛ ولا يوجد تصدير لكل قناة حتى الآن.
- تُرسل الإشارات تنبيهات عبر خدمة التنبيه داخل التطبيق؛ ولا يوجد بعد تفضيل تنبيه لكل قناة سوى مغادرة القناة.