From 09484016f531edb820bb3876c2ff5bdecb8aadd5 Mon Sep 17 00:00:00 2001 From: Rola Date: Tue, 13 Aug 2024 14:12:09 +0200 Subject: [PATCH] Resolve Slack feedback --- core/helpers.py | 34 ++++++++++++++++++++++++++++------ core/resolvers.py | 28 ++++++++++++++++++---------- core/slack_listeners.py | 26 +++++++++++++++----------- core/urls.py | 4 ++++ 4 files changed, 65 insertions(+), 27 deletions(-) diff --git a/core/helpers.py b/core/helpers.py index a4d3569..e1114f6 100644 --- a/core/helpers.py +++ b/core/helpers.py @@ -1,8 +1,8 @@ import logging - from dataclasses import dataclass from typing import Dict, Optional +import requests from slack_sdk.errors import SlackApiError from slack_sdk.models.blocks import ButtonElement, DividerBlock, SectionBlock @@ -10,7 +10,6 @@ from .enums import EndpointName - Logger = logging.getLogger(__name__) @@ -238,19 +237,18 @@ def channel_exists(client, channel_id): types="public_channel,private_channel" ) channels = response["channels"] - for channel in channels: if channel["id"] == channel_id: return True Logger.warning(f"Channel {channel_id} not found") Logger.warning(f"Channels: {channels}") - + return False - + except SlackApiError as e: print(f"Error: {e.response['error']}") - + except Exception as e: print(f"Error: {e}") @@ -334,3 +332,27 @@ def format_comparison(comparison): ) return blocks + + +def bot_is_member_of_channel(client, channel_id): + try: + auth_response = client.auth_test() + bot_user_id = auth_response["user_id"] + + response = client.conversations_members(channel=channel_id) + members = response["members"] + + return bot_user_id in members + except SlackApiError as e: + logger.error( + f"Error checking channel membership: {e.response['error']}" + ) + return False + + +def send_not_member_response(response_url): + message = { + "response_type": "ephemeral", + "text": "I'm not a member of this channel and can't send messages here. Please invite me to the channel using `/invite @Codecov`, or you can interact with me via direct message.", + } + requests.post(response_url, json=message) diff --git a/core/resolvers.py b/core/resolvers.py index 1fefccd..9bd78ed 100644 --- a/core/resolvers.py +++ b/core/resolvers.py @@ -75,16 +75,18 @@ def resolve(self, *args, **kwargs): def post_snippet(self, message): try: - response = self.client.conversations_info(channel=self.command["channel_id"]) - channel = response['channel'] + response = self.client.conversations_info( + channel=self.command["channel_id"] + ) + channel = response["channel"] # Check if it's not a DM with App - if not channel['is_im']: + if not channel["is_im"]: self.client.chat_postEphemeral( - channel=self.command["channel_id"], - user=self.command["user_id"], - text=f"Response too large to display here. you can find it in the Codecov app's DMs", - ) + channel=self.command["channel_id"], + user=self.command["user_id"], + text=f"Response too large to display here. you can find it in the Codecov app's DMs", + ) # Upload the file to bot's direct message response = self.client.files_upload( @@ -220,6 +222,14 @@ def resolve_help(channel_id, user_id, client): "text": "`/codecov help` - Get help\n*Note* that some of commands require you to login to a service first. \n\n", }, }, + {"type": "divider"}, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "✨ *Want to see more commands?* ✨\n\nClick on the bot's name and check out the *Home* tab for additional options and features!", + }, + }, ] client.chat_postEphemeral( @@ -603,9 +613,7 @@ def resolve(self, params_dict, optional_params): if not data: return f"No coverage report found for {path} in {repo}" - formatted_data = ( - f"*Coverage report for {path} in {repo}*:\n" - ) + formatted_data = f"*Coverage report for {path} in {repo}*:\n" for key in data: formatted_data += f"{key.capitalize()}: {data[key]}\n" diff --git a/core/slack_listeners.py b/core/slack_listeners.py index d49ac51..d9af380 100644 --- a/core/slack_listeners.py +++ b/core/slack_listeners.py @@ -6,7 +6,8 @@ from slack_bolt.oauth.oauth_settings import OAuthSettings from core.enums import EndpointName -from core.helpers import configure_notification +from core.helpers import (bot_is_member_of_channel, configure_notification, + send_not_member_response) from core.models import SlackBot, SlackInstallation from service_auth.models import SlackUser @@ -56,14 +57,21 @@ @app.command("/codecov") def handle_codecov_commands(ack, command, say, client): ack() - command_text = command["text"].split(" ")[0] + + command_text = command["text"].strip().split(" ")[0] + response_url = command["response_url"] + + is_member = bot_is_member_of_channel(client, command["channel_id"]) + + if not is_member: + send_not_member_response(response_url) message_payload = [ { "type": "section", "text": { "type": "mrkdwn", - "text": "Invalid command.\n*Need some help?*", + "text": "Invalid command or no input provided.\n*Need some help?*", }, }, { @@ -117,7 +125,7 @@ def handle_codecov_commands(ack, command, say, client): ComponentsResolver(client, command, say)() case "flags": FlagsResolver(client, command, say)() - case "coverage-trends": # use endpoint enum for cases + case "coverage-trends": CoverageTrendsResolver(client, command, say)() case "compare": ComparisonResolver( @@ -157,10 +165,7 @@ def handle_codecov_commands(ack, command, say, client): case "notify-off": NotificationResolver(command, client, say)() case "help": - channel_id = command["channel_id"] - user_id = command["user_id"] - - resolve_help(channel_id, user_id, client) + resolve_help(command["channel_id"], command["user_id"], client) case _: client.chat_postEphemeral( channel=command["channel_id"], @@ -169,12 +174,11 @@ def handle_codecov_commands(ack, command, say, client): ) except Exception as e: - logger.error(e) - + logger.error(f"Error processing command: {e}") client.chat_postEphemeral( channel=command["channel_id"], user=command["user_id"], - text=f"There was an error processing your request. Please try again later {e}.", + text="There was an error processing your request. Please try again later.", ) diff --git a/core/urls.py b/core/urls.py index 55d5c92..05ee560 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,4 +1,5 @@ from django.http import HttpRequest +from django.shortcuts import redirect from django.urls import path from django.views.decorators.csrf import csrf_exempt from slack_bolt.adapter.django import SlackRequestHandler @@ -15,6 +16,9 @@ def slack_events_handler(request: HttpRequest): def slack_oauth_handler(request: HttpRequest): + if "error" in request.GET: + return redirect("/slack/install") + return handler.handle(request)