microsoft / BotFramework-Services

Microsoft Bot Framework Services
Creative Commons Attribution 4.0 International
38 stars 11 forks source link

Custom Adapter receives error: [onTurnError] unhandled error: TypeError: bot.reply is not a function #316

Closed KittPhi closed 3 years ago

KittPhi commented 3 years ago

Hello, We've created a Custom Botbuilder Adapter to connect to the Vonage API called botbuilder-adapter-vonage-js. To test the Adapter's basic functionality, with a basic bot reply, we send an sms to the Vonage number and should get a sms reply back "Hello Back", but instead receive the error below.

[onTurnError] unhandled error: TypeError: bot.reply is not a function

Not sure how to actually debug the Custom Adapter to find where it is broken.

Would be great to find someone familiar with the either the Botkit Core library and Botkit Platform Adapters could help with this. I've attached the Express Server (webhook-server.js) below.

// webhook-server.js
require('dotenv').config();
const express = require('express');
const app = express();
const port = 3000;
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
const SendMessagesAPI = require('./Vonage-SEND-messages-api');
const VonageAdapter = require('botbuilder-adapter-vonage-js');
const Botkit = require('botkit');

const {
  BotFrameworkAdapter,
  InspectionMiddleware,
  MemoryStorage,
  InspectionState,
  UserState,
  ConversationState,
} = require('botbuilder');

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

// This bot's main dialog.
const { IntersectionBot } = require('./bot');
const { Message } = require('@vonage/server-sdk');

const creds = {
  apiKey: process.env.VONAGE_API_KEY,
  apiSecret: process.env.VONAGE_API_SECRET,
  applicationId: process.env.VONAGE_APPLICATION_ID,
  privateKey: process.env.VONAGE_APPLICATION_PRIVATE_KEY_PATH,
};
const config = {
  to_number: process.env.TO_NUMBER,
  from_number: process.env.FROM_NUMBER,
  // enable_incomplete: true
};

// Create Adapter
const adapter = new VonageAdapter(creds, config);

// Create the Storage provider and the various types of BotState.
const memoryStorage = new MemoryStorage();
const inspectionState = new InspectionState(memoryStorage);
const userState = new UserState(memoryStorage);
const conversationState = new ConversationState(memoryStorage);

// Create and add the InspectionMiddleware to the adapter.
adapter.use(
  new InspectionMiddleware(
    inspectionState,
    userState,
    conversationState,
    new MicrosoftAppCredentials(
      process.env.MicrosoftAppId,
      process.env.MicrosoftAppPassword
    )
  )
);

app.post('/webhooks/dlr', (req, res) => {
  res.status(200).end();
});

// Catch-all for errors.
adapter.onTurnError = async (, error) => {
  // This check writes out errors to console log .vs. app insights.
  // NOTE: In production environment, you should consider logging this to Azure
  //       application insights. See https://aka.ms/bottelemetry for telemetry
  //       configuration instructions.
  console.error(`\n [onTurnError] unhandled error: ${error}`);

  // Send a trace activity, which will be displayed in Bot Framework Emulator
  await .sendTraceActivity(
    'OnTurnError Trace',
    `${error}`,
    'https://www.botframework.com/schemas/error',
    'TurnError'
  );

  // Send a message to the user
  await .sendActivity('The bot encountered an error or bug.');
  await .sendActivity(
    'To continue to run this bot, please fix the bot source code.'
  );
  // Clear out state
  await conversationState.clear();
};

// Create the main dialog.
const bot = new IntersectionBot(conversationState, userState);

// Listen for incoming requests.
app.post('/webhooks/inbound', (req, res) => {
  console.log('/webhooks/inbound req.body', req.body);
  adapter.processActivity(req, res, async () => {

    console.log(context);
    // [onTurnError] unhandled error: TypeError: Cannot read property 'from' of undefined
    // await bot.run();

     //  [onTurnError] unhandled error: TypeError: .reply is not a function
    // await .reply('I heard a message!');

    // [onTurnError] unhandled error: TypeError: bot.reply is not a function
    await bot.reply('Hello Back!');

  });
  res.status(200).end();
});

app.post('/webhooks/status', (req, res) => {
  res.status(200).end();
});

app.listen(port, () => {
  console.log(`🌏 Server running at http://localhost:${port}`);
});

Response

🌏 Server running at http://localhost:3000
/webhooks/inbound req.body {
  message_uuid: 'e93a3007-f7a5-436a-8ba7-c46d64343d80',
  to: { type: 'sms', number: '12018994297' },
  from: { type: 'sms', number: '15754947000' },
  timestamp: '2021-08-27T21:14:51.228Z',
  usage: { price: '0.0057', currency: 'EUR' },
  message: {
    content: { type: 'text', text: 'Hello' },
    sms: { num_messages: '1' }
  },
  direction: 'inbound'
}
TurnContext {
  _respondedRef: { responded: false },
  _turnState: TurnContextStateCollection(2) [Map] {
    'httpStatus' => 200,
    Symbol(state) => { state: [Object], hash: '{}' }
  },
  _onSendActivities: [],
  _onUpdateActivity: [],
  _onDeleteActivity: [],
  _turn: 'turn',
  _locale: 'locale',
  bufferedReplyActivities: [],
  _adapter: VonageAdapter {
    middleware: MiddlewareSet { middleware: [Array] },
    BotIdentityKey: Symbol(BotIdentity),
    OAuthScopeKey: Symbol(OAuthScope),
    name: 'Vonage Adapter',
    middlewares: null,
    botkit_worker: [class VonageBotWorker extends BotWorker],
    credentials: {
      apiKey: '4f2ff535',
      apiSecret: 'jtYzPbh3MXr8M1Hr',
      applicationId: '978500cf-7ea8-4d7b-ac54-2b42f67b28a2',
      privateKey: './private.key'
    },
    options: {},
    to_number: '15754947000',
    from_number: '12018994297',
    enable_incomplete: undefined,
    turnError: [AsyncFunction (anonymous)]
  },
  _activity: {
    id: 'e93a3007-f7a5-436a-8ba7-c46d64343d80',
    timestamp: 2021-08-27T21:14:39.573Z,
    channelId: 'vonage-sms',
    conversation: { id: '15754947000' },
    from: { id: '15754947000' },
    recipient: { id: '12018994297' },
    text: 'Hello',
    channelData: {
      message_uuid: 'e93a3007-f7a5-436a-8ba7-c46d64343d80',
      to: [Object],
      from: [Object],
      timestamp: '2021-08-27T21:14:51.228Z',
      usage: [Object],
      message: [Object],
      direction: 'inbound'
    },
    type: 'message'
  }
}

 [onTurnError] unhandled error: TypeError: bot.reply is not a function
stevkan commented 3 years ago

Closed - dupe of #6373