Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

conversation_granularity for slack - per user | per user per channel | per user per thread #10086

Merged
merged 43 commits into from
Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
94dc44e
allow conversation_id to be per user | per user per channel | per use…
srinivasupadhya Nov 5, 2021
bed5ea5
make formatter
srinivasupadhya Nov 5, 2021
36134b0
fix typo
srinivasupadhya Nov 5, 2021
34954e6
Merge branch 'main' into slack_conversation_id
srinivasupadhya Nov 5, 2021
7b053ca
Merge branch 'main' into slack_conversation_id
srinivasupadhya Nov 6, 2021
5a8b91b
Merge branch 'main' into slack_conversation_id
srinivasupadhya Nov 7, 2021
8861c8e
fix review comment
srinivasupadhya Nov 8, 2021
f4a2bc1
Handle syslog writing from the command line (#9513)
PaulNewtech Nov 5, 2021
58cb53b
Update `sanic` to make Rasa compatible with the latest `rasa-sdk` cha…
alwx Nov 4, 2021
4ffb4f1
Reverting back the recent `<conversation_id>`
alwx Nov 4, 2021
92224e9
Update for `list_routes`
alwx Nov 4, 2021
ae363f4
Updated dependencies + test_server.py indentation
alwx Nov 4, 2021
9b8a8c0
Changelog entry
alwx Nov 4, 2021
e331d88
Updated list_routes
alwx Nov 5, 2021
b9ad076
TF updates
alwx Nov 5, 2021
7b9c1c0
fix pytest sanic
wochinge Nov 5, 2021
3dcb737
fix test_hangouts_extract_functions
wochinge Nov 5, 2021
f6f3918
fix route tests
wochinge Nov 5, 2021
afe3e60
black format
wochinge Nov 5, 2021
c4e5f50
fix mypy issues
wochinge Nov 5, 2021
87b6d5c
temporarily disable `no-untyped-call`
wochinge Nov 5, 2021
0914b05
increase timeout
wochinge Nov 5, 2021
3693219
Success markers telemetry (#10065)
alwx Nov 5, 2021
dd794fa
add missing type annotations (#10091)
wochinge Nov 5, 2021
0a23847
Release candidate 3.0.0rc1 (#10093)
joejuzl Nov 5, 2021
c78c5ba
success markers / cleanup (#10081)
ka-bu Nov 5, 2021
63c06e1
add mention of slot events in or statements:
indam23 Nov 3, 2021
6e8a1b5
Merge branch 'slack_conversation_id' of https://github.com/srinivasup…
srinivasupadhya Nov 8, 2021
d33a271
Merge branch 'main' into slack_conversation_id
srinivasupadhya Nov 8, 2021
a723d73
update docs
srinivasupadhya Nov 8, 2021
0aee987
Merge branch 'slack_conversation_id' of https://github.com/srinivasup…
srinivasupadhya Nov 8, 2021
e965d86
docs
srinivasupadhya Nov 8, 2021
140af34
handle empty channel / thread
srinivasupadhya Nov 9, 2021
a80fd1c
add test
srinivasupadhya Nov 9, 2021
ab479e4
Merge branch 'main' into slack_conversation_id
srinivasupadhya Nov 10, 2021
fdeb4d1
formatting
srinivasupadhya Nov 10, 2021
d4bd592
Merge branch 'slack_conversation_id' of https://github.com/srinivasup…
srinivasupadhya Nov 10, 2021
412896a
make get_conversation_id private
srinivasupadhya Nov 10, 2021
2cdefb7
fix make types
srinivasupadhya Nov 10, 2021
aa8c1a7
update changelog
srinivasupadhya Nov 10, 2021
8e006b8
update changelog
srinivasupadhya Nov 10, 2021
5a71d1c
Merge branch 'main' into slack_conversation_id
Nov 10, 2021
b5636a7
Merge branch 'main' into slack_conversation_id
Nov 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/10086.misc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`conversation_granularity` config for slack channel, supports `sender`, `channel`, `thread`.
srinivasupadhya marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions docs/docs/connectors/slack.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ slack:
slack_retry_number_header: "x-slack-retry-num" # Slack HTTP header name indicating the attempt number. This configuration is optional.
errors_ignore_retry: None # Any error codes given by Slack included in this list will be ignored. Error codes are listed [here](https://api.slack.com/events-api#errors).
use_threads: False # If set to True, bot responses will appear as a threaded message in Slack. This configuration is optional and set to False by default.
conversation_granularity: "sender" # sender allows 1 conversation per user (across channels), channel allows 1 conversation per user per channel, thread allows 1 conversation per user per thread. This configuration is optional and set to sender by default.
srinivasupadhya marked this conversation as resolved.
Show resolved Hide resolved
```

Make sure to restart your Rasa X or Rasa Open Source server after changing the
Expand Down
40 changes: 37 additions & 3 deletions rasa/core/channels/slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def from_credentials(cls, credentials: Optional[Dict[Text, Any]]) -> InputChanne
credentials.get("errors_ignore_retry", None),
credentials.get("use_threads", False),
credentials.get("slack_signing_secret", ""),
credentials.get("conversation_granularity", "sender"),
)

def __init__(
Expand All @@ -151,6 +152,7 @@ def __init__(
errors_ignore_retry: Optional[List[Text]] = None,
use_threads: Optional[bool] = False,
slack_signing_secret: Text = "",
conversation_granularity: Optional[Text] = "sender",
) -> None:
"""Create a Slack input channel.

Expand Down Expand Up @@ -182,7 +184,10 @@ def __init__(
slack_signing_secret: Slack creates a unique string for your app and
shares it with you. This allows us to verify requests from Slack
with confidence by verifying signatures using your signing secret.

conversation_granularity: conversation granularity for slack conversations.
sender allows 1 conversation per user (across channels)
channel allows 1 conversation per user per channel
thread allows 1 conversation per user per thread
"""
self.slack_token = slack_token
self.slack_channel = slack_channel
Expand All @@ -192,6 +197,7 @@ def __init__(
self.retry_num_header = slack_retry_number_header
self.use_threads = use_threads
self.slack_signing_secret = slack_signing_secret
self.conversation_granularity = conversation_granularity

self._validate_credentials()

Expand Down Expand Up @@ -506,6 +512,11 @@ async def webhook(request: Request) -> HTTPResponse:
user_message = event.get("text", "")
sender_id = event.get("user", "")
metadata = self.get_metadata(request)
channel_id = metadata.get("out_channel")
thread_id = metadata.get("thread_id")
conversation_id = self._get_conversation_id(
sender_id, channel_id, thread_id
srinivasupadhya marked this conversation as resolved.
Show resolved Hide resolved
)

if "challenge" in output:
return response.json(output.get("challenge"))
Expand All @@ -528,7 +539,7 @@ async def webhook(request: Request) -> HTTPResponse:
request,
on_new_message,
text=self._sanitize_user_message(user_message, metadata["users"]),
sender_id=sender_id,
sender_id=conversation_id,
metadata=metadata,
)
elif content_type == "application/x-www-form-urlencoded":
Expand All @@ -541,8 +552,13 @@ async def webhook(request: Request) -> HTTPResponse:
text = self._get_interactive_response(payload["actions"][0])
if text is not None:
metadata = self.get_metadata(request)
channel_id = metadata.get("out_channel")
thread_id = metadata.get("thread_id")
conversation_id = self._get_conversation_id(
sender_id, channel_id, thread_id
)
return await self.process_message(
request, on_new_message, text, sender_id, metadata
request, on_new_message, text, conversation_id, metadata
)
if payload["actions"][0]["type"] == "button":
# link buttons don't have "value", don't send their clicks to
Expand All @@ -557,6 +573,24 @@ async def webhook(request: Request) -> HTTPResponse:

return slack_webhook

def _get_conversation_id(
self,
sender_id: Optional[Text],
channel_id: Optional[Text],
thread_id: Optional[Text],
) -> Optional[Text]:
conversation_id = sender_id
if self.conversation_granularity == "channel" and sender_id and channel_id:
conversation_id = sender_id + "_" + channel_id
if (
self.conversation_granularity == "thread"
and sender_id
and channel_id
and thread_id
):
conversation_id = sender_id + "_" + channel_id + "_" + thread_id
return conversation_id

def _is_supported_channel(self, slack_event: Dict, metadata: Dict) -> bool:
return (
self._is_direct_message(slack_event)
Expand Down
72 changes: 71 additions & 1 deletion tests/core/channels/test_slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,85 @@ def test_slack_init_token_channel_parameters():
ch = SlackInput("xoxb-test", "test", slack_signing_secret="foobar")
assert ch.slack_token == "xoxb-test"
assert ch.slack_channel == "test"
assert ch.conversation_granularity == "sender"


def test_slack_init_token_channel_conversation_granularity_parameters():
ch = SlackInput(
"xoxb-test",
"test",
slack_signing_secret="foobar",
conversation_granularity="channel",
)
assert ch.slack_token == "xoxb-test"
assert ch.slack_channel == "test"
assert ch.conversation_granularity == "channel"


def test_slack_init_token_channel_threads_parameters():
ch = SlackInput(
"xoxb-test", "test", slack_signing_secret="foobar", use_threads=True
"xoxb-test",
"test",
slack_signing_secret="foobar",
use_threads=True,
conversation_granularity="thread",
)
assert ch.slack_token == "xoxb-test"
assert ch.slack_channel == "test"
assert ch.use_threads is True
assert ch.conversation_granularity == "thread"


def test_get_conversation_id_sender_id():
ch = SlackInput(
"xoxb-test",
"test",
slack_signing_secret="foobar",
use_threads=True,
conversation_granularity="sender",
)
conversation_id = ch._get_conversation_id(
"test_sender_id", "test_channel_id", "test_thread_id"
)
assert conversation_id == "test_sender_id"


def test_get_conversation_id_channel_id():
ch = SlackInput(
"xoxb-test",
"test",
slack_signing_secret="foobar",
use_threads=True,
conversation_granularity="channel",
)
conversation_id = ch._get_conversation_id("test_sender_id", "test_channel_id", None)
assert conversation_id == "test_sender_id_test_channel_id"

conversation_id = ch._get_conversation_id("test_sender_id", None, "test_thread_id")
assert conversation_id == "test_sender_id"


def test_get_conversation_id_thread_id():
ch = SlackInput(
"xoxb-test",
"test",
slack_signing_secret="foobar",
use_threads=True,
conversation_granularity="thread",
)
conversation_id = ch._get_conversation_id(
"test_sender_id", "test_channel_id", "test_thread_id"
)
assert conversation_id == "test_sender_id_test_channel_id_test_thread_id"

conversation_id = ch._get_conversation_id("test_sender_id", None, "test_thread_id")
assert conversation_id == "test_sender_id"

conversation_id = ch._get_conversation_id("test_sender_id", "test_channel_id", None)
assert conversation_id == "test_sender_id"

conversation_id = ch._get_conversation_id("test_sender_id", None, None)
assert conversation_id == "test_sender_id"


def test_is_slack_message_none():
Expand Down