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 ایجاد کنید، توکن ربات را کپی کنید و ربات را به تیمها و کانالهایی که باید بخواند اضافه کنید.
نشانی پایه را کپی کنید
نشانی پایه 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", // Use when Mattermost cannot reach the gateway directly (reverse proxy/public 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تنظیم کرد (مقادیر حساب، فیلدهای سطح بالا را لغو میکنند). - فرمانهای اسلش موجود با محرک یکسان که توسط یکپارچهسازیهای دیگر ایجاد شدهاند، بدون تغییر باقی میمانند (هنگام ثبت نادیده گرفته میشوند)؛ فرمانهایی که ربات ایجاد کرده است، هنگام تغییر نشانی فراخوانی برگشتی بهروزرسانی یا دوباره ایجاد میشوند.
- فراخوانیهای برگشتی فرمان با توکن اختصاصی هر فرمان که هنگام ثبت فرمانهای
oc_*توسط Mattermost بازگردانده میشود، اعتبارسنجی میشوند. - OpenClaw پیش از پذیرش هر فراخوانی برگشتی، ثبت فعلی فرمان Mattermost را تازهسازی میکند؛ بنابراین توکنهای منسوخ فرمانهای اسلش حذفشده یا بازتولیدشده، بدون نیاز به راهاندازی مجدد Gateway دیگر پذیرفته نمیشوند.
- اگر API مربوط به Mattermost نتواند تأیید کند که فرمان همچنان فعلی است، اعتبارسنجی فراخوانی برگشتی بهصورت بسته شکست میخورد؛ اعتبارسنجیهای ناموفق برای مدت کوتاهی در حافظه نهان ذخیره میشوند، جستوجوهای همزمان ادغام میشوند و شروع جستوجوی تازه برای هر فرمان محدودیت نرخ دارد تا فشار بازپخش مهار شود.
- فراخوانیهای برگشتی اسلش زمانی بهصورت بسته شکست میخورند که ثبت ناموفق بوده، راهاندازی ناقص بوده یا توکن فراخوانی برگشتی با توکن ثبتشده فرمان حلشده مطابقت نداشته باشد (توکنی که برای یک فرمان معتبر است، نمیتواند برای فرمان دیگری به اعتبارسنجی بالادستی برسد).
- دریافت فراخوانیهای برگشتی پذیرفتهشده با پاسخ موقت «در حال پردازش...» تأیید میشود؛ پاسخ واقعی بهشکل یک پیام عادی میرسد.
الزام دسترسیپذیری
نقطه پایانی فراخوانی برگشتی باید از سرور Mattermost قابل دسترسی باشد.
callbackUrlرا رویlocalhostتنظیم نکنید، مگر اینکه Mattermost در همان میزبان/فضای نام شبکه OpenClaw اجرا شود.callbackUrlرا روی نشانی پایه Mattermost خود تنظیم نکنید، مگر اینکه آن نشانی/api/channels/mattermost/commandرا از طریق پراکسی معکوس به OpenClaw هدایت کند.- برای بررسی سریع، از
curl https://<gateway-host>/api/channels/mattermost/commandاستفاده کنید؛ یک درخواست GET باید از OpenClaw پاسخ405 Method Not Allowedدریافت کند، نه404.
فهرست مجاز خروجی Mattermost
اگر مقصد فراخوانی برگشتی شما نشانیهای خصوصی/tailnet/داخلی است، ServiceSettings.AllowedUntrustedInternalConnections را در Mattermost طوری تنظیم کنید که میزبان/دامنه فراخوانی برگشتی را دربرگیرد.
از ورودیهای میزبان/دامنه استفاده کنید، نه نشانیهای کامل.
- درست:
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: [">", "!"], // default }, },}نکات:
oncharهمچنان به اشارههای صریح با @ پاسخ میدهد.channels.mattermost.requireMentionهمچنان رعایت میشود، اماchatmodeترجیح داده میشود. تنظیمات مختص هر کانال درgroups.<channelId>.requireMentionبر هر دو اولویت دارند.- پس از اینکه ربات در یک رشته کانال پاسخی قابل مشاهده ارسال کند، پیامهای بعدی در همان رشته بدون اشاره جدید با @ یا پیشوند
oncharپاسخ داده میشوند تا گفتگوهای چندنوبتی رشته بدون وقفه ادامه یابند. مشارکت تا ۷ روز پس از آخرین پاسخ ربات در آن رشته به خاطر سپرده میشود و پس از راهاندازی مجدد Gateway نیز باقی میماند. رشتههایی که ربات فقط مشاهده کرده است، تحت تأثیر قرار نمیگیرند؛ برای اینکه دوباره اشاره صریح لازم باشد، یک پیام سطحبالای جدید آغاز کنید.
رشتهها و نشستها
از 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: "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"], }, },}هنگامی که کاربر روی دکمهای کلیک میکند:
بررسی دسترسی
کلیککننده باید همان بررسیهای سیاست پیام مستقیم/گروه را که برای فرستندهٔ پیام اعمال میشود با موفقیت بگذراند؛ کلیکهای غیرمجاز یک اعلان موقت دریافت میکنند و نادیده گرفته میشوند.
جایگزینی دکمهها با تأیید
همهٔ دکمهها با یک خط تأیید جایگزین میشوند (برای مثال، «✓ Yes توسط @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های مبدأ برای فراخوانهای برگشتی دکمه. بدون آن، فقط مبدأهای local loopback (127.0.0.1،::1) پذیرفته میشوند؛ بنابراین سرور راهدور Mattermost باید در اینجا مجاز شود، وگرنه کلیکهای آن با403رد میشوند. پشت پراکسی معکوس،gateway.trustedProxiesرا نیز تنظیم کنید تا IP واقعی کاربر از سرآیندهای هدایتشده استخراج شود.- اگر مقصد فراخوان برگشتی شما خصوصی/شبکهٔ Tailscale/داخلی است، میزبان/دامنهٔ آن را به
ServiceSettings.AllowedUntrustedInternalConnectionsدر Mattermost اضافه کنید.
یکپارچهسازی مستقیم API (اسکریپتهای خارجی)
اسکریپتها و Webhookهای خارجی میتوانند بهجای عبور از ابزار message عامل، دکمهها را مستقیماً از طریق REST API در Mattermost ارسال کنند. در صورت امکان از 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"}). برای تطبیق با خروجی فشردهٔ JavaScript ({"key":"val"})، ازseparators=(",", ":")استفاده کنید.- همیشه همهٔ فیلدهای زمینه (بهجز
_token) را امضا کنید. Gateway ابتدا_tokenرا حذف میکند و سپس همهٔ موارد باقیمانده را امضا میکند. امضای یک زیرمجموعه باعث شکست بیسروصدای اعتبارسنجی میشود. - از
sort_keys=Trueاستفاده کنید؛ Gateway کلیدها را پیش از امضا مرتب میکند و Mattermost ممکن است هنگام ذخیرهٔ محتوای ارسالی، ترتیب فیلدهای زمینه را تغییر دهد. - راز را از توکن ربات استخراج کنید (بهصورت قطعی)، نه از بایتهای تصادفی. راز باید در فرایندی که دکمهها را ایجاد میکند و Gateway که آنها را اعتبارسنجی میکند یکسان باشد.
آداپتور فهرست راهنما
Plugin مربوط به Mattermost شامل یک آداپتور فهرست راهنما است که نام کانالها و کاربران را از طریق API در Mattermost تفکیک میکند. این قابلیت استفاده از مقصدهای #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" را تنظیم کنید.
خطاهای احراز هویت یا چندحسابی
- توکن ربات، نشانی پایه و فعال بودن حساب را بررسی کنید.
- مشکلات چندحسابی: متغیرهای محیطی فقط برای حساب
defaultاعمال میشوند. - میزبانهای خصوصی/LAN متعلق به 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حذف شده باشد و گزارشها هشدار دهند که فراخوانی برگشتی به یک نشانی local loopback مانندhttp://localhost:18789/...تفکیک شده است، احتمالاً آن نشانی فقط زمانی قابل دسترسی است که Mattermost در همان میزبان/فضای نام شبکه OpenClaw اجرا شود. در عوض، یکcommands.callbackUrlصریح و قابل دسترسی از بیرون تنظیم کنید.
مشکلات دکمهها
- دکمهها بهشکل کادرهای سفید نمایش داده میشوند یا اصلاً نمایش داده نمیشوند: داده دکمه بدساخت است. هر دکمه نمایشی به یک
labelو یکvalueنیاز دارد (دکمههایی که یکی از این دو را نداشته باشند، حذف میشوند). - دکمهها نمایش داده میشوند، اما کلیکها هیچ کاری نمیکنند: بررسی کنید Gateway از سرور Mattermost قابل دسترسی باشد، 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 اضافه کنید.
مرتبط
- مسیریابی کانال - مسیریابی نشست برای پیامها
- نمای کلی کانالها - همه کانالهای پشتیبانیشده
- گروهها - رفتار گفتوگوی گروهی و کنترل اشاره
- جفتسازی - احراز هویت پیام خصوصی و جریان جفتسازی
- امنیت - مدل دسترسی و مقاومسازی