Skip to content

Commit 67028d6

Browse files
seratchfilmaj
andauthored
Add canvases APIs and users.discoverableContacts.lookup API (#1508)
Co-authored-by: Fil Maj <[email protected]>
1 parent 862796c commit 67028d6

File tree

5 files changed

+568
-6
lines changed

5 files changed

+568
-6
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import logging
2+
import os
3+
import time
4+
import unittest
5+
6+
from integration_tests.env_variable_names import SLACK_SDK_TEST_BOT_TOKEN
7+
from integration_tests.helpers import async_test
8+
from slack_sdk.web import WebClient
9+
from slack_sdk.web.async_client import AsyncWebClient
10+
11+
12+
class TestWebClient(unittest.TestCase):
13+
"""Runs integration tests with real Slack API"""
14+
15+
def setUp(self):
16+
self.logger = logging.getLogger(__name__)
17+
self.bot_token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
18+
self.sync_client: WebClient = WebClient(token=self.bot_token)
19+
self.async_client: AsyncWebClient = AsyncWebClient(token=self.bot_token)
20+
21+
def tearDown(self):
22+
pass
23+
24+
def test_sync(self):
25+
client = self.sync_client
26+
27+
# Channel canvas
28+
new_channel = client.conversations_create(name=f"test-{str(time.time()).replace('.', '-')}")
29+
channel_id = new_channel["channel"]["id"]
30+
channel_canvas = client.conversations_canvases_create(
31+
channel_id=channel_id,
32+
document_content={
33+
"type": "markdown",
34+
"markdown": """# My canvas
35+
---
36+
## Hey
37+
What's up?
38+
""",
39+
},
40+
)
41+
self.assertIsNone(channel_canvas.get("error"))
42+
43+
# Standalone canvas
44+
standalone_canvas = client.canvases_create(
45+
title="My canvas",
46+
document_content={
47+
"type": "markdown",
48+
"markdown": """# My canvas
49+
---
50+
## Hey
51+
What's up?
52+
""",
53+
},
54+
)
55+
self.assertIsNone(standalone_canvas.get("error"))
56+
canvas_id = standalone_canvas.get("canvas_id")
57+
58+
sections = client.canvases_sections_lookup(canvas_id=canvas_id, criteria={"contains_text": "Hey"})
59+
section_id = sections["sections"][0]["id"]
60+
61+
edit = client.canvases_edit(
62+
canvas_id=canvas_id,
63+
changes=[
64+
{
65+
"operation": "replace",
66+
"section_id": section_id,
67+
"document_content": {"type": "markdown", "markdown": "## Hey Hey"},
68+
}
69+
],
70+
)
71+
self.assertIsNone(edit.get("error"))
72+
73+
user_id = client.auth_test()["user_id"]
74+
access_set = client.canvases_access_set(
75+
canvas_id=canvas_id,
76+
access_level="write",
77+
user_ids=[user_id],
78+
)
79+
self.assertIsNone(access_set.get("error"))
80+
81+
access_delete = client.canvases_access_delete(canvas_id=canvas_id, user_ids=[user_id])
82+
self.assertIsNone(access_delete.get("error"))
83+
84+
delete = client.canvases_delete(canvas_id=canvas_id)
85+
self.assertIsNone(delete.get("error"))
86+
87+
@async_test
88+
async def test_async(self):
89+
client = self.async_client
90+
91+
# Channel canvas
92+
new_channel = await client.conversations_create(name=f"test-{str(time.time()).replace('.', '-')}")
93+
channel_id = new_channel["channel"]["id"]
94+
channel_canvas = await client.conversations_canvases_create(
95+
channel_id=channel_id,
96+
document_content={
97+
"type": "markdown",
98+
"markdown": """# My canvas
99+
---
100+
## Hey
101+
What's up?
102+
""",
103+
},
104+
)
105+
self.assertIsNone(channel_canvas.get("error"))
106+
107+
# Standalone canvas
108+
standalone_canvas = await client.canvases_create(
109+
title="My canvas",
110+
document_content={
111+
"type": "markdown",
112+
"markdown": """# My canvas
113+
---
114+
## Hey
115+
What's up?
116+
""",
117+
},
118+
)
119+
self.assertIsNone(standalone_canvas.get("error"))
120+
canvas_id = standalone_canvas.get("canvas_id")
121+
122+
sections = await client.canvases_sections_lookup(canvas_id=canvas_id, criteria={"contains_text": "Hey"})
123+
section_id = sections["sections"][0]["id"]
124+
125+
edit = await client.canvases_edit(
126+
canvas_id=canvas_id,
127+
changes=[
128+
{
129+
"operation": "replace",
130+
"section_id": section_id,
131+
"document_content": {"type": "markdown", "markdown": "## Hey Hey"},
132+
}
133+
],
134+
)
135+
self.assertIsNone(edit.get("error"))
136+
137+
user_id = (await client.auth_test())["user_id"]
138+
access_set = await client.canvases_access_set(
139+
canvas_id=canvas_id,
140+
access_level="write",
141+
user_ids=[user_id],
142+
)
143+
self.assertIsNone(access_set.get("error"))
144+
145+
access_delete = await client.canvases_access_delete(canvas_id=canvas_id, user_ids=[user_id])
146+
self.assertIsNone(access_delete.get("error"))
147+
148+
delete = await client.canvases_delete(canvas_id=canvas_id)
149+
self.assertIsNone(delete.get("error"))

slack_sdk/web/async_client.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2244,6 +2244,107 @@ async def calls_update(
22442244
)
22452245
return await self.api_call("calls.update", http_verb="POST", params=kwargs)
22462246

2247+
async def canvases_create(
2248+
self,
2249+
*,
2250+
title: Optional[str] = None,
2251+
document_content: Dict[str, str],
2252+
**kwargs,
2253+
) -> AsyncSlackResponse:
2254+
"""Create Canvas for a user
2255+
https://api.slack.com/methods/canvases.create
2256+
"""
2257+
kwargs.update({"title": title, "document_content": json.dumps(document_content)})
2258+
return await self.api_call("canvases.create", params=kwargs)
2259+
2260+
async def canvases_edit(
2261+
self,
2262+
*,
2263+
canvas_id: str,
2264+
changes: Sequence[Dict[str, Any]],
2265+
**kwargs,
2266+
) -> AsyncSlackResponse:
2267+
"""Update an existing canvas
2268+
https://api.slack.com/methods/canvases.edit
2269+
"""
2270+
kwargs.update({"canvas_id": canvas_id, "changes": json.dumps(changes)})
2271+
return await self.api_call("canvases.edit", params=kwargs)
2272+
2273+
async def canvases_delete(
2274+
self,
2275+
*,
2276+
canvas_id: str,
2277+
**kwargs,
2278+
) -> AsyncSlackResponse:
2279+
"""Deletes a canvas
2280+
https://api.slack.com/methods/canvases.delete
2281+
"""
2282+
kwargs.update({"canvas_id": canvas_id})
2283+
return await self.api_call("canvases.delete", params=kwargs)
2284+
2285+
async def canvases_access_set(
2286+
self,
2287+
*,
2288+
canvas_id: str,
2289+
access_level: str,
2290+
channel_ids: Optional[Union[Sequence[str], str]] = None,
2291+
user_ids: Optional[Union[Sequence[str], str]] = None,
2292+
**kwargs,
2293+
) -> AsyncSlackResponse:
2294+
"""Sets the access level to a canvas for specified entities
2295+
https://api.slack.com/methods/canvases.access.set
2296+
"""
2297+
kwargs.update({"canvas_id": canvas_id, "access_level": access_level})
2298+
if channel_ids is not None:
2299+
if isinstance(channel_ids, (list, Tuple)):
2300+
kwargs.update({"channel_ids": ",".join(channel_ids)})
2301+
else:
2302+
kwargs.update({"channel_ids": channel_ids})
2303+
if user_ids is not None:
2304+
if isinstance(user_ids, (list, Tuple)):
2305+
kwargs.update({"user_ids": ",".join(user_ids)})
2306+
else:
2307+
kwargs.update({"user_ids": user_ids})
2308+
2309+
return await self.api_call("canvases.access.set", params=kwargs)
2310+
2311+
async def canvases_access_delete(
2312+
self,
2313+
*,
2314+
canvas_id: str,
2315+
channel_ids: Optional[Union[Sequence[str], str]] = None,
2316+
user_ids: Optional[Union[Sequence[str], str]] = None,
2317+
**kwargs,
2318+
) -> AsyncSlackResponse:
2319+
"""Create a Channel Canvas for a channel
2320+
https://api.slack.com/methods/canvases.access.delete
2321+
"""
2322+
kwargs.update({"canvas_id": canvas_id})
2323+
if channel_ids is not None:
2324+
if isinstance(channel_ids, (list, Tuple)):
2325+
kwargs.update({"channel_ids": ",".join(channel_ids)})
2326+
else:
2327+
kwargs.update({"channel_ids": channel_ids})
2328+
if user_ids is not None:
2329+
if isinstance(user_ids, (list, Tuple)):
2330+
kwargs.update({"user_ids": ",".join(user_ids)})
2331+
else:
2332+
kwargs.update({"user_ids": user_ids})
2333+
return await self.api_call("canvases.access.delete", params=kwargs)
2334+
2335+
async def canvases_sections_lookup(
2336+
self,
2337+
*,
2338+
canvas_id: str,
2339+
criteria: Dict[str, Any],
2340+
**kwargs,
2341+
) -> AsyncSlackResponse:
2342+
"""Find sections matching the provided criteria
2343+
https://api.slack.com/methods/canvases.sections.lookup
2344+
"""
2345+
kwargs.update({"canvas_id": canvas_id, "criteria": json.dumps(criteria)})
2346+
return await self.api_call("canvases.sections.lookup", params=kwargs)
2347+
22472348
# --------------------------
22482349
# Deprecated: channels.*
22492350
# You can use conversations.* APIs instead.
@@ -3113,6 +3214,19 @@ async def conversations_unarchive(
31133214
kwargs.update({"channel": channel})
31143215
return await self.api_call("conversations.unarchive", params=kwargs)
31153216

3217+
async def conversations_canvases_create(
3218+
self,
3219+
*,
3220+
channel_id: str,
3221+
document_content: Dict[str, str],
3222+
**kwargs,
3223+
) -> AsyncSlackResponse:
3224+
"""Create a Channel Canvas for a channel
3225+
https://api.slack.com/methods/conversations.canvases.create
3226+
"""
3227+
kwargs.update({"channel_id": channel_id, "document_content": json.dumps(document_content)})
3228+
return await self.api_call("conversations.canvases.create", params=kwargs)
3229+
31163230
async def dialog_open(
31173231
self,
31183232
*,
@@ -4931,6 +5045,17 @@ async def users_setPresence(
49315045
kwargs.update({"presence": presence})
49325046
return await self.api_call("users.setPresence", params=kwargs)
49335047

5048+
async def users_discoverableContacts_lookup(
5049+
self,
5050+
email: str,
5051+
**kwargs,
5052+
) -> AsyncSlackResponse:
5053+
"""Lookup an email address to see if someone is on Slack
5054+
https://api.slack.com/methods/users.discoverableContacts.lookup
5055+
"""
5056+
kwargs.update({"email": email})
5057+
return await self.api_call("users.discoverableContacts.lookup", params=kwargs)
5058+
49345059
async def users_profile_get(
49355060
self,
49365061
*,

0 commit comments

Comments
 (0)