Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions docs/_basic/socket_mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
title: Using Socket Mode
lang: en
slug: socket-mode
order: 16
---

<div class="section-content">
With the introduction of [Socket Mode](ADD api.slack.com link when ready), Bolt for Python introduced support in version `1.2.0`. With Socket Mode, instead of creating a server with endpoints that Slack sends payloads too, the app will instead connect to Slack via a WebSocket connection and receive data from Slack over the socket connection. Make sure to enable Socket Mode in your app configuration settings.

To use the Socket Mode, add `SLACK_APP_TOKEN` as an environment variable. You can get your App Token in your app configuration settings under the **Basic Information** section.
</div>

```python
import os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler

# Install the Slack app and get xoxb- token in advance
app = App(token=os.environ["SLACK_BOT_TOKEN"])

if __name__ == "__main__":
# export SLACK_APP_TOKEN=xapp-***
# export SLACK_BOT_TOKEN=xoxb-***
SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()
```
Comment thread
stevengill marked this conversation as resolved.
102 changes: 102 additions & 0 deletions examples/socket_mode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# ------------------------------------------------
# instead of slack_bolt in requirements.txt
import sys

sys.path.insert(1, "..")
# ------------------------------------------------

import logging

logging.basicConfig(level=logging.DEBUG)

import os

from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler

# Install the Slack app and get xoxb- token in advance
app = App(token=os.environ["SLACK_BOT_TOKEN"])


@app.command("/hello-socket-mode")
def hello_command(ack, body):
user_id = body["user_id"]
ack(f"Hi <@{user_id}>!")


@app.event("app_mention")
def event_test(event, say):
say(f"Hi there, <@{event['user']}>!")


def ack_shortcut(ack):
ack()


def open_modal(body, client):
client.views_open(
trigger_id=body["trigger_id"],
view={
"type": "modal",
"callback_id": "socket_modal_submission",
"submit": {"type": "plain_text", "text": "Submit",},
"close": {"type": "plain_text", "text": "Cancel",},
"title": {"type": "plain_text", "text": "Socket Modal",},
"blocks": [
{
"type": "input",
"block_id": "q1",
"label": {"type": "plain_text", "text": "Write anything here!",},
"element": {"action_id": "feedback", "type": "plain_text_input",},
},
{
"type": "input",
"block_id": "q2",
"label": {
"type": "plain_text",
"text": "Can you tell us your favorites?",
},
"element": {
"type": "external_select",
"action_id": "favorite-animal",
"min_query_length": 0,
"placeholder": {
"type": "plain_text",
"text": "Select your favorites",
},
},
},
],
},
)


app.shortcut("socket-mode")(ack=ack_shortcut, lazy=[open_modal])


all_options = [
{"text": {"type": "plain_text", "text": ":cat: Cat"}, "value": "cat",},
{"text": {"type": "plain_text", "text": ":dog: Dog"}, "value": "dog",},
{"text": {"type": "plain_text", "text": ":bear: Bear"}, "value": "bear",},
]


@app.options("favorite-animal")
def external_data_source_handler(ack, body):
keyword = body.get("value")
if keyword is not None and len(keyword) > 0:
options = [o for o in all_options if keyword in o["text"]["text"]]
ack(options=options)
else:
ack(options=all_options)


@app.view("socket_modal_submission")
def submission(ack):
ack()


if __name__ == "__main__":
# export SLACK_APP_TOKEN=xapp-***
# export SLACK_BOT_TOKEN=xoxb-***
SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()
112 changes: 112 additions & 0 deletions examples/socket_mode_async.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# ------------------------------------------------
# instead of slack_bolt in requirements.txt
import sys


sys.path.insert(1, "..")
# ------------------------------------------------

import logging

logging.basicConfig(level=logging.DEBUG)

import os

from slack_bolt.app.async_app import AsyncApp
from slack_bolt.adapter.socket_mode.async_handler import AsyncSocketModeHandler

# Install the Slack app and get xoxb- token in advance
app = AsyncApp(token=os.environ["SLACK_BOT_TOKEN"])


@app.command("/hello-socket-mode")
async def hello_command(ack, body):
user_id = body["user_id"]
await ack(f"Hi <@{user_id}>!")


@app.event("app_mention")
async def event_test(event, say):
await say(f"Hi there, <@{event['user']}>!")


async def ack_shortcut(ack):
await ack()


async def open_modal(body, client):
await client.views_open(
trigger_id=body["trigger_id"],
view={
"type": "modal",
"callback_id": "socket_modal_submission",
"submit": {"type": "plain_text", "text": "Submit",},
"close": {"type": "plain_text", "text": "Cancel",},
"title": {"type": "plain_text", "text": "Socket Modal",},
"blocks": [
{
"type": "input",
"block_id": "q1",
"label": {"type": "plain_text", "text": "Write anything here!",},
"element": {"action_id": "feedback", "type": "plain_text_input",},
},
{
"type": "input",
"block_id": "q2",
"label": {
"type": "plain_text",
"text": "Can you tell us your favorites?",
},
"element": {
"type": "external_select",
"action_id": "favorite-animal",
"min_query_length": 0,
"placeholder": {
"type": "plain_text",
"text": "Select your favorites",
},
},
},
],
},
)


app.shortcut("socket-mode")(ack=ack_shortcut, lazy=[open_modal])


all_options = [
{"text": {"type": "plain_text", "text": ":cat: Cat"}, "value": "cat",},
{"text": {"type": "plain_text", "text": ":dog: Dog"}, "value": "dog",},
{"text": {"type": "plain_text", "text": ":bear: Bear"}, "value": "bear",},
]


@app.options("favorite-animal")
async def external_data_source_handler(ack, body):
keyword = body.get("value")
if keyword is not None and len(keyword) > 0:
options = [o for o in all_options if keyword in o["text"]["text"]]
await ack(options=options)
else:
await ack(options=all_options)


@app.view("socket_modal_submission")
async def submission(ack):
await ack()


# export SLACK_APP_TOKEN=xapp-***
# export SLACK_BOT_TOKEN=xoxb-***


async def main():
handler = AsyncSocketModeHandler(app, os.environ["SLACK_APP_TOKEN"])
await handler.start_async()


if __name__ == "__main__":
import asyncio

asyncio.run(main())
116 changes: 116 additions & 0 deletions examples/socket_mode_oauth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# ------------------------------------------------
# instead of slack_bolt in requirements.txt
import sys

sys.path.insert(1, "..")
# ------------------------------------------------

import logging

logging.basicConfig(level=logging.DEBUG)

import os
from slack_bolt.app import App
from slack_bolt.oauth.oauth_settings import OAuthSettings
from slack_bolt.adapter.socket_mode import SocketModeHandler

app = App(
signing_secret=os.environ["SLACK_SIGNING_SECRET"],
oauth_settings=OAuthSettings(
client_id=os.environ["SLACK_CLIENT_ID"],
client_secret=os.environ["SLACK_CLIENT_SECRET"],
scopes=os.environ["SLACK_SCOPES"].split(","),
),
)


@app.command("/hello-socket-mode")
def hello_command(ack, body):
user_id = body["user_id"]
ack(f"Hi <@{user_id}>!")


@app.event("app_mention")
def event_test(event, say):
say(f"Hi there, <@{event['user']}>!")


def ack_shortcut(ack):
ack()


def open_modal(body, client):
client.views_open(
trigger_id=body["trigger_id"],
view={
"type": "modal",
"callback_id": "socket_modal_submission",
"submit": {"type": "plain_text", "text": "Submit",},
"close": {"type": "plain_text", "text": "Cancel",},
"title": {"type": "plain_text", "text": "Socket Modal",},
"blocks": [
{
"type": "input",
"block_id": "q1",
"label": {"type": "plain_text", "text": "Write anything here!",},
"element": {"action_id": "feedback", "type": "plain_text_input",},
},
{
"type": "input",
"block_id": "q2",
"label": {
"type": "plain_text",
"text": "Can you tell us your favorites?",
},
"element": {
"type": "external_select",
"action_id": "favorite-animal",
"min_query_length": 0,
"placeholder": {
"type": "plain_text",
"text": "Select your favorites",
},
},
},
],
},
)


app.shortcut("socket-mode")(ack=ack_shortcut, lazy=[open_modal])


all_options = [
{"text": {"type": "plain_text", "text": ":cat: Cat"}, "value": "cat",},
{"text": {"type": "plain_text", "text": ":dog: Dog"}, "value": "dog",},
{"text": {"type": "plain_text", "text": ":bear: Bear"}, "value": "bear",},
]


@app.options("favorite-animal")
def external_data_source_handler(ack, body):
keyword = body.get("value")
if keyword is not None and len(keyword) > 0:
options = [o for o in all_options if keyword in o["text"]["text"]]
ack(options=options)
else:
ack(options=all_options)


@app.view("socket_modal_submission")
def submission(ack):
ack()


if __name__ == "__main__":
SocketModeHandler(app, os.environ.get("SLACK_APP_TOKEN")).connect()
app.start()

# export SLACK_APP_TOKEN=
# export SLACK_SIGNING_SECRET=
# export SLACK_CLIENT_ID=
# export SLACK_CLIENT_SECRET=
# export SLACK_SCOPES=
# pip install .[optional]
# pip install slack_bolt
# python socket_mode_oauth.py
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
exclude=["examples", "integration_tests", "tests", "tests.*",]
),
include_package_data=True, # MANIFEST.in
install_requires=["slack_sdk>=3.1.0,<3.2",],
install_requires=["slack_sdk>=3.2.0b6,<3.3",],
setup_requires=["pytest-runner==5.2"],
tests_require=test_dependencies,
test_suite="tests",
Expand Down
2 changes: 2 additions & 0 deletions slack_bolt/adapter/socket_mode/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Don't add async module imports here
from .builtin import SocketModeHandler # noqa
Loading