Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Developing Bots for Slack

Developing Bots for Slack

Slack has become incredibly popular, and it provides a new way for developers to build applications, and services. There is a lot of interest in creating for this platform, but there's more to it than just code. The whole process from research, to publishing and distribution will be covered in this session.

Nic Rosental

October 21, 2016
Tweet

More Decks by Nic Rosental

Other Decks in Programming

Transcript

  1. During this presentation • What’s a bot? • How does

    it integrate with Slack? • Technical details • Publishing 2
  2. What is a bot? An application integrated in Slack that

    responds to certain events, and facilitates a particular function. 3
  3. Slack loves developers • Several integration options • Very friendly

    support, and review process • Continuously improving their offering, and adding new features 4
  4. Integration options • Apps vs custom integrations • Incoming webhooks

    • Slash commands • Bot users • Web API • RTM API • Events API Must read: https://api.slack.com/custom-integrations 5
  5. Apps vs Custom Integrations • A custom integration is intended

    for you and/or your team only. • An app is intended for distribution. 6
  6. Slash commands • On-demand actions • Submits an HTTP request

    to your endpoint • Three flavors: built-in, custom integrations, app commands 10
  7. Custom commands • Built for your team only • Less

    restrictions than app commands • Posts data to your endpoint • Uses POST or GET 12
  8. Custom commands 14 array ( 'token' => 'p4kmwaIEH2fhvWcxK2lpRhhA', 'team_id' =>

    'T024P6FT6', 'team_domain' => 'epiclabs', 'channel_id' => 'C024P6FTC', 'channel_name' => 'general', 'user_id' => 'U024P6FT8', 'user_name' => 'nic', 'command' => '/connecttech', 'text' => 'hi everyone', 'response_url' => 'https://hooks.slack.com/ commands/T024P6FT6/93631069287/ vyMFuDw5sv4JA7rF8dUXx9jg', )
  9. Custom commands 15 public function handle($request, Closure $next) { if($request->input('token')

    === env('SLACK_COMMAND_TOKEN')) { return $next($request); } abort(403, 'You don\'t look like a Slack instance'); }
  10. App commands • Only POST requests • They can only

    send requests to SSL endpoints with valid certificates (no self-signed) • Not all users may be allowed to install apps 16
  11. Bot users • Bots are (mostly) like other users •

    They can be standalone or part of an application • They have a name and icon 17
  12. Web API • HTTP-RPC style • https://slack.com/api/chat.postMessage • Uses bearer

    token obtained via OAuth • During development you can use a test token provided by Slack 18
  13. Real Time Messaging API • Based on web sockets •

    Listen to everything, react to what you want 21
  14. Events API • Implemented very recently • Much less resource

    intensive than RTM API • Subscribe to only the events you are interested in 22
  15. Tools • Botkit • https://howdy.ai/botkit/ • Tons of other clients

    and libraries • https://api.slack.com/community 25
  16. /Lunchbox • A bot that helps you schedule lunch outings.

    • Originally built in NodeJS, then re- written in PHP/Laravel • Installed by over 1,300 Slack teams 26
  17. How it works • A user issues a slash command

    with one or more lunch spots, and optionally a time • The app parses the command • The app posts a message back as the Lunchbox bot, giving options to the users to pick one of more of the spots • Users interact with the message by clicking on the buttons • The app updates the message to show who’s going 27
  18. 28

  19. Nuts & bolts 29 <a href="https://slack.com/oauth/authorize? scope=commands,bot&client_id={{env('SLACK_CLIENT_ID')}}"><img alt="Add to Slack"

    height="40" width="139" src="https:// platform.slack-edge.com/img/add_to_slack.png" srcset="https:// platform.slack-edge.com/img/add_to_slack.png 1x, https:// platform.slack-edge.com/img/[email protected] 2x" /></a>
  20. 30

  21. 31 Route::get('/oauth', ['uses' => 'Auth\OAuthController@oauth']); public function oauth(Request $request) {

    $queryString = [ 'client_id' => env('SLACK_CLIENT_ID'), 'client_secret' => env('SLACK_CLIENT_SECRET'), 'code' => $request->input('code'), 'redirect_uri' => env('SLACK_OAUTH_REDIRECT_URI') ]; $httpClient = new Client(['base_uri' => env('SLACK_AUTH_URL')]); $response = $httpClient->request('GET', env('SLACK_AUTH_URL'), ['query' => $queryString])->getBody(true)->getContents(); // Get team data from exchaging OAuth code for permanent token $teamData = json_decode($response, true); $team = Team::firstOrCreate([ 'access_token' => $teamData['access_token'], 'user_id' => $teamData['user_id'], 'team_name' => $teamData['team_name'], 'team_id' => $teamData['team_id'], 'bot_user_id' => $teamData['bot']['bot_user_id'], 'bot_access_token' => $teamData['bot']['bot_access_token'] ]);
  22. Nuts & bolts 32 Route::post('lunch', ['middleware' => 'slackCommandToken', 'uses' =>

    ‘LunchRequestController@store']); Route::post('button', ['middleware' => 'slackButtonToken', 'uses' => 'RsvpController@store']);
  23. Nuts & bolts 33 array ( 'token' => 'TvtGRbZxWF5x8yQj8LaGuaxS', 'team_id'

    => 'T024P6FT6', 'team_domain' => 'epiclabs', 'channel_id' => 'C2S8W8NDS', 'channel_name' => 'connect16', 'user_id' => 'U024P6FT8', 'user_name' => 'nic', 'command' => '/lunchdev', 'text' => 'at burger place, taco place, or the venue at noon', 'response_url' => 'https://hooks.slack.com/commands/ T024P6FT6/94331958849/yFWwkUFOGThrUfSW5as2YQ99', ) /lunchdev at burger place, taco place, or the venue at noon
  24. Nuts & bolts 34 public function handle($request, Closure $next) {

    if($request->input('token') === env('SLACK_COMMAND_TOKEN')) { return $next($request); } abort(403, 'You don\'t look like a Slack instance'); } // $request->input('token') is the same as $_POST['token']
  25. Nuts & bolts 35 $lunchParams = $request->all(); … $messageParser =

    new MessageParser($lunchParams); … $messageComposer = new MessageComposer( $messageParser->restaurants, $messageParser->timeSegment, $messageParser->channel, $lunchParams['user_name'], $lunchParams[‘callbackId’]); … $this->slack->webApi('chat.postMessage', $messageComposer- >getMessage());
  26. Nuts & bolts 36 array ( 'channel' => 'C2S8W8NDS', 'username'

    => 'LunchboxDev', 'text' => '<!here|here> Friends don’t let friends eat lunch alone. *Organized by*: @nic *When*: noon', 'attachments' => '[{"text":"Pick one or more spots","callback_id":"e5da1240-9736-11e6- be02-7831c1c6b872","color":"#3AA3E3","attachment_type":"default","actions": [{"name":"burger place","text":"burger place","type":"button","value":"burger place"},{"name":"taco place","text":"taco place","type":"button","value":"taco place"},{"name":"the venue","text":"the venue","type":"button","value":"the venue"}]}]', )
  27. 37

  28. array ( 'actions' => array ( 0 => array (

    'name' => 'the venue', 'value' => 'the venue', ), ), … 'original_message' => array ( 'text' => '<!here|here> Friends don’t let friends eat lunch 'type' => 'message', 'subtype' => 'bot_message', 'ts' => '1477018069.000016', ), … Nuts & bolts 38
  29. 39

  30. 43

  31. Share the love • Follow the checklist https://api.slack.com/docs/slack- apps-checklist •

    Make a landing page • Provide documentation (dog food it) • Provide a clear support contact • Use the Slack button • Don’t spam or abuse your users or the platform 44
  32. 45