diff --git a/backend/danswer/bots/slack/blocks.py b/backend/danswer/bots/slack/blocks.py index 32388470c4c..e2f3c39b638 100644 --- a/backend/danswer/bots/slack/blocks.py +++ b/backend/danswer/bots/slack/blocks.py @@ -50,6 +50,9 @@ def _build_custom_semantic_identifier( truncated_blurb = UserIdReplacer.replace_tags_basic(truncated_blurb) truncated_blurb = UserIdReplacer.replace_channels_basic(truncated_blurb) truncated_blurb = UserIdReplacer.replace_special_mentions(truncated_blurb) + truncated_blurb = UserIdReplacer.replace_links(truncated_blurb) + # stop as soon as we see a newline, since these break the link + truncated_blurb = truncated_blurb.split("\n")[0] if truncated_blurb: return f"#{semantic_identifier}: {truncated_blurb}" else: diff --git a/backend/danswer/bots/slack/handlers/handle_feedback.py b/backend/danswer/bots/slack/handlers/handle_feedback.py index ff43c816379..917cfea9eb9 100644 --- a/backend/danswer/bots/slack/handlers/handle_feedback.py +++ b/backend/danswer/bots/slack/handlers/handle_feedback.py @@ -1,3 +1,4 @@ +from slack_sdk import WebClient from sqlalchemy.orm import Session from danswer.configs.constants import QAFeedbackType @@ -5,7 +6,14 @@ from danswer.db.feedback import update_query_event_feedback -def handle_qa_feedback(query_id: int, feedback_type: QAFeedbackType) -> None: +def handle_qa_feedback( + query_id: int, + feedback_type: QAFeedbackType, + client: WebClient, + user_id_to_post_confirmation: str, + channel_id_to_post_confirmation: str, + thread_ts_to_post_confirmation: str, +) -> None: engine = get_sqlalchemy_engine() with Session(engine) as db_session: update_query_event_feedback( @@ -14,3 +22,11 @@ def handle_qa_feedback(query_id: int, feedback_type: QAFeedbackType) -> None: user_id=None, # no "user" for Slack bot for now db_session=db_session, ) + + # post message to slack confirming that feedback was received + client.chat_postEphemeral( + channel=channel_id_to_post_confirmation, + user=user_id_to_post_confirmation, + thread_ts=thread_ts_to_post_confirmation, + text="Thanks for your feedback!", + ) diff --git a/backend/danswer/bots/slack/handlers/handle_message.py b/backend/danswer/bots/slack/handlers/handle_message.py index 9a89b2425d3..d81c5d5ba51 100644 --- a/backend/danswer/bots/slack/handlers/handle_message.py +++ b/backend/danswer/bots/slack/handlers/handle_message.py @@ -107,6 +107,8 @@ def _get_answer(question: QuestionRequest) -> QAResponse: channel=channel, blocks=blocks, thread_ts=message_ts_to_respond_to, + # don't unfurl, since otherwise we will have 5+ previews which makes the message very long + unfurl=False, ) except Exception: logger.exception( diff --git a/backend/danswer/bots/slack/listener.py b/backend/danswer/bots/slack/listener.py index d9bb65b74ad..803005e83c7 100644 --- a/backend/danswer/bots/slack/listener.py +++ b/backend/danswer/bots/slack/listener.py @@ -146,10 +146,17 @@ def _process_slack_event(client: SocketModeClient, req: SocketModeRequest) -> No return block_id = cast(str, action.get("block_id")) + user_id = cast(str, req.payload["user"]["id"]) + channel_id = cast(str, req.payload["container"]["channel_id"]) + thread_ts = cast(str, req.payload["container"]["thread_ts"]) query_event_id = get_query_event_id_from_block_id(block_id) handle_qa_feedback( query_id=query_event_id, feedback_type=feedback_type, + client=client.web_client, + user_id_to_post_confirmation=user_id, + channel_id_to_post_confirmation=channel_id, + thread_ts_to_post_confirmation=thread_ts, ) logger.info(f"Successfully handled QA feedback for event: {query_event_id}") diff --git a/backend/danswer/bots/slack/utils.py b/backend/danswer/bots/slack/utils.py index 4e74f2d651a..5209e9ea665 100644 --- a/backend/danswer/bots/slack/utils.py +++ b/backend/danswer/bots/slack/utils.py @@ -29,6 +29,7 @@ def respond_in_thread( text: str | None = None, blocks: list[Block] | None = None, metadata: Metadata | None = None, + unfurl: bool = True, ) -> None: if not text and not blocks: raise ValueError("One of `text` or `blocks` must be provided") @@ -45,6 +46,8 @@ def respond_in_thread( blocks=blocks, thread_ts=thread_ts, metadata=metadata, + unfurl_links=unfurl, + unfurl_media=unfurl, ) if not response.get("ok"): raise RuntimeError(f"Unable to post message: {response}") diff --git a/backend/danswer/connectors/slack/utils.py b/backend/danswer/connectors/slack/utils.py index 5932a08c5ff..e75fc56c8f0 100644 --- a/backend/danswer/connectors/slack/utils.py +++ b/backend/danswer/connectors/slack/utils.py @@ -179,3 +179,18 @@ def replace_special_mentions(message: str) -> str: message = message.replace("", "@here") message = message.replace("", "@everyone") return message + + @staticmethod + def replace_links(message: str) -> str: + """Replaces slack links e.g. `` -> `URL` and `` -> `DISPLAY`""" + # Find user IDs in the message + possible_link_matches = re.findall(r"<(.*?)>", message) + for possible_link in possible_link_matches: + if possible_link[0] not in ["#", "@", "!"]: + link_display = ( + possible_link + if "|" not in possible_link + else possible_link.split("|")[1] + ) + message = message.replace(f"<{possible_link}>", link_display) + return message