def __init__( self, *, logger: Optional[logging.Logger] = None, # Used in logger name: Optional[str] = None, # Set True when you run this app on a FaaS platform process_before_response: bool = False, # Basic Information > Credentials > Signing Secret signing_secret: Optional[str] = None, # for single-workspace apps token: Optional[str] = None, client: Optional[AsyncWebClient] = None, # for multi-workspace apps installation_store: Optional[AsyncInstallationStore] = None, authorize: Optional[Callable[..., Awaitable[AuthorizeResult]]] = None, # for the OAuth flow oauth_settings: Optional[AsyncOAuthSettings] = None, oauth_flow: Optional[AsyncOAuthFlow] = None, # No need to set (the value is used only in response to ssl_check requests) verification_token: Optional[str] = None, ): """Bolt App that provides functionalities to register middleware/listeners :param name: The application name that will be used in logging. If absent, the source file name will be used instead. :param process_before_response: True if this app runs on Function as a Service. (Default: False) :param signing_secret: The Signing Secret value used for verifying requests from Slack. :param token: The bot access token required only for single-workspace app. :param client: The singleton slack_sdk.web.async_client.AsyncWebClient instance for this app. :param installation_store: The module offering save/find operations of installation data :param authorize: The function to authorize an incoming request from Slack by checking if there is a team/user in the installation data. :param oauth_settings: The settings related to Slack app installation flow (OAuth flow) :param oauth_flow: Manually instantiated slack_bolt.oauth.async_oauth_flow.AsyncOAuthFlow. This is always prioritized over oauth_settings. :param verification_token: Deprecated verification mechanism. This can used only for ssl_check requests. """ signing_secret = signing_secret or os.environ.get( "SLACK_SIGNING_SECRET") token = token or os.environ.get("SLACK_BOT_TOKEN") self._name: str = name or inspect.stack()[1].filename.split( os.path.sep)[-1] self._signing_secret: str = signing_secret self._verification_token: Optional[ str] = verification_token or os.environ.get( "SLACK_VERIFICATION_TOKEN", None) self._framework_logger = logger or get_bolt_logger(AsyncApp) self._token: Optional[str] = token if client is not None: if not isinstance(client, AsyncWebClient): raise BoltError(error_client_invalid_type_async()) self._async_client = client self._token = client.token if token is not None: self._framework_logger.warning( warning_client_prioritized_and_token_skipped()) else: # NOTE: the token here can be None self._async_client = create_async_web_client(token) self._async_authorize: Optional[AsyncAuthorize] = None if authorize is not None: if oauth_settings is not None or oauth_flow is not None: raise BoltError(error_authorize_conflicts()) self._async_authorize = AsyncCallableAuthorize( logger=self._framework_logger, func=authorize) self._async_installation_store: Optional[ AsyncInstallationStore] = installation_store if self._async_installation_store is not None and self._async_authorize is None: self._async_authorize = AsyncInstallationStoreAuthorize( installation_store=self._async_installation_store, logger=self._framework_logger, ) self._async_oauth_flow: Optional[AsyncOAuthFlow] = None if (oauth_settings is None and os.environ.get("SLACK_CLIENT_ID") is not None and os.environ.get("SLACK_CLIENT_SECRET") is not None): # initialize with the default settings oauth_settings = AsyncOAuthSettings() if oauth_flow: if not isinstance(oauth_flow, AsyncOAuthFlow): raise BoltError(error_oauth_flow_invalid_type_async()) self._async_oauth_flow = oauth_flow installation_store = select_consistent_installation_store( client_id=self._async_oauth_flow.client_id, app_store=self._async_installation_store, oauth_flow_store=self._async_oauth_flow.settings. installation_store, logger=self._framework_logger, ) self._async_installation_store = installation_store self._async_oauth_flow.settings.installation_store = installation_store if self._async_oauth_flow._async_client is None: self._async_oauth_flow._async_client = self._async_client if self._async_authorize is None: self._async_authorize = self._async_oauth_flow.settings.authorize elif oauth_settings is not None: if not isinstance(oauth_settings, AsyncOAuthSettings): raise BoltError(error_oauth_settings_invalid_type_async()) installation_store = select_consistent_installation_store( client_id=oauth_settings.client_id, app_store=self._async_installation_store, oauth_flow_store=oauth_settings.installation_store, logger=self._framework_logger, ) self._async_installation_store = installation_store oauth_settings.installation_store = installation_store self._async_oauth_flow = AsyncOAuthFlow(client=self._async_client, logger=self.logger, settings=oauth_settings) if self._async_authorize is None: self._async_authorize = self._async_oauth_flow.settings.authorize if (self._async_installation_store is not None or self._async_authorize is not None) and self._token is not None: self._token = None self._framework_logger.warning(warning_token_skipped()) self._async_middleware_list: List[Union[Callable, AsyncMiddleware]] = [] self._async_listeners: List[AsyncListener] = [] self._async_listener_runner = AsyncioListenerRunner( logger=self._framework_logger, process_before_response=process_before_response, listener_error_handler=AsyncDefaultListenerErrorHandler( logger=self._framework_logger), lazy_listener_runner=AsyncioLazyListenerRunner( logger=self._framework_logger, ), ) self._init_middleware_list_done = False self._init_async_middleware_list() self._server: Optional[AsyncSlackAppServer] = None
def __init__( self, *, logger: Optional[logging.Logger] = None, # Used in logger name: Optional[str] = None, # Set True when you run this app on a FaaS platform process_before_response: bool = False, # Basic Information > Credentials > Signing Secret signing_secret: Optional[str] = None, # for single-workspace apps token: Optional[str] = None, token_verification_enabled: bool = True, client: Optional[WebClient] = None, # for multi-workspace apps authorize: Optional[Callable[..., AuthorizeResult]] = None, installation_store: Optional[InstallationStore] = None, # for v1.0.x compatibility installation_store_bot_only: Optional[bool] = None, # for the OAuth flow oauth_settings: Optional[OAuthSettings] = None, oauth_flow: Optional[OAuthFlow] = None, # No need to set (the value is used only in response to ssl_check requests) verification_token: Optional[str] = None, ): """Bolt App that provides functionalities to register middleware/listeners :param name: The application name that will be used in logging. If absent, the source file name will be used instead. :param process_before_response: True if this app runs on Function as a Service. (Default: False) :param signing_secret: The Signing Secret value used for verifying requests from Slack. :param token: The bot access token required only for single-workspace app. :param token_verification_enabled: Verifies the validity of the given token if True. :param client: The singleton slack_sdk.WebClient instance for this app. :param authorize: The function to authorize an incoming request from Slack by checking if there is a team/user in the installation data. :param installation_store: The module offering save/find operations of installation data :param installation_store_bot_only: Use InstallationStore#find_bot if True (Default: False) :param oauth_settings: The settings related to Slack app installation flow (OAuth flow) :param oauth_flow: Manually instantiated slack_bolt.oauth.OAuthFlow. This is always prioritized over oauth_settings. :param verification_token: Deprecated verification mechanism. This can used only for ssl_check requests. """ signing_secret = signing_secret or os.environ.get( "SLACK_SIGNING_SECRET") token = token or os.environ.get("SLACK_BOT_TOKEN") self._name: str = name or inspect.stack()[1].filename.split( os.path.sep)[-1] self._signing_secret: str = signing_secret self._verification_token: Optional[ str] = verification_token or os.environ.get( "SLACK_VERIFICATION_TOKEN", None) self._framework_logger = logger or get_bolt_logger(App) self._token: Optional[str] = token if client is not None: if not isinstance(client, WebClient): raise BoltError(error_client_invalid_type()) self._client = client self._token = client.token if token is not None: self._framework_logger.warning( warning_client_prioritized_and_token_skipped()) else: self._client = create_web_client( token) # NOTE: the token here can be None # -------------------------------------- # Authorize & OAuthFlow initialization # -------------------------------------- self._authorize: Optional[Authorize] = None if authorize is not None: if oauth_settings is not None or oauth_flow is not None: raise BoltError(error_authorize_conflicts()) self._authorize = CallableAuthorize(logger=self._framework_logger, func=authorize) self._installation_store: Optional[ InstallationStore] = installation_store if self._installation_store is not None and self._authorize is None: self._authorize = InstallationStoreAuthorize( installation_store=self._installation_store, logger=self._framework_logger, bot_only=installation_store_bot_only, ) self._oauth_flow: Optional[OAuthFlow] = None if (oauth_settings is None and os.environ.get("SLACK_CLIENT_ID") is not None and os.environ.get("SLACK_CLIENT_SECRET") is not None): # initialize with the default settings oauth_settings = OAuthSettings() if oauth_flow: self._oauth_flow = oauth_flow installation_store = select_consistent_installation_store( client_id=self._oauth_flow.client_id, app_store=self._installation_store, oauth_flow_store=self._oauth_flow.settings.installation_store, logger=self._framework_logger, ) self._installation_store = installation_store self._oauth_flow.settings.installation_store = installation_store if self._oauth_flow._client is None: self._oauth_flow._client = self._client if self._authorize is None: self._authorize = self._oauth_flow.settings.authorize elif oauth_settings is not None: installation_store = select_consistent_installation_store( client_id=oauth_settings.client_id, app_store=self._installation_store, oauth_flow_store=oauth_settings.installation_store, logger=self._framework_logger, ) self._installation_store = installation_store oauth_settings.installation_store = installation_store self._oauth_flow = OAuthFlow(client=self.client, logger=self.logger, settings=oauth_settings) if self._authorize is None: self._authorize = self._oauth_flow.settings.authorize if (self._installation_store is not None or self._authorize is not None) and self._token is not None: self._token = None self._framework_logger.warning(warning_token_skipped()) # after setting bot_only here, __init__ cannot replace authorize function if installation_store_bot_only is not None and self._oauth_flow is not None: app_bot_only = installation_store_bot_only or False oauth_flow_bot_only = self._oauth_flow.settings.installation_store_bot_only if app_bot_only != oauth_flow_bot_only: self.logger.warning(warning_bot_only_conflicts()) self._oauth_flow.settings.installation_store_bot_only = app_bot_only self._authorize.bot_only = app_bot_only # -------------------------------------- # Middleware Initialization # -------------------------------------- self._middleware_list: List[Union[Callable, Middleware]] = [] self._listeners: List[Listener] = [] listener_executor = ThreadPoolExecutor(max_workers=5) self._listener_runner = ThreadListenerRunner( logger=self._framework_logger, process_before_response=process_before_response, listener_error_handler=DefaultListenerErrorHandler( logger=self._framework_logger), listener_executor=listener_executor, lazy_listener_runner=ThreadLazyListenerRunner( logger=self._framework_logger, executor=listener_executor, ), ) self._init_middleware_list_done = False self._init_middleware_list( token_verification_enabled=token_verification_enabled)