首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Botframework v4中保存和读取v4

在Botframework v4中保存和读取v4
EN

Stack Overflow用户
提问于 2022-01-21 17:07:57
回答 1查看 216关注 0票数 0

你好,我很难处理MSBF中的UserStates

下面是dialogBot.ts的设置

代码语言:javascript
复制
export class DialogBot extends ActivityHandler {
private conversationState: BotState;
private userState: BotState;
private dialog: Dialog;
private dialogState: StatePropertyAccessor<DialogState>;

/**
 *
 * @param {BotState} conversationState
 * @param {BotState} userState
 * @param {Dialog} dialog
 */
constructor(
    conversationState: BotState,
    userState: BotState,
    dialog: Dialog
) {
    super();
    if (!conversationState) {
        throw new Error(
            '[DialogBot]: Missing parameter. conversationState is required'
        );
    }
    if (!userState) {
        throw new Error('[DialogBot]: Missing parameter. userState is required');
    }
    if (!dialog) {
        throw new Error('[DialogBot]: Missing parameter. dialog is required');
    }

    this.conversationState = conversationState as ConversationState;
    this.userState = userState as UserState;
    this.dialog = dialog;
    this.dialogState =
        this.conversationState.createProperty<DialogState>('DialogState');

    this.onMessage(async (context, next) => {
        console.log('Running dialog with Message Activity.');

        // Run the Dialog with the new message Activity.
        await (this.dialog as MainDialog).run(context, this.dialogState);

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

    this.onDialog(async (context, next) => {
        // Save any state changes. The load happened during the execution of the Dialog.
        await this.conversationState.saveChanges(context, false);
        await this.userState.saveChanges(context, false);

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

}

在MainDialog.ts中,我根据传递的userID从数据库中获取一个用户,如果它获取任何内容,则应该保存在UserState中。

mainDialog.ts

代码语言:javascript
复制
export class MainDialog extends CancelAndHelpDialog {
private userProfileAccessor: StatePropertyAccessor<any>;
userState: UserState;

constructor(
    bookingDialog: BookingDialog,
    userState: UserState,
    conversationState: ConversationState
) {
    super('MainDialog');

    // DECLARE DIALOGS HERE
    const createJobOrderDialog = new CreateJobOrderDialog(
        'createJobOrderDialog'
    );
    const checkJobOrderStatusDialog = new CheckJobOrderStatusDialog(
        'checkJobOrderStatusDialog'
    );
    const accountSetupDialog = new AccountSetupDialog(
        'accountSetupDialog',
        userState
    );

    this.userProfileAccessor = userState.createProperty('userProfile');

    this.userState = userState;

    // Define the main dialog and its related components.
    // This is a sample "book a flight" dialog.
    this.addDialog(new TextPrompt('TextPrompt'));

    this.addDialog(bookingDialog);
    this.addDialog(createJobOrderDialog);
    this.addDialog(checkJobOrderStatusDialog);
    this.addDialog(accountSetupDialog);

    this.addDialog(
        new WaterfallDialog(MAIN_WATERFALL_DIALOG, [
            this.accountSetupStep.bind(this),
            this.introStep.bind(this),
            this.actStep.bind(this),
            this.finalStep.bind(this)
        ])
    );

    this.initialDialogId = MAIN_WATERFALL_DIALOG;
}

/**
 * The run method handles the incoming activity (in the form of a DialogContext) and passes it through the dialog system.
 * If no dialog is active, it will start the default dialog.
 * @param {TurnContext} context
 */
public async run(
    context: TurnContext,
    accessor: StatePropertyAccessor<DialogState>
) {
    const dialogSet = new DialogSet(accessor);
    dialogSet.add(this);

    const dialogContext = await dialogSet.createContext(context);
    const results = await dialogContext.continueDialog();
    if (results.status === DialogTurnStatus.empty) {
        await dialogContext.beginDialog(this.id);
    }
}

private async accountSetupStep(
    stepContext: WaterfallStepContext
): Promise<DialogTurnResult> {
    const userProfile = await this.userProfileAccessor.get(
        stepContext.context,
        {}
    );

    stepContext.context.activity.from.id = '*******************';

    userProfile.isHandover = false;
    await this.userProfileAccessor.set(stepContext.context, userProfile);
    // await this.userState.saveChanges(stepContext.context, true);

    const result = await userService.getUser(
        stepContext.context.activity.from.id
    );
    console.log(result);

    if (Object.keys(result).length === 0) {
        return await stepContext.beginDialog('accountSetupDialog');
    } else {
        userProfile.user = result;
        await this.userProfileAccessor.set(stepContext.context, userProfile);
        // await this.userState.saveChanges(stepContext.context, true);

        return await stepContext.next();
    }
}
private async introStep(
    stepContext: WaterfallStepContext
): Promise<DialogTurnResult> {
    const userProfile = await this.userProfileAccessor.get(
        stepContext.context,
        {}
    );
    console.log('INTRO STEP USERPROFILE', userProfile);
    await stepContext.context.sendActivities([
        {
            type: 'message',
            text: `Hi ${userProfile.user.first_name}, welcome to Podmachine. Let us take care of the dirty stuff so you can sound like a Pro!`
        },
        {
            type: 'typing'
        },
        { type: 'delay', value: 1000 },
        {
            type: 'message',
            text: 'To start, you need to submit a job order.'
        },
        {
            type: 'typing'
        },
        { type: 'delay', value: 1000 },
        {
            type: 'message',
            text: `So what's a job order? It's basically sending a request to edit (1) one raw episode audio file to Podmachine team. We'll handle the rest. `
        },
        {
            type: 'typing'
        },
        { type: 'delay', value: 1000 },
        {
            type: 'message',
            text: `Since you're part of the early access users (Yay!), you're entitled to (1) one free job order / edit. Go ahead and click "Create New Job order."`
        },
        {
            type: 'typing'
        },
        { type: 'delay', value: 1000 }
    ]);
    const messageText = (stepContext.options as any).restartMsg
        ? (stepContext.options as any).restartMsg
        : `Please take note that once you submit your job order, Podmachine team will review it first. Make sure all the details you put in your job order are correct. It will be our basis when we do the edits. Thank you!`;
    const promptMessage = MessageFactory.suggestedActions(
        [
            'Create New Job Order',
            'Check Status',
            'Chat with Team',
            'Subscribe Now'
        ],
        messageText
    );
    return await stepContext.prompt('TextPrompt', {
        prompt: promptMessage
    });
}

/**
 * Second step in the waterall.  This will use LUIS to attempt to extract the origin, destination and travel dates.
 * Then, it hands off to the bookingDialog child dialog to collect any remaining details.
 */
private async actStep(
    stepContext: WaterfallStepContext
): Promise<DialogTurnResult> {
    // const bookingDetails = new BookingDetails();
    const userProfile = await this.userProfileAccessor.get(stepContext.context, {});

    console.log('USER PROFILE ACT STEP', userProfile);

    switch (stepContext.result) {
        case 'Create New Job Order':
            return await stepContext.beginDialog('createJobOrderDialog');
            break;

        case 'Check Status':
            return await stepContext.beginDialog('checkJobOrderStatusDialog');
            break;

        case 'Chat with Team':
            userProfile.isHandover = true;
            await stepContext.context.sendActivity(
                `Hi ${userProfile.user.first_name}, we're glad to assist you. Please type your concern below. A Podmachine associate will getback to you within 3-5 minutes. Thank you for your patience.`
            );

            await this.userProfileAccessor.set(stepContext.context, userProfile);

            return await stepContext.endDialog();
            break;

        case 'Upgrade Now':
            await stepContext.context.sendActivity(
                `Redirecting to Upgrade Now page...`
            );

            return await stepContext.endDialog();
            break;

        case 'Schedule a Checkpoint Meeting':
            await stepContext.context.sendActivity(`Feature in progress...`);

            return await stepContext.endDialog();
            break;
        default:
            break;
    }

    return await stepContext.next();
    // return await stepContext.beginDialog('bookingDialog', bookingDetails);
}

我可以在introStep中看到保存的用户详细信息,但是当涉及到actStep时,我不再看到该值,并且它是未定义的。您能帮我实现UserState吗?因为我不确定通过加载它是否正确,来自github的示例不太清楚。

代码语言:javascript
复制
USER PROFILE ACT STEP {}
[onTurnError] unhandled error: DialogContextError: Cannot read properties of undefined (reading 'first_name')
EN

回答 1

Stack Overflow用户

发布于 2022-01-26 01:26:50

看起来你的机器人没有存储状态,所以在下一个回合它无法恢复状态。

您是否正在设置您的机器人正在使用的存储空间?

请检查此文档如何使用存储库:

https://learn.microsoft.com/en-us/azure/bot-service/bot-builder-howto-v4-storage?view=azure-bot-service-4.0&tabs=javascript

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70805047

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档