Skip to content
This repository was archived by the owner on Sep 3, 2025. It is now read-only.

Commit 6a08caf

Browse files
nathanmyeeNathan Yee
andauthored
Add emojis directly and refactor email and Slack messages (#6193)
Co-authored-by: Nathan Yee <nyee@netflix.com>
1 parent 548cef9 commit 6a08caf

File tree

5 files changed

+67
-44
lines changed

5 files changed

+67
-44
lines changed

src/dispatch/conversation/flows.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,14 +296,14 @@ def get_topic_text(subject: Subject) -> str:
296296
"""Returns the topic details based on subject"""
297297
if isinstance(subject, Incident):
298298
return (
299-
f":helmet_with_white_cross: {subject.commander.individual.name}, {subject.commander.team} | "
299+
f"⛑️ {subject.commander.individual.name}, {subject.commander.team} | "
300300
f"Status: {subject.status} | "
301301
f"Type: {subject.incident_type.name} | "
302302
f"Severity: {subject.incident_severity.name} | "
303303
f"Priority: {subject.incident_priority.name}"
304304
)
305305
return (
306-
f":helmet_with_white_cross: {subject.assignee.individual.name}, {subject.assignee.team} | "
306+
f"⛑️ {subject.assignee.individual.name}, {subject.assignee.team} | "
307307
f"Status: {subject.status} | "
308308
f"Type: {subject.case_type.name} | "
309309
f"Severity: {subject.case_severity.name} | "

src/dispatch/messaging/strings.py

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ class MessageType(DispatchEnum):
433433

434434

435435
INCIDENT_NAME_WITH_ENGAGEMENT = {
436-
"title": ":rotating_light: {{name}} Incident Notification",
436+
"title": "🚨 {{name}} Incident Notification",
437437
"title_link": "{{ticket_weblink}}",
438438
"text": NOTIFICATION_PURPOSES_FYI,
439439
"buttons": [
@@ -469,7 +469,7 @@ class MessageType(DispatchEnum):
469469
}
470470

471471
INCIDENT_NAME_WITH_ENGAGEMENT_NO_SELF_JOIN = {
472-
"title": ":rotating_light: {{name}} Incident Notification",
472+
"title": "🚨 {{name}} Incident Notification",
473473
"title_link": "{{ticket_weblink}}",
474474
"text": NOTIFICATION_PURPOSES_FYI,
475475
"buttons": [
@@ -482,13 +482,13 @@ class MessageType(DispatchEnum):
482482
}
483483

484484
CASE_NAME = {
485-
"title": ":briefcase: {{name}} Case Notification",
485+
"title": "💼 {{name}} Case Notification",
486486
"title_link": "{{ticket_weblink}}",
487487
"text": NOTIFICATION_PURPOSES_FYI,
488488
}
489489

490490
CASE_NAME_WITH_ENGAGEMENT = {
491-
"title": ":briefcase: {{name}} Case Notification",
491+
"title": "💼 {{name}} Case Notification",
492492
"title_link": "{{ticket_weblink}}",
493493
"text": NOTIFICATION_PURPOSES_FYI,
494494
"buttons": [
@@ -514,32 +514,39 @@ class MessageType(DispatchEnum):
514514
}
515515

516516
CASE_NAME_WITH_ENGAGEMENT_NO_SELF_JOIN = {
517-
"title": ":briefcase: {{name}} Case Notification",
517+
"title": "💼 {{name}} Case Notification",
518518
"title_link": "{{ticket_weblink}}",
519519
"text": NOTIFICATION_PURPOSES_FYI,
520520
}
521521

522522

523523
CASE_STATUS_CHANGE = {
524-
"title": "*{% set status_emojis = {'Closed': ':white_check_mark:', 'New': ':new:', 'Triage': ':mag:', 'Stable': ':shield:', 'Escalated': ':arrow_up:'} %}{{ status_emojis.get(case_status_new, ':arrows_counterclockwise:') }} Status Change:* {{ case_status_old }} → {{ case_status_new }}",
524+
"title": "{% set status_emojis = {'Closed': '✅', 'New': '🆕', 'Triage': '🔍', 'Stable': '🛡️', 'Escalated': '⬆️'} %}{{ status_emojis.get(case_status_new, '🔄') }} Status Change",
525+
"text": "{{ case_status_old }} → {{ case_status_new }}",
525526
}
526527

527-
CASE_TYPE_CHANGE = {"title": "*:label: Case Type Change:* {{ case_type_old }} → {{ case_type_new }}"}
528+
CASE_TYPE_CHANGE = {
529+
"title": "🏷️ Case Type Change",
530+
"text": "{{ case_type_old }} → {{ case_type_new }}",
531+
}
528532

529533
CASE_SEVERITY_CHANGE = {
530-
"title": "*{% if case_severity_old.view_order < case_severity_new.view_order %}:arrow_up:{% elif case_severity_old.view_order > case_severity_new.view_order %}:arrow_down:{% else %}:left_right_arrow:{% endif %} Severity Change:* {{ case_severity_old.name }} → {{ case_severity_new.name }}",
534+
"title": "{% if case_severity_old.view_order < case_severity_new.view_order %}⬆️{% elif case_severity_old.view_order > case_severity_new.view_order %}⬇️{% else %}↔️{% endif %} Severity Change",
535+
"text": "{{ case_severity_old.name }} → {{ case_severity_new.name }}",
531536
}
532537

533538
CASE_PRIORITY_CHANGE = {
534-
"title": "*{% if case_priority_old.view_order < case_priority_new.view_order %}:arrow_up:{% elif case_priority_old.view_order > case_priority_new.view_order %}:arrow_down:{% else %}:left_right_arrow:{% endif %} Priority Change:* {{ case_priority_old.name }} → {{ case_priority_new.name }}",
539+
"title": "{% if case_priority_old.view_order < case_priority_new.view_order %}⬆️{% elif case_priority_old.view_order > case_priority_new.view_order %}⬇️{% else %}↔️{% endif %} Priority Change",
540+
"text": "{{ case_priority_old.name }} → {{ case_priority_new.name }}",
535541
}
536542

537543
CASE_VISIBILITY_CHANGE = {
538-
"title": "*{% set visibility_emojis = {'Open': ':unlock:', 'Restricted': ':lock:'} %}{{ visibility_emojis.get(case_visibility_new, ':eye:') }} Visibility Change:* {{ case_visibility_old }} → {{ case_visibility_new }}",
544+
"title": "{% set visibility_emojis = {'Open': '🔓', 'Restricted': '🔒'} %}{{ visibility_emojis.get(case_visibility_new, '👁️') }} Visibility Change",
545+
"text": "{{ case_visibility_old }} → {{ case_visibility_new }}",
539546
}
540547

541548
INCIDENT_NAME = {
542-
"title": ":rotating_light: {{name}} Incident Notification",
549+
"title": "🚨 {{name}} Incident Notification",
543550
"title_link": "{{ticket_weblink}}",
544551
"text": NOTIFICATION_PURPOSES_FYI,
545552
}
@@ -552,9 +559,9 @@ class MessageType(DispatchEnum):
552559

553560
INCIDENT_SUMMARY = {"title": "Summary", "text": "{{summary}}"}
554561

555-
INCIDENT_TITLE = {"title": "*:memo: Title:* {{title}}"}
562+
INCIDENT_TITLE = {"title": "📝 Title", "text": "{{title}}"}
556563

557-
CASE_TITLE = {"title": "*:memo: Title:* {{title}}"}
564+
CASE_TITLE = {"title": "📝 Title", "text": "{{title}}"}
558565

559566
CASE_STATUS = {
560567
"title": "Status - {{status}}",
@@ -615,7 +622,8 @@ class MessageType(DispatchEnum):
615622
}
616623

617624
INCIDENT_COMMANDER = {
618-
"title": ":firefighter: Commander: <{{commander_weblink}}|{{commander_fullname}}, {{commander_team}}>",
625+
"title": "🧑‍🚒 Commander - {{commander_fullname}}, {{commander_team}}",
626+
"title_link": "{{commander_weblink}}",
619627
"text": INCIDENT_COMMANDER_DESCRIPTION,
620628
}
621629

@@ -662,17 +670,23 @@ class MessageType(DispatchEnum):
662670
}
663671

664672
INCIDENT_STATUS_CHANGE = {
665-
"title": "*{% set status_emojis = {'Closed': ':white_check_mark:', 'Stable': ':shield:', 'Active': ':fire:'} %}{{ status_emojis.get(incident_status_new, ':arrows_counterclockwise:') }} Status Change:* {{ incident_status_old }} → {{ incident_status_new }}",
673+
"title": "{% set status_emojis = {'Closed': '✅', 'Stable': '🛡️', 'Active': '🔥'} %}{{ status_emojis.get(incident_status_new, '🔄') }} Status Change",
674+
"text": "{{ incident_status_old }} → {{ incident_status_new }}",
666675
}
667676

668-
INCIDENT_TYPE_CHANGE = {"title": "*:label: Incident Type Change:* {{ incident_type_old }} → {{ incident_type_new }}"}
677+
INCIDENT_TYPE_CHANGE = {
678+
"title": "🏷️ Incident Type Change",
679+
"text": "{{ incident_type_old }} → {{ incident_type_new }}",
680+
}
669681

670682
INCIDENT_SEVERITY_CHANGE = {
671-
"title": "*{% if incident_severity_old.view_order < incident_severity_new.view_order %}:arrow_up:{% elif incident_severity_old.view_order > incident_severity_new.view_order %}:arrow_down:{% else %}:left_right_arrow:{% endif %} Severity Change:* {{ incident_severity_old.name }} → {{ incident_severity_new.name }}",
683+
"title": "{% if incident_severity_old.view_order < incident_severity_new.view_order %}⬆️{% elif incident_severity_old.view_order > incident_severity_new.view_order %}⬇️{% else %}↔️{% endif %} Severity Change",
684+
"text": "{{ incident_severity_old.name }} → {{ incident_severity_new.name }}",
672685
}
673686

674687
INCIDENT_PRIORITY_CHANGE = {
675-
"title": "*{% if incident_priority_old.view_order < incident_priority_new.view_order %}:arrow_up:{% elif incident_priority_old.view_order > incident_priority_new.view_order %}:arrow_down:{% else %}:left_right_arrow:{% endif %} Priority Change:* {{ incident_priority_old.name }} → {{ incident_priority_new.name }}",
688+
"title": "{% if incident_priority_old.view_order < incident_priority_new.view_order %}⬆️{% elif incident_priority_old.view_order > incident_priority_new.view_order %}⬇️{% else %}↔️{% endif %} Priority Change",
689+
"text": "{{ incident_priority_old.name }} → {{ incident_priority_new.name }}",
676690
}
677691

678692
INCIDENT_PARTICIPANT_SUGGESTED_READING_ITEM = {
@@ -853,7 +867,8 @@ class MessageType(DispatchEnum):
853867
}
854868

855869
CASE_ASSIGNEE = {
856-
"title": ":female-detective: Assignee: <{{assignee_weblink}}|{{assignee_fullname}}, {{assignee_team}}>",
870+
"title": "🕵️‍♀️ Assignee - {{assignee_fullname}}, {{assignee_team}}",
871+
"title_link": "{{assignee_weblink}}",
857872
"text": CASE_ASSIGNEE_DESCRIPTION,
858873
}
859874

src/dispatch/plugins/dispatch_slack/messaging.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,17 +190,25 @@ def build_unexpected_error_message(guid: str) -> str:
190190
def format_default_text(item: dict):
191191
"""Creates the correct Slack text string based on the item context."""
192192
if item.get("title_link"):
193-
text_part = f"\n{item['text']}" if item.get('text') else ""
194-
return f"*<{item['title_link']}|{item['title']}>*{text_part}"
193+
return f"*<{item['title_link']}|{item['title']}>*\n{item['text']}"
195194
if item.get("datetime"):
196195
return f"*{item['title']}*\n <!date^{int(item['datetime'].timestamp())}^ {{date}} | {item['datetime']}"
197196
if item.get("title"):
198-
text_part = f"\n{item['text']}" if item.get('text') else ""
199-
# Check if title already has formatting (contains asterisks)
200-
if '*' in item['title']:
201-
return f"{item['title']}{text_part}"
197+
# Titles that should be combined on a single line with ": "
198+
single_line_titles = {
199+
"📝 Title",
200+
}
201+
202+
if item.get('text'):
203+
# Check if this title should be on a single line or text contains → (e.g. a state transition)
204+
if item['title'] in single_line_titles or '→' in item['text']:
205+
text_part = f": {item['text']}"
206+
else:
207+
text_part = f"\n{item['text']}"
202208
else:
203-
return f"*{item['title']}*{text_part}"
209+
text_part = ""
210+
211+
return f"*{item['title']}*{text_part}"
204212
return item.get("text", "")
205213

206214

src/dispatch/plugins/dispatch_slack/service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ def create_genai_message_metadata_blocks(
734734
message = json_to_slack_format(message)
735735

736736
# Truncate the text if it exceeds Block Kit's maximum length of 3000 characters
737-
text = f":magic_wand: *{title}*\n\n{message}"
737+
text = f"🪄 *{title}*\n\n{message}"
738738
text = f"{text[:2997]}..." if len(text) > 3000 else text
739739
blocks.append(
740740
Section(text=text),

tests/ai/test_ai_service.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def get_plugin_side_effect(db_session, plugin_type, project_id):
8686
subject=mock_subject,
8787
project=mock_project,
8888
channel_id="test-channel",
89-
important_reaction=":white_check_mark:",
89+
important_reaction="",
9090
participant_email="test@example.com",
9191
)
9292

@@ -152,7 +152,7 @@ def get_plugin_side_effect(db_session, plugin_type, project_id):
152152
subject=mock_subject,
153153
project=mock_project,
154154
channel_id="test-channel",
155-
important_reaction=":white_check_mark:",
155+
important_reaction="",
156156
participant_email="test@example.com",
157157
)
158158

@@ -194,7 +194,7 @@ def test_generate_read_in_summary_cache_hit(
194194
subject=mock_subject,
195195
project=mock_project,
196196
channel_id="test-channel",
197-
important_reaction=":white_check_mark:",
197+
important_reaction="",
198198
participant_email="test@example.com",
199199
)
200200

@@ -248,7 +248,7 @@ def get_plugin_side_effect(db_session, plugin_type, project_id):
248248
subject=mock_subject,
249249
project=mock_project,
250250
channel_id="test-channel",
251-
important_reaction=":white_check_mark:",
251+
important_reaction="",
252252
participant_email="test@example.com",
253253
)
254254

@@ -275,7 +275,7 @@ def test_generate_read_in_summary_no_ai_plugin(self, session, mock_subject, mock
275275
subject=mock_subject,
276276
project=mock_project,
277277
channel_id="test-channel",
278-
important_reaction=":white_check_mark:",
278+
important_reaction="",
279279
participant_email="test@example.com",
280280
)
281281

@@ -313,7 +313,7 @@ def test_generate_read_in_summary_no_conversation_plugin(
313313
subject=mock_subject,
314314
project=mock_project,
315315
channel_id="test-channel",
316-
important_reaction=":white_check_mark:",
316+
important_reaction="",
317317
participant_email="test@example.com",
318318
)
319319

@@ -361,7 +361,7 @@ def get_plugin_side_effect(db_session, plugin_type, project_id):
361361
subject=mock_subject,
362362
project=mock_project,
363363
channel_id="test-channel",
364-
important_reaction=":white_check_mark:",
364+
important_reaction="",
365365
participant_email="test@example.com",
366366
)
367367

@@ -412,7 +412,7 @@ def get_plugin_side_effect(db_session, plugin_type, project_id):
412412
subject=mock_subject,
413413
project=mock_project,
414414
channel_id="test-channel",
415-
important_reaction=":white_check_mark:",
415+
important_reaction="",
416416
participant_email="test@example.com",
417417
)
418418

@@ -442,7 +442,7 @@ def test_generate_read_in_summary_event_query_incident(
442442
subject=mock_subject,
443443
project=mock_project,
444444
channel_id="test-channel",
445-
important_reaction=":white_check_mark:",
445+
important_reaction="",
446446
participant_email="test@example.com",
447447
)
448448

@@ -465,7 +465,7 @@ def test_generate_read_in_summary_event_query_case(self, session, mock_subject,
465465
subject=mock_subject,
466466
project=mock_project,
467467
channel_id="test-channel",
468-
important_reaction=":white_check_mark:",
468+
important_reaction="",
469469
participant_email="test@example.com",
470470
)
471471

@@ -541,7 +541,7 @@ def get_plugin_side_effect(db_session, plugin_type, project_id):
541541
db_session=session,
542542
incident=mock_incident,
543543
project=mock_project,
544-
important_reaction=":fire:",
544+
important_reaction="🔥",
545545
)
546546

547547
# Assertions
@@ -579,7 +579,7 @@ def test_generate_tactical_report_no_ai_plugin(self, session, mock_incident, moc
579579
db_session=session,
580580
incident=mock_incident,
581581
project=mock_project,
582-
important_reaction=":fire:",
582+
important_reaction="🔥",
583583
)
584584
print(type(result))
585585
assert isinstance(result, TacticalReportResponse)
@@ -606,7 +606,7 @@ def test_generate_tactical_report_no_conversation_plugin(
606606
db_session=session,
607607
incident=mock_incident,
608608
project=mock_project,
609-
important_reaction=":fire:",
609+
important_reaction="🔥",
610610
)
611611

612612
assert isinstance(result, TacticalReportResponse)
@@ -642,7 +642,7 @@ def get_plugin_side_effect(db_session, plugin_type, project_id):
642642
db_session=session,
643643
incident=mock_incident,
644644
project=mock_project,
645-
important_reaction=":fire:",
645+
important_reaction="🔥",
646646
)
647647

648648
assert isinstance(result, TacticalReportResponse)
@@ -681,7 +681,7 @@ def get_plugin_side_effect(db_session, plugin_type, project_id):
681681
db_session=session,
682682
incident=mock_incident,
683683
project=mock_project,
684-
important_reaction=":fire:",
684+
important_reaction="🔥",
685685
)
686686

687687
assert isinstance(result, TacticalReportResponse)

0 commit comments

Comments
 (0)