def test_interactions(self): t = Thread(target=start_socket_mode_server(self, 3011)) t.daemon = True t.start() time.sleep(2) # wait for the server app = App(client=self.web_client) result = {"shortcut": False, "command": False} @app.shortcut("do-something") def shortcut_handler(ack): result["shortcut"] = True ack() @app.command("/hello-socket-mode") def command_handler(ack): result["command"] = True ack() handler = SocketModeHandler( app_token="xapp-A111-222-xyz", app=app, trace_enabled=True, ) try: handler.client.ping_pong_trace_enabled = True handler.client.wss_uri = "ws://127.0.0.1:3011/link" handler.connect() assert handler.client.is_connected() is True time.sleep(2) # wait for the message receiver handler.client.send_message("foo") time.sleep(2) assert result["shortcut"] is True assert result["command"] is True finally: handler.client.close() self.server.stop() self.server.close()
def test_tokens_revoked(self): app = App( client=self.web_client, signing_secret=self.signing_secret, installation_store=MyInstallationStore(), ) event_payload = { "token": "verification-token", "enterprise_id": "E111", "api_app_id": "A111", "event": { "type": "tokens_revoked", "tokens": { "oauth": ["W111"], "bot": ["W222"] }, }, "type": "event_callback", "event_id": "Ev111", "event_time": 1606805974, } timestamp, body = str(int(time())), json.dumps(event_payload) request: BoltRequest = BoltRequest(body=body, headers=self.build_headers( timestamp, body)) response = app.dispatch(request) assert response.status == 404 # Enable the built-in event listeners app.enable_token_revocation_listeners() response = app.dispatch(request) assert response.status == 200 # auth.test API call must be skipped assert_auth_test_count(self, 0) sleep(1) # wait a bit after auto ack() assert app.installation_store.delete_bot_called is True assert app.installation_store.delete_installation_called is True assert app.installation_store.delete_all_called is False
def test_uninstallation_and_revokes(self): app = App( client=self.web_client, signing_secret=self.signing_secret, authorize=authorize, ) app._client = WebClient( token="uninstalled-revoked", base_url=self.mock_api_server_base_url ) @app.event("app_uninstalled") def handler1(say: Say): say(channel="C111", text="What's up?") @app.event("tokens_revoked") def handler2(say: Say): say(channel="C111", text="What's up?") app_uninstalled_body = { "token": "verification_token", "team_id": "T_INSTALLED", "enterprise_id": "E_INSTALLED", "api_app_id": "A111", "event": {"type": "app_uninstalled"}, "type": "event_callback", "event_id": "Ev111", "event_time": 1599616881, "authorizations": [ { "enterprise_id": "E_INSTALLED", "team_id": "T_INSTALLED", "user_id": "W111", "is_bot": True, "is_enterprise_install": False, } ], } timestamp, body = str(int(time())), json.dumps(app_uninstalled_body) request: BoltRequest = BoltRequest( body=body, headers=self.build_headers(timestamp, body) ) response = app.dispatch(request) assert response.status == 200 tokens_revoked_body = { "token": "verification_token", "team_id": "T_INSTALLED", "enterprise_id": "E_INSTALLED", "api_app_id": "A111", "event": { "type": "tokens_revoked", "tokens": {"oauth": ["UXXXXXXXX"], "bot": ["UXXXXXXXX"]}, }, "type": "event_callback", "event_id": "Ev111", "event_time": 1599616881, "authorizations": [ { "enterprise_id": "E_INSTALLED", "team_id": "T_INSTALLED", "user_id": "W111", "is_bot": True, "is_enterprise_install": False, } ], } timestamp, body = str(int(time())), json.dumps(tokens_revoked_body) request: BoltRequest = BoltRequest( body=body, headers=self.build_headers(timestamp, body) ) response = app.dispatch(request) assert response.status == 200 # this should not be called when we have authorize assert self.mock_received_requests.get("/auth.test") is None sleep(1) # wait a bit after auto ack() assert self.mock_received_requests["/chat.postMessage"] == 2
# ------------------------------------------------ # instead of slack_bolt in requirements.txt import sys sys.path.insert(1, "../..") # ------------------------------------------------ import falcon import logging import re from slack_bolt import App, Respond, Ack from slack_bolt.adapter.falcon import SlackAppResource from slack_sdk import WebClient logging.basicConfig(level=logging.DEBUG) app = App() # @app.command("/bolt-py-proto", [lambda payload: payload["team_id"] == "T03E94MJU"]) def test_command(logger: logging.Logger, payload: dict, ack: Ack, respond: Respond): logger.info(payload) ack("thanks!") respond(blocks=[{ "type": "section", "block_id": "b", "text": { "type": "mrkdwn", "text": "You can add a button alongside text in your message. ", }, "accessory": {
# ------------------------------------------------ # instead of slack_bolt in requirements.txt import sys sys.path.insert(1, "..") # ------------------------------------------------ import logging logging.basicConfig(level=logging.DEBUG) from slack_bolt import App, Ack app = App() @app.middleware # or app.use(log_request) def log_request(logger, body, next): logger.debug(body) return next() @app.command("/hello-bolt-python") def test_command(body, client, ack, logger): logger.info(body) ack("I got it!") res = client.dialog_open( trigger_id=body["trigger_id"], dialog={ "callback_id": "dialog-callback-id", "title": "Request a Ride",
import os from dotenv import load_dotenv from slack_bolt import App import re load_dotenv() # Initializes your app with your bot token and signing secret app = App(token=os.environ.get("SLACK_API_TOKEN"), signing_secret=os.environ.get("SLACK_SIGNING_SECRET")) @app.message(":wave:") def emoji_handler(payload, say): print(payload) say(f"Hey <@{payload['user']}>, {payload['text']}") @app.message(re.compile("(hello|Hello)")) def hello_handler(payload, say, context): say(f"Hello <@{payload['user']}>!\nHow are you?") @app.event("reaction_added") def reaction_added(payload, say, client): emoji = payload["reaction"] channel_id = payload["item"]["channel"] ts = payload["item"]["ts"] client.reactions_add( name="wave",
# ------------------------------------------------ # instead of slack_bolt in requirements.txt import sys sys.path.insert(1, "vendor") # ------------------------------------------------ import logging from slack_bolt import App from slack_bolt.adapter.aws_lambda import SlackRequestHandler # process_before_response must be True when running on FaaS app = App(process_before_response=True) @app.event("app_mention") def handle_app_mentions(payload, say, logger): logger.info(payload) say("What's up?") @app.command("/hello-bolt-python-lambda") def respond_to_slack_within_3_seconds(ack): ack("Thanks!") SlackRequestHandler.clear_all_log_handlers() logging.basicConfig(format="%(asctime)s %(message)s", level=logging.DEBUG)
from flask import Flask, request from slack_bolt import App from slack_bolt.adapter.flask import SlackRequestHandler from webhook_posting import WebhookPosting posting_proc = WebhookPosting() try: from dotenv import load_dotenv load_dotenv() except ImportError: print(__file__ + r":環境変数の読込にdotenvを使用せず続行します。") utan = App( token=os.getenv(r"UTAN_BOT_TOKEN"), signing_secret=os.getenv(r"UTAN_SIGNING_SECRET") ) # utanに関連づけられたbotに対するメンションイベントを処理します @utan.event(r"app_mention") def read_mention_message(event, say): # イベントがトリガーされたチャンネルへ say() でメッセージを送信します text: str = event[r"text"] # ユーザーの入力テキストから、@メンション文を削除 text = text.replace(text[text.find(r"<@") : (text.find(r">") + 1)], r"") # ユーザーの入力テキストから、改行を削除(対 Watson入力エラー) text = text.replace("\n", r"")
import logging from slack_bolt import App logging.basicConfig(level=logging.DEBUG) # export SLACK_SIGNING_SECRET=*** # export SLACK_BOT_TOKEN=xoxb-*** app = App() # Middleware @app.middleware # or app.use(log_request) def log_request(logger, body, next): logger.info(body) return next() # Events API: https://api.slack.com/events-api @app.event("app_mention") def event_test(say): say("What's up?") # Interactivity: https://api.slack.com/interactivity @app.shortcut("callback-id-here") # @app.command("/hello-bolt-python") def open_modal(ack, client, logger, body): # acknowledge the incoming request from Slack immediately ack() # open a modal
import logging import os from slack_bolt import App logging.basicConfig(level=logging.DEBUG) bolt_app = App() @bolt_app.command("/hey-google-app-engine") def hello(body, ack): user_id = body["user_id"] ack(f"Hi <@{user_id}>!") from flask import Flask, request from slack_bolt.adapter.flask import SlackRequestHandler app = Flask(__name__) handler = SlackRequestHandler(bolt_app) @app.route("/_ah/warmup") def warmup(): # Handle your warmup logic here, e.g. set up a database connection pool return "", 200, {} @app.route("/slack/events", methods=["POST"]) def slack_events(): return handler.handle(request)
def test_valid_multi_auth_secret_absence(self): with pytest.raises(BoltError): App(signing_secret="valid", client_id="111.222", client_secret=None)
def test_valid_multi_auth(self): app = App(signing_secret="valid", client_id="111.222", client_secret="valid") assert app != None
def test_valid_single_auth(self): app = App(signing_secret="valid", token="xoxb-xxx") assert app != None
def test_listener_registration_error(self): app = App(signing_secret="valid", token="xoxb-xxx") with pytest.raises(BoltError): app.action({"type": "invalid_type", "action_id": "a"})(self.simple_listener)
from slack_bolt.adapter.socket_mode import SocketModeHandler from os import environ from miles_slack.slack_files import download_slack_file, upload_slack_file BASE_API_URL = environ.get("BASE_API_URL").rstrip('/') RCLONE_DRIVE = environ.get("RCLONE_DRIVE") DRIVE_PATH_PREFIX = environ.get("DRIVE_PATH_PREFIX") DRIVE_OUTPUT_DIR = environ.get("DRIVE_OUTPUT_DIR") DRIVE_OUTPUT_LINK = environ.get("DRIVE_OUTPUT_LINK") SLACK_BOT_TOKEN = environ.get("SLACK_BOT_TOKEN") SLACK_SOCKET_TOKEN = environ.get("SLACK_SOCKET_TOKEN") app = App(token=SLACK_BOT_TOKEN) command_filter = re.compile(r'<@.*>(.*)') # turns '<@U01KMRM2YTG> hello world' to 'hello world' arg_filter = re.compile(r'\s(.*)') # turns 'find Thomas Web' into 'Thomas Web' @app.event("app_mention") def event_test(say, event, client): say("Got it! Gimmie a hot sec....") logger.debug(f"Event received: {event}") channel = event.get("channel") command = command_filter.findall(event.get("text"))[0].strip() files = event.get("files") if files: for file in files:
# ------------------------------------------------ # instead of slack_bolt in requirements.txt import sys sys.path.insert(1, "..") # ------------------------------------------------ import logging import time logging.basicConfig(level=logging.DEBUG) from slack_bolt import App app = App() @app.middleware # or app.use(log_request) def log_request(logger, body, next): logger.debug(body) return next() def ack_command(body, ack, logger): logger.info(body) ack("Thanks!") def post_button_message(respond): respond(blocks=[{ "type": "section",
client_id=os.environ["SLACK_CLIENT_ID"], client_secret=os.environ["SLACK_CLIENT_SECRET"], scopes=[ "channels:history", "commands", "groups:history", "im:history", "mpim:history", "chat:write", ], state_store=FileOAuthStateStore(expiration_seconds=600, base_dir="./data/states"), installation_store=FileInstallationStore(base_dir="./data/installations"), ) app = App(signing_secret=os.environ["SLACK_SIGNING_SECRET"], oauth_settings=oauth_settings) register_listeners(app) podthai = [ "UJM7Z5VGD", "U014KC3E9MF", "U0145C1684V", "U014CUFPNJG", "U01401MQJAJ" ] podtrick = [ "UJPDYE4VC", "U0146P6DJQJ", "U0145C1AG1K", "U0146VB99AP", "U014CUFJPC4" ] dadpod = ["UJ9R66SHH", "U01401MPLUE", "U014CUFPARJ"] kings = ["UJM7Z5VGD", "UJ9R66SHH", "UJPDYE4VC"] test = ["UJPDYE4VC", "U01CFBL7Z8T"] flask_app = Flask(__name__) handler = SlackRequestHandler(app)
logger = logging.getLogger(__name__) client_id, client_secret, signing_secret = ( os.environ["SLACK_CLIENT_ID"], os.environ["SLACK_CLIENT_SECRET"], os.environ["SLACK_SIGNING_SECRET"], ) app = App( signing_secret=signing_secret, installation_store=DjangoInstallationStore( client_id=client_id, logger=logger, ), oauth_settings=OAuthSettings( client_id=client_id, client_secret=client_secret, state_store=DjangoOAuthStateStore( expiration_seconds=120, logger=logger, ), ), ) @app.event("app_mention") def event_test(body, say, logger): logger.info(body) say("What's up?")
"""main""" import os from logging import config from slack_bolt import App config.fileConfig("logging.conf", disable_existing_loggers=False) # ボットトークンと署名シークレットを使ってアプリを初期化します app = App(token=os.environ.get("SLACK_BOT_TOKEN"), signing_secret=os.environ.get("SLACK_SIGNING_SECRET")) @app.message("hello") def message_hello(message, say): """message hello""" # イベントがトリガーされたチャンネルへ say() でメッセージを送信します say(f"Hey there <@{message['user']}>!") # アプリを起動します if __name__ == "__main__": app.start(port=int(os.environ.get("PORT", 3000)))
# return BoltResponse(status=200, body="Thanks!") def failure(args: FailureArgs) -> BoltResponse: return BoltResponse(status=args.suggested_status_code, body=args.reason) app = App( signing_secret=os.environ.get("SLACK_SIGNING_SECRET"), installation_store=FileInstallationStore(), oauth_settings=OAuthSettings( client_id=os.environ.get("SLACK_CLIENT_ID"), client_secret=os.environ.get("SLACK_CLIENT_SECRET"), scopes=[ "app_mentions:read", "channels:history", "im:history", "chat:write" ], user_scopes=[], redirect_uri=None, install_path="/slack/install", redirect_uri_path="/slack/oauth_redirect", state_store=FileOAuthStateStore(expiration_seconds=600), callback_options=CallbackOptions(success=success, failure=failure), ), ) @app.command("/hello-bolt-python") def test_command(body, respond, client, ack, logger): logger.info(body) ack("Thanks!")
from slack_bolt import App def css(rgb_tuple): css3_db = CSS3_HEX_TO_NAMES names = [] rgb_values = [] for color_hex, color_name in css3_db.items(): names.append(color_name) rgb_values.append(hex_to_rgb(color_hex)) kdt_db = KDTree(rgb_values) distance, index = kdt_db.query(rgb_tuple) return names[index] app = App(token=os.environ["TOKEN"], signing_secret=os.environ["SIGNING"]) def make_image(ack, say, command, body, client): ack() def respond(message): client.chat_postEphemeral( channel=body['channel_id'], user=body['user_id'], text=message.format(user=("<@" + body['user_id'] + ">"))) text = body['text'].split() if len(text) == 1: url = text[0] width = None
from slack_bolt import App import requests from secrets import SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET, SNOOZE_CHANNEL_ID, GOOGLE_SHEETS_ENDPOINT from util.allocations import get_allocations app = App( token=SLACK_BOT_TOKEN, signing_secret=SLACK_SIGNING_SECRET, ) @app.message("") def Message(message, say): if message['text'].startswith("Carmel:"): app.client.reactions_add( channel=message['channel'], timestamp=message['ts'], name='party-carmel', ) if message['text'].startswith("Soumil:"): app.client.reactions_add( channel=message['channel'], timestamp=message['ts'], name='partysoumil', ) if message['text'].startswith("Chris:"): app.client.reactions_add( channel=message['channel'],
credentials are loaded from environment variables welcome message / welcome channel are stored in TOML """ import os import logging import tomlkit logging.basicConfig(level=logging.DEBUG) 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_OAUTH"]) # non-sensitive configuration information stored in config.toml conf_filename = "config.toml" def load_welcome_config(): """ loads the welcome message and channel from conf_filename can be easily expanded to load other config data """ with open(conf_filename, 'r') as conf_file: config = tomlkit.loads(conf_file.read()) return config["welcome"]
def test_signing_secret_absence(self): with pytest.raises(BoltError): App(signing_secret=None, token="xoxb-xxx") with pytest.raises(BoltError): App(signing_secret="", token="xoxb-xxx")
engine=engine, logger=logger, ) try: engine.execute("select count(*) from slack_bots") except Exception as e: installation_store.metadata.create_all(engine) oauth_state_store.metadata.create_all(engine) # update ngrok/production links in slash commands and enable events page # Initializes your app with your bot token and signing secret app = App( logger=logger, signing_secret=signing_secret, installation_store=installation_store, oauth_settings=OAuthSettings( client_id=client_id, client_secret=client_secret, state_store=oauth_state_store, ), ) @app.middleware def log_request(logger: logging.Logger, body: dict, next: Callable): logger.debug(body) return next() def extract_subtype(body: dict, context: BoltContext, next: Callable): context["type"] = body.get("event", {}).get("type", None) next()
def test_valid_single_auth(self): app = App(signing_secret="valid", client=self.web_client) assert app != None
def test_member_join_left_events(self): app = App( client=self.web_client, signing_secret=self.signing_secret, authorize=authorize, ) join_event_body = { "token": "verification_token", "team_id": "T_SOURCE", "enterprise_id": "E_SOURCE", "api_app_id": "A111", "event": { "type": "member_joined_channel", "user": "******", # not self "channel": "C111", "channel_type": "C", "team": "T_INSTALLED", "inviter": "U222", }, "type": "event_callback", "event_id": "Ev111", "event_time": 1599616881, "authorizations": [ { "enterprise_id": "E_INSTALLED", "team_id": "T_INSTALLED", "user_id": "W111", "is_bot": True, "is_enterprise_install": False, } ], } left_event_body = { "token": "verification_token", "team_id": "T_SOURCE", "enterprise_id": "E_SOURCE", "api_app_id": "A111", "event": { "type": "member_left_channel", "user": "******", # not self "channel": "C111", "channel_type": "C", "team": "T_INSTALLED", }, "type": "event_callback", "event_id": "Ev111", "event_time": 1599616881, "authorizations": [ { "enterprise_id": "E_INSTALLED", "team_id": "T_INSTALLED", "user_id": "W111", "is_bot": True, "is_enterprise_install": False, } ], } @app.event("member_joined_channel") def handle_app_mention(say): say("What's up?") @app.event("member_left_channel") def handle_app_mention(say): say("What's up?") timestamp, body = str(int(time())), json.dumps(join_event_body) request: BoltRequest = BoltRequest( body=body, headers=self.build_headers(timestamp, body) ) response = app.dispatch(request) assert response.status == 200 assert_auth_test_count(self, 1) timestamp, body = str(int(time())), json.dumps(left_event_body) request: BoltRequest = BoltRequest( body=body, headers=self.build_headers(timestamp, body) ) response = app.dispatch(request) assert response.status == 200 sleep(1) # wait a bit after auto ack() # the listeners should not be executed assert self.mock_received_requests["/chat.postMessage"] == 2
def test_token_absence(self): with pytest.raises(BoltError): App(signing_secret="valid", token=None) with pytest.raises(BoltError): App(signing_secret="valid", token="")
# ------------------------------------------------ # instead of slack_bolt in requirements.txt import sys sys.path.insert(1, "../..") # ------------------------------------------------ from slack_bolt import App from slack_bolt.adapter.starlette import SlackRequestHandler app = App() @app.event("app_mention") def handle_app_mentions(body, say, logger): logger.info(body) say("What's up?") app_handler = SlackRequestHandler(app) from starlette.applications import Starlette from starlette.requests import Request from starlette.routing import Route async def endpoint(req: Request): return await app_handler.handle(req) api = Starlette(
import os import re import CONSTS from slack_bolt import App from slack_bolt.adapter.socket_mode import SocketModeHandler app = App(token=os.environ.get("SLACK_BOT_TOKEN")) MANAGER = os.environ.get("MANAGER", "the manager") MAX_MESSAGE_LEN = os.environ.get("MAX_MESSAGE_LEN", CONSTS.MAX_MESSAGE_LEN) LINK_PATTERN = re.compile('<.+?\|(.+?)>') # Check liveness @app.event("app_mention") def event_test(say): say("Hi there!") def strip_links(message): for match in LINK_PATTERN.finditer(message): message = re.sub(LINK_PATTERN, match.groups()[0], message, 1) return message @app.event("message") def make_it_short(client, message): channel_id = message["channel"] if message["channel_type"] in ["group", "channel" ] and "thread_ts" not in message: