Как динамически настроить аватар пользователя в BotFramework-WebChat на основе авторизованного пользователя с помощью OAuthCard - PullRequest
0 голосов
/ 12 апреля 2019

Я разработал чат-бота с использованием Microsoft Bot Framework V4 и использовал BotFramework-WebChat для предоставления пользователю чата с веб-сайта с помощью DirectLine Token,

Я могу установить аватар бота и аватара пользователя, назначив статический URL общедоступного изображения. Проблема в том, что я хочу динамически настроить аватар пользователя в веб-чате, используя следующие шаги

  1. Получить иконку пользователя с помощью Microsoft Graph API после входа в OAuthCard
  2. Установить подписанное изображение пользователя в Webchat styleSetOptions динамически.

Я прошел демонстрацию по настройке сервера фреймворка бота и веб-чата для бота, следуя предоставленным примерам

бот-сервер == https://github.com/Microsoft/BotBuilder-Samples

webchat == https://github.com/Microsoft/BotFramework-WebChat

но нет надлежащего примера или документации о том, как установить изображение пользователя после того, как пользователь вошел в систему с использованием подписанного объекта пользователя.

может указать одну точку в правильном направлении о том, как этого достичь.

Заранее спасибо

1 Ответ

1 голос
/ 24 апреля 2019

Этого можно добиться, заключив вызов API Graph и получая результат в результате процесса входа в AAD. Следующий код основан на BotBuilder-Samples 24.bot-authentication-msgraph sample и BotFramework-WebChat 17.chat-send-history sample с использованием React.Component.

(Обратите внимание, что образец Graph, находящийся в данный момент в главной ветке, не включает получение фотографии пользователя для входа в AAD. У меня есть PR, который добавляет эту функцию в образец, однако я также включил его здесь. I использовал образец WebChat в качестве справочного материала для построения ниже.)

WebChat

Вам понадобятся эти файлы из образца # 17, за которым следует файл App.js, который необходимо изменить:

  • публичный [папка]
    • favicon.ico
    • index.html
    • manifest.json
  • src [папка]
    • App.js
    • index.css
    • index.js
  • .env
  • package.json

App.js:

Примечание: я генерирую токен прямой линии локально в отдельном проекте. Предполагается, что в профиле AAD есть фотография.

import React from 'react';

import ReactWebChat, { createDirectLine, createStore} from 'botframework-webchat';

export default class extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      directLine: null,
      avatarState: false, // Sets value to false; Is updated to true after login
      // Sets the default styleOptions used during rendering
      styleOptions: {
          botAvatarImage: 'https://docs.microsoft.com/en-us/azure/bot-service/v4sdk/media/logo_bot.svg?view=azure-bot-service-4.0',
          botAvatarInitials: 'BF',
          userAvatarImage: 'https://github.com/compulim.png?size=64',
          userAvatarInitials: 'WC'
        }
    };

    // Creates the listener filtering for a new avatar image and applies to styleOptions
    this.store = createStore(
      {},
      () => next => action => {
        if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
          }
        if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY' 
          && action.payload.activity.attachments 
          && 0 in action.payload.activity.attachments
          && this.state.avatarState === false) {
            let attachments = action.payload.activity.attachments;
            if ('content' in attachments[0] && 'images' in attachments[0].content) {
              this.setState(() => ({
                  styleOptions: {
                    userAvatarImage: attachments[0].content.images[0].contentUrl
                  },
                  avatarState: true
              }));
            }
        }

        return next(action);
      }
    )
  }

  componentDidMount() {
    this.fetchToken();
  }

  async fetchToken() {
    const res = await fetch('http://localhost:3979/directline/token', { method: 'POST' });
    const { token } = await res.json();

    this.setState(() => ({
      directLine: createDirectLine({ token })
    }));
  }

  render() {
    return (
      this.state.directLine ?
        <ReactWebChat
          className="chat"
          directLine={ this.state.directLine }
          styleOptions={ this.state.styleOptions }
          store={ this.store }
          { ...this.props }
        />
      :
        <div>Connecting to bot&hellip;</div>
    );
  }
}
* * Package.json тысяча сорок-девять
{
  "name": "change-avatar",
  "version": "0.1.0",
  "private": true,
  "homepage": "",
  "dependencies": {
    "botframework-webchat": ">= 0.0.0-0",
    "react": "^16.6.3",
    "react-dom": "^16.6.3",
    "react-scripts": "2.1.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "eject": "react-scripts eject"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

MS Graph Bot

Обновите следующие файлы в образце № 24:

bot.js:

Заменить async processStep на:

async processStep(step) {
    // We do not need to store the token in the bot. When we need the token we can
    // send another prompt. If the token is valid the user will not need to log back in.
    // The token will be available in the Result property of the task.
    const tokenResponse = step.result;

    // If the user is authenticated the bot can use the token to make API calls.
    if (tokenResponse !== undefined) {
        let parts = await this.commandState.get(step.context);
        if (!parts) {
            parts = step.context.activity.text;
        }
        const command = parts.split(' ')[0].toLowerCase();
        if (command === 'me') {
            await OAuthHelpers.listMe(step.context, tokenResponse);
        } else if (command === 'send') {
            await OAuthHelpers.sendMail(step.context, tokenResponse, parts.split(' ')[1].toLowerCase());
        } else if (command === 'recent') {
            await OAuthHelpers.listRecentMail(step.context, tokenResponse);
        } else {
            let photoResponse = await OAuthHelpers.loginData(step.context, tokenResponse);
            const card = CardFactory.heroCard(
                `Welcome ${ photoResponse.displayName }, you are now logged in.`,
                [photoResponse],
                []
            );
            const reply = ({ type: ActivityTypes.Message });
            reply.attachments = [card];
            await step.context.sendActivity(reply);
        }
    } else {
        // Ask the user to try logging in later as they are not logged in.
        await step.context.sendActivity(`We couldn't log you in. Please try again later.`);
    }
    return await step.endDialog();
};

OAuth-helpers.js:

Добавить static async loginData:

/**
 * Displays information about the user in the bot.
 * @param {TurnContext} turnContext A TurnContext instance containing all the data needed for processing this conversation turn.
 * @param {TokenResponse} tokenResponse A response that includes a user token.
 */
static async loginData(turnContext, tokenResponse) {
    if (!turnContext) {
        throw new Error('OAuthHelpers.loginData(): `turnContext` cannot be undefined.');
    }
    if (!tokenResponse) {
        throw new Error('OAuthHelpers.loginData(): `tokenResponse` cannot be undefined.');
    }

    try {
        // Pull in the data from Microsoft Graph.
        const client = new SimpleGraphClient(tokenResponse.token);
        const me = await client.getMe();
        const photoResponse = await client.getPhoto();

        // Attaches user's profile photo to the reply activity.
        if (photoResponse != null) {
            let replyAttachment;
            const base64 = Buffer.from(photoResponse, 'binary').toString('base64');
            replyAttachment = {
                contentType: 'image/jpeg',
                contentUrl: `data:image/jpeg;base64,${ base64 }`
            };
            replyAttachment.displayName = me.displayName;
            return (replyAttachment);
        }
    } catch (error) {
        throw error;
    }
}

простой граф-client.js:

Добавить async getPhoto:

/**
 * Collects the user's photo.
 */
async getPhoto() {
    return await this.graphClient
        .api('/me/photo/$value')
        .responseType('ArrayBuffer')
        .version('beta')
        .get()
        .then((res) => {
            return res;
        })
        .catch((err) => {
            console.log(err);
        });
}

package.json:

Убедитесь, что @microsoft/microsoft-graph-client устанавливает версию 1.0.0 из-за серьезных изменений, связанных с получением AAD 'displayName' в последующих версиях.

После того, как приведенный выше код был реализован, я смог войти в систему, после чего сразу же обновил аватар пользователя.

Надежда на помощь!

...