diff --git a/.gitignore b/.gitignore index ea79bd824..68dd7ab37 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,5 @@ tmp.txt logs/ .pytype/ +*.db +.env* diff --git a/slack_sdk/web/async_client.py b/slack_sdk/web/async_client.py index 5bf0a1858..c6d94e9a2 100644 --- a/slack_sdk/web/async_client.py +++ b/slack_sdk/web/async_client.py @@ -393,7 +393,7 @@ async def admin_conversations_rename( async def admin_conversations_search(self, **kwargs) -> AsyncSlackResponse: """Search for public or private channels in an Enterprise organization.""" - return await self.api_call("admin.conversations.search", json=kwargs) + return await self.api_call("admin.conversations.search", params=kwargs) async def admin_conversations_convertToPrivate( self, *, channel_id: str, **kwargs @@ -538,7 +538,7 @@ async def admin_conversations_getTeams( """ kwargs.update({"channel_id": channel_id}) - return await self.api_call("admin.conversations.getTeams", json=kwargs) + return await self.api_call("admin.conversations.getTeams", params=kwargs) async def admin_emoji_add(self, **kwargs) -> AsyncSlackResponse: """Add an emoji.""" @@ -668,11 +668,11 @@ async def admin_inviteRequests_approve( async def admin_inviteRequests_approved_list(self, **kwargs) -> AsyncSlackResponse: """List all approved workspace invite requests.""" - return await self.api_call("admin.inviteRequests.approved.list", json=kwargs) + return await self.api_call("admin.inviteRequests.approved.list", params=kwargs) async def admin_inviteRequests_denied_list(self, **kwargs) -> AsyncSlackResponse: """List all denied workspace invite requests.""" - return await self.api_call("admin.inviteRequests.denied.list", json=kwargs) + return await self.api_call("admin.inviteRequests.denied.list", params=kwargs) async def admin_inviteRequests_deny( self, *, invite_request_id: str, **kwargs @@ -687,7 +687,7 @@ async def admin_inviteRequests_deny( async def admin_inviteRequests_list(self, **kwargs) -> AsyncSlackResponse: """List all pending workspace invite requests.""" - return await self.api_call("admin.inviteRequests.list", json=kwargs) + return await self.api_call("admin.inviteRequests.list", params=kwargs) async def admin_teams_admins_list( self, *, team_id: str, **kwargs @@ -716,7 +716,7 @@ async def admin_teams_create( async def admin_teams_list(self, **kwargs) -> AsyncSlackResponse: """List all teams on an Enterprise organization.""" - return await self.api_call("admin.teams.list", json=kwargs) + return await self.api_call("admin.teams.list", params=kwargs) async def admin_teams_owners_list( self, *, team_id: str, **kwargs @@ -904,7 +904,7 @@ async def admin_users_list(self, *, team_id: str, **kwargs) -> AsyncSlackRespons team_id (str): ID of the team. e.g. 'T1234' """ kwargs.update({"team_id": team_id}) - return await self.api_call("admin.users.list", json=kwargs) + return await self.api_call("admin.users.list", params=kwargs) async def admin_users_remove( self, *, team_id: str, user_id: str, **kwargs @@ -1392,7 +1392,7 @@ async def chat_update( async def chat_scheduledMessages_list(self, **kwargs) -> AsyncSlackResponse: """Lists all scheduled messages.""" - return await self.api_call("chat.scheduledMessages.list", json=kwargs) + return await self.api_call("chat.scheduledMessages.list", params=kwargs) async def conversations_archive( self, *, channel: str, **kwargs diff --git a/slack_sdk/web/client.py b/slack_sdk/web/client.py index 80879276c..6900df34f 100644 --- a/slack_sdk/web/client.py +++ b/slack_sdk/web/client.py @@ -364,7 +364,7 @@ def admin_conversations_rename( def admin_conversations_search(self, **kwargs) -> SlackResponse: """Search for public or private channels in an Enterprise organization.""" - return self.api_call("admin.conversations.search", json=kwargs) + return self.api_call("admin.conversations.search", params=kwargs) def admin_conversations_convertToPrivate( self, *, channel_id: str, **kwargs @@ -505,7 +505,7 @@ def admin_conversations_getTeams( """ kwargs.update({"channel_id": channel_id}) - return self.api_call("admin.conversations.getTeams", json=kwargs) + return self.api_call("admin.conversations.getTeams", params=kwargs) def admin_emoji_add(self, **kwargs) -> SlackResponse: """Add an emoji.""" @@ -631,11 +631,11 @@ def admin_inviteRequests_approve( def admin_inviteRequests_approved_list(self, **kwargs) -> SlackResponse: """List all approved workspace invite requests.""" - return self.api_call("admin.inviteRequests.approved.list", json=kwargs) + return self.api_call("admin.inviteRequests.approved.list", params=kwargs) def admin_inviteRequests_denied_list(self, **kwargs) -> SlackResponse: """List all denied workspace invite requests.""" - return self.api_call("admin.inviteRequests.denied.list", json=kwargs) + return self.api_call("admin.inviteRequests.denied.list", params=kwargs) def admin_inviteRequests_deny( self, *, invite_request_id: str, **kwargs @@ -650,7 +650,7 @@ def admin_inviteRequests_deny( def admin_inviteRequests_list(self, **kwargs) -> SlackResponse: """List all pending workspace invite requests.""" - return self.api_call("admin.inviteRequests.list", json=kwargs) + return self.api_call("admin.inviteRequests.list", params=kwargs) def admin_teams_admins_list(self, *, team_id: str, **kwargs) -> SlackResponse: """List all of the admins on a given workspace. @@ -675,7 +675,7 @@ def admin_teams_create( def admin_teams_list(self, **kwargs) -> SlackResponse: """List all teams on an Enterprise organization.""" - return self.api_call("admin.teams.list", json=kwargs) + return self.api_call("admin.teams.list", params=kwargs) def admin_teams_owners_list(self, *, team_id: str, **kwargs) -> SlackResponse: """List all of the admins on a given workspace. @@ -855,7 +855,7 @@ def admin_users_list(self, *, team_id: str, **kwargs) -> SlackResponse: team_id (str): ID of the team. e.g. 'T1234' """ kwargs.update({"team_id": team_id}) - return self.api_call("admin.users.list", json=kwargs) + return self.api_call("admin.users.list", params=kwargs) def admin_users_remove( self, *, team_id: str, user_id: str, **kwargs @@ -1313,7 +1313,7 @@ def chat_update(self, *, channel: str, ts: str, **kwargs) -> SlackResponse: def chat_scheduledMessages_list(self, **kwargs) -> SlackResponse: """Lists all scheduled messages.""" - return self.api_call("chat.scheduledMessages.list", json=kwargs) + return self.api_call("chat.scheduledMessages.list", params=kwargs) def conversations_archive(self, *, channel: str, **kwargs) -> SlackResponse: """Archives a conversation. diff --git a/slack_sdk/web/internal_utils.py b/slack_sdk/web/internal_utils.py index 39023fe63..0f499880d 100644 --- a/slack_sdk/web/internal_utils.py +++ b/slack_sdk/web/internal_utils.py @@ -219,7 +219,8 @@ def _next_cursor_is_present(data) -> bool: Returns: A boolean value. """ - present = ( + # Only admin.conversations.search returns next_cursor at the top level + present = ("next_cursor" in data and data["next_cursor"] != "") or ( "response_metadata" in data and "next_cursor" in data["response_metadata"] and data["response_metadata"]["next_cursor"] != "" diff --git a/slack_sdk/web/legacy_client.py b/slack_sdk/web/legacy_client.py index d2d2998ce..91bab73cd 100644 --- a/slack_sdk/web/legacy_client.py +++ b/slack_sdk/web/legacy_client.py @@ -381,7 +381,7 @@ def admin_conversations_rename( def admin_conversations_search(self, **kwargs) -> Union[Future, SlackResponse]: """Search for public or private channels in an Enterprise organization.""" - return self.api_call("admin.conversations.search", json=kwargs) + return self.api_call("admin.conversations.search", params=kwargs) def admin_conversations_convertToPrivate( self, *, channel_id: str, **kwargs @@ -522,7 +522,7 @@ def admin_conversations_getTeams( """ kwargs.update({"channel_id": channel_id}) - return self.api_call("admin.conversations.getTeams", json=kwargs) + return self.api_call("admin.conversations.getTeams", params=kwargs) def admin_emoji_add(self, **kwargs) -> Union[Future, SlackResponse]: """Add an emoji.""" @@ -652,13 +652,13 @@ def admin_inviteRequests_approved_list( self, **kwargs ) -> Union[Future, SlackResponse]: """List all approved workspace invite requests.""" - return self.api_call("admin.inviteRequests.approved.list", json=kwargs) + return self.api_call("admin.inviteRequests.approved.list", params=kwargs) def admin_inviteRequests_denied_list( self, **kwargs ) -> Union[Future, SlackResponse]: """List all denied workspace invite requests.""" - return self.api_call("admin.inviteRequests.denied.list", json=kwargs) + return self.api_call("admin.inviteRequests.denied.list", params=kwargs) def admin_inviteRequests_deny( self, *, invite_request_id: str, **kwargs @@ -673,7 +673,7 @@ def admin_inviteRequests_deny( def admin_inviteRequests_list(self, **kwargs) -> Union[Future, SlackResponse]: """List all pending workspace invite requests.""" - return self.api_call("admin.inviteRequests.list", json=kwargs) + return self.api_call("admin.inviteRequests.list", params=kwargs) def admin_teams_admins_list( self, *, team_id: str, **kwargs @@ -700,7 +700,7 @@ def admin_teams_create( def admin_teams_list(self, **kwargs) -> Union[Future, SlackResponse]: """List all teams on an Enterprise organization.""" - return self.api_call("admin.teams.list", json=kwargs) + return self.api_call("admin.teams.list", params=kwargs) def admin_teams_owners_list( self, *, team_id: str, **kwargs @@ -886,7 +886,7 @@ def admin_users_list( team_id (str): ID of the team. e.g. 'T1234' """ kwargs.update({"team_id": team_id}) - return self.api_call("admin.users.list", json=kwargs) + return self.api_call("admin.users.list", params=kwargs) def admin_users_remove( self, *, team_id: str, user_id: str, **kwargs @@ -1378,7 +1378,7 @@ def chat_update( def chat_scheduledMessages_list(self, **kwargs) -> Union[Future, SlackResponse]: """Lists all scheduled messages.""" - return self.api_call("chat.scheduledMessages.list", json=kwargs) + return self.api_call("chat.scheduledMessages.list", params=kwargs) def conversations_archive( self, *, channel: str, **kwargs diff --git a/slack_sdk/web/slack_response.py b/slack_sdk/web/slack_response.py index 99a1ed263..7d47f145c 100644 --- a/slack_sdk/web/slack_response.py +++ b/slack_sdk/web/slack_response.py @@ -142,7 +142,10 @@ def __next__(self): params = self.req_args.get("params", {}) if params is None: params = {} - params.update({"cursor": self.data["response_metadata"]["next_cursor"]}) + next_cursor = self.data.get("response_metadata", {}).get( + "next_cursor" + ) or self.data.get("next_cursor") + params.update({"cursor": next_cursor}) self.req_args.update({"params": params}) # This method sends a request in a synchronous way diff --git a/tests/slack_sdk/web/test_web_client_issue_1049.py b/tests/slack_sdk/web/test_web_client_issue_1049.py new file mode 100644 index 000000000..ebe364266 --- /dev/null +++ b/tests/slack_sdk/web/test_web_client_issue_1049.py @@ -0,0 +1,26 @@ +import json +import unittest + +from slack_sdk.web import WebClient +from tests.slack_sdk.web.mock_web_api_server import ( + setup_mock_web_api_server, + cleanup_mock_web_api_server, +) + + +class TestWebClient_Issue_1049(unittest.TestCase): + def setUp(self): + setup_mock_web_api_server(self) + + def tearDown(self): + cleanup_mock_web_api_server(self) + + def test_the_pattern(self): + client = WebClient( + base_url="http://localhost:8888", + token="xoxb-admin_convo_pagination", + ) + pages = [] + for page in client.admin_conversations_search(query="announcement"): + pages.append(page) + self.assertEqual(len(pages), 2) diff --git a/tests/slack_sdk_fixture/web_response_admin_convo_pagination.json b/tests/slack_sdk_fixture/web_response_admin_convo_pagination.json new file mode 100644 index 000000000..6b7bd7efd --- /dev/null +++ b/tests/slack_sdk_fixture/web_response_admin_convo_pagination.json @@ -0,0 +1,28 @@ +{ + "ok": true, + "conversations": [ + { + "id": "C013T0FTKU3", + "name": "random", + "purpose": "test", + "member_count": 11, + "created": 1589700571, + "creator_id": "W111", + "is_private": false, + "is_archived": false, + "is_general": false, + "last_activity_ts": 1599130434000900, + "is_ext_shared": false, + "is_global_shared": false, + "is_org_default": false, + "is_org_mandatory": false, + "is_org_shared": false, + "is_frozen": false, + "internal_team_ids_count": 1, + "internal_team_ids_sample_team": "T111", + "pending_connected_team_ids": [], + "is_pending_ext_shared": false + } + ], + "next_cursor": "1" +} diff --git a/tests/slack_sdk_fixture/web_response_admin_convo_pagination_1.json b/tests/slack_sdk_fixture/web_response_admin_convo_pagination_1.json new file mode 100644 index 000000000..3a6a2ffa3 --- /dev/null +++ b/tests/slack_sdk_fixture/web_response_admin_convo_pagination_1.json @@ -0,0 +1,5 @@ +{ + "ok": true, + "conversations": [], + "next_cursor": "" +}