Skip to content

Commit

Permalink
Update NestBot: add team_join event handler
Browse files Browse the repository at this point in the history
  • Loading branch information
arkid15r committed Jan 3, 2025
1 parent befc4d8 commit 282691b
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 2 deletions.
12 changes: 11 additions & 1 deletion backend/apps/slack/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,25 @@

NEST_BOT_NAME = "NestBot"

OWASP_APPSEC_CHANNEL_ID = "C0F7D6DFH"
OWASP_ASKOWASP_CHANNEL_ID = "C04TQ3TAB"
OWASP_CHAPTER_LONDON_CHANNEL_ID = "C1WAV9UKY"
OWASP_COMMUNITY_CHANNEL_ID = "C04T40NND"
OWASP_CONTRIBUTE_CHANNEL_ID = "C04DH8HEPTR"
OWASP_DEVELOPERS_CHANNEL_ID = "C04V77UNH"
OWASP_DEVSECOPS_CHANNEL_ID = "C1KF6H39T"
OWASP_GSOC_CHANNEL_ID = "CFJLZNFN1"
OWASP_JOBS_CHANNEL_ID = "C0Y12A3FC"
OWASP_LEADERS_CHANNEL_ID = "C66R5JF6V"
OWASP_MENTORS_CHANNEL_ID = "C1H191DEE"
OWASP_PROJECT_JUICE_SHOP_CHANNEL_ID = "C255XSY04"
OWASP_PROJECT_NEST_CHANNEL_ID = "C07JLLG2GFQ"
OWASP_PROJECT_NETTACKER_CHANNEL_ID = "CQZGG24FQ"
OWASP_PROJECT_THREAT_DRAGON_CHANNEL_ID = "CURE8PQ68"
OWASP_THREAT_MODELING_CHANNEL_ID = "C1CS3C6AF"

NL = "\n"
NLNL = "\n\n"
NLNL = 2 * NL

FEEDBACK_CHANNEL_MESSAGE = (
f"💬 You can share feedback on your {NEST_BOT_NAME} experience "
Expand Down
2 changes: 1 addition & 1 deletion backend/apps/slack/events/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from apps.slack.events import url_verification
from apps.slack.events import team_join, url_verification
from apps.slack.events.user_joined_channel import contribute, gsoc
90 changes: 90 additions & 0 deletions backend/apps/slack/events/team_join.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""Slack bot user joined team handler."""

from django.conf import settings

from apps.slack.apps import SlackConfig
from apps.slack.blocks import markdown
from apps.slack.constants import (
FEEDBACK_CHANNEL_MESSAGE,
NL,
OWASP_APPSEC_CHANNEL_ID,
OWASP_ASKOWASP_CHANNEL_ID,
OWASP_CHAPTER_LONDON_CHANNEL_ID,
OWASP_COMMUNITY_CHANNEL_ID,
OWASP_CONTRIBUTE_CHANNEL_ID,
OWASP_DEVELOPERS_CHANNEL_ID,
OWASP_DEVSECOPS_CHANNEL_ID,
OWASP_GSOC_CHANNEL_ID,
OWASP_JOBS_CHANNEL_ID,
OWASP_LEADERS_CHANNEL_ID,
OWASP_MENTORS_CHANNEL_ID,
OWASP_PROJECT_JUICE_SHOP_CHANNEL_ID,
OWASP_PROJECT_NEST_CHANNEL_ID,
OWASP_THREAT_MODELING_CHANNEL_ID,
)


def handler(event, client, ack):
"""Slack new team user handler."""
ack()
if not settings.SLACK_EVENTS_ENABLED:
return

user_id = event["user"]
conversation = client.conversations_open(users=user_id)

client.chat_postMessage(
channel=conversation["channel"]["id"],
blocks=[
markdown(
f"*Welcome to the OWASP Slack Community, <@{user_id}>!*{NL}"
"We're excited to have you join us! Whether you're a newcomer to OWASP or "
"a seasoned contributor, this is the space to connect, collaborate, "
f"and learn together!{2*NL}"
),
markdown(
f"*Get Started*:{NL}"
"To explore the full spectrum of OWASP's projects, chapters, and resources, "
f"check out <{settings.SITE_URL}|*OWASP Nest*>. It's your gateway to discovering "
"ways to contribute, stay informed, and connect with the OWASP community. "
"From finding projects aligned with your interests to engaging with chapters in "
f"your area, OWASP Nest makes it easier to navigate and get involved."
),
markdown(
f"*Connect and Grow:*{NL}"
f" • Visit OWASP channels <#{OWASP_COMMUNITY_CHANNEL_ID}> and "
f"<#{OWASP_ASKOWASP_CHANNEL_ID}> to engage with the broader community.{2*NL}"
f" • Find your local chapter channel (normally chapter specific channels have "
f"`#chapter-<name>` format, e.g. <#{OWASP_CHAPTER_LONDON_CHANNEL_ID}>){2*NL}"
f" • Dive into project-specific channels, like `#project-<name>` (e.g. "
f"<#{OWASP_PROJECT_JUICE_SHOP_CHANNEL_ID}>, <#{OWASP_PROJECT_NEST_CHANNEL_ID}>) "
f"to engage directly with the project specific communities.{2*NL}"
f" • Explore topic channels like <#{OWASP_APPSEC_CHANNEL_ID}>, "
f"<#{OWASP_DEVSECOPS_CHANNEL_ID}>, <#{OWASP_THREAT_MODELING_CHANNEL_ID}> to "
f"engage with like-minded individuals.{2*NL}"
f" • Join <#{OWASP_JOBS_CHANNEL_ID}> to discover job opportunities in the cyber "
f"security field."
),
markdown(
f"*Learn and Engage:*{NL}"
f" • Explore <#{OWASP_CONTRIBUTE_CHANNEL_ID}> for opportunities to get involved "
f"in OWASP projects and initiatives.{2*NL}"
f" • Join leadership channels: <#{OWASP_LEADERS_CHANNEL_ID}> and "
f"<#{OWASP_MENTORS_CHANNEL_ID}> to connect with OWASP leaders and mentors.{2*NL}"
f" • Learn about OWASP's participation in Google Summer of Code in "
f"<#{OWASP_GSOC_CHANNEL_ID}>.{2*NL}"
f" • Connect with developers in <#{OWASP_DEVELOPERS_CHANNEL_ID}> to discuss "
f"development practices and tools."
),
markdown(
"We're here to support your journey in making software security visible and "
"strengthening the security of the software we all depend on. Have questions or "
"need help? Don't hesitate to ask—this community thrives on collaboration!"
),
markdown(f"{FEEDBACK_CHANNEL_MESSAGE}"),
],
)


if SlackConfig.app:
SlackConfig.app.event("team_join")(handler)
44 changes: 44 additions & 0 deletions backend/tests/slack/events/team_join_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from unittest.mock import Mock

import pytest

from apps.slack.events.team_join import handler


class TestSlackHandler:
@pytest.fixture()
def mock_slack_config(self, mocker):
mock_app = Mock()
mocker.patch("apps.slack.apps.SlackConfig.app", mock_app)
return mock_app

def test_handler_user_joined(self, mocker):
mock_ack = Mock()
mock_client = Mock()
mock_conversation = {"channel": {"id": "C67890"}}
mock_client.conversations_open.return_value = mock_conversation

handler({"user": "U12345"}, mock_client, mock_ack)

mock_ack.assert_called_once()
mock_client.conversations_open.assert_called_once_with(users="U12345")
mock_client.chat_postMessage.assert_called_once()

call_args = mock_client.chat_postMessage.call_args[1]

assert call_args["channel"] == "C67890"
assert "blocks" in call_args

blocks = call_args["blocks"]

block_texts = [
block["text"]["text"]
for block in blocks
if block["type"] == "section" and "text" in block
]

assert any("*Welcome to the OWASP Slack Community" in text for text in block_texts)
assert any("OWASP Nest" in text for text in block_texts)
assert any("#chapter-<name>" in text for text in block_texts)
assert any("<#C255XSY04>" in text for text in block_texts)
assert any("We're here to support your journey" in text for text in block_texts)

0 comments on commit 282691b

Please sign in to comment.