Hubot-slack: Send Direct Message from user name

Created on 28 Jul 2016  Â·  30Comments  Â·  Source: slackapi/hubot-slack

  • [x] I've read and understood the Contributing guidelines and have done my best effort to follow them.
  • [x] I've read and agree to the Code of Conduct.
  • [x] I've searched for any related issues and avoided creating a duplicate issue.

    Description

Cannot send direct message from the user name / user id.
Direct channel id needed (Starting with "D")
The only workaround i found is to direct message the bot and then store this direct channel id for later reuse...

Reproducible in:

hubot-pokemongo version: dev branch
OS version(s): *
Device(s): *

Steps to reproduce:

  1. Download hubot-pokemongo from the dev branch (npm version can't handle v4 of hubot-slack at all, rawText removed)
  2. cd /path/to/hubot && npm install /path/to/hubot-pokemongo
  3. Add "hubot-pokemongo" to your external-script.json
  4. set hubot-slack to version 4.0.1
  5. start hubot with the slack adapter
  6. In slack, /invite @hubot in channel, setup an address with pogo add 43.6043278 1.446728(and wish that niantic & pokevision servers are up) (This address should get some pokemon, as it's in the center of city)
  7. pogo timer 1 and pogo range 1000 to faster result

    Expected result:

    robot.messageRoom(username, message) send direct message to the username
    (Working with hubot-slack 3.4.2)

    Actual result:

    robot.messageRoom(username, message) throws errors on the channel id.
    Could only send direct message with the Direct message/channel ID (starting with D).
    Cannot "self open" direct message channel.

Full error : Unhandled rejection SlackRTMError: invalid channel id

Attachments:

The call to robot.messageRoom (or robot.send) can be found here

Thanks !

bug

Most helpful comment

Having the same issue, here is my current workaround.

room = robot.adapter.client.rtm.dataStore.getDMByName res.message.user.name
robot.messageRoom room.id, "Hello, this is a private message!"

All 30 comments

Having the same issue, here is my current workaround.

room = robot.adapter.client.rtm.dataStore.getDMByName res.message.user.name
robot.messageRoom room.id, "Hello, this is a private message!"

Note that even with @AvonGenesis's "fix", hubot does not open a new DM channel when one doesn't exist yet. I swapped out the code in hubot-help to use the code above, and I get "can't read property id of undefined" error:

Sep 13 08:38:10 host1 hubot: [Tue Sep 13 2016 08:38:10 GMT-0700 (PDT)] ERROR TypeError: Cannot read property 'id' of undefined
Sep 13 08:38:10 host1 hubot: at TextListener.callback (/home/hubot/my_bot/node_modules/hubot-help/src/help.coffee:78:7, <js>:28:38)
Sep 13 08:38:10 host1 hubot: at executeListener (/home/hubot/my_bot/node_modules/hubot/src/listener.coffee:65:11, <js>:53:19)
Sep 13 08:38:10 host1 hubot: at allDone (/home/hubot/my_bot/node_modules/hubot/src/middleware.coffee:44:37, <js>:34:16)
Sep 13 08:38:10 host1 hubot: at /home/hubot/my_bot/node_modules/async/lib/async.js:274:13
Sep 13 08:38:10 host1 hubot: at Object.async.eachSeries (/home/hubot/my_bot/node_modules/async/lib/async.js:142:20)
Sep 13 08:38:10 host1 hubot: at Object.async.reduce (/home/hubot/my_bot/node_modules/async/lib/async.js:268:15)
Sep 13 08:38:10 host1 hubot: at /home/hubot/my_bot/node_modules/hubot/src/middleware.coffee:49:7, <js>:37:22
Sep 13 08:38:10 host1 hubot: at _combinedTickCallback (internal/process/next_tick.js:67:7)
Sep 13 08:38:10 host1 hubot: at process._tickCallback (internal/process/next_tick.js:98:9)

The interesting thing here is that I'm not sure why you would even try to use a DM in this case—I was attempting to do so, then ran into what @iancward did. Then I realized that targeting a user's ID does the same thing, without the previous instantiation of a DM channel with the bot being required:

getUser = (msg, bot, userInputUser) ->
  try
    user = bot.adapter.client.rtm.dataStore.getUserByName(userInputUser)
    if user
      logger "getUser: Got results for #{userInputUser} by name"
      return user
  try
    user = bot.adapter.client.rtm.dataStore.getUserById(userInputUser)
    if user
      logger "getUser: Got results for #{userInputUser} by id"
      return user

  logger "getUser ERROR: No results for #{userInputUser}"

bot.messageRoom getUser(msg, bot, username).id, message

To me, this makes the usage and/or necessity of DM IDs basically useless.

@qualman I don't know if I understand; were you able to find a way to send a message to a user that didn't have a DM channel opened previously? I'm building a custom script and had to use robot.adapter.client.web.im.open to open a new DM before I could robot.messageRoom room.id, "message".

@iancward correct. Using the above (which is just a simple try to resolve the user by name and id) you get the user object back. Then you can just use the messageRoom function to target the user's id (U12345678) and it works just the same as targeting the DM ID (D12345678), without having to dink around with initiating a DM session and getting an ID. I.e., it sends a user, whom the bot has never communicated with before, a DM.

Unless this is an unintended ability or something, I don't see why you would try to use DM when you can just target the user ID.

I actually never had problem with getUserbyName. If you send the User ID to messageRoom, you get Unhandled rejection SlackRTMError: invalid channel id if the channel is not yet opened.

Sep 13 09:03:00 host1 hubot: [Tue Sep 13 2016 09:03:00 GMT-0700 (PDT)] DEBUG Sending to U24L4SZJ6: action is: cheese
Sep 13 09:03:00 host1 hubot: [Tue Sep 13 2016 09:03:00 GMT-0700 (PDT)] DEBUG ~~~~~~~
Sep 13 09:03:00 host1 hubot: [Tue Sep 13 2016 09:03:00 GMT-0700 (PDT)] DEBUG action is: cheese
Sep 13 09:03:00 host1 hubot: Unhandled rejection SlackRTMError: invalid channel id
Sep 13 09:03:00 host1 hubot: at RTMClient.handleMessageAck [as _handleMessageAck] (/home/hubot/my_bot/node_modules/@slack/client/lib/clients/rtm/client.js:497:40)
Sep 13 09:03:00 host1 hubot: at RTMClient._handleWsMessageViaEventHandler (/home/hubot/my_bot/node_modules/@slack/client/lib/clients/rtm/client.js:460:12)
Sep 13 09:03:00 host1 hubot: at RTMClient.handleWsMessage (/home/hubot/my_bot/node_modules/@slack/client/lib/clients/rtm/client.js:420:10)
Sep 13 09:03:00 host1 hubot: at WebSocket.wrapper (/home/hubot/my_bot/node_modules/@slack/client/node_modules/lodash/lodash.js:4762:19)
Sep 13 09:03:00 host1 hubot: at emitTwo (events.js:106:13)
Sep 13 09:03:00 host1 hubot: at WebSocket.emit (events.js:191:7)
Sep 13 09:03:00 host1 hubot: at Receiver.ontext (/home/hubot/my_bot/node_modules/ws/lib/WebSocket.js:841:10)
Sep 13 09:03:00 host1 hubot: at /home/hubot/my_bot/node_modules/ws/lib/Receiver.js:536:18
Sep 13 09:03:00 host1 hubot: at Receiver.applyExtensions (/home/hubot/my_bot/node_modules/ws/lib/Receiver.js:371:5)
Sep 13 09:03:00 host1 hubot: at /home/hubot/my_bot/node_modules/ws/lib/Receiver.js:508:14
Sep 13 09:03:00 host1 hubot: at Receiver.flush (/home/hubot/my_bot/node_modules/ws/lib/Receiver.js:347:3)
Sep 13 09:03:00 host1 hubot: at Receiver.opcodes.1.finish (/home/hubot/my_bot/node_modules/ws/lib/Receiver.js:541:12)
Sep 13 09:03:00 host1 hubot: at Receiver.<anonymous> (/home/hubot/my_bot/node_modules/ws/lib/Receiver.js:499:31)
Sep 13 09:03:00 host1 hubot: at Receiver.add (/home/hubot/my_bot/node_modules/ws/lib/Receiver.js:103:24)
Sep 13 09:03:00 host1 hubot: at TLSSocket.realHandler (/home/hubot/my_bot/node_modules/ws/lib/WebSocket.js:825:20)
Sep 13 09:03:00 host1 hubot: at emitOne (events.js:96:13)
Sep 13 09:03:00 host1 hubot: at TLSSocket.emit (events.js:188:7)
Sep 13 09:03:00 host1 hubot: at readableAddChunk (_stream_readable.js:177:18)
Sep 13 09:03:00 host1 hubot: at TLSSocket.Readable.push (_stream_readable.js:135:10)
Sep 13 09:03:00 host1 hubot: at TLSWrap.onread (net.js:542:20)

@iancward are you using the adapter from npm? I was getting this issue too, then I realized that hubot-slack in npm hasn't gone to v4 yet, so I started targeting package.json here at the repo. Once I did that, user ID messaging worked.

you mean hubot-slack on npm? https://www.npmjs.com/package/hubot-slack is version 4.0.4.
And I have this in package.json:
"hubot-slack": "^4.0.4"

Oh, i tried a bit ago, so it must have been updated since then.

In that case, I am very confused. I am confident that targeting by user ID is working here, I'm on effective version 4.0.2 ("hubot-slack": "git://github.com/slackhq/hubot-slack.git#825de6b",). Maybe one of the contributors can speak to this...

Note: Sending a message to a DM Id requires a DM to have been opened first. Sending a message to a User Id will automatically create the DM in the background, and succeed. It is recommended to _always_ initiate DMs via User Id, rather than DM Id when possible.

Does that fact resolve this issue?

Also: Username works too.

@DEGoodmanWilson I think that's what I had tried to do (see log in post above), but I got the "invalid channel id" message. Now that I have a DM created already, it's hard to test, but I can see if I can try to reproduce with a different user.

Interesting. I get invalid_channel_id if I leave off the @-sign in the username in the API tester
https://api.slack.com/methods/chat.postMessage/test
But if the @-sign is included, it works. Now I need to check how this stuff is wired in this project.

@DEGoodmanWilson Ok, then I don't feel like a total failure; I didn't prepend an "@" symbol to the DM. I did a getUserById and then tried to messageRoom to user.id, which won't include the @ symbol.

OK, good, so if we get that in one of the places where we are sending a message to that user, we can prepend an @ to get the right behavior then. I'll roll that out for 4.0.5 today.

So it looks like the _only_ way to send a message to a user _by username_ is to prepend the username with an @. Strings without @'s are interpreted as channel names. Arguable, a user _is also_ a channel, but hey we work with what we are given ;)

So, there are three options:
Set the envelope room to a user id
Set the envelope room to a username, manually prepended with an @
Look at this PR, and start just using user objects as envelopes: https://github.com/slackhq/hubot-slack/pull/358

Feedback, please!

Well, now that I think of it, I don't think the issue was with using the @ symbol.
In my test above, I essentially did this:
res.messageRoom 'U24L4SZJ6', 'action is: cheese'

and got the invalid channel id error mentioned above. At least, I think I did this; maybe I just sent the user object instead. In either case, I just tried sending a DM to a new person using the API tester and it opened a new channel for me. Maybe I am going crazy...

Yeah, I figured out what that is happening ;) Try it now with the PR #358, I think I have the more important bug that you are reporting sorted out here now too.

So, in #358 the following all work:

    robot.messageRoom "general", "whoa"
    robot.messageRoom "C1234", "yeah"
    robot.messageRoom "@don", "hello again"
    robot.messageRoom "U1234", "hello"

Would the messageRoom <channel_name> work both for public channels as well as private groups?

Ah, it looks like putting a # before a private channel works in the API tester.

The # is optional for all channels. The original difficulty stems from the fact that sometimes, when possible, we would send messages via the RTM api, which _requires_ a channel or DM ID, and does not accept names for channels or users.

This seems to work for public channels, but it doesn't seem to want to work for private groups. Is that expected?

Private groups are a bit weird. That said, in my testing sending messages to both "private-channel" and "#private-channel" worked…

Unless you mean MPDMs? Those don't have names, so…they have to be referred to by ID :(

I had something like this:

robot.router.post '/hubot/hook/:room, (req, res) ->
  channel = req.params.room
  robot.messageRoom channel, "this is a test message"
  res.send 'OK'

If I hit the webhook with the channel name (without #), it worked if I specified a public channel, but when I tried the name of a private group (private channel), I got this error:
Unhandled rejection SlackAPIError: channel_not_found

Just to check: Is Hubot a member of that private channel? If it isn't, that's the expected error.

d'oh! that would make a difference, wouldn't it.

I updated hubot-slack to version 4.0.5 in my package.json and it looks like hubot is still unable to open a new DM.
I see something like:

Sep 19 10:46:56 host1 hubot: [Mon Sep 19 2016 10:46:56 GMT-0700 (PDT)] DEBUG  Sending to ian.ward: <snip>
Sep 19 10:46:56 host1 hubot: Unhandled rejection SlackAPIError: channel_not_found
Sep 19 10:46:56 host1 hubot: at makeAPICallPromiseResolverInner (/home/hubot/my_bot/node_modules/@slack/client/lib/clients/client.js:156:22)
Sep 19 10:46:56 host1 hubot: at handleHttpResponse (/home/hubot/my_bot/node_modules/@slack/client/lib/clients/transports/call-transport.js:105:5)
Sep 19 10:46:56 host1 hubot: at handleTransportResponse (/home/hubot/my_bot/node_modules/@slack/client/lib/clients/transports/call-transport.js:142:19)
Sep 19 10:46:56 host1 hubot: at apply (/home/hubot/my_bot/node_modules/@slack/client/node_modules/lodash/lodash.js:484:17)
Sep 19 10:46:56 host1 hubot: at wrapper (/home/hubot/my_bot/node_modules/@slack/client/node_modules/lodash/lodash.js:5156:16)
Sep 19 10:46:56 host1 hubot: at Request.handleRequestTranportRes (/home/hubot/my_bot/node_modules/@slack/client/lib/clients/transports/request.js:20:5)
Sep 19 10:46:56 host1 hubot: at apply (/home/hubot/my_bot/node_modules/@slack/client/node_modules/lodash/lodash.js:484:17)
Sep 19 10:46:56 host1 hubot: at Request.wrapper [as _callback] (/home/hubot/my_bot/node_modules/@slack/client/node_modules/lodash/lodash.js:5156:16)
Sep 19 10:46:56 host1 hubot: at Request.self.callback (/home/hubot/my_bot/node_modules/request/request.js:187:22)
Sep 19 10:46:56 host1 hubot: at emitTwo (events.js:106:13)
Sep 19 10:46:56 host1 hubot: at Request.emit (events.js:191:7)
Sep 19 10:46:56 host1 hubot: at Request.<anonymous> (/home/hubot/my_bot/node_modules/request/request.js:1044:10)
Sep 19 10:46:56 host1 hubot: at emitOne (events.js:96:13)
Sep 19 10:46:56 host1 hubot: at Request.emit (events.js:188:7)
Sep 19 10:46:56 host1 hubot: at IncomingMessage.<anonymous> (/home/hubot/my_bot/node_modules/request/request.js:965:12)
Sep 19 10:46:56 host1 hubot: at emitNone (events.js:91:20)
Sep 19 10:46:56 host1 hubot: at IncomingMessage.emit (events.js:185:7)
Sep 19 10:46:56 host1 hubot: at endReadableNT (_stream_readable.js:975:12)
Sep 19 10:46:56 host1 hubot: at _combinedTickCallback (internal/process/next_tick.js:74:11)
Sep 19 10:46:56 host1 hubot: at process._tickCallback (internal/process/next_tick.js:98:9)
Was this page helpful?
0 / 5 - 0 ratings