scrapinghub / slackbot

A chat bot for Slack (https://slack.com).
MIT License
1.26k stars 394 forks source link

How do you DM an arbitrary user? #142

Open lovato opened 7 years ago

lovato commented 7 years ago

Hi. I read all docs, all issues, and still have no luck. Something is still wrong.

I cannot post something direct to someone. This code:

def say_to_slack(channel, text, attachments=None):
    url = u'https://hooks.slack.com/services/T4xxxx/B4xxx/duzzzzzz'
    headers = {u'Content-type': u'application/json'}
    data = {'text': text,
            "channel": channel,
            "link_names": 1,
            "username": "bot_name",
            "icon_url": "https://avata...ab_72.png",
            "attachments": attachments
            }
    return requests.post(url, data=json.dumps(data), headers=headers)

Posts anything to a channel, but when I try to post to someone, it "sort of" works, but the message gets delivered through Slack's Slackbot, not from my bot. So, looks odd from the receiver perspective.

I tryed too directly on CLI: client.rtm_send_message(client.find_channel_by_name('channel_x'),'test') It works for a channel. client.rtm_send_message(client.find_user_by_name('user_x'),'test') Nothing happens on Slack. And I got no error back. I dont even know if this is allowed.

Do I need to set up some missing permission for direct messages? Am I using the wrong code? Since the bot is running on a loop, I imagined just getting the running client (but there is client object to get on the default examples), and call a send method.

Any advice?

lovato commented 7 years ago

I tryed this:

image

Then I took a look on the dispatcher code, and it indeed uses a channel field to pass a username. In any case, it never worked. I only can get error messages if I use a channel as a destination.

lovato commented 7 years ago

Now I tried: bot._client.rtm_send_message('C542xxxxx','test') Works... but when I try a user, nothing happens.

lovato commented 7 years ago

and... it worked. This method also says a CHANNEL, but specifically this one accepts a username. bot._client.send_message('U4N1xxxxx', 'test2')

So, I wonder...

if self._errors_to:
                        self._client.rtm_send_message(msg['channel'], reply)
                        self._client.rtm_send_message(self._errors_to,
                                                      '{}\n{}'.format(reply,
                                                                      tb))
                    else:
                        self._client.rtm_send_message(msg['channel'],
                                                      '{}\n{}'.format(reply,
                                                                      tb))

Is it really working? Or it needs to be send_message ???

Tks

jtatum commented 7 years ago

Slack DMs are weird. Replying to a DM is simple, but starting a new DM is a pain. You have to establish a DM channel. See https://api.slack.com/methods/im.open.

Note that DM channels start with D and while they're often similar to user IDs, that's not guaranteed. Also, as mentioned, the DM has to be "open" before you can send to it. This is already the case if a user DMed a bot, but if a bot needs to DM a random user, it will need to use the im.open method.

jtatum commented 7 years ago

Incidentally, the errors_to code probably does this slightly wrong, but I think that's okay for the common case - generally, bot owners have DMed the bot at least once. That said, it's probably something we should look at in the future and maybe add some convenience methods for doing this.

twcurrie commented 7 years ago

This PR will allow you to directly message the sender of a message: https://github.com/lins05/slackbot/pull/161