Search code examples
botframework

How to detect end of dialog in Botframework v4?


I'm trying to kick off a feedback dialog following the completion of any other dialog in the system. I found this answer which says to use onEndDialog, but that isn't a valid function in ActivityHandler, only onDialog. My "main dialog" is in bot.js extending ActivityHandler, which is why I am not extending ComponentDialog. Given how this is set up, is there any way to determine when a dialog has ended? I tried to check the dialog stack in onDialog, but it reads as no dialog for the welcome message and initial message from the user, and after that always reads as dialog running. Is there a way I can modify my function/bot handler to detect an end of dialog event? Here is the onDialog function I've tried.

        this.onDialog(async (context, next) => {
            const currentDialog = await this.dialogState.get(context, {});
            if (currentDialog.dialogStack) {
                console.log('Dialog is running');
            } else {
                console.log('Dialog is not running');
            }

            // By calling next() you ensure that the next BotHandler is run.
            await next();
        });

I have considered adding an extra step to the end of every dialog to call the feedback dialog (likely via replaceDialog), but I'm not sure that would be a best practice.


Solution

  • I came up with a better solution, which builds on @mdrichardson's solution and addresses saving the dialogStack as mentioned in the comments for that answer. It's not complicated at all to save and check the previous state of the dialogStack.

    Note that since the original question, I started setting some values in conversation state from onMembersAdded, so my conversationData should always be defined. Instead I check for !conversationData.dialogStack. For this solution, I also added an OR check for !conversationData which should account for having no conversation state at all as well as having a state but no dialog stack.

            // Add this in constructor of your bot.js file
            this.onDialog(async (context, next) => {
    
                // Set up end of dialog messages
                const conversationData = await this.dialogState.get(context);
                if (!conversationData || !conversationData.dialogStack) {
                    console.log('Dialog not started');
                    conversationData.previousDialogLength = 0;
                } else {
                    console.log('Dialog running');
                    console.log(conversationData.dialogStack, conversationData.previousDialogLength);
                    if (conversationData.dialogStack.length == 0 && conversationData.previousDialogLength != 0) {
                        console.log('Dialog ended');
                        await context.sendActivity('Placeholder for End of Dialog action');
                    }
                    conversationData.previousDialogLength = conversationData.dialogStack.length;
                }
                await this.conversationState.saveChanges(context);
    
                return await next();
            });