microsoft / botframework-sdk

Bot Framework provides the most comprehensive experience for building conversation applications.
MIT License
7.48k stars 2.44k forks source link

Sending a message outside of a dialog (without Session) #1239

Closed etherealiska closed 8 years ago

etherealiska commented 8 years ago

I'm trying to send messages whenever our http server gets a post request. The only time I can successfully send messages with the bot is when we are inside a dialog, but we need more freedom when deciding who or where we send the message to. I thought using Universalbot.send or ChatConnector.send with a correctly configured message object would work, but it doesn't.

import { ChatConnector, IChatConnectorAddress, IMessage,
         IIdentity, Message, UniversalBot, IAddress } from 'botbuilder';

const appId = process.env['ID'];
const appPassword = process.env['SECRET'];
const connector = new ChatConnector({ appId, appPassword });
const bot = new UniversalBot(connector);

let usr: IIdentity = {
    id: "randomuserid:teamid",
    name: "randomuser"
}
let chatBot: IIdentity = {
    id: "chatbotid:teamid",
    name: "beboop"
}

let conv: IIdentity = {
    id: "chatbotid:teamid:otherid",
    isGroup: false
}
let adr: IChatConnectorAddress = {
    channelId: "slack",
    user: usr,
    bot: chatBot,
    serviceUrl: 'https://slack.botframework.com'
}

connector.startConversation(adr, (err, address) => {
    let msgs = [new Message().text('Please work').address(address).toMessage()];

    if (err) {
        httpserver.send(`Error when starting conversation: ${JSON.stringify(err)}`);
    }

    connector.send(msgs, (err) => {
        if (err) {
            httpserver.send(`Error when sending messages with connector: ${JSON.stringify(err)}`);
        }
    });

    bot.send(msgs[0], (err) => {
        if (err) {
            httpserver.send(`Error when sending messages with universalBot: ${JSON.stringify(err)}`);
        }
    });

    httpserver.send(`The address info is ${JSON.stringify(address)}`);
}

I don't get any errors when sending the messages anymore. And it prints out the address of the "new" conversation.

{  
   "channelId": "slack",
   "user": {  
      "id": "randomuserid:teamid",
      "name": "randomuser"
   },
   "bot": {  
      "id": "chatbotid:teamid",
      "name": "beboop"
   },
   "serviceUrl": "https://slack.botframework.com",
   "conversation": {  
      "id": "randomuserid:teamid:otherid"
   }
}

So I'm guessing it's getting the wrong id of the conversation that already existed (that's what the conv variable represents. We had the bot eval a bunch of stuff inside the dialog so we could see what the session variables were. It says that the conversation between randomuser and the bot is "B254Z90TF:T03C6CW9H:D270N8FK4". StartConversation gave us back the "wrong" conversation id so we are wondering how to fix it or if we're barking up the wrong tree how do we send a message to any user that we want?

willportnoy commented 8 years ago

Are https://github.com/Microsoft/BotBuilder/issues/1193#issuecomment-246418074 and https://github.com/Microsoft/BotBuilder/issues/196#issuecomment-216407279 relevant for your question?

etherealiska commented 8 years ago

Relevant yes, but the answer is outdated. bot.beginDialog() takes an IAddress as the first parameter not an object with the keys to and from. I have an IAddress created, and a new dialog does not begin when I call beginDialog() whether or not I specify the conversation id. I have also tried multiple conversation ids.

etherealiska commented 8 years ago

I also think it has to do with the session object. That is the only way I've been able to get a message to send, and the root dialog / automatically starts whenever the bot is added to a channel through slack not the framework. I have not been able to initiate anything bot related using the framework. And it seems like the users/channels are constantly in a dialog with the bot. Just trying to relay more information.

craigjensen commented 8 years ago

This is a bug in the Slack channel (StartConversation is returning an incorrectly formatted ConversationId). We'll get a fix ready and it will go live the next time we deploy - probably later this week.

etherealiska commented 8 years ago

So here is how we got direct messages working. We ended up using the session object for testing purposes, but theoretically you don't need to since you can compose the address object if you know the correct id's.

let testSession = <Session>{} ;

bot.dialog('/', [
    (session) => {
        testSession = session;
        session.send('Session saved!');
        Prompts.text(session, "Test > ");
    }
]);

const poke: RequestHandler = (req, res, next) => {
    let testAddress = <IChatConnectorAddress> {
        channelId: 'slack',
        user: testSession.message.address.user,
        conversation: testSession.message.address.conversation,
        bot: testSession.message.address.bot,
        serviceUrl: 'https://slack.botframework.com',
        useAuth: true
    }

    let msg = new Message()
                .text(`<@${testAddress.user.name}> Holla!`)
                .address(testAddress);

    bot.send(msg, (err) => {
        if (err) {
            httpserver.send(`Error when sending messages with universalBot: ${JSON.stringify(err)}`);
            return next();
        }
    });
}

httpserver.get('/poke', poke)

Enter a dialog with your bot, and then it saves the session. Use your http server to poke it and see if you get a message.

slidenerd commented 7 years ago

Well you could also access the user as session.message.user instead of session.address.user right? Do they stay the same in that case