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ها
راهاندازی سریع
از در دسترس بودن 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 هنگام ثبت دستورهای
oc_*توسط OpenClaw برمیگرداند، اعتبارسنجی میشوند. - OpenClaw پیش از پذیرش هر بازخوانی، ثبت فعلی دستور Mattermost را تازهسازی میکند؛ بنابراین توکنهای قدیمی دستورهای اسلش حذفشده یا بازتولیدشده بدون راهاندازی مجدد Gateway دیگر پذیرفته نمیشوند.
- اگر API مربوط به Mattermost نتواند تأیید کند که دستور همچنان فعلی است، اعتبارسنجی بهصورت بسته شکست میخورد؛ اعتبارسنجیهای ناموفق برای مدت کوتاهی در حافظهٔ نهان ذخیره میشوند، جستوجوهای همزمان ادغام میشوند و شروع جستوجوهای تازه برای هر دستور با محدودیت نرخ انجام میشود تا فشار بازپخش محدود بماند.
- هنگامی که ثبت ناموفق باشد، راهاندازی ناقص بوده باشد یا توکن بازخوانی با توکن ثبتشدهٔ دستور حلشده مطابقت نداشته باشد، بازخوانیهای اسلش بهصورت بسته شکست میخورند (توکنی که برای یک دستور معتبر است، نمیتواند برای دستور دیگری به اعتبارسنجی بالادستی برسد).
- بازخوانیهای پذیرفتهشده با یک پاسخ موقت «در حال پردازش...» تأیید میشوند؛ پاسخ واقعی بهصورت یک پیام عادی میرسد.
الزام دسترسیپذیری
نقطهٔ پایانی بازخوانی باید از سرور Mattermost قابلدسترسی باشد.
- مگر اینکه Mattermost در همان میزبان/فضای نام شبکهٔ OpenClaw اجرا شود،
callbackUrlرا رویlocalhostتنظیم نکنید. - مگر اینکه نشانی URL پایهٔ Mattermost مسیر
/api/channels/mattermost/commandرا با پروکسی معکوس به OpenClaw هدایت کند،callbackUrlرا روی آن نشانی تنظیم نکنید. - یک بررسی سریع
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.implicitMentions.threadParticipation: falseرا تنظیم کنید. بازنویسیهای حساب ازchannels.mattermost.accounts.<id>.implicitMentionsاستفاده میکنند. Mattermost در حال حاضر واقعیتهایreplyToBotیاquotedBotرا تولید نمیکند، بنابراین این پرچمها در اینجا اثری ندارند.
رشتهها و نشستها
برای کنترل اینکه پاسخهای کانال و گروه در کانال اصلی بمانند یا زیر پست محرک یک رشته آغاز کنند، از channels.mattermost.replyToMode استفاده کنید.
off(پیشفرض): فقط زمانی در یک رشته پاسخ دهید که پست ورودی از قبل در یک رشته باشد.first: برای پستهای سطح بالای کانال/گروه، زیر آن پست یک رشته آغاز کنید و گفتوگو را به یک نشست مختص رشته هدایت کنید.allوbatched: امروزه برای Mattermost رفتاری مشابهfirstدارند، زیرا پس از ایجاد ریشهٔ رشته در Mattermost، بخشهای بعدی و رسانهها در همان رشته ادامه پیدا میکنند.- پیامهای مستقیم حتی وقتی
replyToModeتنظیم شده باشد، بهطور پیشفرض ازoffاستفاده میکنند.
برای بازنویسی حالت گفتوگوهای direct، group یا channel از channels.mattermost.replyToModeByChatType استفاده کنید. برای وارد کردن پیامهای مستقیم به رشتهبندی، 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 ارسال میکند و ابتدا باید کانال مستقیم را پیدا کند، بهطور پیشفرض خطاهای موقت ایجاد کانال مستقیم را دوباره امتحان میکند.
برای تنظیم سراسری این رفتار در Plugin مربوط به Mattermost از channels.mattermost.dmChannelRetry و برای یک حساب از channels.mattermost.accounts.<id>.dmChannelRetry استفاده کنید. مقادیر پیشفرض:
{ channels: { mattermost: { dmChannelRetry: { maxRetries: 3, initialDelayMs: 1000, maxDelayMs: 10000, timeoutMs: 30000, }, }, },}نکتهها:
- این تنظیم فقط برای ایجاد کانال پیام مستقیم (
/api/v4/channels/direct) اعمال میشود، نه برای تمام فراخوانیهای API در Mattermost. - تلاشهای مجدد از عقبنشینی نمایی همراه با نوسان تصادفی استفاده میکنند و برای خطاهای موقتی مانند محدودیت نرخ، پاسخهای 5xx و خطاهای شبکه یا پایان مهلت اعمال میشوند.
- خطاهای سمت کارخواه 4xx بهجز
429دائمی در نظر گرفته میشوند و دوباره امتحان نمیشوند.
استریم پیشنمایش
Mattermost فرایند تفکر، فعالیت ابزار و متن جزئی پاسخ را در یک پست پیشنویس پیشنمایش استریم میکند که وقتی ارسال پاسخ نهایی ایمن باشد، در همان محل نهایی میشود. در حالت partial، پیشنمایش بهجای پر کردن کانال با پیامهای جداگانه برای هر قطعه، روی همان شناسه پست بهروزرسانی میشود. در حالت block، پیشنمایش بین متن تکمیلشده و بلوکهای فعالیت ابزار جابهجا میشود؛ بنابراین بلوکهای قبلی بهجای بازنویسیشدن با بلوک بعدی، بهصورت پستهای مستقل قابلمشاهده باقی میمانند. خروجیهای نهایی رسانهای یا خطا، ویرایشهای در انتظار پیشنمایش را لغو میکنند و بهجای نهاییکردن یک پست پیشنمایش بلااستفاده، از تحویل عادی استفاده میکنند.
استریم پیشنمایش در حالت partial بهطور پیشفرض فعال است. آن را از طریق channels.mattermost.streaming.mode پیکربندی کنید (مقادیر اسکالر/بولی قدیمی streaming توسط openclaw doctor --fix مهاجرت داده میشوند):
{ 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":"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"], }, },}وقتی کاربری روی یک دکمه کلیک میکند:
بررسی دسترسی
کلیککننده باید همان بررسیهای سیاست پیام مستقیم/گروه را که برای فرستنده پیام اعمال میشود با موفقیت پشت سر بگذارد؛ کلیکهای غیرمجاز یک اعلان موقت دریافت میکنند و نادیده گرفته میشوند.
جایگزینی دکمهها با تأییدیه
همه دکمهها با یک خط تأیید جایگزین میشوند (برای مثال، "✓ Yes selected by @user").
عامل گزینه انتخابشده را دریافت میکند
عامل گزینه انتخابشده را بهصورت یک پیام ورودی (بههمراه یک رویداد سیستمی) دریافت و پاسخ میدهد.
نکتههای پیادهسازی
- فراخوانهای بازگشتی دکمه از اعتبارسنجی HMAC-SHA256 استفاده میکنند (خودکار است و به پیکربندی نیاز ندارد).
- هنگام کلیک، کل بلوک پیوست جایگزین میشود؛ بنابراین همه دکمهها با هم حذف میشوند و حذف جزئی ممکن نیست.
- شناسههای کنش حاوی خط تیره یا زیرخط بهطور خودکار پاکسازی میشوند (محدودیت مسیریابی Mattermost).
- کلیکهایی که
action_idآنها با کنشی در پست اصلی مطابقت ندارد، با403("کنش ناشناخته") رد میشوند.
پیکربندی و دسترسپذیری
channels.mattermost.capabilities: آرایهای از رشتههای قابلیت. برای فعالکردن توضیح ابزار دکمهها در اعلان سیستمی عامل،"inlineButtons"را اضافه کنید.channels.mattermost.interactions.callbackBaseUrl: نشانی پایه خارجی اختیاری برای فراخوانهای بازگشتی دکمه (برای مثالhttps://gateway.example.com). وقتی Mattermost نمیتواند مستقیماً در میزبان اتصال Gateway به آن دسترسی داشته باشد، از این گزینه استفاده کنید.- در پیکربندیهای چندحسابی، میتوانید همین فیلد را در
channels.mattermost.accounts.<id>.interactions.callbackBaseUrlنیز تنظیم کنید. - اگر
interactions.callbackBaseUrlحذف شده باشد، OpenClaw نشانی فراخوان بازگشتی را ازgateway.customBindHost+gateway.port(پیشفرض 18789) استخراج میکند و سپس بهhttp://localhost:<port>بازمیگردد. مسیر فراخوان بازگشتی/mattermost/interactions/<accountId>است. - قاعده دسترسپذیری: نشانی فراخوان بازگشتی دکمه باید از سرور Mattermost قابلدسترسی باشد.
localhostفقط زمانی کار میکند که Mattermost و OpenClaw روی یک میزبان/فضای نام شبکه اجرا شوند. channels.mattermost.interactions.allowedSourceIps: فهرست مجاز IP مبدأ برای فراخوانهای بازگشتی دکمه. بدون آن، فقط مبدأهای حلقه محلی (127.0.0.1،::1) پذیرفته میشوند؛ بنابراین سرور راهدور Mattermost باید در اینجا مجاز شود، وگرنه کلیکهای آن با403رد میشوند. پشت یک پراکسی معکوس،gateway.trustedProxiesرا نیز تنظیم کنید تا IP واقعی کارخواه از سرآیندهای هدایتشده استخراج شود.- اگر مقصد فراخوان بازگشتی شما خصوصی/tailnet/داخلی است، میزبان/دامنه آن را به
ServiceSettings.AllowedUntrustedInternalConnectionsدر Mattermost اضافه کنید.
یکپارچهسازی مستقیم API (اسکریپتهای خارجی)
اسکریپتهای خارجی و Webhookها میتوانند بهجای عبور از ابزار message عامل، دکمهها را مستقیماً از طریق REST API مربوط به Mattermost ارسال کنند. ابزار message در OpenClaw را ترجیح دهید. برای یکپارچهسازی مستقیم، buildButtonAttachments را از @openclaw/mattermost/api.js وارد کنید؛ اگر 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"}). برای مطابقت با خروجی فشردهٔ JavaScript ({"key":"val"}) ازseparators=(",", ":")استفاده کنید.- همیشه همهٔ فیلدهای context را (بهجز
_token) امضا کنید. Gateway ابتدا_tokenرا حذف میکند و سپس تمام موارد باقیمانده را امضا میکند. امضای زیرمجموعهای از فیلدها باعث شکست بیصدای تأیید میشود. - از
sort_keys=Trueاستفاده کنید؛ Gateway پیش از امضا کلیدها را مرتب میکند و Mattermost ممکن است هنگام ذخیرهسازی payload ترتیب فیلدهای context را تغییر دهد. - secret را از bot token بهصورت قطعی استخراج کنید، نه از بایتهای تصادفی. secret باید در فرایندی که دکمهها را ایجاد میکند و Gatewayای که تأیید را انجام میدهد یکسان باشد.
آداپتور دایرکتوری
Plugin مربوط به Mattermost شامل یک آداپتور دایرکتوری است که نام کانالها و کاربران را از طریق API مربوط به Mattermost تفکیک میکند. این قابلیت، استفاده از مقصدهای #channel-name و @username را در تحویلهای openclaw message send و Cron/Webhook ممکن میسازد.
هیچ پیکربندیای لازم نیست؛ آداپتور از bot token موجود در پیکربندی حساب استفاده میکند.
چندحسابی
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 تعیین میکند وقتی حسابی مشخص نشده است، از کدام حساب استفاده شود.
عیبیابی
پاسخی در کانالها دریافت نمیشود
مطمئن شوید bot در کانال حضور دارد و به آن اشاره کنید (oncall)، از یک پیشوند راهانداز استفاده کنید (onchar)، یا chatmode: "onmessage" را تنظیم کنید.
خطاهای احراز هویت یا چندحسابی
- bot token، نشانی پایه و فعالبودن حساب را بررسی کنید.
- مشکلات چندحسابی: متغیرهای محیطی فقط برای حساب
defaultاعمال میشوند. - میزبانهای خصوصی/LAN مربوط به Mattermost به
network.dangerouslyAllowPrivateNetwork: trueنیاز دارند (محافظ SSRF بهطور پیشفرض IPهای خصوصی را مسدود میکند).
دستورهای بومی اسلش ناموفقاند
Unauthorized: invalid command token.: OpenClaw توکن callback را نپذیرفت. دلایل معمول:- ثبت دستور اسلش هنگام راهاندازی ناموفق بوده یا فقط بخشی از آن تکمیل شده است
- callback به Gateway یا حساب نادرست میرسد
- Mattermost همچنان دستورهای قدیمیای دارد که به مقصد callback قبلی اشاره میکنند
- Gateway بدون فعالسازی دوبارهٔ دستورهای اسلش راهاندازی مجدد شده است
- اگر دستورهای بومی اسلش از کار افتادند، گزارشها را برای
mattermost: failed to register slash commandsیاmattermost: native slash commands enabled but no commands could be registeredبررسی کنید. - اگر
callbackUrlحذف شده باشد و گزارشها هشدار دهند که callback به یک URL حلقهٔ محلی مانندhttp://localhost:18789/...تفکیک شده است، احتمالاً آن URL فقط زمانی قابل دسترسی است که Mattermost در همان میزبان/فضای نام شبکهٔ OpenClaw اجرا شود. بهجای آن، یکcommands.callbackUrlصریح و قابل دسترسی از بیرون تنظیم کنید.
مشکلات دکمهها
- دکمهها بهشکل کادرهای سفید نمایش داده میشوند یا اصلاً نمایش داده نمیشوند: دادهٔ دکمه نادرست است. هر دکمهٔ نمایشی به یک
labelو یکvalueنیاز دارد (دکمههایی که یکی از این دو را نداشته باشند حذف میشوند). - دکمهها نمایش داده میشوند، اما کلیکها کاری انجام نمیدهند: بررسی کنید Gateway از سرور Mattermost قابل دسترسی باشد، IP سرور Mattermost در
channels.mattermost.interactions.allowedSourceIpsگنجانده شده باشد (بدون آن فقط حلقهٔ محلی پذیرفته میشود) وServiceSettings.AllowedUntrustedInternalConnectionsبرای مقصدهای خصوصی شامل میزبان callback باشد. - دکمهها هنگام کلیک خطای 404 برمیگردانند: احتمالاً
idدکمه حاوی خط تیره یا زیرخط است. مسیریاب action در Mattermost با شناسههای غیرالفباییعددی دچار اختلال میشود. فقط از[a-zA-Z0-9]استفاده کنید. - Gateway پیام
rejected callback sourceرا ثبت میکند: کلیک از IPای خارج ازinteractions.allowedSourceIpsآمده است. سرور Mattermost یا ingress خود را به فهرست مجاز اضافه کنید و در پشت reverse proxy،gateway.trustedProxiesرا تنظیم کنید. - Gateway پیام
invalid _tokenرا ثبت میکند: HMAC مطابقت ندارد. بررسی کنید که همهٔ فیلدهای context را امضا میکنید (نه زیرمجموعهای از آنها)، کلیدهای مرتبشده را بهکار میبرید و از JSON فشرده (بدون فاصله) استفاده میکنید. بخش HMAC در بالا را ببینید. - Gateway پیام
missing _token in contextرا ثبت میکند: فیلد_tokenدر context دکمه وجود ندارد. هنگام ساخت payload یکپارچهسازی، مطمئن شوید این فیلد گنجانده شده است. - Gateway کلیک را با
Unknown actionرد میکند:context.action_idبا هیچ action باidدر پست مطابقت ندارد. هر دو را روی یک مقدار پاکسازیشدهٔ یکسان تنظیم کنید. - Agent دکمهها را ارائه نمیکند:
capabilities: ["inlineButtons"]را به پیکربندی کانال Mattermost اضافه کنید.
مرتبط
- مسیریابی کانال - مسیریابی نشست برای پیامها
- نمای کلی کانالها - همهٔ کانالهای پشتیبانیشده
- گروهها - رفتار گفتوگوی گروهی و محدودسازی بر اساس اشاره
- جفتسازی - احراز هویت پیام مستقیم و جریان جفتسازی
- امنیت - مدل دسترسی و مقاومسازی