Skip to content

Commit 4b97ca0

Browse files
committed
chore: Sync with master
2 parents 373dbc2 + 0c43766 commit 4b97ca0

File tree

20 files changed

+244
-77
lines changed

20 files changed

+244
-77
lines changed

bot/slack/base.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from slack.web.client import WebClient
2+
13
from bot.storage import SubscriptionStorage
24

35

@@ -6,5 +8,6 @@ class SlackBotBase:
68
Class containing common attributes for `Messenger` and `Runner`
79
"""
810

9-
def __init__(self):
11+
def __init__(self, token: str):
1012
self.storage = SubscriptionStorage()
13+
self.client: WebClient = WebClient(token)

bot/slack/bot.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
* `.run` to execute slash commands.
77
"""
88

9-
from typing import Optional
10-
119
from ..utils.log import Logger
1210
from .messenger import Messenger
1311
from .runner import Runner
@@ -27,6 +25,7 @@ def __init__(
2725
logger: Logger,
2826
base_url: str,
2927
secret: str,
28+
bot_id: str,
3029
):
3130
Messenger.__init__(self, token)
32-
Runner.__init__(self, logger, base_url, secret)
31+
Runner.__init__(self, logger, base_url, secret, token, bot_id)

bot/slack/messenger.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ class Messenger(SlackBotBase):
1414
Sends Slack messages according to received GitHub events.
1515
"""
1616

17-
def __init__(self, token: str):
18-
SlackBotBase.__init__(self)
19-
self.client: WebClient = WebClient(token)
17+
def __init__(self, token):
18+
SlackBotBase.__init__(self, token)
2019

2120
def inform(self, event: GitHubEvent):
2221
"""

bot/slack/runner.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
from json import dumps as json_dumps
99
from typing import Any
1010

11+
from sentry_sdk import capture_message
12+
from slack.errors import SlackApiError
1113
from werkzeug.datastructures import Headers, ImmutableMultiDict
1214

1315
from ..models.github import EventType, convert_keywords_to_events
1416
from ..utils.json import JSON
1517
from ..utils.list_manip import intersperse
1618
from ..utils.log import Logger
1719
from .base import SlackBotBase
20+
from .templates import error_message
1821

1922

2023
class Runner(SlackBotBase):
@@ -29,11 +32,14 @@ def __init__(
2932
logger: Logger,
3033
base_url: str,
3134
secret: str,
35+
token: str,
36+
bot_id: str,
3237
):
33-
SlackBotBase.__init__(self)
38+
super(self.__class__, self).__init__(token)
3439
self.logger = logger
3540
self.base_url = base_url
3641
self.secret = secret.encode("utf-8")
42+
self.bot_id = bot_id
3743

3844
def verify(
3945
self,
@@ -126,6 +132,13 @@ def run_subscribe_command(
126132
:param args: `list` of events to subscribe to.
127133
"""
128134

135+
in_channel = self.check_bot_in_channel(current_channel=current_channel)
136+
if not in_channel:
137+
return error_message(
138+
"Unable to subscribe. To receive notifications, "
139+
"you need to invite @GitHub to this conversation "
140+
"using `/invite @Selene`")
141+
129142
repository = args[0]
130143
if repository.find('/') == -1:
131144
return self.send_wrong_syntax_message()
@@ -301,6 +314,24 @@ def run_list_command(
301314
"blocks": blocks,
302315
}
303316

317+
def check_bot_in_channel(
318+
self,
319+
current_channel: str,
320+
) -> bool:
321+
subscriptions = self.storage.get_subscriptions(channel=current_channel)
322+
323+
if len(subscriptions) != 0:
324+
return True
325+
try:
326+
response = self.client.conversations_members(
327+
channel=current_channel)
328+
return self.bot_id in response["members"]
329+
330+
except SlackApiError as E:
331+
capture_message(
332+
f"SlackApiError {E} Failed to fetch conversation member for {current_channel}"
333+
)
334+
304335
@staticmethod
305336
def run_help_command(args: list[str]) -> dict[str, Any]:
306337
"""

bot/slack/templates.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from typing import Any
2+
3+
4+
def error_message(text: str) -> dict[str, Any]:
5+
attachments = [
6+
{
7+
"color":
8+
"#bb2124",
9+
"blocks": [
10+
{
11+
"type": "section",
12+
"text": {
13+
"type": "mrkdwn",
14+
"text": text,
15+
},
16+
},
17+
],
18+
},
19+
]
20+
21+
return {
22+
"response_type": "ephemeral",
23+
"attachments": attachments,
24+
}

bot/storage/subscriptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def get_subscriptions(
6464
self,
6565
channel: Optional[str] = None,
6666
repository: Optional[str] = None,
67-
) -> tuple["Subscription"]:
67+
) -> tuple["Subscription", ...]:
6868
"""
6969
Queries the subscriptions database. Filters are applied depending on arguments passed.
7070

bot/utils/log.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ def log_command(self, log_text: str):
1212
Logs the latest command to `./data/logs`.
1313
:param log_text: Information about the latest command to be saved.
1414
"""
15+
16+
if self.N == 0:
17+
# Early exit
18+
return
19+
1520
# Read
1621
with open('data/logs', 'a+') as file:
1722
file.seek(0)

main.py

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from bot.github import GitHubApp
2626
from bot.models.github.event import GitHubEvent
2727
from bot.slack import SlackBot
28+
from bot.slack.templates import error_message
2829
from bot.utils.log import Logger
2930

3031
app = Flask(__name__)
@@ -39,9 +40,9 @@ def manage_github_events():
3940
Then uses an instance of `SlackBot` to send appropriate messages to appropriate channels.
4041
"""
4142

42-
is_valid_request, error_message = github_app.verify(request)
43+
is_valid_request, message = github_app.verify(request)
4344
if not is_valid_request:
44-
return make_response(error_message, 400)
45+
return make_response(message, 400)
4546

4647
event: Optional[GitHubEvent] = github_app.parse(
4748
event_type=request.headers["X-GitHub-Event"],
@@ -68,21 +69,7 @@ def manage_slack_commands() -> Union[dict, str, None]:
6869
headers=request.headers,
6970
)
7071
if not is_valid_request:
71-
attachments = [{
72-
"color":
73-
"#bb2124",
74-
"blocks": [{
75-
"type": "section",
76-
"text": {
77-
"type": "mrkdwn",
78-
"text": f"⚠️ Couldn't fulfill your request: {message}"
79-
}
80-
}]
81-
}]
82-
return {
83-
"response_type": "ephemeral",
84-
"attachments": attachments,
85-
}
72+
return error_message(f"⚠️ Couldn't fulfill your request: {message}")
8673

8774
# Unlike GitHub webhooks, Slack does not send the data in `requests.json`.
8875
# Instead, the data is passed in `request.form`.
@@ -119,6 +106,7 @@ def complete_auth():
119106
logger=Logger(int(os.environ.get("LOG_LAST_N_COMMANDS", 100))),
120107
base_url=os.environ["BASE_URL"],
121108
secret=os.environ["SLACK_SIGNING_SECRET"],
109+
bot_id=os.environ["SLACK_BOT_ID"],
122110
)
123111

124112
github_app = GitHubApp(

samples/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ GITHUB_WEBHOOK_SECRET=3dbd2c253813c65b296b7acf67470b7e7bc116e3
88
HOST_PORT=9999
99
LOG_LAST_N_COMMANDS=100
1010
SENTRY_DSN=https://exampledsn.ingest.sentry.io/123
11+
SLACK_BOT_ID=B0101010101
1112
SLACK_OAUTH_TOKEN=xoxb-3943959636919-3982289583824-iKtJsairxpmjH2yrVMg99nFG

samples/.env.dev

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ GITHUB_APP_CLIENT_SECRET=e2fbe2fbe2fbe2fbe2fbe2e2fbe2fbe2e2fbe2fb
88
GITHUB_WEBHOOK_SECRET=3dbd2c253813c65b296b7acf67470b7e7bc116e3
99
HOST_PORT=9999
1010
LOG_LAST_N_COMMANDS=100
11-
MANIFEST_ACCESS_TOKEN=xoxe.xoxp-1-Mi0yLTM5NDM5NTk2MzY5MTktMzk3MTE1NDE0MTcyOS00NDU5MTIxNTI0NTgyLTQ0ODk0MjE4NTMzOTItOGVhYmFmOTQ4ZDkyNGQzNTZhMjFiYThkMjU0ZDA4MzFhNTY4NTFkNzdlNGIzMDM1ZTM3NGYyZjUwYjIwYmUxMA
12-
MANIFEST_REFRESH_TOKEN=xoxe-1-My0xLTM5NDM5NTk2MzY5MTktNDQ1OTEyMTUyNDU4Mi00NDY4MTc4OTUxNzk2LTk4ZWU5Zjg0ZGQ5YTg3OTYzMDU2YjJiODNiMjU3ZTAzOTZkNmMxOGI3MTEyM2UyMmZhZDcyNWJhN2NjOWU1MDM
11+
MANIFEST_REFRESH_TOKEN=xoxe-1-randomTOKENstringPRODUCEDbySLACK
1312
SENTRY_DSN=https://[email protected]/6227373
13+
SLACK_BOT_ID=B0101010101
1414
SLACK_OAUTH_TOKEN=xoxb-3943959636919-3982289583824-iKtJsairxpmjH2yrVMg99nFG

0 commit comments

Comments
 (0)