Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 75f481d

Browse files
committed
🙈 Version 1.0 complete
0 parents  commit 75f481d

File tree

15 files changed

+790
-0
lines changed

15 files changed

+790
-0
lines changed

‎.gitignore‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
build/*
2+
env/*
3+
env_vars.py
4+
*.pyc

‎LICENSE‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2016 Shannon Burns
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

‎README.md‎

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# pythOnBoarding Bot
2+
## Building a simple bot using [Slack's Events API](https://api.slack.com/events-api) in Python
3+
This bot is an example implementation of building a Slack App with Slack's Python SDK, [python-slackclient](http://python-slackclient.readthedocs.io/en/latest/). We'll cover all the basic steps you'll need to create and configure your first Slack App in python.
4+
5+
PythOnBoarding Bot is designed to greet new users on your team and introduce them to some nifty features in Slack.
6+
7+
>![onboarding](https://cloud.githubusercontent.com/assets/32463/20369171/690028d2-ac0c-11e6-95a1-c3078762fddd.gif)
8+
9+
Let's go write some code. You got this! :sparkles:
10+
11+
#### Technical Requirements
12+
13+
This example uses [Python](https://www.python.org/downloads/), specifically version 2.7 so you'll need to make sure you are using the correct version of Python. We'll also use a number of python packages you can install through [pip.](https://pip.pypa.io/en/stable/installing/)
14+
15+
###### Here's a list of what we'll need:
16+
17+
- **[Python](https://www.python.org/downloads/)**, the programming language we're
18+
going to use.
19+
- **[Pip](https://pip.pypa.io/en/stable/installing/)**, the Python package manager
20+
we'll use for installing packages we need.
21+
- **[Virtualenv](https://virtualenv.pypa.io/en/latest/installation/)** or another
22+
tool to manage a virtual environment
23+
24+
Once you've installed Python, pip and virtualenv, you can install all additional
25+
dependent libraries using pip and the `requirements.txt` file included in this
26+
project, including [Flask](http://flask.pocoo.org/), a web development micro
27+
framework for Python and [python-slackclient](http://python-slackclient.readthedocs.io/en/latest/), a
28+
Slack client for Python. :snake:
29+
30+
After you've cloned this repository locally, you'll want to create a virtual
31+
environment to keep the dependencies for this project isolated from any other
32+
project you may be working on.
33+
34+
If you're using `virtualenv` run the following commands from the root of your
35+
project directory:
36+
37+
```bash
38+
virtualenv env
39+
```
40+
41+
Then activate your new virtual environment:
42+
43+
```bash
44+
source env/bin/activate
45+
```
46+
47+
After that, you can install all the Python packages this project will need with
48+
this command:
49+
50+
```bash
51+
pip install -r requirements.txt
52+
```
53+
54+
###### Server Requirements
55+
56+
Slack will be delivering events to your app's server so your server needs to be able to receive incoming HTTPS traffic from Slack.
57+
58+
If you are running this project locally, you'll need to set up tunnels for Slack to connect to your endpoints. [Ngrok](https://ngrok.com/) is an easy to use tunneling tool that supports HTTPS, which is required by Slack.
59+
60+
You'll likely want to test events coming to your server without going through the actions on your Slack team. [Postman](https://www.getpostman.com/) is a useful tool you can use to recreate requests sent from Slack to your server. This is especially helpful for events like user join, where the workflow to recreate the event requires quite a bit of set up.
61+
62+
## Let's get started :tada:
63+
* **[Section 1: ~~Steal~~ Build This Bot](docs/Section-1.md)** :point_left:
64+
* [Section 2: Create a Slack App and Bot User](docs/Section-2.md)
65+
* [Section 3: Subscribe to Events](docs/Section-3.md)
66+
* [Section 4: App Credentials](docs/Section-4.md)
67+
* [Section 5: Make it Go](docs/Section-5.md)
68+
69+
## Further Reading and Getting Help
70+
71+
### Documentation
72+
73+
##### Slack Documentation
74+
* [Getting started with Slack apps](https://api.slack.com/slack-apps)
75+
* [Slack Events API documentation](https://api.slack.com/events)
76+
* [Slack Web API documentation](https://api.slack.com/web)
77+
78+
##### Documentation for Tools
79+
* [virtualenv](https://virtualenv.pypa.io/en/latest/userguide/)
80+
* [flask](http://flask.pocoo.org/)
81+
* [python-slackclient](http://python-slackclient.readthedocs.io/en/latest/)
82+
* [ngrok](https://ngrok.com/docs)
83+
* [postman](https://www.getpostman.com/docs/)
84+
85+
### Where to Find Help
86+
87+
Wondering what to do if you can't get this dang tutorial to work for you?
88+
The Slack Developer community is an awesome place to get help when you're confused
89+
or stuck. We have an excellent 'search first' culture and Slack is committed to
90+
improving our tutorials and documentation based on your feedback. If you've
91+
checked the [Slack API documentation](https://api.slack.com/), reached the end
92+
of your google patience and found [StackOverflow](http://stackoverflow.com/questions/tagged/slack-api)
93+
to be unhelpful, try asking for help in the [Dev4Slack](http://dev4slack.xoxco.com/)
94+
Slack team.
95+
96+
### Feedback
97+
I'd love to improve this project, so if you've got some ideas :bulb:, feedback
98+
:raising_hand: or praise :love_letter: please file an issue, submit a PR or
99+
reach out to me through [Github](https://github.com/karishay) or on
100+
[Twitter](https://twitter.com/karishannon)!

‎app.py‎

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
A routing layer for the onboarding bot tutorial built using
4+
[Slack's Events API](https://api.slack.com/events-api) in Python
5+
"""
6+
import json
7+
import bot
8+
from flask import Flask, request, make_response, render_template
9+
10+
pyBot = bot.Bot()
11+
slack = pyBot.client
12+
13+
app = Flask(__name__)
14+
15+
16+
def _event_handler(event_type, slack_event):
17+
"""
18+
A helper function that routes events from Slack to our Bot
19+
by event type and subtype.
20+
21+
Parameters
22+
----------
23+
event_type : str
24+
type of event recieved from Slack
25+
slack_event : dict
26+
JSON response from a Slack reaction event
27+
28+
Returns
29+
----------
30+
obj
31+
Response object with 200 - ok or 500 - No Event Handler error
32+
33+
"""
34+
team_id = slack_event["team_id"]
35+
# ================ Team Join Events =============== #
36+
# When the user first joins a team, the type of event will be team_join
37+
if event_type == "team_join":
38+
user_id = slack_event["event"]["user"]["id"]
39+
# Send the onboarding message
40+
pyBot.onboarding_message(team_id, user_id)
41+
return make_response("Welcome Message Sent", 200,)
42+
43+
# ============== Share Message Events ============= #
44+
# If the user has shared the onboarding message, the event type will be
45+
# message. We'll also need to check that this is a message that has been
46+
# shared by looking into the attachments for "is_shared".
47+
elif event_type == "message" and slack_event["event"].get("attachments"):
48+
user_id = slack_event["event"].get("user")
49+
if slack_event["event"]["attachments"][0].get("is_share"):
50+
# Update the onboarding message and check off "Share this Message"
51+
pyBot.update_share(team_id, user_id)
52+
return make_response("Welcome message updates with shared message",
53+
200,)
54+
55+
# ============= Reaction Added Events ============= #
56+
# If the user has added an emoji reaction to the onboarding message
57+
elif event_type == "reaction_added":
58+
user_id = slack_event["event"]["user"]
59+
# Update the onboarding message
60+
pyBot.update_emoji(team_id, user_id)
61+
return make_response("Welcome message updates with reactji", 200,)
62+
63+
# =============== Pin Added Events ================ #
64+
# If the user has added an emoji reaction to the onboarding message
65+
elif event_type == "pin_added":
66+
user_id = slack_event["event"]["user"]
67+
# Update the onboarding message
68+
pyBot.update_pin(team_id, user_id)
69+
return make_response("Welcome message updates with pin", 200,)
70+
71+
# ============= Event Type Not Found! ============= #
72+
# If the event_type does not have a handler
73+
message = "You have not added an event handler for the %s" % event_type
74+
# Return a helpful error message
75+
return make_response(message, 200, {"X-Slack-No-Retry": 1})
76+
77+
78+
@app.route("/install", methods=["GET"])
79+
def pre_install():
80+
"""This route renders the installation page with 'Add to Slack' button."""
81+
# Since we've set the client ID and scope on our Bot object, we can change
82+
# them more easily while we're developing our app.
83+
client_id = pyBot.oauth["client_id"]
84+
scope = pyBot.oauth["scope"]
85+
# Our template is using the Jinja templating language to dynamically pass
86+
# our client id and scope
87+
return render_template("install.html", client_id=client_id, scope=scope)
88+
89+
90+
@app.route("/thanks", methods=["GET", "POST"])
91+
def thanks():
92+
"""
93+
This route is called by Slack after the user installs our app. It will
94+
exchange the temporary authorization code Slack sends for an OAuth token
95+
which we'll save on the bot object to use later.
96+
To let the user know what's happened it will also render a thank you page.
97+
"""
98+
# Let's grab that temporary authorization code Slack's sent us from
99+
# the request's parameters.
100+
code_arg = request.args.get('code')
101+
# The bot's auth method to handles exchanging the code for an OAuth token
102+
pyBot.auth(code_arg)
103+
return render_template("thanks.html")
104+
105+
106+
@app.route("/listening", methods=["GET", "POST"])
107+
def hears():
108+
"""
109+
This route listens for incoming events from Slack and uses the event
110+
handler helper function to route events to our Bot.
111+
"""
112+
slack_event = json.loads(request.data)
113+
114+
# ============= Slack URL Verification ============ #
115+
# In order to verify the url of our endpoint, Slack will send a challenge
116+
# token in a request and check for this token in the response our endpoint
117+
# sends back.
118+
# For more info: https://api.slack.com/events/url_verification
119+
if "challenge" in slack_event:
120+
return make_response(slack_event["challenge"], 200, {"content_type":
121+
"application/json"
122+
})
123+
124+
# ============ Slack Token Verification =========== #
125+
# We can verify the request is coming from Slack by checking that the
126+
# verification token in the request matches our app's settings
127+
if pyBot.verification != slack_event.get("token"):
128+
message = "Invalid Slack verification token: %s \npyBot has: \
129+
%s\n\n" % (slack_event["token"], pyBot.verification)
130+
# By adding "X-Slack-No-Retry" : 1 to our response headers, we turn off
131+
# Slack's automatic retries during development.
132+
make_response(message, 403, {"X-Slack-No-Retry": 1})
133+
134+
# ====== Process Incoming Events from Slack ======= #
135+
# If the incoming request is an Event we've subcribed to
136+
if "event" in slack_event:
137+
event_type = slack_event["event"]["type"]
138+
# Then handle the event by event_type and have your bot respond
139+
return _event_handler(event_type, slack_event)
140+
# If our bot hears things that are not events we've subscribed to,
141+
# send a quirky but helpful error response
142+
return make_response("[NO EVENT IN SLACK REQUEST] These are not the droids\
143+
you're looking for.", 404, {"X-Slack-No-Retry": 1})
144+
145+
146+
if __name__ == '__main__':
147+
app.run(debug=True)

0 commit comments

Comments
 (0)