首页 > 解决方案 > Bot Framework v4 Node.js 位置

问题描述

我正在设计一个聊天机器人,并试图找到一些关于如何将 Azure Maps 服务作为 Bot Framework V4 的一部分实施的 Node.js 示例代码和/或文档。在 V3 中如何实现这一点的示例有很多,但似乎没有针对 Node.js 的 V4 解决方案的示例。我希望在我的 botbuilder-dialog 流程中创建一个步骤,该步骤将启动一个简单的“我们也在哪里运送它”位置对话框,该对话框将引导用户完成对话框并将地址结果存储为该用户配置文件的一部分。对此的任何帮助或建议将不胜感激。

标签: node.jsbotframeworkazure-maps

解决方案


是的,这是可行的。我创建了一个类(可能有点矫枉过正,但很好),我在其中使用我提供的参数调用 API 来获取地图。我决定使用Azure Maps(与Bing Maps相比)只是因为我很好奇它的不同之处。您也没有任何理由不能使用 Bing 地图执行此操作。

在机器人中,我使用了一个组件对话框,因为我是如何设计机器人的其余部分的。当对话框结束时,它将从堆栈中掉下来并返回到父对话框。

在我的场景中,机器人为用户提供了几个选择。“向我发送地图”生成地图并将其在活动中发送给客户端/用户。其他任何事情都会让用户继续结束对话。

您将需要决定如何获取用户的位置。我在开发这个时考虑到了网络聊天,所以我从浏览器获取地理位置并将其返回给机器人,以便在getMap()被调用时使用。

const { ActivityTypes, InputHints } = require('botbuilder');
const fetch = require('node-fetch');

class MapHelper {
  async getMap(context, latitude, longitude) {
    var requestOptions = {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json'
      },
      redirect: 'follow'
    };

    const result = await fetch(`https://atlas.microsoft.com/map/static/png?subscription-key=${ process.env.AZURE_MAPS_KEY }&api-version=1.0&layer=basic&zoom=13&center=${ longitude },${ latitude }&language=en-US&pins=default|al.67|la12 3|lc000000||'You!'${ longitude } ${ latitude }&format=png`, requestOptions)
      .then(response => response.arrayBuffer())
      .then(async result => {
        const bufferedData = Buffer.from(result, 'binary');
        const base64 = bufferedData.toString('base64');
        const reply = { type: ActivityTypes.Message };
        const attachment = {
          contentType: 'image/png',
          contentUrl: `data:image/png;base64,${ base64 }`
        };

        reply.attachments = [attachment];
        await context.sendActivity(reply, null, InputHints.IgnoringInput);
      })
      .catch(error => {
        if (error) throw new Error(error);
      });

    return result;
  };
};

module.exports.MapHelper = MapHelper;
const { ChoicePrompt, ChoiceFactory, ComponentDialog, ListStyle, WaterfallDialog } = require('botbuilder-dialogs');
const { MapHelper } = require('./mapHelper');

const CONFIRM_LOCALE_DIALOG = 'confirmLocaleDialog';
const CHOICE_PROMPT = 'confirmPrompt';

class ConfirmLocaleDialog extends ComponentDialog {
  constructor() {
    super(CONFIRM_LOCALE_DIALOG);

    this.addDialog(new ChoicePrompt(CHOICE_PROMPT))
      .addDialog(new WaterfallDialog(CONFIRM_LOCALE_DIALOG, [
        this.askLocationStep.bind(this),
        this.getMapStep.bind(this)
    ]));

    this.initialDialogId = CONFIRM_LOCALE_DIALOG;
  }

  async askLocationStep(stepContext) {
    const choices = ['Send me a map', "I'll have none of this nonsense!"];
    return await stepContext.prompt(CHOICE_PROMPT, {
      prompt: 'Good sir, may I pinpoint you on a map?',
      choices: ChoiceFactory.toChoices(choices),
      style: ListStyle.suggestedAction
    });
  }

  async getMapStep(stepContext) {
    const { context, context: { activity } } = stepContext;
    const text = activity.text.toLowerCase();
    if (text === 'send me a map') {
      const { latitude, longitude } = activity.channelData;
      const mapHelper = new MapHelper();
      await mapHelper.getMap(context, latitude, longitude);

      const message = 'Thanks for sharing!';
      await stepContext.context.sendActivity(message);
      return await stepContext.endDialog();
    } else {
      await stepContext.context.sendActivity('No map for you!');
      return await stepContext.endDialog();
    }
  }
}

module.exports.ConfirmLocaleDialog = ConfirmLocaleDialog;
module.exports.CONFIRM_LOCALE_DIALOG = CONFIRM_LOCALE_DIALOG;

在此处输入图像描述

希望有帮助!

- - 编辑 - -

根据请求,可以使用以下方法从浏览器获取位置数据。当然,这取决于用户授予对位置数据的访问权限。

navigator.geolocation.getCurrentPosition( async (position) => {
  const { latitude, longitude } = position.coords;
  // Do something with the data;
  console.log(latitude, longitude)
})

推荐阅读