Skip to content

Commit

Permalink
Add canvases APIs and users.discoverableContacts.lookup API (#1508)
Browse files Browse the repository at this point in the history
Co-authored-by: Fil Maj <maj.fil@gmail.com>
  • Loading branch information
seratch and filmaj authored Jun 13, 2024
1 parent 862796c commit 67028d6
Show file tree
Hide file tree
Showing 5 changed files with 568 additions and 6 deletions.
149 changes: 149 additions & 0 deletions integration_tests/web/test_canvases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import logging
import os
import time
import unittest

from integration_tests.env_variable_names import SLACK_SDK_TEST_BOT_TOKEN
from integration_tests.helpers import async_test
from slack_sdk.web import WebClient
from slack_sdk.web.async_client import AsyncWebClient


class TestWebClient(unittest.TestCase):
"""Runs integration tests with real Slack API"""

def setUp(self):
self.logger = logging.getLogger(__name__)
self.bot_token = os.environ[SLACK_SDK_TEST_BOT_TOKEN]
self.sync_client: WebClient = WebClient(token=self.bot_token)
self.async_client: AsyncWebClient = AsyncWebClient(token=self.bot_token)

def tearDown(self):
pass

def test_sync(self):
client = self.sync_client

# Channel canvas
new_channel = client.conversations_create(name=f"test-{str(time.time()).replace('.', '-')}")
channel_id = new_channel["channel"]["id"]
channel_canvas = client.conversations_canvases_create(
channel_id=channel_id,
document_content={
"type": "markdown",
"markdown": """# My canvas
---
## Hey
What's up?
""",
},
)
self.assertIsNone(channel_canvas.get("error"))

# Standalone canvas
standalone_canvas = client.canvases_create(
title="My canvas",
document_content={
"type": "markdown",
"markdown": """# My canvas
---
## Hey
What's up?
""",
},
)
self.assertIsNone(standalone_canvas.get("error"))
canvas_id = standalone_canvas.get("canvas_id")

sections = client.canvases_sections_lookup(canvas_id=canvas_id, criteria={"contains_text": "Hey"})
section_id = sections["sections"][0]["id"]

edit = client.canvases_edit(
canvas_id=canvas_id,
changes=[
{
"operation": "replace",
"section_id": section_id,
"document_content": {"type": "markdown", "markdown": "## Hey Hey"},
}
],
)
self.assertIsNone(edit.get("error"))

user_id = client.auth_test()["user_id"]
access_set = client.canvases_access_set(
canvas_id=canvas_id,
access_level="write",
user_ids=[user_id],
)
self.assertIsNone(access_set.get("error"))

access_delete = client.canvases_access_delete(canvas_id=canvas_id, user_ids=[user_id])
self.assertIsNone(access_delete.get("error"))

delete = client.canvases_delete(canvas_id=canvas_id)
self.assertIsNone(delete.get("error"))

@async_test
async def test_async(self):
client = self.async_client

# Channel canvas
new_channel = await client.conversations_create(name=f"test-{str(time.time()).replace('.', '-')}")
channel_id = new_channel["channel"]["id"]
channel_canvas = await client.conversations_canvases_create(
channel_id=channel_id,
document_content={
"type": "markdown",
"markdown": """# My canvas
---
## Hey
What's up?
""",
},
)
self.assertIsNone(channel_canvas.get("error"))

# Standalone canvas
standalone_canvas = await client.canvases_create(
title="My canvas",
document_content={
"type": "markdown",
"markdown": """# My canvas
---
## Hey
What's up?
""",
},
)
self.assertIsNone(standalone_canvas.get("error"))
canvas_id = standalone_canvas.get("canvas_id")

sections = await client.canvases_sections_lookup(canvas_id=canvas_id, criteria={"contains_text": "Hey"})
section_id = sections["sections"][0]["id"]

edit = await client.canvases_edit(
canvas_id=canvas_id,
changes=[
{
"operation": "replace",
"section_id": section_id,
"document_content": {"type": "markdown", "markdown": "## Hey Hey"},
}
],
)
self.assertIsNone(edit.get("error"))

user_id = (await client.auth_test())["user_id"]
access_set = await client.canvases_access_set(
canvas_id=canvas_id,
access_level="write",
user_ids=[user_id],
)
self.assertIsNone(access_set.get("error"))

access_delete = await client.canvases_access_delete(canvas_id=canvas_id, user_ids=[user_id])
self.assertIsNone(access_delete.get("error"))

delete = await client.canvases_delete(canvas_id=canvas_id)
self.assertIsNone(delete.get("error"))
125 changes: 125 additions & 0 deletions slack_sdk/web/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2244,6 +2244,107 @@ async def calls_update(
)
return await self.api_call("calls.update", http_verb="POST", params=kwargs)

async def canvases_create(
self,
*,
title: Optional[str] = None,
document_content: Dict[str, str],
**kwargs,
) -> AsyncSlackResponse:
"""Create Canvas for a user
https://api.slack.com/methods/canvases.create
"""
kwargs.update({"title": title, "document_content": json.dumps(document_content)})
return await self.api_call("canvases.create", params=kwargs)

async def canvases_edit(
self,
*,
canvas_id: str,
changes: Sequence[Dict[str, Any]],
**kwargs,
) -> AsyncSlackResponse:
"""Update an existing canvas
https://api.slack.com/methods/canvases.edit
"""
kwargs.update({"canvas_id": canvas_id, "changes": json.dumps(changes)})
return await self.api_call("canvases.edit", params=kwargs)

async def canvases_delete(
self,
*,
canvas_id: str,
**kwargs,
) -> AsyncSlackResponse:
"""Deletes a canvas
https://api.slack.com/methods/canvases.delete
"""
kwargs.update({"canvas_id": canvas_id})
return await self.api_call("canvases.delete", params=kwargs)

async def canvases_access_set(
self,
*,
canvas_id: str,
access_level: str,
channel_ids: Optional[Union[Sequence[str], str]] = None,
user_ids: Optional[Union[Sequence[str], str]] = None,
**kwargs,
) -> AsyncSlackResponse:
"""Sets the access level to a canvas for specified entities
https://api.slack.com/methods/canvases.access.set
"""
kwargs.update({"canvas_id": canvas_id, "access_level": access_level})
if channel_ids is not None:
if isinstance(channel_ids, (list, Tuple)):
kwargs.update({"channel_ids": ",".join(channel_ids)})
else:
kwargs.update({"channel_ids": channel_ids})
if user_ids is not None:
if isinstance(user_ids, (list, Tuple)):
kwargs.update({"user_ids": ",".join(user_ids)})
else:
kwargs.update({"user_ids": user_ids})

return await self.api_call("canvases.access.set", params=kwargs)

async def canvases_access_delete(
self,
*,
canvas_id: str,
channel_ids: Optional[Union[Sequence[str], str]] = None,
user_ids: Optional[Union[Sequence[str], str]] = None,
**kwargs,
) -> AsyncSlackResponse:
"""Create a Channel Canvas for a channel
https://api.slack.com/methods/canvases.access.delete
"""
kwargs.update({"canvas_id": canvas_id})
if channel_ids is not None:
if isinstance(channel_ids, (list, Tuple)):
kwargs.update({"channel_ids": ",".join(channel_ids)})
else:
kwargs.update({"channel_ids": channel_ids})
if user_ids is not None:
if isinstance(user_ids, (list, Tuple)):
kwargs.update({"user_ids": ",".join(user_ids)})
else:
kwargs.update({"user_ids": user_ids})
return await self.api_call("canvases.access.delete", params=kwargs)

async def canvases_sections_lookup(
self,
*,
canvas_id: str,
criteria: Dict[str, Any],
**kwargs,
) -> AsyncSlackResponse:
"""Find sections matching the provided criteria
https://api.slack.com/methods/canvases.sections.lookup
"""
kwargs.update({"canvas_id": canvas_id, "criteria": json.dumps(criteria)})
return await self.api_call("canvases.sections.lookup", params=kwargs)

# --------------------------
# Deprecated: channels.*
# You can use conversations.* APIs instead.
Expand Down Expand Up @@ -3113,6 +3214,19 @@ async def conversations_unarchive(
kwargs.update({"channel": channel})
return await self.api_call("conversations.unarchive", params=kwargs)

async def conversations_canvases_create(
self,
*,
channel_id: str,
document_content: Dict[str, str],
**kwargs,
) -> AsyncSlackResponse:
"""Create a Channel Canvas for a channel
https://api.slack.com/methods/conversations.canvases.create
"""
kwargs.update({"channel_id": channel_id, "document_content": json.dumps(document_content)})
return await self.api_call("conversations.canvases.create", params=kwargs)

async def dialog_open(
self,
*,
Expand Down Expand Up @@ -4931,6 +5045,17 @@ async def users_setPresence(
kwargs.update({"presence": presence})
return await self.api_call("users.setPresence", params=kwargs)

async def users_discoverableContacts_lookup(
self,
email: str,
**kwargs,
) -> AsyncSlackResponse:
"""Lookup an email address to see if someone is on Slack
https://api.slack.com/methods/users.discoverableContacts.lookup
"""
kwargs.update({"email": email})
return await self.api_call("users.discoverableContacts.lookup", params=kwargs)

async def users_profile_get(
self,
*,
Expand Down
Loading

0 comments on commit 67028d6

Please sign in to comment.