@@ -6,7 +6,7 @@ import { setMattermostRuntime } from "../runtime.js";
66import { resolveMattermostAccount } from "./accounts.js" ;
77import type { MattermostClient , MattermostPost } from "./client.js" ;
88import {
9- buildButtonAttachments ,
9+ buildButtonProps ,
1010 computeInteractionCallbackUrl ,
1111 createMattermostInteractionHandler ,
1212 resolveInteractionCallbackPath ,
@@ -15,9 +15,39 @@ import {
1515 setInteractionSecret ,
1616} from "./interactions.js" ;
1717
18- type ButtonAttachments = ReturnType < typeof buildButtonAttachments > ;
19- type ButtonAttachment = ButtonAttachments [ number ] ;
20- type ButtonAction = NonNullable < ButtonAttachment [ "actions" ] > [ number ] ;
18+ type ButtonAction = {
19+ id : string ;
20+ type : "button" ;
21+ name : string ;
22+ style ?: "default" | "primary" | "danger" ;
23+ integration : { url : string ; context : Record < string , unknown > } ;
24+ } ;
25+ type ButtonAttachment = { text : string ; actions ?: ButtonAction [ ] } ;
26+ type ButtonAttachments = ButtonAttachment [ ] ;
27+ type ButtonPropsInput = {
28+ callbackUrl : string ;
29+ accountId ?: string ;
30+ buttons : Array < {
31+ id : string ;
32+ name : string ;
33+ style ?: "default" | "primary" | "danger" ;
34+ context ?: Record < string , unknown > ;
35+ } > ;
36+ text ?: string ;
37+ } ;
38+
39+ function buildButtonAttachmentsForTest ( params : ButtonPropsInput ) : ButtonAttachments {
40+ const signedChannelId = params . buttons [ 0 ] ?. context ?. __openclaw_channel_id ;
41+ const props = buildButtonProps ( {
42+ ...params ,
43+ channelId : typeof signedChannelId === "string" ? signedChannelId : "test-channel" ,
44+ } ) ;
45+ const attachments = props ?. attachments ;
46+ if ( ! Array . isArray ( attachments ) ) {
47+ throw new Error ( "Expected button attachments" ) ;
48+ }
49+ return attachments as ButtonAttachments ;
50+ }
2151
2252function requireFirstAttachment ( attachments : ButtonAttachments ) : ButtonAttachment {
2353 const [ attachment ] = attachments ;
@@ -45,7 +75,7 @@ function requireAction(attachments: ButtonAttachments, index = 0): ButtonAction
4575
4676function generateInteractionToken ( context : Record < string , unknown > , accountId ?: string ) : string {
4777 const actionId = typeof context . action_id === "string" ? context . action_id : "test" ;
48- const attachments = buildButtonAttachments ( {
78+ const attachments = buildButtonAttachmentsForTest ( {
4979 callbackUrl : "https://gateway.example.com/mattermost/interactions/test" ,
5080 accountId,
5181 buttons : [ { id : actionId , name : "Test" , context } ] ,
@@ -323,15 +353,15 @@ describe("resolveInteractionCallbackPath", () => {
323353 } ) ;
324354} ) ;
325355
326- // ── buildButtonAttachments ─────── ────────────────────────────────────
356+ // ── buildButtonProps attachments ────────────────────────────────────
327357
328- describe ( "buildButtonAttachments " , ( ) => {
358+ describe ( "buildButtonProps attachments " , ( ) => {
329359 beforeEach ( ( ) => {
330360 setInteractionSecret ( "test-bot-token" ) ;
331361 } ) ;
332362
333363 it ( "returns an array with one attachment containing all buttons" , ( ) => {
334- const result = buildButtonAttachments ( {
364+ const result = buildButtonAttachmentsForTest ( {
335365 callbackUrl : "http://localhost:18789/mattermost/interactions/default" ,
336366 buttons : [
337367 { id : "btn1" , name : "Click Me" } ,
@@ -344,7 +374,7 @@ describe("buildButtonAttachments", () => {
344374 } ) ;
345375
346376 it ( "sets type to 'button' on every action" , ( ) => {
347- const result = buildButtonAttachments ( {
377+ const result = buildButtonAttachmentsForTest ( {
348378 callbackUrl : "http://localhost:18789/cb" ,
349379 buttons : [ { id : "a" , name : "A" } ] ,
350380 } ) ;
@@ -353,7 +383,7 @@ describe("buildButtonAttachments", () => {
353383 } ) ;
354384
355385 it ( "includes HMAC _token in integration context" , ( ) => {
356- const result = buildButtonAttachments ( {
386+ const result = buildButtonAttachmentsForTest ( {
357387 callbackUrl : "http://localhost:18789/cb" ,
358388 buttons : [ { id : "test" , name : "Test" } ] ,
359389 } ) ;
@@ -363,7 +393,7 @@ describe("buildButtonAttachments", () => {
363393 } ) ;
364394
365395 it ( "includes sanitized action_id in integration context" , ( ) => {
366- const result = buildButtonAttachments ( {
396+ const result = buildButtonAttachmentsForTest ( {
367397 callbackUrl : "http://localhost:18789/cb" ,
368398 buttons : [ { id : "my_action" , name : "Do It" } ] ,
369399 } ) ;
@@ -375,7 +405,7 @@ describe("buildButtonAttachments", () => {
375405 } ) ;
376406
377407 it ( "merges custom context into integration context" , ( ) => {
378- const result = buildButtonAttachments ( {
408+ const result = buildButtonAttachmentsForTest ( {
379409 callbackUrl : "http://localhost:18789/cb" ,
380410 buttons : [ { id : "btn" , name : "Go" , context : { tweet_id : "123" , batch : true } } ] ,
381411 } ) ;
@@ -389,7 +419,7 @@ describe("buildButtonAttachments", () => {
389419
390420 it ( "passes callback URL to each button integration" , ( ) => {
391421 const url = "http://localhost:18789/mattermost/interactions/default" ;
392- const result = buildButtonAttachments ( {
422+ const result = buildButtonAttachmentsForTest ( {
393423 callbackUrl : url ,
394424 buttons : [
395425 { id : "a" , name : "A" } ,
@@ -403,7 +433,7 @@ describe("buildButtonAttachments", () => {
403433 } ) ;
404434
405435 it ( "preserves button style" , ( ) => {
406- const result = buildButtonAttachments ( {
436+ const result = buildButtonAttachmentsForTest ( {
407437 callbackUrl : "http://localhost/cb" ,
408438 buttons : [
409439 { id : "ok" , name : "OK" , style : "primary" } ,
@@ -416,7 +446,7 @@ describe("buildButtonAttachments", () => {
416446 } ) ;
417447
418448 it ( "uses provided text for the attachment" , ( ) => {
419- const result = buildButtonAttachments ( {
449+ const result = buildButtonAttachmentsForTest ( {
420450 callbackUrl : "http://localhost/cb" ,
421451 buttons : [ { id : "x" , name : "X" } ] ,
422452 text : "Choose an action:" ,
@@ -426,7 +456,7 @@ describe("buildButtonAttachments", () => {
426456 } ) ;
427457
428458 it ( "defaults to empty string text when not provided" , ( ) => {
429- const result = buildButtonAttachments ( {
459+ const result = buildButtonAttachmentsForTest ( {
430460 callbackUrl : "http://localhost/cb" ,
431461 buttons : [ { id : "x" , name : "X" } ] ,
432462 } ) ;
@@ -435,7 +465,7 @@ describe("buildButtonAttachments", () => {
435465 } ) ;
436466
437467 it ( "generates verifiable tokens" , ( ) => {
438- const result = buildButtonAttachments ( {
468+ const result = buildButtonAttachmentsForTest ( {
439469 callbackUrl : "http://localhost/cb" ,
440470 buttons : [ { id : "verify_me" , name : "V" , context : { extra : "data" } } ] ,
441471 } ) ;
@@ -447,7 +477,7 @@ describe("buildButtonAttachments", () => {
447477 } ) ;
448478
449479 it ( "generates tokens that verify even when Mattermost reorders context keys" , ( ) => {
450- const result = buildButtonAttachments ( {
480+ const result = buildButtonAttachmentsForTest ( {
451481 callbackUrl : "http://localhost/cb" ,
452482 buttons : [ { id : "do_action" , name : "Do" , context : { tweet_id : "42" , category : "ai" } } ] ,
453483 } ) ;
0 commit comments