diff --git a/docs/api-docs/slack_sdk/index.html b/docs/api-docs/slack_sdk/index.html index abfe55bc3..13ce7cbc6 100644 --- a/docs/api-docs/slack_sdk/index.html +++ b/docs/api-docs/slack_sdk/index.html @@ -3095,12 +3095,18 @@

Note

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> SlackResponse: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: @@ -9760,7 +9766,7 @@

Methods

-def conversations_invite(self, *, channel: str, users: Union[str, Sequence[str]], **kwargs) ‑> SlackResponse +def conversations_invite(self, *, channel: str, users: Union[str, Sequence[str]], force: Optional[bool] = None, **kwargs) ‑> SlackResponse

Invites users to a channel. @@ -9774,12 +9780,18 @@

Methods

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> SlackResponse: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: diff --git a/docs/api-docs/slack_sdk/oauth/installation_store/amazon_s3/index.html b/docs/api-docs/slack_sdk/oauth/installation_store/amazon_s3/index.html index a4c5f88c3..b4f611d70 100644 --- a/docs/api-docs/slack_sdk/oauth/installation_store/amazon_s3/index.html +++ b/docs/api-docs/slack_sdk/oauth/installation_store/amazon_s3/index.html @@ -133,6 +133,10 @@

Module slack_sdk.oauth.installation_store.amazon_s3Module slack_sdk.oauth.installation_store.amazon_s3Classes

self.logger.debug(f"S3 put_object response: {response}") def save_bot(self, bot: Bot): + if bot.bot_token is None: + self.logger.debug("Skipped saving a new row because of the absense of bot token in it") + return + none = "none" e_id = bot.enterprise_id or none t_id = bot.team_id or none @@ -610,10 +621,13 @@

Classes

data = json.loads(body) installation = Installation(**data) - if installation is not None and user_id is not None: + has_user_installation = user_id is not None and installation is not None + no_bot_token_installation = installation is not None and installation.bot_token is None + should_find_bot_installation = has_user_installation or no_bot_token_installation + if should_find_bot_installation: # Retrieve the latest bot token, just in case # See also: https://github.com/slackapi/bolt-python/issues/664 - latest_bot_installation = self.find_installation( + latest_bot_installation = self.find_bot( enterprise_id=enterprise_id, team_id=team_id, is_enterprise_install=is_enterprise_install, diff --git a/docs/api-docs/slack_sdk/oauth/installation_store/file/index.html b/docs/api-docs/slack_sdk/oauth/installation_store/file/index.html index 8de95633e..2ae413703 100644 --- a/docs/api-docs/slack_sdk/oauth/installation_store/file/index.html +++ b/docs/api-docs/slack_sdk/oauth/installation_store/file/index.html @@ -105,6 +105,10 @@

Module slack_sdk.oauth.installation_store.fileModule slack_sdk.oauth.installation_store.fileClasses

class FileInstallationStore -(*, base_dir: str = '/Users/seratch/.bolt-app-installation', historical_data_enabled: bool = True, client_id: Optional[str] = None, logger: logging.Logger = <Logger slack_sdk.oauth.installation_store.file (WARNING)>) +(*, base_dir: str = '/Users/kazuhiro.sera/.bolt-app-installation', historical_data_enabled: bool = True, client_id: Optional[str] = None, logger: logging.Logger = <Logger slack_sdk.oauth.installation_store.file (WARNING)>)

The installation store interface.

@@ -373,6 +380,10 @@

Classes

f.write(entity) def save_bot(self, bot: Bot): + if bot.bot_token is None: + self.logger.debug("Skipped saving a new row because of the absense of bot token in it") + return + none = "none" e_id = bot.enterprise_id or none t_id = bot.team_id or none @@ -465,10 +476,13 @@

Classes

data = json.loads(f.read()) installation = Installation(**data) - if installation is not None and user_id is not None: + has_user_installation = user_id is not None and installation is not None + no_bot_token_installation = installation is not None and installation.bot_token is None + should_find_bot_installation = has_user_installation or no_bot_token_installation + if should_find_bot_installation: # Retrieve the latest bot token, just in case # See also: https://github.com/slackapi/bolt-python/issues/664 - latest_bot_installation = self.find_installation( + latest_bot_installation = self.find_bot( enterprise_id=enterprise_id, team_id=team_id, is_enterprise_install=is_enterprise_install, diff --git a/docs/api-docs/slack_sdk/oauth/installation_store/index.html b/docs/api-docs/slack_sdk/oauth/installation_store/index.html index e73f9cc59..761c0921c 100644 --- a/docs/api-docs/slack_sdk/oauth/installation_store/index.html +++ b/docs/api-docs/slack_sdk/oauth/installation_store/index.html @@ -162,30 +162,17 @@

Classes

else: self.bot_scopes = bot_scopes self.bot_refresh_token = bot_refresh_token + if bot_token_expires_at is not None: - if type(bot_token_expires_at) == datetime: - self.bot_token_expires_at = int(bot_token_expires_at.timestamp()) # type: ignore - elif type(bot_token_expires_at) == str and not re.match("^\\d+$", bot_token_expires_at): - self.bot_token_expires_at = int(_from_iso_format_to_unix_timestamp(bot_token_expires_at)) - else: - self.bot_token_expires_at = int(bot_token_expires_at) + self.bot_token_expires_at = _timestamp_to_type(bot_token_expires_at, int) elif bot_token_expires_in is not None: self.bot_token_expires_at = int(time()) + bot_token_expires_in else: self.bot_token_expires_at = None + self.is_enterprise_install = is_enterprise_install or False - if type(installed_at) == float: - self.installed_at = installed_at # type: ignore - elif type(installed_at) == datetime: - self.installed_at = installed_at.timestamp() # type: ignore - elif type(installed_at) == str: - if re.match("^\\d+.\\d+$", installed_at): - self.installed_at = float(installed_at) - else: - self.installed_at = _from_iso_format_to_unix_timestamp(installed_at) - else: - raise ValueError(f"Unsupported data format for installed_at {installed_at}") + self.installed_at = _timestamp_to_type(installed_at, float) self.custom_values = custom_values if custom_values is not None else {} @@ -340,7 +327,7 @@

Methods

class FileInstallationStore -(*, base_dir: str = '/Users/seratch/.bolt-app-installation', historical_data_enabled: bool = True, client_id: Optional[str] = None, logger: logging.Logger = <Logger slack_sdk.oauth.installation_store.file (WARNING)>) +(*, base_dir: str = '/Users/kazuhiro.sera/.bolt-app-installation', historical_data_enabled: bool = True, client_id: Optional[str] = None, logger: logging.Logger = <Logger slack_sdk.oauth.installation_store.file (WARNING)>)

The installation store interface.

@@ -429,6 +416,10 @@

Methods

f.write(entity) def save_bot(self, bot: Bot): + if bot.bot_token is None: + self.logger.debug("Skipped saving a new row because of the absense of bot token in it") + return + none = "none" e_id = bot.enterprise_id or none t_id = bot.team_id or none @@ -521,10 +512,13 @@

Methods

data = json.loads(f.read()) installation = Installation(**data) - if installation is not None and user_id is not None: + has_user_installation = user_id is not None and installation is not None + no_bot_token_installation = installation is not None and installation.bot_token is None + should_find_bot_installation = has_user_installation or no_bot_token_installation + if should_find_bot_installation: # Retrieve the latest bot token, just in case # See also: https://github.com/slackapi/bolt-python/issues/664 - latest_bot_installation = self.find_installation( + latest_bot_installation = self.find_bot( enterprise_id=enterprise_id, team_id=team_id, is_enterprise_install=is_enterprise_install, @@ -781,14 +775,9 @@

Inherited members

else: self.bot_scopes = bot_scopes self.bot_refresh_token = bot_refresh_token + if bot_token_expires_at is not None: - if type(bot_token_expires_at) == datetime: - ts: float = bot_token_expires_at.timestamp() # type: ignore - self.bot_token_expires_at = int(ts) - elif type(bot_token_expires_at) == str and not re.match("^\\d+$", bot_token_expires_at): - self.bot_token_expires_at = int(_from_iso_format_to_unix_timestamp(bot_token_expires_at)) - else: - self.bot_token_expires_at = bot_token_expires_at # type: ignore + self.bot_token_expires_at = _timestamp_to_type(bot_token_expires_at, int) elif bot_token_expires_in is not None: self.bot_token_expires_at = int(time()) + bot_token_expires_in else: @@ -801,14 +790,9 @@

Inherited members

else: self.user_scopes = user_scopes self.user_refresh_token = user_refresh_token + if user_token_expires_at is not None: - if type(user_token_expires_at) == datetime: - ts: float = user_token_expires_at.timestamp() # type: ignore - self.user_token_expires_at = int(ts) - elif type(user_token_expires_at) == str and not re.match("^\\d+$", user_token_expires_at): - self.user_token_expires_at = int(_from_iso_format_to_unix_timestamp(user_token_expires_at)) - else: - self.user_token_expires_at = user_token_expires_at # type: ignore + self.user_token_expires_at = _timestamp_to_type(user_token_expires_at, int) elif user_token_expires_in is not None: self.user_token_expires_at = int(time()) + user_token_expires_in else: @@ -824,17 +808,8 @@

Inherited members

if installed_at is None: self.installed_at = datetime.now().timestamp() - elif type(installed_at) == float: - self.installed_at = installed_at # type: ignore - elif type(installed_at) == datetime: - self.installed_at = installed_at.timestamp() # type: ignore - elif type(installed_at) == str: - if re.match("^\\d+.\\d+$", installed_at): - self.installed_at = float(installed_at) - else: - self.installed_at = _from_iso_format_to_unix_timestamp(installed_at) else: - raise ValueError(f"Unsupported data format for installed_at {installed_at}") + self.installed_at = _timestamp_to_type(installed_at, float) self.custom_values = custom_values if custom_values is not None else {} diff --git a/docs/api-docs/slack_sdk/oauth/installation_store/internals.html b/docs/api-docs/slack_sdk/oauth/installation_store/internals.html index 016e80f51..0cff9cf81 100644 --- a/docs/api-docs/slack_sdk/oauth/installation_store/internals.html +++ b/docs/api-docs/slack_sdk/oauth/installation_store/internals.html @@ -26,38 +26,53 @@

Module slack_sdk.oauth.installation_store.internals Expand source code -
import platform
-import datetime
+
import sys
+from datetime import datetime, timezone
+from typing import Type, TypeVar, Union
 
-(major, minor, patch) = platform.python_version_tuple()
-is_python_3_6: bool = int(major) == 3 and int(minor) >= 6
 
-utc_timezone = datetime.timezone.utc
-
-
-def _from_iso_format_to_datetime(iso_datetime_str: str) -> datetime.datetime:
-    if is_python_3_6:
-        elements = iso_datetime_str.split(" ")
-        ymd = elements[0].split("-")
-        hms = elements[1].split(":")
-        return datetime.datetime(
-            int(ymd[0]),
-            int(ymd[1]),
-            int(ymd[2]),
-            int(hms[0]),
-            int(hms[1]),
-            int(hms[2]),
-            0,
-            utc_timezone,
-        )
+def _from_iso_format_to_datetime(iso_datetime_str: str) -> datetime:
+    if sys.version_info[:2] == (3, 6):
+        format = "%Y-%m-%d %H:%M:%S"
+        if "." in iso_datetime_str:
+            format += ".%f"
+        return datetime.strptime(iso_datetime_str, format).replace(tzinfo=timezone.utc)
     else:
         if "+" not in iso_datetime_str:
             iso_datetime_str += "+00:00"
-        return datetime.datetime.fromisoformat(iso_datetime_str)
+        return datetime.fromisoformat(iso_datetime_str)
 
 
 def _from_iso_format_to_unix_timestamp(iso_datetime_str: str) -> float:
-    return _from_iso_format_to_datetime(iso_datetime_str).timestamp()
+ return _from_iso_format_to_datetime(iso_datetime_str).timestamp() + + +TimestampType = TypeVar("TimestampType", float, int) + + +def _timestamp_to_type(ts: Union[TimestampType, datetime, str], target_type: Type[TimestampType]) -> TimestampType: + result: TimestampType + + if isinstance(ts, target_type): + # unnecessary type casting makes pytype happy + result = target_type(ts) + + # although a type of the timestamp is just checked, + # pytype doesn't consider the following line valid: + # result = ts + # see https://github.com/google/pytype/issues/1012 + + elif isinstance(ts, datetime): + result = target_type(ts.timestamp()) + elif isinstance(ts, str): + try: + result = target_type(ts) + except ValueError: + result = target_type(_from_iso_format_to_unix_timestamp(ts)) + else: + raise ValueError(f"Unsupported data format for timestamp {ts}") + + return result
diff --git a/docs/api-docs/slack_sdk/oauth/installation_store/models/bot.html b/docs/api-docs/slack_sdk/oauth/installation_store/models/bot.html index b881cd70b..5bf567e8b 100644 --- a/docs/api-docs/slack_sdk/oauth/installation_store/models/bot.html +++ b/docs/api-docs/slack_sdk/oauth/installation_store/models/bot.html @@ -26,14 +26,11 @@

Module slack_sdk.oauth.installation_store.models.bot Expand source code -
import re
-from datetime import datetime  # type: ignore
+
from datetime import datetime  # type: ignore
 from time import time
 from typing import Optional, Union, Dict, Any, Sequence
 
-from slack_sdk.oauth.installation_store.internals import (
-    _from_iso_format_to_unix_timestamp,
-)
+from slack_sdk.oauth.installation_store.internals import _timestamp_to_type
 
 
 class Bot:
@@ -98,30 +95,17 @@ 

Module slack_sdk.oauth.installation_store.models.botClasses

else: self.bot_scopes = bot_scopes self.bot_refresh_token = bot_refresh_token + if bot_token_expires_at is not None: - if type(bot_token_expires_at) == datetime: - self.bot_token_expires_at = int(bot_token_expires_at.timestamp()) # type: ignore - elif type(bot_token_expires_at) == str and not re.match("^\\d+$", bot_token_expires_at): - self.bot_token_expires_at = int(_from_iso_format_to_unix_timestamp(bot_token_expires_at)) - else: - self.bot_token_expires_at = int(bot_token_expires_at) + self.bot_token_expires_at = _timestamp_to_type(bot_token_expires_at, int) elif bot_token_expires_in is not None: self.bot_token_expires_at = int(time()) + bot_token_expires_in else: self.bot_token_expires_at = None + self.is_enterprise_install = is_enterprise_install or False - if type(installed_at) == float: - self.installed_at = installed_at # type: ignore - elif type(installed_at) == datetime: - self.installed_at = installed_at.timestamp() # type: ignore - elif type(installed_at) == str: - if re.match("^\\d+.\\d+$", installed_at): - self.installed_at = float(installed_at) - else: - self.installed_at = _from_iso_format_to_unix_timestamp(installed_at) - else: - raise ValueError(f"Unsupported data format for installed_at {installed_at}") + self.installed_at = _timestamp_to_type(installed_at, float) self.custom_values = custom_values if custom_values is not None else {} diff --git a/docs/api-docs/slack_sdk/oauth/installation_store/models/index.html b/docs/api-docs/slack_sdk/oauth/installation_store/models/index.html index 00420bab5..a091dcac8 100644 --- a/docs/api-docs/slack_sdk/oauth/installation_store/models/index.html +++ b/docs/api-docs/slack_sdk/oauth/installation_store/models/index.html @@ -127,30 +127,17 @@

Classes

else: self.bot_scopes = bot_scopes self.bot_refresh_token = bot_refresh_token + if bot_token_expires_at is not None: - if type(bot_token_expires_at) == datetime: - self.bot_token_expires_at = int(bot_token_expires_at.timestamp()) # type: ignore - elif type(bot_token_expires_at) == str and not re.match("^\\d+$", bot_token_expires_at): - self.bot_token_expires_at = int(_from_iso_format_to_unix_timestamp(bot_token_expires_at)) - else: - self.bot_token_expires_at = int(bot_token_expires_at) + self.bot_token_expires_at = _timestamp_to_type(bot_token_expires_at, int) elif bot_token_expires_in is not None: self.bot_token_expires_at = int(time()) + bot_token_expires_in else: self.bot_token_expires_at = None + self.is_enterprise_install = is_enterprise_install or False - if type(installed_at) == float: - self.installed_at = installed_at # type: ignore - elif type(installed_at) == datetime: - self.installed_at = installed_at.timestamp() # type: ignore - elif type(installed_at) == str: - if re.match("^\\d+.\\d+$", installed_at): - self.installed_at = float(installed_at) - else: - self.installed_at = _from_iso_format_to_unix_timestamp(installed_at) - else: - raise ValueError(f"Unsupported data format for installed_at {installed_at}") + self.installed_at = _timestamp_to_type(installed_at, float) self.custom_values = custom_values if custom_values is not None else {} @@ -404,14 +391,9 @@

Methods

else: self.bot_scopes = bot_scopes self.bot_refresh_token = bot_refresh_token + if bot_token_expires_at is not None: - if type(bot_token_expires_at) == datetime: - ts: float = bot_token_expires_at.timestamp() # type: ignore - self.bot_token_expires_at = int(ts) - elif type(bot_token_expires_at) == str and not re.match("^\\d+$", bot_token_expires_at): - self.bot_token_expires_at = int(_from_iso_format_to_unix_timestamp(bot_token_expires_at)) - else: - self.bot_token_expires_at = bot_token_expires_at # type: ignore + self.bot_token_expires_at = _timestamp_to_type(bot_token_expires_at, int) elif bot_token_expires_in is not None: self.bot_token_expires_at = int(time()) + bot_token_expires_in else: @@ -424,14 +406,9 @@

Methods

else: self.user_scopes = user_scopes self.user_refresh_token = user_refresh_token + if user_token_expires_at is not None: - if type(user_token_expires_at) == datetime: - ts: float = user_token_expires_at.timestamp() # type: ignore - self.user_token_expires_at = int(ts) - elif type(user_token_expires_at) == str and not re.match("^\\d+$", user_token_expires_at): - self.user_token_expires_at = int(_from_iso_format_to_unix_timestamp(user_token_expires_at)) - else: - self.user_token_expires_at = user_token_expires_at # type: ignore + self.user_token_expires_at = _timestamp_to_type(user_token_expires_at, int) elif user_token_expires_in is not None: self.user_token_expires_at = int(time()) + user_token_expires_in else: @@ -447,17 +424,8 @@

Methods

if installed_at is None: self.installed_at = datetime.now().timestamp() - elif type(installed_at) == float: - self.installed_at = installed_at # type: ignore - elif type(installed_at) == datetime: - self.installed_at = installed_at.timestamp() # type: ignore - elif type(installed_at) == str: - if re.match("^\\d+.\\d+$", installed_at): - self.installed_at = float(installed_at) - else: - self.installed_at = _from_iso_format_to_unix_timestamp(installed_at) else: - raise ValueError(f"Unsupported data format for installed_at {installed_at}") + self.installed_at = _timestamp_to_type(installed_at, float) self.custom_values = custom_values if custom_values is not None else {} diff --git a/docs/api-docs/slack_sdk/oauth/installation_store/models/installation.html b/docs/api-docs/slack_sdk/oauth/installation_store/models/installation.html index 6f2d29099..663070ca7 100644 --- a/docs/api-docs/slack_sdk/oauth/installation_store/models/installation.html +++ b/docs/api-docs/slack_sdk/oauth/installation_store/models/installation.html @@ -26,14 +26,11 @@

Module slack_sdk.oauth.installation_store.models.install Expand source code -
import re
-from datetime import datetime  # type: ignore
+
from datetime import datetime  # type: ignore
 from time import time
 from typing import Optional, Union, Dict, Any, Sequence
 
-from slack_sdk.oauth.installation_store.internals import (
-    _from_iso_format_to_unix_timestamp,
-)
+from slack_sdk.oauth.installation_store.internals import _timestamp_to_type
 from slack_sdk.oauth.installation_store.models.bot import Bot
 
 
@@ -128,14 +125,9 @@ 

Module slack_sdk.oauth.installation_store.models.install else: self.bot_scopes = bot_scopes self.bot_refresh_token = bot_refresh_token + if bot_token_expires_at is not None: - if type(bot_token_expires_at) == datetime: - ts: float = bot_token_expires_at.timestamp() # type: ignore - self.bot_token_expires_at = int(ts) - elif type(bot_token_expires_at) == str and not re.match("^\\d+$", bot_token_expires_at): - self.bot_token_expires_at = int(_from_iso_format_to_unix_timestamp(bot_token_expires_at)) - else: - self.bot_token_expires_at = bot_token_expires_at # type: ignore + self.bot_token_expires_at = _timestamp_to_type(bot_token_expires_at, int) elif bot_token_expires_in is not None: self.bot_token_expires_at = int(time()) + bot_token_expires_in else: @@ -148,14 +140,9 @@

Module slack_sdk.oauth.installation_store.models.install else: self.user_scopes = user_scopes self.user_refresh_token = user_refresh_token + if user_token_expires_at is not None: - if type(user_token_expires_at) == datetime: - ts: float = user_token_expires_at.timestamp() # type: ignore - self.user_token_expires_at = int(ts) - elif type(user_token_expires_at) == str and not re.match("^\\d+$", user_token_expires_at): - self.user_token_expires_at = int(_from_iso_format_to_unix_timestamp(user_token_expires_at)) - else: - self.user_token_expires_at = user_token_expires_at # type: ignore + self.user_token_expires_at = _timestamp_to_type(user_token_expires_at, int) elif user_token_expires_in is not None: self.user_token_expires_at = int(time()) + user_token_expires_in else: @@ -171,17 +158,8 @@

Module slack_sdk.oauth.installation_store.models.install if installed_at is None: self.installed_at = datetime.now().timestamp() - elif type(installed_at) == float: - self.installed_at = installed_at # type: ignore - elif type(installed_at) == datetime: - self.installed_at = installed_at.timestamp() # type: ignore - elif type(installed_at) == str: - if re.match("^\\d+.\\d+$", installed_at): - self.installed_at = float(installed_at) - else: - self.installed_at = _from_iso_format_to_unix_timestamp(installed_at) else: - raise ValueError(f"Unsupported data format for installed_at {installed_at}") + self.installed_at = _timestamp_to_type(installed_at, float) self.custom_values = custom_values if custom_values is not None else {} @@ -355,14 +333,9 @@

Classes

else: self.bot_scopes = bot_scopes self.bot_refresh_token = bot_refresh_token + if bot_token_expires_at is not None: - if type(bot_token_expires_at) == datetime: - ts: float = bot_token_expires_at.timestamp() # type: ignore - self.bot_token_expires_at = int(ts) - elif type(bot_token_expires_at) == str and not re.match("^\\d+$", bot_token_expires_at): - self.bot_token_expires_at = int(_from_iso_format_to_unix_timestamp(bot_token_expires_at)) - else: - self.bot_token_expires_at = bot_token_expires_at # type: ignore + self.bot_token_expires_at = _timestamp_to_type(bot_token_expires_at, int) elif bot_token_expires_in is not None: self.bot_token_expires_at = int(time()) + bot_token_expires_in else: @@ -375,14 +348,9 @@

Classes

else: self.user_scopes = user_scopes self.user_refresh_token = user_refresh_token + if user_token_expires_at is not None: - if type(user_token_expires_at) == datetime: - ts: float = user_token_expires_at.timestamp() # type: ignore - self.user_token_expires_at = int(ts) - elif type(user_token_expires_at) == str and not re.match("^\\d+$", user_token_expires_at): - self.user_token_expires_at = int(_from_iso_format_to_unix_timestamp(user_token_expires_at)) - else: - self.user_token_expires_at = user_token_expires_at # type: ignore + self.user_token_expires_at = _timestamp_to_type(user_token_expires_at, int) elif user_token_expires_in is not None: self.user_token_expires_at = int(time()) + user_token_expires_in else: @@ -398,17 +366,8 @@

Classes

if installed_at is None: self.installed_at = datetime.now().timestamp() - elif type(installed_at) == float: - self.installed_at = installed_at # type: ignore - elif type(installed_at) == datetime: - self.installed_at = installed_at.timestamp() # type: ignore - elif type(installed_at) == str: - if re.match("^\\d+.\\d+$", installed_at): - self.installed_at = float(installed_at) - else: - self.installed_at = _from_iso_format_to_unix_timestamp(installed_at) else: - raise ValueError(f"Unsupported data format for installed_at {installed_at}") + self.installed_at = _timestamp_to_type(installed_at, float) self.custom_values = custom_values if custom_values is not None else {} diff --git a/docs/api-docs/slack_sdk/oauth/installation_store/sqlalchemy/index.html b/docs/api-docs/slack_sdk/oauth/installation_store/sqlalchemy/index.html index 9e6c71a23..646ac7c79 100644 --- a/docs/api-docs/slack_sdk/oauth/installation_store/sqlalchemy/index.html +++ b/docs/api-docs/slack_sdk/oauth/installation_store/sqlalchemy/index.html @@ -237,6 +237,7 @@

Module slack_sdk.oauth.installation_store.sqlalchemyModule slack_sdk.oauth.installation_store.sqlalchemyClasses

c.client_id == self.client_id, c.enterprise_id == enterprise_id, c.team_id == team_id, + c.bot_token.is_not(None), # the latest one that has a bot token ) ) .order_by(desc(c.installed_at)) @@ -697,25 +698,24 @@

Classes

installed_at=row["installed_at"], ) - if user_id is not None and installation is not None: + has_user_installation = user_id is not None and installation is not None + no_bot_token_installation = installation is not None and installation.bot_token is None + should_find_bot_installation = has_user_installation or no_bot_token_installation + if should_find_bot_installation: # Retrieve the latest bot token, just in case # See also: https://github.com/slackapi/bolt-python/issues/664 - where_clause = and_( - c.client_id == self.client_id, - c.enterprise_id == enterprise_id, - c.team_id == team_id, - c.bot_token.is_not(None), # the latest one that has a bot token + latest_bot_installation = self.find_bot( + enterprise_id=enterprise_id, + team_id=team_id, + is_enterprise_install=is_enterprise_install, ) - query = self.installations.select().where(where_clause).order_by(desc(c.installed_at)).limit(1) - with self.engine.connect() as conn: - result: object = conn.execute(query) - for row in result.mappings(): # type: ignore - installation.bot_token = row["bot_token"] - installation.bot_id = row["bot_id"] - installation.bot_user_id = row["bot_user_id"] - installation.bot_scopes = row["bot_scopes"] - installation.bot_refresh_token = row["bot_refresh_token"] - installation.bot_token_expires_at = row["bot_token_expires_at"] + if latest_bot_installation is not None and installation.bot_token != latest_bot_installation.bot_token: + installation.bot_id = latest_bot_installation.bot_id + installation.bot_user_id = latest_bot_installation.bot_user_id + installation.bot_token = latest_bot_installation.bot_token + installation.bot_scopes = latest_bot_installation.bot_scopes + installation.bot_refresh_token = latest_bot_installation.bot_refresh_token + installation.bot_token_expires_at = latest_bot_installation.bot_token_expires_at return installation diff --git a/docs/api-docs/slack_sdk/oauth/installation_store/sqlite3/index.html b/docs/api-docs/slack_sdk/oauth/installation_store/sqlite3/index.html index 8211ef8db..ede4c3635 100644 --- a/docs/api-docs/slack_sdk/oauth/installation_store/sqlite3/index.html +++ b/docs/api-docs/slack_sdk/oauth/installation_store/sqlite3/index.html @@ -87,9 +87,9 @@

Module slack_sdk.oauth.installation_store.sqlite3 enterprise_url text, team_id text not null default '', team_name text, - bot_token text not null, - bot_id text not null, - bot_user_id text not null, + bot_token text, + bot_id text, + bot_user_id text, bot_scopes text, bot_refresh_token text, -- since v3.8 bot_token_expires_at datetime, -- since v3.8 @@ -252,6 +252,10 @@

Module slack_sdk.oauth.installation_store.sqlite3 self.save_bot(installation.to_bot()) def save_bot(self, bot: Bot): + if bot.bot_token is None: + self.logger.debug("Skipped saving a new row because of the absense of bot token in it") + return + with self.connect() as conn: conn.execute( """ @@ -723,9 +727,9 @@

Classes

enterprise_url text, team_id text not null default '', team_name text, - bot_token text not null, - bot_id text not null, - bot_user_id text not null, + bot_token text, + bot_id text, + bot_user_id text, bot_scopes text, bot_refresh_token text, -- since v3.8 bot_token_expires_at datetime, -- since v3.8 @@ -888,6 +892,10 @@

Classes

self.save_bot(installation.to_bot()) def save_bot(self, bot: Bot): + if bot.bot_token is None: + self.logger.debug("Skipped saving a new row because of the absense of bot token in it") + return + with self.connect() as conn: conn.execute( """ @@ -1335,9 +1343,9 @@

Methods

enterprise_url text, team_id text not null default '', team_name text, - bot_token text not null, - bot_id text not null, - bot_user_id text not null, + bot_token text, + bot_id text, + bot_user_id text, bot_scopes text, bot_refresh_token text, -- since v3.8 bot_token_expires_at datetime, -- since v3.8 diff --git a/docs/api-docs/slack_sdk/oauth/state_store/file/index.html b/docs/api-docs/slack_sdk/oauth/state_store/file/index.html index d9cf53bd5..416e6d781 100644 --- a/docs/api-docs/slack_sdk/oauth/state_store/file/index.html +++ b/docs/api-docs/slack_sdk/oauth/state_store/file/index.html @@ -110,7 +110,7 @@

Classes

class FileOAuthStateStore -(*, expiration_seconds: int, base_dir: str = '/Users/seratch/.bolt-app-oauth-state', client_id: Optional[str] = None, logger: logging.Logger = <Logger slack_sdk.oauth.state_store.file (WARNING)>) +(*, expiration_seconds: int, base_dir: str = '/Users/kazuhiro.sera/.bolt-app-oauth-state', client_id: Optional[str] = None, logger: logging.Logger = <Logger slack_sdk.oauth.state_store.file (WARNING)>)
diff --git a/docs/api-docs/slack_sdk/oauth/state_store/index.html b/docs/api-docs/slack_sdk/oauth/state_store/index.html index 3a9a7bc6e..a07fae3c7 100644 --- a/docs/api-docs/slack_sdk/oauth/state_store/index.html +++ b/docs/api-docs/slack_sdk/oauth/state_store/index.html @@ -80,7 +80,7 @@

Classes

class FileOAuthStateStore -(*, expiration_seconds: int, base_dir: str = '/Users/seratch/.bolt-app-oauth-state', client_id: Optional[str] = None, logger: logging.Logger = <Logger slack_sdk.oauth.state_store.file (WARNING)>) +(*, expiration_seconds: int, base_dir: str = '/Users/kazuhiro.sera/.bolt-app-oauth-state', client_id: Optional[str] = None, logger: logging.Logger = <Logger slack_sdk.oauth.state_store.file (WARNING)>)
diff --git a/docs/api-docs/slack_sdk/socket_mode/aiohttp/index.html b/docs/api-docs/slack_sdk/socket_mode/aiohttp/index.html index d7dd02569..c8a87697c 100644 --- a/docs/api-docs/slack_sdk/socket_mode/aiohttp/index.html +++ b/docs/api-docs/slack_sdk/socket_mode/aiohttp/index.html @@ -267,8 +267,8 @@

Module slack_sdk.socket_mode.aiohttp

if self.logger.level <= logging.DEBUG: # The following logging prints every single received message # except empty message data ones. - type = WSMsgType(message.type) - message_type = type.name if type is not None else message.type + m_type = WSMsgType(message.type) + message_type = m_type.name if m_type is not None else message.type message_data = message.data if isinstance(message_data, bytes): message_data = message_data.decode("utf-8") @@ -723,8 +723,8 @@

Args

if self.logger.level <= logging.DEBUG: # The following logging prints every single received message # except empty message data ones. - type = WSMsgType(message.type) - message_type = type.name if type is not None else message.type + m_type = WSMsgType(message.type) + message_type = m_type.name if m_type is not None else message.type message_data = message.data if isinstance(message_data, bytes): message_data = message_data.decode("utf-8") @@ -1310,8 +1310,8 @@

Methods

if self.logger.level <= logging.DEBUG: # The following logging prints every single received message # except empty message data ones. - type = WSMsgType(message.type) - message_type = type.name if type is not None else message.type + m_type = WSMsgType(message.type) + message_type = m_type.name if m_type is not None else message.type message_data = message.data if isinstance(message_data, bytes): message_data = message_data.decode("utf-8") diff --git a/docs/api-docs/slack_sdk/version.html b/docs/api-docs/slack_sdk/version.html index a437d5e81..b73817208 100644 --- a/docs/api-docs/slack_sdk/version.html +++ b/docs/api-docs/slack_sdk/version.html @@ -28,7 +28,7 @@

Module slack_sdk.version

Expand source code
"""Check the latest version at https://pypi.org/project/slack-sdk/"""
-__version__ = "3.26.0"
+__version__ = "3.26.1"

diff --git a/docs/api-docs/slack_sdk/web/async_client.html b/docs/api-docs/slack_sdk/web/async_client.html index 9c4770384..d41f465a9 100644 --- a/docs/api-docs/slack_sdk/web/async_client.html +++ b/docs/api-docs/slack_sdk/web/async_client.html @@ -2894,12 +2894,18 @@

Module slack_sdk.web.async_client

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> AsyncSlackResponse: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: @@ -8056,12 +8062,18 @@

Note

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> AsyncSlackResponse: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: @@ -14721,7 +14733,7 @@

Methods

-async def conversations_invite(self, *, channel: str, users: Union[str, Sequence[str]], **kwargs) ‑> AsyncSlackResponse +async def conversations_invite(self, *, channel: str, users: Union[str, Sequence[str]], force: Optional[bool] = None, **kwargs) ‑> AsyncSlackResponse

Invites users to a channel. @@ -14735,12 +14747,18 @@

Methods

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> AsyncSlackResponse: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: diff --git a/docs/api-docs/slack_sdk/web/client.html b/docs/api-docs/slack_sdk/web/client.html index a79b1e66d..d0b859021 100644 --- a/docs/api-docs/slack_sdk/web/client.html +++ b/docs/api-docs/slack_sdk/web/client.html @@ -2885,12 +2885,18 @@

Module slack_sdk.web.client

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> SlackResponse: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: @@ -8047,12 +8053,18 @@

Note

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> SlackResponse: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: @@ -14712,7 +14724,7 @@

Methods

-def conversations_invite(self, *, channel: str, users: Union[str, Sequence[str]], **kwargs) ‑> SlackResponse +def conversations_invite(self, *, channel: str, users: Union[str, Sequence[str]], force: Optional[bool] = None, **kwargs) ‑> SlackResponse

Invites users to a channel. @@ -14726,12 +14738,18 @@

Methods

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> SlackResponse: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: diff --git a/docs/api-docs/slack_sdk/web/index.html b/docs/api-docs/slack_sdk/web/index.html index 94363d148..0f5c80955 100644 --- a/docs/api-docs/slack_sdk/web/index.html +++ b/docs/api-docs/slack_sdk/web/index.html @@ -3306,12 +3306,18 @@

Note

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> SlackResponse: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: @@ -9971,7 +9977,7 @@

Methods

-def conversations_invite(self, *, channel: str, users: Union[str, Sequence[str]], **kwargs) ‑> SlackResponse +def conversations_invite(self, *, channel: str, users: Union[str, Sequence[str]], force: Optional[bool] = None, **kwargs) ‑> SlackResponse

Invites users to a channel. @@ -9985,12 +9991,18 @@

Methods

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> SlackResponse: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: diff --git a/docs/api-docs/slack_sdk/web/legacy_client.html b/docs/api-docs/slack_sdk/web/legacy_client.html index a6b2d11bc..06c140ca2 100644 --- a/docs/api-docs/slack_sdk/web/legacy_client.html +++ b/docs/api-docs/slack_sdk/web/legacy_client.html @@ -2895,12 +2895,18 @@

Module slack_sdk.web.legacy_client

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> Union[Future, SlackResponse]: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: @@ -8057,12 +8063,18 @@

Note

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> Union[Future, SlackResponse]: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: @@ -14722,7 +14734,7 @@

Methods

-def conversations_invite(self, *, channel: str, users: Union[str, Sequence[str]], **kwargs) ‑> Union[_asyncio.Future, LegacySlackResponse] +def conversations_invite(self, *, channel: str, users: Union[str, Sequence[str]], force: Optional[bool] = None, **kwargs) ‑> Union[_asyncio.Future, LegacySlackResponse]

Invites users to a channel. @@ -14736,12 +14748,18 @@

Methods

*, channel: str, users: Union[str, Sequence[str]], + force: Optional[bool] = None, **kwargs, ) -> Union[Future, SlackResponse]: """Invites users to a channel. https://api.slack.com/methods/conversations.invite """ - kwargs.update({"channel": channel}) + kwargs.update( + { + "channel": channel, + "force": force, + } + ) if isinstance(users, (list, Tuple)): kwargs.update({"users": ",".join(users)}) else: diff --git a/slack_sdk/version.py b/slack_sdk/version.py index dc5491ff4..114c441ae 100644 --- a/slack_sdk/version.py +++ b/slack_sdk/version.py @@ -1,2 +1,2 @@ """Check the latest version at https://pypi.org/project/slack-sdk/""" -__version__ = "3.26.0" +__version__ = "3.26.1"