КОМАНДЫ бот. «TypeError: source.on не является функцией» в методе «createConversation» - PullRequest
0 голосов
/ 18 октября 2019

У меня есть бот TEAMS node.js, работающий локально (с ngrok). Я получаю сообщения от клиента TEAMS, и эхо работает

context.sendActivity(`You said '${context.activity.text}'`);

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

Мой код:

...
await BotConnector.MicrosoftAppCredentials.trustServiceUrl(sServiceUrl);

var credentials = new BotConnector.MicrosoftAppCredentials({
    appId: "XXXXXXXXXXXX",
    appPassword: "YYYYYYYYYYYYY"
});

var connectorClient = new BotConnector.ConnectorClient(credentials, { baseUri: sServiceUrl });

const parameters = {
    members: [{ id: sUserId }],
    isGroup: false,
    channelData:
    {
        tenant: {
            id: sTenantId
        }
    }
};

// Here I get the error: "TypeError: source.on is not a function"
var conversationResource = await connectorClient.conversations.createConversation(parameters);

await connectorClient.conversations.sendToConversation(conversationResource.id, {
   type: "message",
   from: { id: credentials.appId },
   recipient: { id: sUserId },
   text: 'This a message from Bot Connector Client (NodeJS)'
});

Строковые значения верны, и у меня есть действительный соединительКлиент.

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

Диего

Ответы [ 4 ]

0 голосов
/ 28 октября 2019

Я нашел свою проблему. Я должен установить учетные данные / conector / trust в правильном порядке:

credentials = new MicrosoftAppCredentials(process.env.MicrosoftAppId, process.env.MicrosoftAppPassword);

connectorClient = new ConnectorClient(credentials, { baseUri: activity.serviceUrl });

MicrosoftAppCredentials.trustServiceUrl(activity.serviceUrl);
0 голосов
/ 21 октября 2019

Я создал своего бота с Yeoman, поэтому у меня был запущенный пример, который может отвечать на входящее сообщение. https://docs.microsoft.com/es-es/azure/bot-service/javascript/bot-builder-javascript-quickstart?view=azure-bot-service-4.0

При этом я могу ответить на входящее сообщение, и оно работает

Мой полный код:

index.js: // Создан автоматически, без изменений

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

const dotenv = require('dotenv');
const path = require('path');
const restify = require('restify');

// Import required bot services.
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
const { BotFrameworkAdapter } = require('botbuilder');

// This bot's main dialog.
const { MyBot } = require('./bot');

// Import required bot configuration.
const ENV_FILE = path.join(__dirname, '.env');
dotenv.config({ path: ENV_FILE });

// Create HTTP server
const server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, () => {
    console.log(`\n${ server.name } listening to ${ server.url }`);
    console.log(`\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator`);
    console.log(`\nTo test your bot, see: https://aka.ms/debug-with-emulator`);
});

// Create adapter.
// See https://aka.ms/about-bot-adapter to learn more about how bots work.
const adapter = new BotFrameworkAdapter({
    appId: process.env.MicrosoftAppId,
    appPassword: process.env.MicrosoftAppPassword
});

// Catch-all for errors.
adapter.onTurnError = async (context, error) => {
    // This check writes out errors to console log .vs. app insights.
    console.error(`\n [onTurnError]: ${ error }`);
    // Send a message to the user
    await context.sendActivity(`Oops. Something went wrong!`);
};

// Create the main dialog.
const myBot = new MyBot();

// Listen for incoming requests.
server.post('/api/messages', (req, res) => {
    adapter.processActivity(req, res, async (context) => {
        // Route to main dialog.
        await myBot.run(context);
    });
});

Мой файл бота. bot.js // создан автоматически, изменен для добавления активных сообщений

   const { ConnectorClient, MicrosoftAppCredentials, BotConnector } = require('botframework-connector');
   const { ActivityHandler } = require('botbuilder');

   class MyBot extends ActivityHandler {

    constructor() {
        super();
        // See https://aka.ms/about-bot-activity-message to learn more about the message and other activity types.
        this.onMessage(async (context, next) => {
            //await context.sendActivity(`You said '${context.activity.text}'`); // It works
            var activity = context.activity;
            await MicrosoftAppCredentials.trustServiceUrl(activity.serviceUrl);
            var connectorClient = new ConnectorClient(credentials, { baseUri: activity.serviceUrl });
            const parameters = {
                members: [{ id: activity.from.id }],
                isGroup: false,
                channelData:
                {
                    tenant: {
                        id: activity.conversation.tenantId
                    }
                }
            };
        var conversationResource = await connectorClient.conversations.createConversation(parameters);  

    });
}

module.exports.MyBot = MyBot;

В 'createConversation' я получаю сообщение об ошибке:

 [onTurnError]: TypeError: source.on is not a function

Этот код будет в методе,чтобы вызывать его при необходимости, я помещаю его в «onMessage» только для упрощения

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

Спасибо за помощь,

Диего

0 голосов
/ 25 октября 2019

У меня есть трассировка стека ошибки, и она, похоже, связана с модулем узла «отложенный поток». Я добавляю в качестве ответа, так как это слишком долго для комментария:

(node:28248) UnhandledPromiseRejectionWarning: TypeError: source.on is not a function
        at Function.DelayedStream.create ([Bot Project Path]\node_modules\delayed-stream\lib\delayed_stream.js:33:10)
        at FormData.CombinedStream.append ([Bot Project Path]\node_modules\combined-stream\lib\combined_stream.js:45:37)
        at FormData.append ([Bot Project Path]\node_modules\form-data\lib\form_data.js:74:3)
        at MicrosoftAppCredentials.refreshToken ([Bot Project Path]\node_modules\botframework-connector\lib\auth\microsoftAppCredentials.js:127:20)
        at MicrosoftAppCredentials.getToken ([Bot Project Path]\node_modules\botframework-connector\lib\auth\microsoftAppCredentials.js:91:32)
        at MicrosoftAppCredentials.signRequest ([Bot Project Path]\node_modules\botframework-connector\lib\auth\microsoftAppCredentials.js:71:38)
        at SigningPolicy.signRequest ([Bot Project Path]\node_modules\@azure\ms-rest-js\dist\msRest.node.js:2980:44)
        at SigningPolicy.sendRequest ([Bot Project Path]\node_modules\@azure\ms-rest-js\dist\msRest.node.js:2984:21)
        at ConnectorClient.ServiceClient.sendRequest ([Bot Project Path]\node_modules\@azure\ms-rest-js\dist\msRest.node.js:3230:29)
        at ConnectorClient.ServiceClient.sendOperationRequest ([Bot Project Path]\node_modules\@azure\ms-rest-js\dist\msRest.node.js:3352:27)
0 голосов
/ 19 октября 2019

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

Здесь я добавляю промежуточное программное обеспечение Teams к адаптеру в index.js и выполняю вызов, который запускает проактивное сообщение из шага водопадав mainDialog.js. Расположение кода не должно иметь значения, если вы можете передать context in.

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

Наконец, обязательно доверьтесь serviceUrl. Я делаю это с помощью метода onTurn в mainBot.js.

Надеюсь на помощь!

index.js

const teams = require('botbuilder-teams');

const adapter = new BotFrameworkAdapter({
  appId: process.env.MicrosoftAppId,
  appPassword: process.env.MicrosoftAppPassword
})
  .use(new teams.TeamsMiddleware())

mainDialog.js

const { ConnectorClient, MicrosoftAppCredentials } = require('botframework-connector');

async teamsProactiveMessage ( stepContext ) {
  const credentials = new MicrosoftAppCredentials(process.env.MicrosoftAppId, process.env.MicrosoftAppPassword);
  const connector = new ConnectorClient(credentials, { baseUri: stepContext.context.activity.serviceUrl });
  const roster = await connector.conversations.getConversationMembers(stepContext.context.activity.conversation.id);

  const parameters = {
    members: [
      {
        id: roster[0].id
      }
    ],
    channelData: {
      tenant: {
        id: roster[0].tenantId
      }
    }
  };

  const conversationResource = await connector.conversations.createConversation(parameters);
  const message = MessageFactory.text('This is a proactive message');
  await connector.conversations.sendToConversation(conversationResource.id, message);

  return stepContext.next();
}

mainBot.js

this.onTurn(async (context, next) => {
  if (context.activity.channelId === 'msteams') {
    MicrosoftAppCredentials.trustServiceUrl(context.activity.serviceUrl);
  }
  await next();
});

enter image description here

...