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

Developing Bots for Slack - ConvergeSE 2017

Developing Bots for Slack - ConvergeSE 2017

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

June 16, 2017
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 internal integrations • Incoming webhooks

    • Slash commands • Bot users • Web API • RTM API • Events API Must read: https://api.slack.com/internal-integrations 5
  5. Apps vs Internal Integrations • A internal 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 9
  7. App commands • 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 11
  8. App Commands 13 array ( 'token' => 'p4kmwaIEH2fhvWcxK2lpRhhA', 'team_id' =>

    'T024P6FT6', 'team_domain' => 'epiclabs', 'channel_id' => 'C024P6FTC', 'channel_name' => 'general', 'user_id' => 'U024P6FT8', 'user_name' => 'nic', 'command' => ‘/convergese', 'text' => 'hi everyone', 'response_url' => 'https://hooks.slack.com/ commands/T024P6FT6/93631069287/ vyMFuDw5sv4JA7rF8dUXx9jg', )
  9. App Commands 14 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. Bot users • Bots are (mostly) like other users •

    They can be standalone or part of an application • They have a name and icon 15
  11. 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 16
  12. Real Time Messaging API • Based on web sockets •

    Listen to everything, react to what you want 19
  13. Events API • Much less resource intensive than RTM API

    • Subscribe to only the events you are interested in 20
  14. Tools • Botkit • https://howdy.ai/botkit/ • Tons of other clients

    and libraries • https://api.slack.com/community 23
  15. /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 24
  16. 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 25
  17. 26

  18. Nuts & bolts 27 <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>
  19. 28

  20. 29 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'] ]);
  21. Nuts & bolts 30 Route::post('lunch', ['middleware' => 'slackCommandToken', 'uses' =>

    ‘LunchRequestController@store']); Route::post('button', ['middleware' => 'slackButtonToken', 'uses' => 'RsvpController@store']); /lunch /button
  22. Nuts & bolts 31 [ '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
  23. Nuts & bolts 32 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']
  24. Nuts & bolts 33 $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());
  25. Nuts & bolts 34 [ '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”}]}]' ]
  26. 35

  27. [ 'actions' => [ 0 => [ 'name' => 'the

    venue', 'value' => 'the venue', ], ], ] … 'original_message' => [ 'text' => '<!here|here> Friends don’t let friends eat lunch 'type' => 'message', 'subtype' => 'bot_message', 'ts' => '1477018069.000016', ], Nuts & bolts 36
  28. 37

  29. 41

  30. 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 42
  31. 43