Developer and self-hosted
Mattermost
الحالة: Plugin قابل للتنزيل (رمز البوت + أحداث WebSocket). تُدعَم القنوات والقنوات الخاصة والرسائل المباشرة الجماعية والرسائل المباشرة. Mattermost منصة مراسلة للفرق يمكن استضافتها ذاتيًا (mattermost.com).
التثبيت
سجل npm
openclaw plugins install @openclaw/mattermostنسخة محلية
openclaw plugins install ./path/to/local/mattermost-pluginالتفاصيل: الإضافات
الإعداد السريع
التأكد من توفر Plugin
ثبّت @openclaw/mattermost باستخدام الأمر أعلاه، ثم أعد تشغيل Gateway إذا كان قيد التشغيل بالفعل.
إنشاء بوت Mattermost
أنشئ حساب بوت في Mattermost، وانسخ رمز البوت، وأضف البوت إلى الفرق والقنوات التي ينبغي له قراءتها.
نسخ عنوان URL الأساسي
انسخ عنوان URL الأساسي لـ Mattermost (مثل https://chat.example.com). تُزال اللاحقة /api/v4 تلقائيًا.
تهيئة OpenClaw وتشغيل Gateway
الحد الأدنى من التهيئة:
{ channels: { mattermost: { enabled: true, botToken: "mm-token", baseUrl: "https://chat.example.com", dmPolicy: "pairing", }, },}بديل غير تفاعلي:
openclaw channels add --channel mattermost --bot-token <token> --http-url https://chat.example.comأوامر الشرطة المائلة الأصلية
أوامر الشرطة المائلة الأصلية اختيارية. عند تمكينها، يسجّل OpenClaw أوامر الشرطة المائلة oc_* في كل فريق يكون البوت عضوًا فيه، ويتلقى طلبات POST للاستدعاء العكسي على خادم HTTP الخاص بـ Gateway.
{ channels: { mattermost: { commands: { native: true, nativeSkills: true, callbackPath: "/api/channels/mattermost/command", // يُستخدم عندما يتعذر على Mattermost الوصول إلى Gateway مباشرةً (وكيل عكسي/عنوان URL عام). callbackUrl: "https://gateway.example.com/api/channels/mattermost/command", }, }, },}الأوامر المسجّلة: /oc_status و/oc_model و/oc_models و/oc_new و/oc_help و/oc_think و/oc_reasoning و/oc_verbose و/oc_queue. عند ضبط nativeSkills: true، تُسجّل أوامر Skills أيضًا بصيغة /oc_<skill>.
ملاحظات السلوك
- القيمة الافتراضية لكل من
nativeوnativeSkillsهي"auto"، والتي تعني التعطيل في Mattermost. اضبطهما صراحةً علىtrue. - القيمة الافتراضية لـ
callbackPathهي/api/channels/mattermost/command. - إذا حُذفت
callbackUrl، يشتق OpenClaw العنوانhttp://<gateway.customBindHost or localhost>:<gateway.port, default 18789><callbackPath>. وتعود عناوين ربط أحرف البدل (0.0.0.0و::) إلىlocalhost. - في إعدادات الحسابات المتعددة، يمكن ضبط
commandsفي المستوى الأعلى أو ضمنchannels.mattermost.accounts.<id>.commands(تتجاوز قيم الحساب حقول المستوى الأعلى). - تُترك أوامر الشرطة المائلة الحالية التي لها المشغّل نفسه وأنشأتها عمليات تكامل أخرى دون تغيير (يتخطاها التسجيل)؛ أما الأوامر التي أنشأها البوت فتُحدَّث أو يُعاد إنشاؤها عندما يتغير عنوان URL للاستدعاء العكسي.
- تُتحقق استدعاءات الأوامر العكسية باستخدام الرموز الخاصة بكل أمر التي يعيدها Mattermost عندما يسجّل OpenClaw أوامر
oc_*. - يحدّث OpenClaw تسجيل أوامر Mattermost الحالي قبل قبول كل استدعاء عكسي، ولذلك يتوقف قبول الرموز القديمة العائدة إلى أوامر شرطة مائلة محذوفة أو معاد إنشاؤها دون الحاجة إلى إعادة تشغيل Gateway.
- يفشل التحقق من الاستدعاء العكسي بصورة مغلقة إذا تعذر على واجهة API لـ Mattermost تأكيد أن الأمر لا يزال حاليًا؛ وتُخزّن عمليات التحقق الفاشلة مؤقتًا لفترة وجيزة، وتُدمج عمليات البحث المتزامنة، ويُقيَّد معدل بدء عمليات البحث الجديدة لكل أمر للحد من ضغط إعادة التشغيل.
- تفشل استدعاءات الشرطة المائلة بصورة مغلقة عند فشل التسجيل، أو اكتمال بدء التشغيل جزئيًا، أو عدم مطابقة رمز الاستدعاء العكسي للرمز المسجّل للأمر الذي جرى حله (لا يمكن لرمز صالح لأمر واحد الوصول إلى التحقق في المنبع لأمر مختلف).
- يُقرّ باستلام الاستدعاءات العكسية المقبولة برد مؤقت "جارٍ المعالجة..."؛ وتصل الإجابة الفعلية كرسالة عادية.
متطلب إمكانية الوصول
يجب أن يكون طرف الاستدعاء العكسي قابلًا للوصول من خادم Mattermost.
- لا تضبط
callbackUrlعلىlocalhostإلا إذا كان Mattermost يعمل على المضيف نفسه أو ضمن مساحة اسم الشبكة نفسها التي يعمل فيها OpenClaw. - لا تضبط
callbackUrlعلى عنوان URL الأساسي لـ Mattermost ما لم يكن ذلك العنوان يمرر/api/channels/mattermost/commandعبر وكيل عكسي إلى OpenClaw. - يمكن إجراء تحقق سريع باستخدام
curl https://<gateway-host>/api/channels/mattermost/command؛ إذ يجب أن يعيد طلب GET الاستجابة405 Method Not Allowedمن OpenClaw، وليس404.
قائمة السماح للاتصالات الصادرة من Mattermost
إذا كان الاستدعاء العكسي يستهدف عناوين خاصة أو ضمن tailnet أو داخلية، فاضبط ServiceSettings.AllowedUntrustedInternalConnections في Mattermost بحيث يتضمن مضيف أو نطاق الاستدعاء العكسي.
استخدم إدخالات المضيف أو النطاق، لا عناوين URL الكاملة.
- صحيح:
gateway.tailnet-name.ts.net - خطأ:
https://gateway.tailnet-name.ts.net
متغيرات البيئة (الحساب الافتراضي)
اضبط القيم التالية على مضيف Gateway إذا كنت تفضّل متغيرات البيئة:
MATTERMOST_BOT_TOKEN=...MATTERMOST_URL=https://chat.example.com
أوضاع الدردشة
يستجيب Mattermost تلقائيًا للرسائل المباشرة. ويتحكم chatmode في سلوك القنوات:
oncall (الافتراضي)
لا تستجب في القنوات إلا عند الإشارة إلى البوت باستخدام @.
onmessage
استجب لكل رسالة في القناة.
onchar
استجب عندما تبدأ الرسالة ببادئة تشغيل.
مثال على التهيئة:
{ channels: { mattermost: { chatmode: "onchar", oncharPrefixes: [">", "!"], // الافتراضي }, },}ملاحظات:
- يستجيب
oncharأيضًا للإشارات الصريحة باستخدام @. - يظل
channels.mattermost.requireMentionمعمولًا به، لكن يُفضَّلchatmode. وتتغلب إعداداتgroups.<channelId>.requireMentionالخاصة بكل قناة على كليهما. - بعد أن يرسل البوت ردًا ظاهرًا في سلسلة محادثة ضمن قناة، يُجاب عن الرسائل اللاحقة في السلسلة نفسها دون إشارة جديدة باستخدام @ أو بادئة
onchar، ما يضمن استمرار محادثات السلسلة متعددة الأدوار. ويُتذكّر الاشتراك لمدة 7 أيام بعد آخر رد للبوت في تلك السلسلة، ويستمر عبر عمليات إعادة تشغيل Gateway. ولا تتأثر السلاسل التي راقبها البوت فقط؛ ابدأ رسالة جديدة في المستوى الأعلى لفرض إشارة صريحة مجددًا.
سلاسل المحادثات والجلسات
استخدم channels.mattermost.replyToMode للتحكم في بقاء ردود القنوات والمجموعات داخل القناة الرئيسية أو بدء سلسلة محادثة أسفل المنشور المشغّل.
off(الافتراضي): لا ترد داخل سلسلة إلا إذا كان المنشور الوارد موجودًا بالفعل في سلسلة.first: بالنسبة إلى منشورات القنوات أو المجموعات في المستوى الأعلى، ابدأ سلسلة أسفل ذلك المنشور ووجّه المحادثة إلى جلسة مقيّدة بنطاق السلسلة.allوbatched: لهما السلوك نفسه الذي يملكهfirstفي Mattermost حاليًا، لأنه بمجرد وجود جذر لسلسلة Mattermost، تستمر الأجزاء اللاحقة والوسائط ضمن السلسلة نفسها.- القيمة الافتراضية للرسائل المباشرة هي
offحتى عند ضبطreplyToMode.
استخدم channels.mattermost.replyToModeByChatType لتجاوز الوضع في دردشات direct أو group أو channel. اضبط direct لتفعيل سلاسل المحادثات للرسائل المباشرة:
off(الافتراضي): تبقى الرسائل المباشرة دون سلاسل ضمن جلسة متواصلة واحدة.firstأوallأوbatched: تبدأ كل رسالة مباشرة في المستوى الأعلى سلسلة Mattermost تدعمها جلسة جديدة مستقلة.
{ channels: { mattermost: { replyToMode: "all", replyToModeByChatType: { direct: "first", }, }, },}ملاحظات:
- تستخدم الجلسات المقيّدة بنطاق السلسلة معرّف المنشور المشغّل بوصفه جذر السلسلة.
firstوallمتكافئان حاليًا، لأنه بمجرد وجود جذر لسلسلة Mattermost، تستمر الأجزاء اللاحقة والوسائط ضمن السلسلة نفسها.- تتقدم التجاوزات الخاصة بنوع الدردشة على
replyToMode. وبدون تجاوزdirect، تحتفظ عمليات النشر الحالية بالرسائل المباشرة المسطحة التي لا تستخدم سلاسل.
التحكم في الوصول (الرسائل المباشرة)
- الافتراضي:
channels.mattermost.dmPolicy = "pairing"(يتلقى المرسلون غير المعروفين رمز إقران). القيم الأخرى:allowlistوopenوdisabled. - وافق باستخدام:
openclaw pairing list mattermostopenclaw pairing approve mattermost <CODE>
- الرسائل المباشرة العامة:
channels.mattermost.dmPolicy="open"بالإضافة إلىchannels.mattermost.allowFrom=["*"](يفرض مخطط التهيئة حرف البدل). - يقبل
channels.mattermost.allowFromمعرّفات المستخدمين (موصى بها) وإدخالاتaccessGroup:<name>. راجع مجموعات الوصول.
القنوات (المجموعات)
- الافتراضي:
channels.mattermost.groupPolicy = "allowlist"(يتطلب الإشارة). - أضف المرسلين إلى قائمة السماح باستخدام
channels.mattermost.groupAllowFrom(يُوصى بمعرّفات المستخدمين). - يقبل
channels.mattermost.groupAllowFromإدخالاتaccessGroup:<name>. راجع مجموعات الوصول. - توجد تجاوزات الإشارة لكل قناة ضمن
channels.mattermost.groups.<channelId>.requireMention، أو ضمنchannels.mattermost.groups["*"].requireMentionللقيمة الافتراضية. - مطابقة
@usernameقابلة للتغيير ولا تُفعَّل إلا عند ضبطchannels.mattermost.dangerouslyAllowNameMatching: true. - القنوات المفتوحة:
channels.mattermost.groupPolicy="open"(يتطلب الإشارة). - ترتيب الحل:
channels.mattermost.groupPolicy، ثمchannels.defaults.groupPolicy، ثم"allowlist". - ملاحظة وقت التشغيل: إذا كان قسم
channels.mattermostمفقودًا بالكامل، يفشل وقت التشغيل بصورة مغلقة إلىgroupPolicy="allowlist"في فحوصات المجموعات (حتى إذا كانchannels.defaults.groupPolicyمضبوطًا)، ويسجّل تحذيرًا لمرة واحدة.
مثال:
{ channels: { mattermost: { groupPolicy: "open", groups: { "*": { requireMention: true }, "team-channel-id": { requireMention: false }, }, }, },}أهداف التسليم الصادر
استخدم صيغ الأهداف التالية مع openclaw message send أو Cron/Webhook:
| الهدف | يتم التسليم إلى |
|---|---|
channel:<id> |
قناة حسب المعرّف |
channel:<name> أو #channel-name |
قناة حسب الاسم، ويُبحث عنها عبر الفرق التي ينتمي إليها البوت |
user:<id> أو mattermost:<id> |
رسالة مباشرة مع ذلك المستخدم |
@username |
رسالة مباشرة (يُحل اسم المستخدم عبر واجهة API لـ Mattermost) |
تدعم عمليات الإرسال الصادرة مرفقًا واحدًا كحد أقصى لكل رسالة؛ قسّم الملفات المتعددة إلى عمليات إرسال منفصلة.
إعادة محاولة قناة الرسائل المباشرة
عندما يرسل OpenClaw إلى هدف رسالة مباشرة في Mattermost ويحتاج أولًا إلى حل القناة المباشرة، فإنه يعيد افتراضيًا محاولة حالات الفشل المؤقتة في إنشاء القناة المباشرة.
استخدم channels.mattermost.dmChannelRetry لضبط هذا السلوك عموميًا في Plugin الخاص بـ Mattermost، أو channels.mattermost.accounts.<id>.dmChannelRetry لحساب واحد. القيم الافتراضية:
{ channels: { mattermost: { dmChannelRetry: { maxRetries: 3, initialDelayMs: 1000, maxDelayMs: 10000, timeoutMs: 30000, }, }, },}ملاحظات:
- ينطبق هذا فقط على إنشاء قناة الرسائل المباشرة (
/api/v4/channels/direct)، وليس على كل استدعاء لواجهة Mattermost API. - تستخدم عمليات إعادة المحاولة تراجعًا أُسّيًا مع تفاوت عشوائي، وتنطبق على حالات الفشل المؤقتة مثل حدود المعدل، واستجابات 5xx، وأخطاء الشبكة أو انتهاء المهلة.
- تُعامل أخطاء العميل 4xx بخلاف
429على أنها دائمة ولا يُعاد تنفيذها.
البث التدفقي للمعاينة
يبث Mattermost التفكير ونشاط الأدوات ونص الرد الجزئي إلى منشور معاينة مسودة يُستكمل في موضعه عندما تصبح الإجابة النهائية آمنة للإرسال. في وضع partial، تُحدَّث المعاينة باستخدام معرّف المنشور نفسه بدلًا من إغراق القناة برسائل لكل جزء. في وضع block، تتناوب المعاينة بين النص المكتمل وكتل نشاط الأدوات، بحيث تظل الكتل السابقة ظاهرة كمنشورات مستقلة بدلًا من استبدالها بالكتلة التالية. تلغي النتائج النهائية التي تتضمن وسائط أو أخطاء تعديلات المعاينة المعلّقة، وتستخدم التسليم العادي بدلًا من إرسال منشور معاينة مؤقت عديم الفائدة.
يكون البث التدفقي للمعاينة مفعّلًا افتراضيًا في وضع partial. اضبطه عبر channels.mattermost.streaming (سلسلة تحدد الوضع، أو قيمة منطقية، أو كائن مثل { mode: "progress" }):
{ channels: { mattermost: { streaming: "partial", // off | partial | block | progress }, },}أوضاع البث التدفقي
partial(الافتراضي): منشور معاينة واحد يُعدَّل مع نمو الرد، ثم يُستكمل بالإجابة الكاملة.- يتناوب
blockفي المعاينة بين النص المكتمل وكتل نشاط الأدوات، بحيث تظل كل كتلة ظاهرة كمنشور مستقل بدلًا من استبدالها في موضعها. تتشارك تحديثات الأدوات المتوازية والمتتالية منشور نشاط الأدوات الحالي. - يعرض
progressمعاينة للحالة أثناء التوليد، ولا ينشر الإجابة النهائية إلا عند الاكتمال. - يعطّل
offالبث التدفقي للمعاينة. عند ضبطblockStreaming: true، تظل كتل المساعد المكتملة تُسلَّم كردود كتل عادية (منشورات منفصلة) بدلًا من منشور نهائي واحد مدمج.
ملاحظات حول سلوك البث التدفقي
- إذا تعذّر استكمال البث التدفقي في موضعه (مثلًا إذا حُذف المنشور أثناء البث)، يعود OpenClaw إلى إرسال منشور نهائي جديد حتى لا يضيع الرد مطلقًا.
- تُحجب الحمولات التي تحتوي على التفكير فقط من منشورات القناة، بما في ذلك النص الذي يصل على هيئة اقتباس كتلي
> Thinking. اضبط/reasoning onلرؤية التفكير في الواجهات الأخرى؛ بينما يحتفظ منشور Mattermost النهائي بالإجابة فقط. - راجع البث التدفقي للاطلاع على مصفوفة ربط القنوات.
التفاعلات (أداة الرسائل)
- استخدم
message action=reactمعchannel=mattermost. - يمثّل
messageIdمعرّف منشور Mattermost. - يقبل
emojiأسماءً مثلthumbsupأو:+1:(النقطتان الرأسيتان اختياريتان). - اضبط
remove=true(قيمة منطقية) لإزالة تفاعل. - تُمرَّر أحداث إضافة التفاعل وإزالته كأحداث نظام إلى جلسة الوكيل الموجّهة، مع خضوعها لفحوصات سياسة الرسائل المباشرة/المجموعات نفسها المطبقة على الرسائل.
أمثلة:
message action=react channel=mattermost target=channel:<channelId> messageId=<postId> emoji=thumbsupmessage action=react channel=mattermost target=channel:<channelId> messageId=<postId> emoji=thumbsup remove=trueالإعداد:
channels.mattermost.actions.reactions: تفعيل/تعطيل إجراءات التفاعل (القيمة الافتراضية true).- تجاوز خاص بكل حساب:
channels.mattermost.accounts.<id>.actions.reactions.
الأزرار التفاعلية (أداة الرسائل)
أرسل رسائل تحتوي على أزرار قابلة للنقر. عندما ينقر مستخدم على زر، يتلقى الوكيل الاختيار ويمكنه الرد.
تأتي الأزرار من حمولة presentation الدلالية (في ردود الوكيل العادية وفي message action=send). يعرض OpenClaw أزرار القيم كأزرار Mattermost تفاعلية، ويُبقي أزرار عناوين URL ظاهرة في نص الرسالة، ويحوّل قوائم التحديد إلى نص مقروء.
message action=send channel=mattermost target=channel:<channelId> presentation={"blocks":[{"type":"buttons","buttons":[{"label":"Yes","value":"yes"},{"label":"No","value":"no"}]}]}حقول زر العرض:
labelstringrequiredتسمية العرض (الاسم البديل: text).
valuestringالقيمة التي تُعاد عند النقر، وتُستخدم معرّفًا للإجراء (الأسماء البديلة: callback_data وcallbackData). مطلوبة للزر القابل للنقر ما لم يكن url مضبوطًا.
urlstringزر رابط؛ يُعرض كنص label: url في متن الرسالة بدلًا من زر تفاعلي.
style"primary" | "secondary" | "success" | "danger"نمط الزر. يطبّق Mattermost النمط الافتراضي على القيم التي لا يدعمها.
للإعلان عن دعم الأزرار في مطالبة نظام الوكيل، أضف inlineButtons إلى إمكانات القناة:
{ channels: { mattermost: { capabilities: ["inlineButtons"], }, },}عندما ينقر مستخدم على زر:
فحص الوصول
يجب أن يجتاز الناقر فحوصات سياسة الرسائل المباشرة/المجموعات نفسها المطبقة على مُرسل الرسالة؛ وتتلقى النقرات غير المصرح بها إشعارًا مؤقتًا وتُتجاهل.
استبدال الأزرار بالتأكيد
تُستبدل جميع الأزرار بسطر تأكيد (مثلًا: "✓ تم تحديد نعم بواسطة @user").
تلقي الوكيل للاختيار
يتلقى الوكيل الاختيار كرسالة واردة (بالإضافة إلى حدث نظام) ثم يرد.
ملاحظات التنفيذ
- تستخدم استدعاءات رجوع الأزرار التحقق باستخدام HMAC-SHA256 (تلقائي، ولا يتطلب إعدادًا).
- تُستبدل كتلة المرفق بالكامل عند النقر، لذا تُزال جميع الأزرار معًا، ولا يمكن إزالتها جزئيًا.
- تُعقَّم معرّفات الإجراءات التي تحتوي على شرطات أو شرطات سفلية تلقائيًا (بسبب قيود توجيه Mattermost).
- تُرفض النقرات التي لا يطابق فيها
action_idإجراءً في المنشور الأصلي بالرمز403("إجراء غير معروف").
الإعداد وإمكانية الوصول
channels.mattermost.capabilities: مصفوفة من سلاسل الإمكانات. أضف"inlineButtons"لتفعيل وصف أداة الأزرار في مطالبة نظام الوكيل.channels.mattermost.interactions.callbackBaseUrl: عنوان URL أساسي خارجي اختياري لاستدعاءات رجوع الأزرار (مثلًاhttps://gateway.example.com). استخدمه عندما يتعذر على Mattermost الوصول مباشرةً إلى Gateway عند مضيف الربط الخاص به.- في إعدادات الحسابات المتعددة، يمكنك أيضًا ضبط الحقل نفسه ضمن
channels.mattermost.accounts.<id>.interactions.callbackBaseUrl. - إذا حُذف
interactions.callbackBaseUrl، يشتق OpenClaw عنوان URL لاستدعاء الرجوع منgateway.customBindHost+gateway.port(القيمة الافتراضية 18789)، ثم يعود إلىhttp://localhost:<port>. مسار استدعاء الرجوع هو/mattermost/interactions/<accountId>. - قاعدة إمكانية الوصول: يجب أن يكون عنوان URL لاستدعاء رجوع الزر قابلًا للوصول من خادم Mattermost. لا يعمل
localhostإلا عندما يعمل Mattermost وOpenClaw على المضيف/نطاق اسم الشبكة نفسه. channels.mattermost.interactions.allowedSourceIps: قائمة سماح لعناوين IP المصدر الخاصة باستدعاءات رجوع الأزرار. بدونها، لا تُقبل سوى مصادر local loopback (127.0.0.1و::1)، لذا يجب إضافة خادم Mattermost البعيد إلى قائمة السماح هنا وإلا ستُرفض نقراته بالرمز403. عند العمل خلف وكيل عكسي، اضبط أيضًاgateway.trustedProxiesحتى يُشتق عنوان IP الحقيقي للعميل من الترويسات المُمرَّرة.- إذا كان هدف استدعاء الرجوع خاصًا أو ضمن شبكة tailnet أو داخليًا، فأضف مضيفه/نطاقه إلى
ServiceSettings.AllowedUntrustedInternalConnectionsفي Mattermost.
التكامل المباشر مع API (البرامج النصية الخارجية)
يمكن للبرامج النصية الخارجية وWebhooks نشر الأزرار مباشرةً عبر Mattermost REST API بدلًا من المرور عبر أداة message الخاصة بالوكيل. استخدم buildButtonAttachments() من Plugin متى أمكن؛ وإذا كنت تنشر JSON خامًا، فاتبع القواعد التالية:
بنية الحمولة:
{ channel_id: "<channelId>", message: "Choose an option:", props: { attachments: [ { actions: [ { id: "mybutton01", // alphanumeric only - see below type: "button", // required, or clicks are silently ignored name: "Approve", // display label style: "primary", // optional: "default", "primary", "danger" integration: { url: "https://gateway.example.com/mattermost/interactions/default", context: { action_id: "mybutton01", // must match button id action: "approve", // ... any custom fields ... _token: "<hmac>", // see HMAC section below }, }, }, ], }, ], },}إنشاء رمز HMAC
يتحقق Gateway من نقرات الأزرار باستخدام HMAC-SHA256. يجب أن تُنشئ البرامج النصية الخارجية رموزًا تطابق منطق التحقق في Gateway:
اشتقاق السر من رمز البوت
HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)، بترميز سداسي عشري.
إنشاء كائن السياق
أنشئ كائن السياق بجميع الحقول باستثناء _token.
إجراء التسلسل بمفاتيح مرتبة
أجرِ التسلسل باستخدام مفاتيح مرتبة تكراريًا ومن دون مسافات (إذ يوحّد Gateway الكائنات المتداخلة أيضًا وينتج JSON مضغوطًا).
توقيع الحمولة
HMAC-SHA256(key=secret, data=serializedContext)
إضافة الرمز
أضف الملخّص السداسي العشري الناتج كقيمة _token في السياق.
مثال بلغة Python:
secret = hmac.new( b"openclaw-mattermost-interactions", bot_token.encode(), hashlib.sha256).hexdigest() ctx = {"action_id": "mybutton01", "action": "approve"}payload = json.dumps(ctx, sort_keys=True, separators=(",", ":"))token = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest() context = {**ctx, "_token": token}أخطاء HMAC الشائعة
- تضيف
json.dumpsفي Python مسافات افتراضيًا ({"key": "val"}). استخدمseparators=(",", ":")لمطابقة المخرجات المضغوطة في JavaScript ({"key":"val"}). - وقّع دائمًا جميع حقول السياق (باستثناء
_token). يزيل Gateway الحقل_tokenثم يوقّع كل ما تبقى. يؤدي توقيع مجموعة فرعية إلى فشل التحقق بصمت. - استخدم
sort_keys=True؛ إذ يرتب Gateway المفاتيح قبل التوقيع، وقد يعيد Mattermost ترتيب حقول السياق عند تخزين الحمولة. - اشتق السر من رمز البوت (بصورة حتمية)، وليس من بايتات عشوائية. يجب أن يكون السر متماثلًا في العملية التي تنشئ الأزرار وفي Gateway الذي يتحقق منها.
محوّل الدليل
يتضمن Plugin الخاص بـ Mattermost محوّل دليل يحل أسماء القنوات والمستخدمين عبر Mattermost API. يتيح هذا استخدام الوجهات #channel-name و@username في openclaw message send وعمليات التسليم عبر Cron/Webhook.
لا يلزم أي إعداد؛ إذ يستخدم المحوّل رمز البوت من إعداد الحساب.
الحسابات المتعددة
يدعم Mattermost حسابات متعددة ضمن channels.mattermost.accounts:
{ channels: { mattermost: { accounts: { default: { name: "الأساسي", botToken: "mm-token", baseUrl: "https://chat.example.com" }, alerts: { name: "التنبيهات", botToken: "mm-token-2", baseUrl: "https://alerts.example.com" }, }, }, },}تتجاوز قيم الحساب الحقول ذات المستوى الأعلى؛ ويحدد channels.mattermost.defaultAccount الحساب المستخدم عند عدم تحديد حساب.
استكشاف الأخطاء وإصلاحها
لا توجد ردود في القنوات
تأكد من وجود البوت في القناة، ثم اذكره (oncall)، أو استخدم بادئة تشغيل (onchar)، أو عيّن chatmode: "onmessage".
أخطاء المصادقة أو الحسابات المتعددة
- تحقق من رمز البوت وعنوان URL الأساسي ومن تمكين الحساب.
- مشكلات الحسابات المتعددة: تنطبق متغيرات البيئة على حساب
defaultفقط. - تحتاج مضيفات Mattermost الخاصة أو الموجودة على شبكة LAN إلى
network.dangerouslyAllowPrivateNetwork: true(يحظر واقي SSRF عناوين IP الخاصة افتراضيًا).
فشل أوامر الشرطة المائلة الأصلية
Unauthorized: invalid command token.: لم يقبل OpenClaw رمز الاستدعاء. تشمل الأسباب المعتادة:- فشل تسجيل أمر الشرطة المائلة أو اكتماله جزئيًا فقط عند بدء التشغيل
- وصول الاستدعاء إلى Gateway أو الحساب الخطأ
- لا يزال Mattermost يحتفظ بأوامر قديمة تشير إلى وجهة استدعاء سابقة
- أُعيد تشغيل Gateway دون إعادة تفعيل أوامر الشرطة المائلة
- إذا توقفت أوامر الشرطة المائلة الأصلية عن العمل، فتحقق من السجلات بحثًا عن
mattermost: failed to register slash commandsأوmattermost: native slash commands enabled but no commands could be registered. - إذا حُذف
callbackUrlوحذرت السجلات من أن الاستدعاء حُلّ إلى عنوان local loopback مثلhttp://localhost:18789/...، فمن المحتمل ألا يكون عنوان URL هذا قابلًا للوصول إلا عندما يعمل Mattermost على المضيف أو نطاق أسماء الشبكة نفسه الذي يعمل عليه OpenClaw. عيّن بدلًا منهcommands.callbackUrlصريحًا يمكن الوصول إليه خارجيًا.
مشكلات الأزرار
- تظهر الأزرار كمربعات بيضاء أو لا تظهر إطلاقًا: بيانات الزر غير صحيحة البنية. يحتاج كل زر عرض إلى
labelوvalue(تُستبعد الأزرار التي ينقصها أي منهما). - تظهر الأزرار، لكن النقر عليها لا يؤدي إلى شيء: تحقق من إمكانية وصول خادم Mattermost إلى Gateway، ومن تضمين عنوان IP لخادم Mattermost في
channels.mattermost.interactions.allowedSourceIps(لا يُقبل سوى local loopback من دونه)، ومن أنServiceSettings.AllowedUntrustedInternalConnectionsيتضمن مضيف الاستدعاء للوجهات الخاصة. - تُرجع الأزرار الخطأ 404 عند النقر: من المرجح أن يحتوي
idالخاص بالزر على شرطات أو شرطات سفلية. يتعطل موجّه إجراءات Mattermost عند استخدام معرّفات تحتوي على محارف غير أبجدية رقمية. استخدم[a-zA-Z0-9]فقط. - تسجل سجلات Gateway الرسالة
rejected callback source: جاءت النقرة من عنوان IP خارجinteractions.allowedSourceIps. أضف خادم Mattermost أو نقطة الدخول إلى قائمة السماح، وعيّنgateway.trustedProxiesعند العمل خلف وكيل عكسي. - تسجل سجلات Gateway الرسالة
invalid _token: عدم تطابق HMAC. تحقق من توقيع جميع حقول السياق (لا مجموعة فرعية منها)، واستخدام مفاتيح مرتبة، واستخدام JSON مضغوط (من دون مسافات). راجع قسم HMAC أعلاه. - تسجل سجلات Gateway الرسالة
missing _token in context: الحقل_tokenغير موجود في سياق الزر. تأكد من تضمينه عند إنشاء حمولة التكامل. - يرفض Gateway النقرة بالرسالة
Unknown action: لا يطابقcontext.action_idأيidلإجراء في المنشور. عيّنهما كليهما على القيمة المنقحة نفسها. - لا يعرض الوكيل أزرارًا: أضف
capabilities: ["inlineButtons"]إلى إعدادات قناة Mattermost.
ذو صلة
- توجيه القنوات - توجيه الجلسات للرسائل
- نظرة عامة على القنوات - جميع القنوات المدعومة
- المجموعات - سلوك المحادثات الجماعية والتحكم بالوصول عبر الإشارة
- الاقتران - مصادقة الرسائل المباشرة وتدفق الاقتران
- الأمان - نموذج الوصول والتقوية