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 البرمجية. - تستخدم إعادة المحاولة تراجعًا أُسّيًا مع تفاوت عشوائي، وتنطبق على الإخفاقات العابرة مثل حدود المعدل، واستجابات 5xx، وأخطاء الشبكة أو انتهاء المهلة.
- تُعامل أخطاء العميل 4xx بخلاف
429على أنها دائمة ولا تُعاد محاولتها.
البث التدفقي للمعاينة
يبث Mattermost التفكير ونشاط الأدوات ونص الرد الجزئي إلى منشور معاينة مسودة يُستكمل في موضعه عندما تصبح الإجابة النهائية آمنة للإرسال. في وضع partial، تُحدَّث المعاينة باستخدام معرّف المنشور نفسه بدلًا من إغراق القناة برسائل لكل جزء. وفي وضع block، تتناوب المعاينة بين النص المكتمل وكتل نشاط الأدوات، بحيث تظل الكتل السابقة ظاهرة كمنشورات مستقلة بدلًا من استبدالها بالكتلة التالية. تلغي النتائج النهائية للوسائط/الأخطاء تعديلات المعاينة المعلّقة وتستخدم التسليم العادي بدلًا من إرسال منشور معاينة مؤقت.
يكون البث التدفقي للمعاينة مفعّلًا افتراضيًا في وضع partial. اضبطه عبر channels.mattermost.streaming.mode (يرحّل openclaw doctor --fix قيم streaming العددية/المنطقية القديمة):
{ channels: { mattermost: { streaming: { mode: "partial" }, // off | partial | block | progress }, },}أوضاع البث التدفقي
partial(الافتراضي): منشور معاينة واحد يُعدَّل مع نمو الرد، ثم يُستكمل بالإجابة الكاملة.- يُناوب
blockالمعاينة بين النص المكتمل وكتل نشاط الأدوات، بحيث تظل كل كتلة ظاهرة كمنشور مستقل بدلًا من استبدالها في موضعها. تشترك تحديثات الأدوات المتوازية والمتتالية في منشور نشاط الأدوات الحالي. - يعرض
progressمعاينة للحالة أثناء الإنشاء، ولا ينشر الإجابة النهائية إلا عند الاكتمال. - يعطّل
offالبث التدفقي للمعاينة. معstreaming.block.enabled: 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":"نعم","value":"yes"},{"label":"لا","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 المصدر لاستدعاءات الأزرار الراجعة. من دونها، لا تُقبل إلا المصادر المحلية (127.0.0.1،::1)؛ لذلك يجب إضافة خادم Mattermost البعيد إلى قائمة السماح هنا، وإلا تُرفض نقراته باستخدام403. وعند العمل خلف وكيل عكسي، اضبط أيضًاgateway.trustedProxiesكي يُشتق عنوان IP الحقيقي للعميل من الترويسات المُمرّرة.- إذا كان هدف الاستدعاء الراجع خاصًا/ضمن شبكة tailnet/داخليًا، فأضف مضيفه/نطاقه إلى
ServiceSettings.AllowedUntrustedInternalConnectionsفي Mattermost.
التكامل المباشر مع واجهة API (البرامج النصية الخارجية)
يمكن للبرامج النصية الخارجية وWebhooks نشر الأزرار مباشرةً عبر واجهة Mattermost REST API بدلًا من المرور عبر أداة message الخاصة بالوكيل. يُفضَّل استخدام أداة message الخاصة بـ OpenClaw. للتكاملات المباشرة، استورد buildButtonAttachments من @openclaw/mattermost/api.js؛ وإذا كنت تنشر JSON خامًا، فاتبع هذه القواعد:
بنية الحمولة:
{ channel_id: "<channelId>", message: "اختر خيارًا:", props: { attachments: [ { actions: [ { id: "mybutton01", // أحرف وأرقام فقط - انظر أدناه type: "button", // مطلوب، وإلا تُتجاهل النقرات بصمت name: "موافقة", // تسمية العرض style: "primary", // اختياري: "default"، "primary"، "danger" integration: { url: "https://gateway.example.com/mattermost/interactions/default", context: { action_id: "mybutton01", // يجب أن يطابق معرّف الزر action: "approve", // ... أي حقول مخصصة ... _token: "<hmac>", // راجع قسم HMAC أدناه }, }, }, ], }, ], },}إنشاء رمز 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: "Primary", botToken: "mm-token", baseUrl: "https://chat.example.com" }, alerts: { name: "Alerts", botToken: "mm-token-2", baseUrl: "https://alerts.example.com" }, }, }, },}تتجاوز قيم الحساب الحقول ذات المستوى الأعلى؛ ويحدد channels.mattermost.defaultAccount الحساب المستخدم عند عدم تحديد حساب.
استكشاف الأخطاء وإصلاحها
لا توجد ردود في القنوات
تأكد من وجود البوت في القناة والإشارة إليه (oncall)، أو استخدم بادئة تشغيل (onchar)، أو عيّن chatmode: "onmessage".
أخطاء المصادقة أو الحسابات المتعددة
- تحقق من رمز البوت وعنوان URL الأساسي وما إذا كان الحساب مفعّلًا.
- مشكلات الحسابات المتعددة: لا تنطبق متغيرات البيئة إلا على حساب
default. - تحتاج مضيفات Mattermost الخاصة أو الموجودة على الشبكة المحلية إلى
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وحذرت السجلات من أن معاودة الاتصال تحولت إلى عنوان URL للاسترجاع الحلقي مثلhttp://localhost:18789/...، فمن المرجح ألا يكون عنوان URL هذا قابلًا للوصول إلا عندما يعمل Mattermost على المضيف أو نطاق الشبكة نفسه الذي يعمل عليه OpenClaw. عيّن بدلًا منهcommands.callbackUrlصريحًا يمكن الوصول إليه خارجيًا.
مشكلات الأزرار
- تظهر الأزرار كمربعات بيضاء أو لا تظهر إطلاقًا: بيانات الزر غير صحيحة. يحتاج كل زر عرض إلى
labelوvalue(تُستبعد الأزرار التي تفتقد أيًا منهما). - تُعرض الأزرار لكن النقرات لا تفعل شيئًا: تحقق من إمكانية وصول خادم Mattermost إلى Gateway، ومن تضمين عنوان IP لخادم Mattermost في
channels.mattermost.interactions.allowedSourceIps(لا يُقبل من دونه إلا الاسترجاع الحلقي)، ومن أن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.
ذو صلة
- توجيه القنوات - توجيه جلسات الرسائل
- نظرة عامة على القنوات - جميع القنوات المدعومة
- المجموعات - سلوك المحادثات الجماعية والتحكم عبر الإشارات
- الاقتران - مصادقة الرسائل المباشرة وتدفق الاقتران
- الأمان - نموذج الوصول والتقوية