|
@@ -1,8 +1,11 @@
|
|
|
from __future__ import annotations
|
|
|
|
|
|
-from typing import Any, Mapping
|
|
|
+from collections import defaultdict
|
|
|
+from typing import Any, Mapping, MutableMapping
|
|
|
|
|
|
-from sentry.models import Activity, Organization, Team, User
|
|
|
+from sentry.models import Activity, NotificationSetting, Organization, Team, User
|
|
|
+from sentry.notifications.types import GroupSubscriptionReason
|
|
|
+from sentry.types.integrations import ExternalProviders
|
|
|
|
|
|
from .base import GroupActivityNotification
|
|
|
|
|
@@ -18,33 +21,34 @@ def _get_team_option(assignee_id: int, organization: Organization) -> Team | Non
|
|
|
return Team.objects.filter(id=assignee_id, organization=organization).first()
|
|
|
|
|
|
|
|
|
+def is_team_assignee(activity: Activity) -> bool:
|
|
|
+ assignee_type: str | None = activity.data.get("assigneeType")
|
|
|
+ return assignee_type == "team"
|
|
|
+
|
|
|
+
|
|
|
def get_assignee_str(activity: Activity, organization: Organization) -> str:
|
|
|
"""Get a human-readable version of the assignment's target."""
|
|
|
|
|
|
assignee_id = activity.data.get("assignee")
|
|
|
- assignee_type = activity.data.get("assigneeType", "user")
|
|
|
assignee_email: str | None = activity.data.get("assigneeEmail")
|
|
|
|
|
|
- if assignee_type == "user":
|
|
|
- # TODO(mgaeta): Refactor GroupAssigneeManager to not make IDs into strings.
|
|
|
- if str(activity.user_id) == str(assignee_id):
|
|
|
- return "themselves"
|
|
|
-
|
|
|
- assignee_user = _get_user_option(assignee_id)
|
|
|
- if assignee_user:
|
|
|
- assignee: str = assignee_user.get_display_name()
|
|
|
- return assignee
|
|
|
- if assignee_email:
|
|
|
- return assignee_email
|
|
|
- return "an unknown user"
|
|
|
-
|
|
|
- if assignee_type == "team":
|
|
|
+ if is_team_assignee(activity):
|
|
|
assignee_team = _get_team_option(assignee_id, organization)
|
|
|
if assignee_team:
|
|
|
return f"the {assignee_team.slug} team"
|
|
|
return "an unknown team"
|
|
|
|
|
|
- raise NotImplementedError("Unknown Assignee Type")
|
|
|
+ # TODO(mgaeta): Refactor GroupAssigneeManager to not make IDs into strings.
|
|
|
+ if str(activity.user_id) == str(assignee_id):
|
|
|
+ return "themselves"
|
|
|
+
|
|
|
+ assignee_user = _get_user_option(assignee_id)
|
|
|
+ if assignee_user:
|
|
|
+ assignee: str = assignee_user.get_display_name()
|
|
|
+ return assignee
|
|
|
+ if assignee_email:
|
|
|
+ return assignee_email
|
|
|
+ return "an unknown user"
|
|
|
|
|
|
|
|
|
class AssignedActivityNotification(GroupActivityNotification):
|
|
@@ -68,3 +72,30 @@ class AssignedActivityNotification(GroupActivityNotification):
|
|
|
author, assignee = assignee, author
|
|
|
|
|
|
return f"Issue assigned to {assignee} by {author}"
|
|
|
+
|
|
|
+ def get_participants_with_group_subscription_reason(
|
|
|
+ self,
|
|
|
+ ) -> Mapping[ExternalProviders, Mapping[Team | User, int]]:
|
|
|
+ """Hack to tack on the assigned team to the list of users subscribed to the group."""
|
|
|
+ users_by_provider = super().get_participants_with_group_subscription_reason()
|
|
|
+ if is_team_assignee(self.activity):
|
|
|
+ assignee_id = self.activity.data.get("assignee")
|
|
|
+ assignee_team = _get_team_option(assignee_id, self.organization)
|
|
|
+
|
|
|
+ if assignee_team:
|
|
|
+ teams_by_provider = NotificationSetting.objects.filter_to_accepting_recipients(
|
|
|
+ parent=self.project,
|
|
|
+ recipients=[assignee_team],
|
|
|
+ type=self.notification_setting_type,
|
|
|
+ )
|
|
|
+ actors_by_provider: MutableMapping[
|
|
|
+ ExternalProviders,
|
|
|
+ MutableMapping[Team | User, int],
|
|
|
+ ] = defaultdict(dict)
|
|
|
+ actors_by_provider.update({**users_by_provider})
|
|
|
+ for provider, teams in teams_by_provider.items():
|
|
|
+ for team in teams:
|
|
|
+ actors_by_provider[provider][team] = GroupSubscriptionReason.assigned
|
|
|
+ return actors_by_provider
|
|
|
+
|
|
|
+ return users_by_provider
|