Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 12 additions & 19 deletions backend/apps/slack/commands/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,20 @@ class Events(CommandBase):

def get_template_context(self, command):
"""Get the template context."""
events_data = get_events_data() or []
valid_events = [event for event in events_data if event.start_date]
sorted_events = sorted(valid_events, key=lambda x: x.start_date)

categorized_events = {}
for event in sorted_events:
category = event.category or "Other"
if category not in categorized_events:
categorized_events[category] = {"events": []}
categorized_events[category]["events"].append(
{
"name": event.name,
"url": event.url,
"start_date": event.start_date,
"end_date": event.end_date,
"description": event.description,
}
)
upcoming_events = [
{
"description": event.description,
"end_date": event.end_date,
"location": event.suggested_location,
"name": event.name,
"start_date": event.start_date,
"url": event.url,
}
for event in sorted(get_events_data(), key=lambda e: e.start_date)
]

return {
**super().get_template_context(command),
"categorized_events": categorized_events,
"upcoming_events": upcoming_events,
"website_url": OWASP_WEBSITE_URL,
}
18 changes: 12 additions & 6 deletions backend/apps/slack/templates/events.jinja
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
*Upcoming OWASP Events:*{{ SECTION_BREAK }}{{ DIVIDER }}{{ SECTION_BREAK }}
{%- for category, category_data in categorized_events.items() %}
*Category: {{ category.replace('_', ' ').title() }}*{{ NL }}{{ SECTION_BREAK }}
{%- for event in category_data.events %}
*{{ loop.index }}. {% if event.url %}<{{ event.url }}|{{ event.name }}>{% else %}{{ event.name }}{% endif %}*
Start Date: {{ event.start_date }}{% if event.end_date %}{{ NL }}End Date: {{ event.end_date }}{% endif %}{% if event.description %}{{ NL }}_{{ event.description }}_{% endif %}{{ NL }}{{ NL }}{%- if not loop.last %}{{ SECTION_BREAK }}{% endif %}
{%- for event in upcoming_events %}
*{% if loop.index %}{{ loop.index }}. {% endif %}{% if event.url %}<{{ event.url }}|{{ event.name }}>{% else %}{{ event.name }}{% endif %}*
_{%- if event.start_date and event.end_date -%}
{%- if event.start_date == event.end_date -%}
{{ event.start_date.strftime('%b %-d, %Y') }}
{%- else -%}
{{ event.start_date.strftime('%b') }} {{ event.start_date.strftime('%-d') }} — {{ event.end_date.strftime('%-d') }}, {{ event.end_date.strftime('%Y') }}
{%- endif -%}
{%- else -%}
{{ event.start_date.strftime('%b %-d, %Y') }}
{%- endif %} | {{ event.location }}_
{%- if event.description %}{{ NL }}{{ event.description }}{% endif %}{{ NL }}{%- if not loop.last %}{{ SECTION_BREAK }}{% endif %}
{%- endfor %}
{{ SECTION_BREAK }}{{ DIVIDER }}{{ SECTION_BREAK }}
{%- endfor %}
🔍 For more information about upcoming events, please visit <{{ website_url }}/events/|OWASP Events>{{ NL }}
12 changes: 6 additions & 6 deletions backend/apps/slack/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def get_staff_data(timeout=30):
logger.exception("Unable to parse OWASP staff data file", extra={"file_path": file_path})


def get_events_data():
def get_events_data(limit=9):
"""Get events data.

Returns
Expand All @@ -126,11 +126,11 @@ def get_events_data():
"""
from apps.owasp.models.event import Event

try:
return Event.objects.filter(start_date__gte=timezone.now()).order_by("start_date")
except Exception as e:
logger.exception("Failed to fetch events data via database", extra={"error": str(e)})
return None
return Event.objects.filter(
start_date__gte=timezone.now(),
).order_by(
"start_date",
)[:limit]


def get_sponsors_data(limit=10):
Expand Down
119 changes: 74 additions & 45 deletions backend/tests/apps/slack/commands/events_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import datetime, timezone
from unittest.mock import MagicMock, patch

import pytest
Expand All @@ -7,33 +8,44 @@


class MockEvent:
def __init__(self, name, category, start_date, end_date, url, description):
def __init__(self, name, start_date, end_date, suggested_location, url, description):
self.name = name
self.category = category
self.start_date = start_date
self.end_date = end_date
self.start_date = (
datetime.strptime(start_date, "%Y-%m-%d").replace(tzinfo=timezone.utc).date()
if start_date
else None
)
self.end_date = (
datetime.strptime(end_date, "%Y-%m-%d").replace(tzinfo=timezone.utc).date()
if end_date
else None
)
self.suggested_location = suggested_location
self.url = url
self.description = description


mock_events = [
MockEvent(
name="OWASP Snow 2025",
category="AppSec Days",
start_date="2025-03-14",
end_date="March 14, 2025",
url="https://example.com/snow",
description="Regional conference",
),
MockEvent(
name="OWASP Global AppSec EU 2025",
category="Global",
start_date="2025-05-26",
end_date="May 26-30, 2025",
url="https://example.com/eu",
description="Premier conference",
),
]
mock_events = sorted(
[
MockEvent(
name="OWASP Snow 2025",
start_date="2025-03-14",
end_date="2025-03-14",
suggested_location="Denver, CO",
url="https://example.com/snow",
description="Regional conference",
),
MockEvent(
name="OWASP Global AppSec EU 2025",
start_date="2025-05-26",
end_date="2025-05-30",
suggested_location="Amsterdam, Netherlands",
url="https://example.com/eu",
description="Premier conference",
),
],
key=lambda x: x.start_date,
)


class TestEventsHandler:
Expand Down Expand Up @@ -82,27 +94,44 @@ def test_handler_responses(
mock_slack_client.conversations_open.assert_called_once_with(
users=mock_slack_command["user_id"]
)
blocks = mock_slack_client.chat_postMessage.call_args[1]["blocks"]
assert blocks[0]["text"]["text"] == expected_header
assert blocks[1]["type"] == "divider"
mock_slack_client.chat_postMessage.assert_called_once()

sent_blocks = mock_slack_client.chat_postMessage.call_args[1]["blocks"]
assert sent_blocks[0]["type"] == "section"
assert sent_blocks[0]["text"]["text"] == expected_header
assert sent_blocks[1]["type"] == "divider"

if has_events_data:
current_block = 2
assert "*Category: Appsec Days*" in blocks[current_block]["text"]["text"]
current_block += 1
event_block = blocks[current_block]["text"]["text"]
assert "*1. <https://example.com/snow|OWASP Snow 2025>*" in event_block
assert "Start Date: 2025-03-14" in event_block
assert "End Date: March 14, 2025" in event_block
assert "_Regional conference_" in event_block
current_block += 1
assert blocks[current_block]["type"] == "divider"
current_block += 1
assert "*Category: Global*" in blocks[current_block]["text"]["text"]
current_block += 1
event_block = blocks[current_block]["text"]["text"]
assert "*1. <https://example.com/eu|OWASP Global AppSec EU 2025>*" in event_block
assert "Start Date: 2025-05-26" in event_block
assert "End Date: May 26-30, 2025" in event_block
assert "_Premier conference_" in event_block
footer_block = blocks[-1]["text"]["text"]
assert "🔍 For more information about upcoming events" in footer_block
event1 = mock_events[0]
event1_text_found = False
for block in sent_blocks:
if block.get("type") == "section" and "text" in block and "text" in block["text"]:
block_text = block["text"]["text"]
if (
f"*1. <{event1.url}|{event1.name}>*" in block_text
and "Mar 14, 2025" in block_text
and "Denver, CO" in block_text
and event1.description in block_text
):
event1_text_found = True
break
assert event1_text_found, "Block containing Event 1 details not found or incorrect"

event2 = mock_events[1]
event2_text_found = False
for block in sent_blocks:
if block.get("type") == "section" and "text" in block and "text" in block["text"]:
block_text = block["text"]["text"]
if (
f"*2. <{event2.url}|{event2.name}>*" in block_text
and "May 26 — 30, 2025" in block_text
and "Amsterdam, Netherlands" in block_text
and event2.description in block_text
):
event2_text_found = True
break
assert event2_text_found, "Block containing Event 2 details not found or incorrect"

footer_block = sent_blocks[-1]
assert footer_block["type"] == "section"
assert "🔍 For more information about upcoming events" in footer_block["text"]["text"]
2 changes: 1 addition & 1 deletion frontend/src/server/queries/homeQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const GET_MAIN_PAGE_DATA = gql`
contributorsStats
countriesStats
}
upcomingEvents(limit: 6) {
upcomingEvents(limit: 9) {
category
endDate
key
Expand Down