Skip to content

Commit c04e899

Browse files
srtaalejzimeg
andauthored
feat(web-api): add slackLists methods (#1772)
Co-authored-by: Eden Zimbelman <eden.zimbelman@salesforce.com>
1 parent e802f17 commit c04e899

File tree

5 files changed

+859
-4
lines changed

5 files changed

+859
-4
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import logging
2+
import os
3+
import unittest
4+
5+
from integration_tests.env_variable_names import (
6+
SLACK_SDK_TEST_BOT_TOKEN,
7+
)
8+
from integration_tests.helpers import async_test
9+
from slack_sdk.web import WebClient
10+
from slack_sdk.web.async_client import AsyncWebClient
11+
from slack_sdk.models.blocks import RichTextBlock
12+
from slack_sdk.models.blocks.block_elements import RichTextSection, RichTextText
13+
14+
15+
class TestSlackLists(unittest.TestCase):
16+
"""Runs integration tests with real Slack API testing the slackLists.* APIs"""
17+
18+
def setUp(self):
19+
if not hasattr(self, "logger"):
20+
self.logger = logging.getLogger(__name__)
21+
self.bot_token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
22+
self.async_client: AsyncWebClient = AsyncWebClient(token=self.bot_token)
23+
self.sync_client: WebClient = WebClient(token=self.bot_token)
24+
25+
def tearDown(self):
26+
pass
27+
28+
def test_create_list_with_dicts(self):
29+
"""Test creating a list with description_blocks as dicts"""
30+
client = self.sync_client
31+
32+
create_response = client.slackLists_create(
33+
name="Test Sales Pipeline",
34+
description_blocks=[
35+
{
36+
"type": "rich_text",
37+
"elements": [
38+
{
39+
"type": "rich_text_section",
40+
"elements": [{"type": "text", "text": "This is a test list for integration testing"}],
41+
}
42+
],
43+
}
44+
],
45+
schema=[
46+
{"key": "deal_name", "name": "Deal Name", "type": "text", "is_primary_column": True},
47+
{"key": "amount", "name": "Amount", "type": "number", "options": {"format": "currency", "precision": 2}},
48+
],
49+
)
50+
51+
self.assertIsNotNone(create_response)
52+
self.assertTrue(create_response["ok"])
53+
self.assertIn("list", create_response)
54+
list_id = create_response["list"]["id"]
55+
self.logger.info(f"✓ Created list with ID: {list_id}")
56+
57+
def test_create_list_with_rich_text_blocks(self):
58+
"""Test creating a list with RichTextBlock objects"""
59+
client = self.sync_client
60+
61+
create_response = client.slackLists_create(
62+
name="Test List with Rich Text Blocks",
63+
description_blocks=[
64+
RichTextBlock(
65+
elements=[RichTextSection(elements=[RichTextText(text="Created with RichTextBlock objects!")])]
66+
)
67+
],
68+
schema=[{"key": "task_name", "name": "Task", "type": "text", "is_primary_column": True}],
69+
)
70+
71+
self.assertIsNotNone(create_response)
72+
self.assertTrue(create_response["ok"])
73+
list_id = create_response["list"]["id"]
74+
self.logger.info(f"✓ Created list with RichTextBlocks, ID: {list_id}")
75+
76+
@async_test
77+
async def test_create_list_async(self):
78+
"""Test creating a list with async client"""
79+
client = self.async_client
80+
81+
create_response = await client.slackLists_create(
82+
name="Async Test List", schema=[{"key": "item_name", "name": "Item", "type": "text", "is_primary_column": True}]
83+
)
84+
85+
self.assertIsNotNone(create_response)
86+
self.assertTrue(create_response["ok"])
87+
list_id = create_response["list"]["id"]
88+
self.logger.info(f"✓ Created list asynchronously, ID: {list_id}")

slack_sdk/web/async_client.py

Lines changed: 244 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from slack_sdk.web.async_chat_stream import AsyncChatStream
2222

2323
from ..models.attachments import Attachment
24-
from ..models.blocks import Block
24+
from ..models.blocks import Block, RichTextBlock
2525
from ..models.metadata import Metadata, EntityMetadata, EventAndEntityMetadata
2626
from .async_base_client import AsyncBaseClient, AsyncSlackResponse
2727
from .internal_utils import (
@@ -4925,6 +4925,249 @@ async def search_messages(
49254925
)
49264926
return await self.api_call("search.messages", http_verb="GET", params=kwargs)
49274927

4928+
async def slackLists_access_delete(
4929+
self,
4930+
*,
4931+
list_id: str,
4932+
channel_ids: Optional[List[str]] = None,
4933+
user_ids: Optional[List[str]] = None,
4934+
**kwargs,
4935+
) -> AsyncSlackResponse:
4936+
"""Revoke access to a List for specified entities.
4937+
https://docs.slack.dev/reference/methods/slackLists.access.delete
4938+
"""
4939+
kwargs.update({"list_id": list_id, "channel_ids": channel_ids, "user_ids": user_ids})
4940+
kwargs = _remove_none_values(kwargs)
4941+
return await self.api_call("slackLists.access.delete", json=kwargs)
4942+
4943+
async def slackLists_access_set(
4944+
self,
4945+
*,
4946+
list_id: str,
4947+
access_level: str,
4948+
channel_ids: Optional[List[str]] = None,
4949+
user_ids: Optional[List[str]] = None,
4950+
**kwargs,
4951+
) -> AsyncSlackResponse:
4952+
"""Set the access level to a List for specified entities.
4953+
https://docs.slack.dev/reference/methods/slackLists.access.set
4954+
"""
4955+
kwargs.update({"list_id": list_id, "access_level": access_level, "channel_ids": channel_ids, "user_ids": user_ids})
4956+
kwargs = _remove_none_values(kwargs)
4957+
return await self.api_call("slackLists.access.set", json=kwargs)
4958+
4959+
async def slackLists_create(
4960+
self,
4961+
*,
4962+
name: str,
4963+
description_blocks: Optional[Union[str, Sequence[Union[Dict, RichTextBlock]]]] = None,
4964+
schema: Optional[List[Dict[str, Any]]] = None,
4965+
copy_from_list_id: Optional[str] = None,
4966+
include_copied_list_records: Optional[bool] = None,
4967+
todo_mode: Optional[bool] = None,
4968+
**kwargs,
4969+
) -> AsyncSlackResponse:
4970+
"""Creates a List.
4971+
https://docs.slack.dev/reference/methods/slackLists.create
4972+
"""
4973+
kwargs.update(
4974+
{
4975+
"name": name,
4976+
"description_blocks": description_blocks,
4977+
"schema": schema,
4978+
"copy_from_list_id": copy_from_list_id,
4979+
"include_copied_list_records": include_copied_list_records,
4980+
"todo_mode": todo_mode,
4981+
}
4982+
)
4983+
kwargs = _remove_none_values(kwargs)
4984+
return await self.api_call("slackLists.create", json=kwargs)
4985+
4986+
async def slackLists_download_get(
4987+
self,
4988+
*,
4989+
list_id: str,
4990+
job_id: str,
4991+
**kwargs,
4992+
) -> AsyncSlackResponse:
4993+
"""Retrieve List download URL from an export job to download List contents.
4994+
https://docs.slack.dev/reference/methods/slackLists.download.get
4995+
"""
4996+
kwargs.update(
4997+
{
4998+
"list_id": list_id,
4999+
"job_id": job_id,
5000+
}
5001+
)
5002+
kwargs = _remove_none_values(kwargs)
5003+
return await self.api_call("slackLists.download.get", json=kwargs)
5004+
5005+
async def slackLists_download_start(
5006+
self,
5007+
*,
5008+
list_id: str,
5009+
include_archived: Optional[bool] = None,
5010+
**kwargs,
5011+
) -> AsyncSlackResponse:
5012+
"""Initiate a job to export List contents.
5013+
https://docs.slack.dev/reference/methods/slackLists.download.start
5014+
"""
5015+
kwargs.update(
5016+
{
5017+
"list_id": list_id,
5018+
"include_archived": include_archived,
5019+
}
5020+
)
5021+
kwargs = _remove_none_values(kwargs)
5022+
return await self.api_call("slackLists.download.start", json=kwargs)
5023+
5024+
async def slackLists_items_create(
5025+
self,
5026+
*,
5027+
list_id: str,
5028+
duplicated_item_id: Optional[str] = None,
5029+
parent_item_id: Optional[str] = None,
5030+
initial_fields: Optional[List[Dict[str, Any]]] = None,
5031+
**kwargs,
5032+
) -> AsyncSlackResponse:
5033+
"""Add a new item to an existing List.
5034+
https://docs.slack.dev/reference/methods/slackLists.items.create
5035+
"""
5036+
kwargs.update(
5037+
{
5038+
"list_id": list_id,
5039+
"duplicated_item_id": duplicated_item_id,
5040+
"parent_item_id": parent_item_id,
5041+
"initial_fields": initial_fields,
5042+
}
5043+
)
5044+
kwargs = _remove_none_values(kwargs)
5045+
return await self.api_call("slackLists.items.create", json=kwargs)
5046+
5047+
async def slackLists_items_delete(
5048+
self,
5049+
*,
5050+
list_id: str,
5051+
id: str,
5052+
**kwargs,
5053+
) -> AsyncSlackResponse:
5054+
"""Deletes an item from an existing List.
5055+
https://docs.slack.dev/reference/methods/slackLists.items.delete
5056+
"""
5057+
kwargs.update(
5058+
{
5059+
"list_id": list_id,
5060+
"id": id,
5061+
}
5062+
)
5063+
kwargs = _remove_none_values(kwargs)
5064+
return await self.api_call("slackLists.items.delete", json=kwargs)
5065+
5066+
async def slackLists_items_deleteMultiple(
5067+
self,
5068+
*,
5069+
list_id: str,
5070+
ids: List[str],
5071+
**kwargs,
5072+
) -> AsyncSlackResponse:
5073+
"""Deletes multiple items from an existing List.
5074+
https://docs.slack.dev/reference/methods/slackLists.items.deleteMultiple
5075+
"""
5076+
kwargs.update(
5077+
{
5078+
"list_id": list_id,
5079+
"ids": ids,
5080+
}
5081+
)
5082+
kwargs = _remove_none_values(kwargs)
5083+
return await self.api_call("slackLists.items.deleteMultiple", json=kwargs)
5084+
5085+
async def slackLists_items_info(
5086+
self,
5087+
*,
5088+
list_id: str,
5089+
id: str,
5090+
include_is_subscribed: Optional[bool] = None,
5091+
**kwargs,
5092+
) -> AsyncSlackResponse:
5093+
"""Get a row from a List.
5094+
https://docs.slack.dev/reference/methods/slackLists.items.info
5095+
"""
5096+
kwargs.update(
5097+
{
5098+
"list_id": list_id,
5099+
"id": id,
5100+
"include_is_subscribed": include_is_subscribed,
5101+
}
5102+
)
5103+
kwargs = _remove_none_values(kwargs)
5104+
return await self.api_call("slackLists.items.info", json=kwargs)
5105+
5106+
async def slackLists_items_list(
5107+
self,
5108+
*,
5109+
list_id: str,
5110+
limit: Optional[int] = None,
5111+
cursor: Optional[str] = None,
5112+
archived: Optional[bool] = None,
5113+
**kwargs,
5114+
) -> AsyncSlackResponse:
5115+
"""Get records from a List.
5116+
https://docs.slack.dev/reference/methods/slackLists.items.list
5117+
"""
5118+
kwargs.update(
5119+
{
5120+
"list_id": list_id,
5121+
"limit": limit,
5122+
"cursor": cursor,
5123+
"archived": archived,
5124+
}
5125+
)
5126+
kwargs = _remove_none_values(kwargs)
5127+
return await self.api_call("slackLists.items.list", json=kwargs)
5128+
5129+
async def slackLists_items_update(
5130+
self,
5131+
*,
5132+
list_id: str,
5133+
cells: List[Dict[str, Any]],
5134+
**kwargs,
5135+
) -> AsyncSlackResponse:
5136+
"""Updates cells in a List.
5137+
https://docs.slack.dev/reference/methods/slackLists.items.update
5138+
"""
5139+
kwargs.update(
5140+
{
5141+
"list_id": list_id,
5142+
"cells": cells,
5143+
}
5144+
)
5145+
kwargs = _remove_none_values(kwargs)
5146+
return await self.api_call("slackLists.items.update", json=kwargs)
5147+
5148+
async def slackLists_update(
5149+
self,
5150+
*,
5151+
id: str,
5152+
name: Optional[str] = None,
5153+
description_blocks: Optional[Union[str, Sequence[Union[Dict, RichTextBlock]]]] = None,
5154+
todo_mode: Optional[bool] = None,
5155+
**kwargs,
5156+
) -> AsyncSlackResponse:
5157+
"""Update a List.
5158+
https://docs.slack.dev/reference/methods/slackLists.update
5159+
"""
5160+
kwargs.update(
5161+
{
5162+
"id": id,
5163+
"name": name,
5164+
"description_blocks": description_blocks,
5165+
"todo_mode": todo_mode,
5166+
}
5167+
)
5168+
kwargs = _remove_none_values(kwargs)
5169+
return await self.api_call("slackLists.update", json=kwargs)
5170+
49285171
async def stars_add(
49295172
self,
49305173
*,

0 commit comments

Comments
 (0)