Skip to content

Commit

Permalink
Refactors converstion creation flow.
Browse files Browse the repository at this point in the history
  • Loading branch information
metroid-samus committed Sep 28, 2023
1 parent e7f1c62 commit 423876a
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 140 deletions.
206 changes: 79 additions & 127 deletions src/dispatch/case/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

from dispatch.case import service as case_service
from dispatch.case.models import CaseRead
from dispatch.conversation import service as conversation_service
from dispatch.conversation.models import ConversationCreate
from dispatch.conversation import flows as conversation_flows
from dispatch.database.core import SessionLocal
from dispatch.decorators import background_task
from dispatch.document import flows as document_flows
Expand Down Expand Up @@ -154,94 +153,6 @@ def case_add_or_reactivate_participant_flow(
return participant


def create_conversation(case: Case, conversation_target: str, db_session: SessionLocal):
"""Create external communication conversation."""
plugin = plugin_service.get_active_instance(
db_session=db_session, project_id=case.project.id, plugin_type="conversation"
)
conversation = plugin.instance.create_threaded(
case=case, conversation_id=conversation_target, db_session=db_session
)
conversation.update({"resource_type": plugin.plugin.slug, "resource_id": conversation["id"]})

event_service.log_case_event(
db_session=db_session,
source=plugin.plugin.title,
description="Case conversation created",
case_id=case.id,
)

return conversation


def create_conversation_flow(
conversation_target: str,
case: Case,
individual_participants: list,
db_session: SessionLocal,
):
conversation_plugin = plugin_service.get_active_instance(
db_session=db_session, project_id=case.project.id, plugin_type="conversation"
)
if conversation_plugin:
if not conversation_target:
conversation_target = case.case_type.conversation_target
if conversation_target:
try:
# TODO: Refactor conversation creation using conversation_flows module
conversation = create_conversation(case, conversation_target, db_session)
conversation_in = ConversationCreate(
resource_id=conversation["resource_id"],
resource_type=conversation["resource_type"],
weblink=conversation["weblink"],
thread_id=conversation["timestamp"],
channel_id=conversation["id"],
)
case.conversation = conversation_service.create(
db_session=db_session, conversation_in=conversation_in
)

event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description="Conversation added to case",
case_id=case.id,
)
# wait until all resources are created before adding suggested participants
individual_participants = [x.email for x, _ in individual_participants]

for email in individual_participants:
# we don't rely on on this flow to add folks to the conversation because in this case
# we want to do it in bulk
case_add_or_reactivate_participant_flow(
db_session=db_session,
user_email=email,
case_id=case.id,
add_to_conversation=False,
)
# explicitly add the assignee to the conversation
all_participants = individual_participants + [case.assignee.individual.email]
conversation_plugin.instance.add_to_thread(
case.conversation.channel_id,
case.conversation.thread_id,
all_participants,
)
event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description="Case participants added to conversation.",
case_id=case.id,
)
except Exception as e:
event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description=f"Creation of case conversation failed. Reason: {e}",
case_id=case.id,
)
log.exception(e)


def update_conversation(case: Case, db_session: SessionLocal):
"""Updates external communication conversation."""
plugin = plugin_service.get_active_instance(
Expand Down Expand Up @@ -285,6 +196,7 @@ def case_new_create_flow(
case_id=case.id,
individual_participants=individual_participants,
team_participants=team_participants,
conversation_target=conversation_target
)

if case.case_priority.page_assignee:
Expand All @@ -309,9 +221,6 @@ def case_new_create_flow(
else:
log.warning("Case assignee not paged. No plugin of type oncall enabled.")

# we create the conversation and add participants to the thread
create_conversation_flow(conversation_target, case, individual_participants, db_session)

db_session.add(case)
db_session.commit()

Expand Down Expand Up @@ -699,56 +608,99 @@ def case_create_resources_flow(
individual_participants: List[str],
team_participants: List[str],
conversation_target: str = None,
create_resources: bool = True,
) -> None:
"""Runs the case resource creation flow."""
case = get(db_session=db_session, case_id=case_id)

if case.assignee:
individual_participants.append((case.assignee.individual, None))

# we create the tactical group
direct_participant_emails = [i.email for i, _ in individual_participants]
if create_resources:
# we create the tactical group
direct_participant_emails = [i.email for i, _ in individual_participants]

indirect_participant_emails = [t.email for t in team_participants]
indirect_participant_emails = [t.email for t in team_participants]

if not case.groups:
group_flows.create_group(
subject=case,
group_type=GroupType.tactical,
group_participants=list(set(direct_participant_emails + indirect_participant_emails)),
db_session=db_session,
)
if not case.groups:
group_flows.create_group(
subject=case,
group_type=GroupType.tactical,
group_participants=list(set(direct_participant_emails + indirect_participant_emails)),
db_session=db_session,
)

# we create the storage folder
storage_members = []
if case.tactical_group:
storage_members = [case.tactical_group.email]
# we create the storage folder
storage_members = []
if case.tactical_group:
storage_members = [case.tactical_group.email]
# direct add members if not group exists
else:
storage_members = direct_participant_emails

# direct add members if not group exists
else:
storage_members = direct_participant_emails
if not case.storage:
storage_flows.create_storage(
subject=case, storage_members=storage_members, db_session=db_session
)

# we create the investigation document
if not case.case_document:
document_flows.create_document(
subject=case,
document_type=DocumentResourceTypes.case,
document_template=case.case_type.case_template_document,
db_session=db_session,
)

# we update the ticket
ticket_flows.update_case_ticket(case=case, db_session=db_session)

if not case.storage:
storage_flows.create_storage(
subject=case, storage_members=storage_members, db_session=db_session
# we update the case document
document_flows.update_document(
document=case.case_document, project_id=case.project.id, db_session=db_session
)

# we create the investigation document
if not case.case_document:
document_flows.create_document(
subject=case,
document_type=DocumentResourceTypes.case,
document_template=case.case_type.case_template_document,
try:
# we create the conversation and add participants to the thread
conversation_flows.create_case_conversation(case, conversation_target, db_session)

event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description="Conversation added to case",
case_id=case.id,
)
# wait until all resources are created before adding suggested participants
individual_participants = [x.email for x, _ in individual_participants]

# we create the conversation and add participants to the thread
create_conversation_flow(conversation_target, case, individual_participants, db_session)
for email in individual_participants:
# we don't rely on on this flow to add folks to the conversation because in this case
# we want to do it in bulk
case_add_or_reactivate_participant_flow(
db_session=db_session,
user_email=email,
case_id=case.id,
add_to_conversation=False,
)
# explicitly add the assignee to the conversation
all_participants = individual_participants + [case.assignee.individual.email]

# we update the ticket
ticket_flows.update_case_ticket(case=case, db_session=db_session)
# # we add the participant to the conversation
conversation_flows.add_case_participants(
case=case, participant_emails=all_participants, db_session=db_session
)

# we update the case document
document_flows.update_document(
document=case.case_document, project_id=case.project.id, db_session=db_session
)
event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description="Case participants added to conversation.",
case_id=case.id,
)
except Exception as e:
event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description=f"Creation of case conversation failed. Reason: {e}",
case_id=case.id,
)
log.exception(e)
97 changes: 91 additions & 6 deletions src/dispatch/conversation/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from typing import TypeVar, List

from dispatch.case.models import Case
from dispatch.conference.models import Conference
from dispatch.database.core import SessionLocal, resolve_attr
from dispatch.document.models import Document
Expand All @@ -22,7 +23,59 @@
Resource = TypeVar("Resource", Document, Conference, Storage, Ticket)


def create_conversation(incident: Incident, db_session: SessionLocal):
def create_case_conversation(case: Case, conversation_target: str, db_session: SessionLocal):
"""Create external communication conversation."""

plugin = plugin_service.get_active_instance(
db_session=db_session, project_id=case.project.id, plugin_type="conversation"
)
if not plugin:
log.warning("Conversation not created. No conversation plugin enabled.")
return

if not conversation_target:
conversation_target = case.case_type.conversation_target

if conversation_target:
try:
conversation = plugin.instance.create_threaded(
case=case, conversation_id=conversation_target, db_session=db_session
)
except Exception as e:
# TODO: consistency across exceptions
log.exception(e)

if not conversation:
log.error(f"Conversation not created. Plugin {plugin.plugin.slug} encountered an error.")
return

conversation.update({"resource_type": plugin.plugin.slug, "resource_id": conversation["id"]})

conversation_in = ConversationCreate(
resource_id=conversation["resource_id"],
resource_type=conversation["resource_type"],
weblink=conversation["weblink"],
thread_id=conversation["timestamp"],
channel_id=conversation["id"],
)
case.conversation = create(
db_session=db_session, conversation_in=conversation_in
)

event_service.log_case_event(
db_session=db_session,
source=plugin.plugin.title,
description="Case conversation created",
case_id=case.id,
)

db_session.add(case)
db_session.commit()

return case.conversation


def create_incident_conversation(incident: Incident, db_session: SessionLocal):
"""Creates a conversation."""
plugin = plugin_service.get_active_instance(
db_session=db_session, project_id=incident.project.id, plugin_type="conversation"
Expand Down Expand Up @@ -59,8 +112,7 @@ def create_conversation(incident: Incident, db_session: SessionLocal):
weblink=external_conversation["weblink"],
channel_id=external_conversation["id"],
)
conversation = create(conversation_in=conversation_in, db_session=db_session)
incident.conversation = conversation
incident.conversation = create(conversation_in=conversation_in, db_session=db_session)

db_session.add(incident)
db_session.commit()
Expand All @@ -72,7 +124,7 @@ def create_conversation(incident: Incident, db_session: SessionLocal):
incident_id=incident.id,
)

return conversation
return incident.conversation


def archive_conversation(incident: Incident, db_session: SessionLocal):
Expand Down Expand Up @@ -262,8 +314,41 @@ def add_conversation_bookmarks(incident: Incident, db_session: SessionLocal):
log.exception(e)


def add_participants(incident: Incident, participant_emails: List[str], db_session: SessionLocal):
"""Adds one or more participants to the conversation."""
def add_case_participants(case: Case, participant_emails: List[str], db_session: SessionLocal):
"""Adds one or more participants to the case conversation."""
if not case.conversation:
log.warning(
"Case participant(s) not added to conversation. No conversation available for this case."
)
return

plugin = plugin_service.get_active_instance(
db_session=db_session, project_id=case.project.id, plugin_type="conversation"
)
if not plugin:
log.warning(
"Case participant(s) not added to conversation. No conversation plugin enabled."
)
return

try:
plugin.instance.add_to_thread(
case.conversation.channel_id,
case.conversation.thread_id,
participant_emails,
)
except Exception as e:
event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description=f"Adding participant(s) to case conversation failed. Reason: {e}",
case_id=case.id,
)
log.exception(e)


def add_incident_participants(incident: Incident, participant_emails: List[str], db_session: SessionLocal):
"""Adds one or more participants to the incident conversation."""
if not incident.conversation:
log.warning(
"Incident participant(s) not added to conversation. No conversation available for this incident."
Expand Down
Loading

0 comments on commit 423876a

Please sign in to comment.