We're Hiring!

Mattermost, Inc.

Interactive Dialog cannot call from interactive message button

When I post a json to URL: http://<mattermost_server>/api/v4/actions/dialogs/open
A dialog cannot open, the server log is below:

{"level":"debug","ts":1624384129.090824,"caller":"web/handlers.go:106","msg":"Received HTTP request","method":"POST","url":"/api/v4/actions/dialogs/open","request_id":"ignquxpg8fbr9p5uerzsyrmuih","host":<mattermost_server>,"scheme":"","status_code":"200"}
{"level":"debug","ts":1624384129.094713,"caller":"mlog/log.go:226","msg":"Action integration error.","path":"/api/v4/posts/z7iiame8hf8ttjiyfpqnohuiye/actions/message","request_id":"kgsgud34y7ycxgrzc68h1hgema","ip_addr":<ip_addr>,"user_id":<user_id>,"method":"POST","err_where":"DoPostActionWithCookie","http_code":400,"err_details":"err=EOF"}
{"level":"debug","ts":1624384129.096068,"caller":"web/handlers.go:106","msg":"Received HTTP request","method":"POST","url":"/api/v4/posts/z7iiame8hf8ttjiyfpqnohuiye/actions/message","request_id":"kgsgud34y7ycxgrzc68h1hgema","host":<mattermost_server>,"scheme":"","status_code":"400"}

Same request for slash command is successfully worked.
**Who can tell me why this happens and what’s wrong with my request **
How can i call interactive dialog from interactive message button?

mattermost server version is 5.35.0

Based on this error message, it would appear that somewhere in your code, there is an unexpected end of feature (EOF) that is causing an error to be thrown. It could be caused by a syntax error, a parameter that is not being parsed correctly, etc, so I would suggest validating your code as a preliminary first step.

Thank you for your kind advice

My simple test code is here

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/mattermost/mattermost-server/model"
)

func main() {
	http.HandleFunc("/command", func(w http.ResponseWriter, r *http.Request) {
		defer r.Body.Close()

		// Catch message button action
		b, _ := ioutil.ReadAll(r.Body)
		var payload model.PostActionIntegrationRequest
		json.Unmarshal(b, &payload)
		triggerId := payload.TriggerId

		// Build Request
		request := model.OpenDialogRequest{
			TriggerId: triggerId,
			URL:       "http://localhost:8080/actions/dialog",
			Dialog: model.Dialog{
				Title: "Sample Interactive Dialog",
				Elements: []model.DialogElement{{
					DisplayName: "Title",
					Name:        "title",
					Type:        "text",
				}, {
					DisplayName: "Message",
					Name:        "message",
					Type:        "textarea",
				}},
			},
		}

		// Open Interactive Dialog
		by, _ := json.Marshal(request)
		req, _ := http.NewRequest(http.MethodPost, "https://<my-mattermost-server>/api/v4/actions/dialogs/open", bytes.NewReader(by))
		req.Header.Add("Content-Type", "application/json")
		resp, err := http.DefaultClient.Do(req)
		fmt.Printf("%#v\n", resp)
		if err != nil {
			fmt.Printf("%#v\n", err)
		}

	})
	if err := http.ListenAndServe(":1129", nil); err != nil {
		log.Fatal(err)
	}
}

And the response is below

&http.Response{Status:"200 OK", StatusCode:200, Proto:"HTTP/1.1", ProtoMajor:1, ProtoMinor:1, Header:http.Header{"Content-Length":[]string{"15"}, "Content-Type":[]string{"application/json"}, "Date":[]string{"Wed, 23 Jun 2021 15:54:11 GMT"}, "Server":[]string{"Apache/2.4.38 (Debian)"}, "Vary":[]string{"Accept-Encoding"}, "X-Ratelimit-Limit":[]string{"101"}, "X-Ratelimit-Remaining":[]string{"100"}, "X-Ratelimit-Reset":[]string{"1"}, "X-Request-Id":[]string{"djfc77h4fjnuugwji3cqw5en4h"}, "X-Version-Id":[]string{"5.35.0.5.35.0.28c048ab54ded5c80a3c67404996226d.false"}}, Body:(*http.bodyEOFSignal)(0xc00026eb80), ContentLength:15, TransferEncoding:[]string(nil), Close:false, Uncompressed:false, Trailer:http.Header(nil), Request:(*http.Request)(0xc0000de800), TLS:(*tls.ConnectionState)(0xc0000c1080)}

I think the interactive dialog can be opened when the interactive message button is pressed.
Because the following description is in the documentation.
“Integrations can use this endpoint to open dialogs when users click message buttons or select an option from a menu, or use a custom slash command.”
https://docs.mattermost.com/developer/interactive-dialogs.html
However, I haven’t actually seen a sample code that opens an interactive dialog from an interactive message button.
Is it possible for anyone to provide that sample code?

I have not been able to get this to work either. I think their documentation is wrong. I built a slash command, that can provide interactive messages or interactive dialog depending on what the user is building. If the Interactive Dialog occurs immediately after the end user uses a slash command, the dialog will open. But, using the interactive message to open an interactive dialog fails.

For some reason, the trigger id of a slash command works, but the interactive message trigger id does not.

Since I am not the only person running into this issue, I should probably open a bug ticket on the docs or a feature request on the interactive dialog.

1 Like

I would suggest taking a look at this message thread on the Mattermost Community Server :slight_smile: Let me know if it’s helpful!

1 Like

Wow, so I just need to return a response to Mattermost when they click the button in the message. I am guessing that I am doing that when processing the slash command, but not when using the button. I will test this out soon.

@XxLilBoPeepsxX Thank you! The post you shared allowed me to close a long standing issue on my end!

1 Like

@smk4664 Can you show me your sample code?
My code still doesn’t work.

1 Like

@ht918 Well, my code is in Python, but in your main() function, where you catch the button action, you will want to respond to the http request with a Json object. I use an empty dictionary.

from django.http import JsonResponse
from django_rq import get_queue

handle_interaction(request, *args, **kwargs):
    trigger_id = request.Post.get("trigger_id")
    get_queue("default").enqueue("my_function", trigger_id)
    return JsonResponse({})

This is the basics, my_function handles sending the interactive dialog, which is done inside an RQ worker. I return the JsonResponse before the worker fires the Interactive Dialog off. Timing is important here, as Mattermost must receive the 200 OK with the empty JsonResponse before the interactive dialog occurs. And, after you return the response, you have 3 seconds before the trigger_id is invalidated. You could also provide a message within the JsonResponse, and that will get posted back to the user, but I found that annoying due to the way our chat commands work.

What I find interesting, is that you don’t need to respond to the slash_command, only to the interactions.

1 Like

I do not write go, but it seems like your

func(w http.ResponseWriter

should be similar to

responseWriter.Header().Set("Content-Type", "application/json")
responseWriter.WriteHeader(http.StatusOK)
jsonData := []byte(`{}`)
responseWriter.Write(jsonData)
2 Likes

@smk4664 Thank you for your kind information!!
It works for me!!!

2 Likes