update slack_sdk dependency to latest version (#2947)
# What this PR does - update `slackclient` dependency to latest version. The version we were using was 5 years old 😲 - first followed the v2 migration guide [here](https://github.com/slackapi/python-slack-sdk/wiki/Migrating-to-2.x) followed by the v3 migration guide [here](https://slack.dev/python-slack-sdk/v3-migration/). The main changes were: - The PyPI project was renamed from `slackclient` to `slack_sdk` - it is discouraged/harder to call `api_call` and encouraged to call the helper methods (ex. `chat_postMessage`; [note](https://github.com/slackapi/python-slack-sdk/wiki/Migrating-to-2.x#web-client-api-changes) in migration guide docs) - In 1.x, a failed api call would return the error payload to you and have you handle the error. In 2.x, a failed api call will throw an exception. To handle this in your code, you will have to wrap api calls with a try except block. Since we overload `WebClient.api_call` this was an easy change and only required a one line change - remove `apps.slack.slack_client.slack_server.SlackClientServer` class. The new version of `slack_sdk` handles the case that we needed to overload for in the first place. - merged `apps/slack/slack_client/slack_client.py` and `apps/slack/slack_client/exceptions.py` into `apps/slack/client.py` ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required)
This commit is contained in:
parent
0dea5661c4
commit
a9155130df
43 changed files with 253 additions and 502 deletions
|
|
@ -6,9 +6,8 @@ from typing import TYPE_CHECKING
|
|||
from django.utils import timezone
|
||||
|
||||
from apps.schedules.ical_utils import calculate_shift_diff, parse_event_uid
|
||||
from apps.slack.client import SlackAPIException, SlackAPITokenException, SlackClientWithErrorHandling
|
||||
from apps.slack.scenarios import scenario_step
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException, SlackAPITokenException
|
||||
from common.custom_celery_tasks import shared_dedicated_queue_retry_task
|
||||
|
||||
from .task_logger import task_logger
|
||||
|
|
@ -152,8 +151,7 @@ def notify_ical_schedule_shift(schedule_pk):
|
|||
report_blocks = step.get_report_blocks_ical(new_shifts, upcoming_shifts, schedule, schedule.empty_oncall)
|
||||
|
||||
try:
|
||||
slack_client.api_call(
|
||||
"chat.postMessage",
|
||||
slack_client.chat_postMessage(
|
||||
channel=schedule.channel,
|
||||
blocks=report_blocks,
|
||||
text=f"On-call shift for schedule {schedule.name} has changed",
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ def test_next_shift_notification_long_shifts(
|
|||
|
||||
with patch("apps.alerts.tasks.notify_ical_schedule_shift.datetime", Mock(wraps=datetime)) as mock_datetime:
|
||||
mock_datetime.datetime.now.return_value = datetime.datetime(2021, 9, 29, 12, 0, tzinfo=pytz.UTC)
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_ical_schedule_shift(ical_schedule.pk)
|
||||
|
||||
slack_blocks = mock_slack_api_call.call_args_list[0][1]["blocks"]
|
||||
|
|
@ -203,7 +203,7 @@ def test_overrides_changes_no_current_no_triggering_notification(
|
|||
schedule.prev_ical_file_overrides = ical_before
|
||||
schedule.save()
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_ical_schedule_shift(schedule.pk)
|
||||
|
||||
assert not mock_slack_api_call.called
|
||||
|
|
@ -251,7 +251,7 @@ def test_no_changes_no_triggering_notification(
|
|||
schedule.empty_oncall = False
|
||||
schedule.save()
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_ical_schedule_shift(schedule.pk)
|
||||
|
||||
assert not mock_slack_api_call.called
|
||||
|
|
@ -299,7 +299,7 @@ def test_current_shift_changes_trigger_notification(
|
|||
schedule.empty_oncall = False
|
||||
schedule.save()
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_ical_schedule_shift(schedule.pk)
|
||||
|
||||
assert mock_slack_api_call.called
|
||||
|
|
@ -363,7 +363,7 @@ def test_current_shift_changes_swap_split(
|
|||
schedule.empty_oncall = False
|
||||
schedule.save()
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_ical_schedule_shift(schedule.pk)
|
||||
|
||||
text_block = mock_slack_api_call.call_args_list[0][1]["blocks"][0]["text"]["text"]
|
||||
|
|
@ -432,7 +432,7 @@ def test_next_shift_changes_no_triggering_notification(
|
|||
on_call_shift_2.add_rolling_users([[user2]])
|
||||
schedule.refresh_ical_file()
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_ical_schedule_shift(schedule.pk)
|
||||
|
||||
assert not mock_slack_api_call.called
|
||||
|
|
@ -499,7 +499,7 @@ def test_lower_priority_changes_no_triggering_notification(
|
|||
on_call_shift_2.add_rolling_users([[user2]])
|
||||
schedule.refresh_ical_file()
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_ical_schedule_shift(schedule.pk)
|
||||
|
||||
assert not mock_slack_api_call.called
|
||||
|
|
@ -629,7 +629,7 @@ def test_vtimezone_changes_no_triggering_notification(
|
|||
schedule.cached_ical_file_primary = ical_after
|
||||
schedule.save()
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_ical_schedule_shift(schedule.pk)
|
||||
|
||||
assert not mock_slack_api_call.called
|
||||
|
|
@ -686,7 +686,7 @@ def test_no_changes_no_triggering_notification_from_old_to_new_task_version(
|
|||
schedule.empty_oncall = False
|
||||
schedule.save()
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_ical_schedule_shift(schedule.pk)
|
||||
|
||||
assert not mock_slack_api_call.called
|
||||
|
|
@ -748,7 +748,7 @@ def test_current_shift_changes_trigger_notification_from_old_to_new_task_version
|
|||
on_call_shift.add_rolling_users([[user2]])
|
||||
schedule.refresh_ical_file()
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_ical_schedule_shift(schedule.pk)
|
||||
|
||||
assert mock_slack_api_call.called
|
||||
|
|
@ -813,7 +813,7 @@ def test_next_shift_notification_long_and_short_shifts(
|
|||
schedule.empty_oncall = False
|
||||
schedule.save()
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_ical_schedule_shift(schedule.pk)
|
||||
|
||||
assert mock_slack_api_call.called
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ from datetime import timedelta
|
|||
import pytest
|
||||
from django.utils import timezone
|
||||
|
||||
from apps.slack.client import SlackClientWithErrorHandling
|
||||
from apps.slack.scenarios.distribute_alerts import AlertShootingStep
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ from django.core.cache import cache
|
|||
|
||||
from apps.alerts.models.alert_group_counter import ConcurrentUpdateError
|
||||
from apps.alerts.tasks import resolve_alert_group_by_source_if_needed
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException
|
||||
from apps.slack.client import SlackAPIException, SlackClientWithErrorHandling
|
||||
from common.custom_celery_tasks import shared_dedicated_queue_retry_task
|
||||
from common.custom_celery_tasks.create_alert_base_task import CreateAlertBaseTask
|
||||
|
||||
|
|
@ -159,8 +158,6 @@ def notify_about_integration_ratelimit_in_slack(organization_id, text, **kwargs)
|
|||
if slack_team_identity is not None:
|
||||
try:
|
||||
sc = SlackClientWithErrorHandling(slack_team_identity.bot_access_token)
|
||||
sc.api_call(
|
||||
"chat.postMessage", channel=organization.general_log_channel_id, text=text, team=slack_team_identity
|
||||
)
|
||||
sc.chat_postMessage(channel=organization.general_log_channel_id, text=text, team=slack_team_identity)
|
||||
except SlackAPIException as e:
|
||||
logger.warning(f"Slack exception {e} while sending message for organization {organization_id}")
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
from apps.public_api.constants import VALID_DATE_FOR_DELETE_INCIDENT
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import SlackAPITokenException
|
||||
from apps.slack.client import SlackAPITokenException, SlackClientWithErrorHandling
|
||||
|
||||
|
||||
def team_has_slack_token_for_deleting(alert_group):
|
||||
if alert_group.slack_message and alert_group.slack_message.slack_team_identity:
|
||||
sc = SlackClientWithErrorHandling(alert_group.slack_message.slack_team_identity.bot_access_token)
|
||||
try:
|
||||
sc.api_call(
|
||||
"auth.test",
|
||||
)
|
||||
sc.auth_test()
|
||||
except SlackAPITokenException:
|
||||
return False
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -154,14 +154,13 @@ def test_followup_offsets():
|
|||
assert ShiftSwapRequest.FOLLOWUP_OFFSETS[idx] > FOLLOWUP_WINDOW
|
||||
|
||||
|
||||
@patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call")
|
||||
@patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage")
|
||||
@pytest.mark.django_db
|
||||
def test_send_shift_swap_request_followup(mock_slack_api_call, shift_swap_request_test_setup):
|
||||
def test_send_shift_swap_request_followup(mock_slack_chat_post_message, shift_swap_request_test_setup):
|
||||
shift_swap_request = shift_swap_request_test_setup()
|
||||
send_shift_swap_request_slack_followup(shift_swap_request.pk)
|
||||
|
||||
mock_slack_api_call.assert_called_once_with(
|
||||
"chat.postMessage",
|
||||
mock_slack_chat_post_message.assert_called_once_with(
|
||||
channel=shift_swap_request.slack_message.channel_id,
|
||||
thread_ts=shift_swap_request.slack_message.slack_id,
|
||||
reply_broadcast=True,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ def test_no_empty_shifts_no_triggering_notification(
|
|||
|
||||
empty_shifts_report_sent_at = schedule.empty_shifts_report_sent_at
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_about_empty_shifts_in_schedule(schedule.pk)
|
||||
|
||||
assert not mock_slack_api_call.called
|
||||
|
|
@ -97,7 +97,7 @@ def test_empty_shifts_trigger_notification(
|
|||
|
||||
empty_shifts_report_sent_at = schedule.empty_shifts_report_sent_at
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_about_empty_shifts_in_schedule(schedule.pk)
|
||||
|
||||
assert mock_slack_api_call.called
|
||||
|
|
@ -160,7 +160,7 @@ def test_empty_non_empty_shifts_trigger_notification(
|
|||
|
||||
empty_shifts_report_sent_at = schedule.empty_shifts_report_sent_at
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_about_empty_shifts_in_schedule(schedule.pk)
|
||||
|
||||
assert mock_slack_api_call.called
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ def test_no_gaps_no_triggering_notification(
|
|||
|
||||
gaps_report_sent_at = schedule.gaps_report_sent_at
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_about_gaps_in_schedule(schedule.pk)
|
||||
|
||||
assert not mock_slack_api_call.called
|
||||
|
|
@ -113,7 +113,7 @@ def test_gaps_in_the_past_no_triggering_notification(
|
|||
|
||||
gaps_report_sent_at = schedule.gaps_report_sent_at
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_about_gaps_in_schedule(schedule.pk)
|
||||
|
||||
assert not mock_slack_api_call.called
|
||||
|
|
@ -165,7 +165,7 @@ def test_gaps_now_trigger_notification(
|
|||
|
||||
assert schedule.has_gaps is False
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_about_gaps_in_schedule(schedule.pk)
|
||||
|
||||
assert mock_slack_api_call.called
|
||||
|
|
@ -219,7 +219,7 @@ def test_gaps_near_future_trigger_notification(
|
|||
|
||||
assert schedule.has_gaps is False
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_about_gaps_in_schedule(schedule.pk)
|
||||
|
||||
assert mock_slack_api_call.called
|
||||
|
|
@ -271,7 +271,7 @@ def test_gaps_later_than_7_days_no_triggering_notification(
|
|||
|
||||
gaps_report_sent_at = schedule.gaps_report_sent_at
|
||||
|
||||
with patch("apps.slack.slack_client.SlackClientWithErrorHandling.api_call") as mock_slack_api_call:
|
||||
with patch("apps.slack.client.SlackClientWithErrorHandling.chat_postMessage") as mock_slack_api_call:
|
||||
notify_about_gaps_in_schedule(schedule.pk)
|
||||
|
||||
assert not mock_slack_api_call.called
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import logging
|
||||
import typing
|
||||
|
||||
from apps.slack.constants import SLACK_RATE_LIMIT_DELAY
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import (
|
||||
from apps.slack.client import (
|
||||
SlackAPIChannelArchivedException,
|
||||
SlackAPIException,
|
||||
SlackAPIRateLimitException,
|
||||
SlackAPITokenException,
|
||||
SlackClientWithErrorHandling,
|
||||
)
|
||||
from apps.slack.constants import SLACK_RATE_LIMIT_DELAY
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from apps.alerts.models import AlertGroup
|
||||
|
|
@ -36,8 +36,7 @@ class AlertGroupSlackService:
|
|||
|
||||
logger.info(f"Update message for alert_group {alert_group.pk}")
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"chat.update",
|
||||
self._slack_client.chat_update(
|
||||
channel=alert_group.slack_message.channel_id,
|
||||
ts=alert_group.slack_message.slack_id,
|
||||
attachments=alert_group.render_slack_attachments(),
|
||||
|
|
@ -77,8 +76,7 @@ class AlertGroupSlackService:
|
|||
return
|
||||
|
||||
try:
|
||||
result = self._slack_client.api_call(
|
||||
"chat.postMessage",
|
||||
result = self._slack_client.chat_postMessage(
|
||||
channel=alert_group.slack_message.channel_id,
|
||||
text=text,
|
||||
attachments=attachments,
|
||||
|
|
|
|||
|
|
@ -2,44 +2,42 @@ import logging
|
|||
from typing import Optional, Tuple
|
||||
|
||||
from django.utils import timezone
|
||||
from slackclient import SlackClient
|
||||
from slackclient.exceptions import TokenRefreshError
|
||||
from slack_sdk.errors import SlackApiError
|
||||
from slack_sdk.web import WebClient
|
||||
|
||||
from apps.slack.constants import SLACK_RATE_LIMIT_DELAY
|
||||
|
||||
from .exceptions import (
|
||||
SlackAPIChannelArchivedException,
|
||||
SlackAPIException,
|
||||
SlackAPIRateLimitException,
|
||||
SlackAPITokenException,
|
||||
)
|
||||
from .slack_client_server import SlackClientServer
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SlackClientWithErrorHandling(SlackClient):
|
||||
def __init__(self, token=None, **kwargs):
|
||||
class SlackAPIException(Exception):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.response = {}
|
||||
if "response" in kwargs:
|
||||
self.response = kwargs["response"]
|
||||
super().__init__(*args)
|
||||
|
||||
|
||||
class SlackAPITokenException(SlackAPIException):
|
||||
pass
|
||||
|
||||
|
||||
class SlackAPIChannelArchivedException(SlackAPIException):
|
||||
pass
|
||||
|
||||
|
||||
class SlackAPIRateLimitException(SlackAPIException):
|
||||
pass
|
||||
|
||||
|
||||
class SlackClientWithErrorHandling(WebClient):
|
||||
def paginated_api_call(self, method: str, paginated_key: str, **kwargs):
|
||||
"""
|
||||
This method is rewritten because we want to use custom server SlackClientServer for SlackClient
|
||||
`paginated_key` represents a key from the response which is paginated. For example "users" or "channels"
|
||||
"""
|
||||
super().__init__(token=token, **kwargs)
|
||||
api_method = getattr(self, method)
|
||||
|
||||
proxies = kwargs.get("proxies")
|
||||
|
||||
if self.refresh_token:
|
||||
if callable(self.token_update_callback):
|
||||
token = None
|
||||
else:
|
||||
raise TokenRefreshError("Token refresh callback function is required when using refresh token.")
|
||||
# Slack app configs
|
||||
self.server = SlackClientServer(token=token, connect=False, proxies=proxies)
|
||||
|
||||
def paginated_api_call(self, *args, **kwargs):
|
||||
# It's a key from response which is paginated. For example "users" or "channels"
|
||||
listed_key = kwargs["paginated_key"]
|
||||
|
||||
response = self.api_call(*args, **kwargs)
|
||||
response = api_method(**kwargs)
|
||||
cumulative_response = response
|
||||
|
||||
while (
|
||||
|
|
@ -48,25 +46,30 @@ class SlackClientWithErrorHandling(SlackClient):
|
|||
and response["response_metadata"]["next_cursor"] != ""
|
||||
):
|
||||
kwargs["cursor"] = response["response_metadata"]["next_cursor"]
|
||||
response = self.api_call(*args, **kwargs)
|
||||
cumulative_response[listed_key] += response[listed_key]
|
||||
response = api_method(**kwargs)
|
||||
cumulative_response[paginated_key] += response[paginated_key]
|
||||
|
||||
return cumulative_response
|
||||
|
||||
def paginated_api_call_with_ratelimit(self, *args, **kwargs) -> Tuple[dict, Optional[str], bool]:
|
||||
def paginated_api_call_with_ratelimit(
|
||||
self, method: str, paginated_key: str, **kwargs
|
||||
) -> Tuple[dict, Optional[str], bool]:
|
||||
"""
|
||||
This method do paginated api call and handle slack rate limit error in order to return collected data and have
|
||||
ability to continue doing paginated requests from the last successful cursor. Return last successful cursor
|
||||
instead of next cursor to avoid data loss during delay time
|
||||
This method does paginated api calls and handle slack rate limit errors in order to return collected data
|
||||
and have the ability to continue doing paginated requests from the last successful cursor.
|
||||
|
||||
Return last successful cursor instead of next cursor to avoid data loss during delay time.
|
||||
|
||||
`paginated_key` represents a key from the response which is paginated. For example "users" or "channels"
|
||||
"""
|
||||
# It's a key from response which is paginated. For example "users" or "channels"
|
||||
listed_key = kwargs["paginated_key"]
|
||||
api_method = getattr(self, method)
|
||||
|
||||
cumulative_response = {}
|
||||
cursor = kwargs.get("cursor")
|
||||
cursor = kwargs["cursor"]
|
||||
rate_limited = False
|
||||
|
||||
try:
|
||||
response = self.api_call(*args, **kwargs)
|
||||
response = api_method(**kwargs)
|
||||
cumulative_response = response
|
||||
cursor = response["response_metadata"]["next_cursor"]
|
||||
|
||||
|
|
@ -77,8 +80,8 @@ class SlackClientWithErrorHandling(SlackClient):
|
|||
):
|
||||
next_cursor = response["response_metadata"]["next_cursor"]
|
||||
kwargs["cursor"] = next_cursor
|
||||
response = self.api_call(*args, **kwargs)
|
||||
cumulative_response[listed_key] += response[listed_key]
|
||||
response = api_method(**kwargs)
|
||||
cumulative_response[paginated_key] += response[paginated_key]
|
||||
cursor = next_cursor
|
||||
|
||||
except SlackAPIRateLimitException:
|
||||
|
|
@ -87,7 +90,10 @@ class SlackClientWithErrorHandling(SlackClient):
|
|||
return cumulative_response, cursor, rate_limited
|
||||
|
||||
def api_call(self, *args, **kwargs):
|
||||
response = super(SlackClientWithErrorHandling, self).api_call(*args, **kwargs)
|
||||
try:
|
||||
response = super(SlackClientWithErrorHandling, self).api_call(*args, **kwargs)
|
||||
except SlackApiError as err:
|
||||
response = err.response
|
||||
|
||||
if not response["ok"]:
|
||||
exception_text = "Slack API Call Error: {} \nArgs: {} \nKwargs: {} \nResponse: {}".format(
|
||||
|
|
@ -5,11 +5,11 @@ import uuid
|
|||
|
||||
from django.db import models
|
||||
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import (
|
||||
from apps.slack.client import (
|
||||
SlackAPIChannelArchivedException,
|
||||
SlackAPIException,
|
||||
SlackAPITokenException,
|
||||
SlackClientWithErrorHandling,
|
||||
)
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
|
|
@ -83,11 +83,7 @@ class SlackMessage(models.Model):
|
|||
sc = SlackClientWithErrorHandling(self.slack_team_identity.bot_access_token)
|
||||
result = None
|
||||
try:
|
||||
result = sc.api_call(
|
||||
"chat.getPermalink",
|
||||
channel=self.channel_id,
|
||||
message_ts=self.slack_id,
|
||||
)
|
||||
result = sc.chat_getPermalink(channel=self.channel_id, message_ts=self.slack_id)
|
||||
except SlackAPIException as e:
|
||||
if e.response["error"] == "message_not_found":
|
||||
return "https://slack.com/resources/using-slack/page/404"
|
||||
|
|
@ -143,8 +139,7 @@ class SlackMessage(models.Model):
|
|||
channel_id = slack_message.channel_id
|
||||
|
||||
try:
|
||||
result = sc.api_call(
|
||||
"chat.postMessage",
|
||||
result = sc.chat_postMessage(
|
||||
channel=channel_id,
|
||||
text=text,
|
||||
blocks=blocks,
|
||||
|
|
@ -190,7 +185,7 @@ class SlackMessage(models.Model):
|
|||
if slack_user_identity:
|
||||
channel_members = []
|
||||
try:
|
||||
channel_members = sc.api_call("conversations.members", channel=channel_id)["members"]
|
||||
channel_members = sc.conversations_members(channel=channel_id)["members"]
|
||||
except SlackAPIException as e:
|
||||
if e.response["error"] == "fetch_members_failed":
|
||||
logger.warning(
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ from django.db import models
|
|||
from django.db.models import JSONField
|
||||
|
||||
from apps.api.permissions import RBACPermission
|
||||
from apps.slack.client import SlackAPIException, SlackAPITokenException, SlackClientWithErrorHandling
|
||||
from apps.slack.constants import SLACK_INVALID_AUTH_RESPONSE, SLACK_WRONG_TEAM_NAMES
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException, SlackAPITokenException
|
||||
from apps.user_management.models.user import User
|
||||
from common.insight_log.chatops_insight_logs import ChatOpsEvent, ChatOpsTypePlug, write_chatops_insight_log
|
||||
|
||||
|
|
@ -87,7 +86,7 @@ class SlackTeamIdentity(models.Model):
|
|||
def bot_id(self):
|
||||
if self.cached_bot_id is None:
|
||||
sc = SlackClientWithErrorHandling(self.bot_access_token)
|
||||
auth = sc.api_call("auth.test")
|
||||
auth = sc.auth_test()
|
||||
self.cached_bot_id = auth.get("bot_id")
|
||||
self.save(update_fields=["cached_bot_id"])
|
||||
return self.cached_bot_id
|
||||
|
|
@ -99,7 +98,7 @@ class SlackTeamIdentity(models.Model):
|
|||
next_cursor = None
|
||||
members = []
|
||||
while next_cursor != "" or next_cursor is None:
|
||||
result = sc.api_call("users.list", cursor=next_cursor, team=self)
|
||||
result = sc.users_list(cursor=next_cursor, team=self)
|
||||
next_cursor = result["response_metadata"]["next_cursor"]
|
||||
members += result["members"]
|
||||
|
||||
|
|
@ -110,7 +109,7 @@ class SlackTeamIdentity(models.Model):
|
|||
if self.cached_name is None or self.cached_name in SLACK_WRONG_TEAM_NAMES:
|
||||
try:
|
||||
sc = SlackClientWithErrorHandling(self.bot_access_token)
|
||||
result = sc.api_call("team.info")
|
||||
result = sc.team_info()
|
||||
self.cached_name = result["team"]["name"]
|
||||
self.save()
|
||||
except SlackAPIException as e:
|
||||
|
|
@ -125,7 +124,7 @@ class SlackTeamIdentity(models.Model):
|
|||
def app_id(self):
|
||||
if not self.cached_app_id:
|
||||
sc = SlackClientWithErrorHandling(self.bot_access_token)
|
||||
result = sc.api_call("bots.info", bot=self.bot_id)
|
||||
result = sc.bots_info(bot=self.bot_id)
|
||||
app_id = result["bot"]["app_id"]
|
||||
self.cached_app_id = app_id
|
||||
self.save(update_fields=["cached_app_id"])
|
||||
|
|
@ -140,10 +139,10 @@ class SlackTeamIdentity(models.Model):
|
|||
**User.build_permissions_query(RBACPermission.Permissions.CHATOPS_WRITE, organization),
|
||||
)
|
||||
|
||||
def get_conversation_members(self, slack_client, channel_id):
|
||||
def get_conversation_members(self, slack_client: SlackClientWithErrorHandling, channel_id: str):
|
||||
try:
|
||||
members = slack_client.paginated_api_call(
|
||||
"conversations.members", channel=channel_id, paginated_key="members"
|
||||
"conversations_members", paginated_key="members", channel=channel_id
|
||||
)["members"]
|
||||
except SlackAPITokenException as e:
|
||||
logger.warning(
|
||||
|
|
|
|||
|
|
@ -4,10 +4,9 @@ import typing
|
|||
import requests
|
||||
from django.db import models
|
||||
|
||||
from apps.slack.client import SlackAPIException, SlackAPITokenException, SlackClientWithErrorHandling
|
||||
from apps.slack.constants import SLACK_BOT_ID
|
||||
from apps.slack.scenarios.notified_user_not_in_channel import NotifiedUserNotInChannelStep
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException, SlackAPITokenException
|
||||
from apps.user_management.models import Organization, User
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
|
|
@ -135,8 +134,7 @@ class SlackUserIdentity(models.Model):
|
|||
]
|
||||
|
||||
sc = SlackClientWithErrorHandling(self.slack_team_identity.bot_access_token)
|
||||
return sc.api_call(
|
||||
"chat.postMessage",
|
||||
return sc.chat_postMessage(
|
||||
channel=self.im_channel_id,
|
||||
text="You are invited to look at an alert group!",
|
||||
blocks=blocks,
|
||||
|
|
@ -158,11 +156,7 @@ class SlackUserIdentity(models.Model):
|
|||
if self.cached_slack_login is None or self.cached_slack_login == "slack_token_revoked_unable_to_cache_login":
|
||||
sc = SlackClientWithErrorHandling(self.slack_team_identity.bot_access_token)
|
||||
try:
|
||||
result = sc.api_call(
|
||||
"users.info",
|
||||
user=self.slack_id,
|
||||
team=self.slack_team_identity,
|
||||
)
|
||||
result = sc.users_info(user=self.slack_id, team=self.slack_team_identity)
|
||||
self.cached_slack_login = result["user"]["name"]
|
||||
self.save()
|
||||
except SlackAPITokenException as e:
|
||||
|
|
@ -187,11 +181,7 @@ class SlackUserIdentity(models.Model):
|
|||
if self.cached_timezone is None or self.cached_timezone == "None":
|
||||
sc = SlackClientWithErrorHandling(self.slack_team_identity.bot_access_token)
|
||||
try:
|
||||
result = sc.api_call(
|
||||
"users.info",
|
||||
user=self.slack_id,
|
||||
timeout=5,
|
||||
)
|
||||
result = sc.users_info(user=self.slack_id)
|
||||
tz_from_slack = result["user"].get("tz", "UTC")
|
||||
if tz_from_slack == "None" or tz_from_slack is None:
|
||||
tz_from_slack = "UTC"
|
||||
|
|
@ -210,7 +200,7 @@ class SlackUserIdentity(models.Model):
|
|||
if self.cached_im_channel_id is None:
|
||||
sc = SlackClientWithErrorHandling(self.slack_team_identity.bot_access_token)
|
||||
try:
|
||||
result = sc.api_call("conversations.open", users=self.slack_id, return_im=True)
|
||||
result = sc.conversations_open(users=self.slack_id, return_im=True)
|
||||
self.cached_im_channel_id = result["channel"]["id"]
|
||||
self.save()
|
||||
except SlackAPIException as e:
|
||||
|
|
@ -225,11 +215,7 @@ class SlackUserIdentity(models.Model):
|
|||
sc = SlackClientWithErrorHandling(self.slack_team_identity.bot_access_token)
|
||||
logger.info("Update user profile info")
|
||||
try:
|
||||
result = sc.api_call(
|
||||
"users.info",
|
||||
user=self.slack_id,
|
||||
team=self.slack_team_identity,
|
||||
)
|
||||
result = sc.users_info(user=self.slack_id, team=self.slack_team_identity)
|
||||
except SlackAPITokenException as e:
|
||||
logger.warning(f"Unable to get user info due token revoked or account inactive: {e}")
|
||||
result = None
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@ from django.db.models import JSONField
|
|||
from django.utils import timezone
|
||||
|
||||
from apps.api.permissions import RBACPermission
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException
|
||||
from apps.slack.client import SlackAPIException, SlackClientWithErrorHandling
|
||||
from apps.user_management.models.user import User
|
||||
from common.public_primary_keys import generate_public_primary_key, increase_public_primary_key_length
|
||||
|
||||
|
|
@ -69,10 +68,10 @@ class SlackUserGroup(models.Model):
|
|||
|
||||
@property
|
||||
def can_be_updated(self) -> bool:
|
||||
sc = SlackClientWithErrorHandling(self.slack_team_identity.bot_access_token)
|
||||
sc = SlackClientWithErrorHandling(self.slack_team_identity.bot_access_token, timeout=5)
|
||||
|
||||
try:
|
||||
sc.api_call("usergroups.update", usergroup=self.slack_id, timeout=5)
|
||||
sc.usergroups_update(usergroup=self.slack_id)
|
||||
return True
|
||||
except (SlackAPIException, requests.exceptions.Timeout):
|
||||
return False
|
||||
|
|
@ -112,11 +111,7 @@ class SlackUserGroup(models.Model):
|
|||
def update_members(self, slack_ids):
|
||||
sc = SlackClientWithErrorHandling(self.slack_team_identity.bot_access_token)
|
||||
|
||||
sc.api_call(
|
||||
"usergroups.users.update",
|
||||
usergroup=self.slack_id,
|
||||
users=slack_ids,
|
||||
)
|
||||
sc.usergroups_users_update(usergroup=self.slack_id, users=slack_ids)
|
||||
|
||||
self.members = slack_ids
|
||||
self.save(update_fields=("members",))
|
||||
|
|
@ -132,18 +127,14 @@ class SlackUserGroup(models.Model):
|
|||
sc = SlackClientWithErrorHandling(slack_team_identity.bot_access_token)
|
||||
bot_access_token_accepted = True
|
||||
try:
|
||||
usergroups_list = sc.api_call(
|
||||
"usergroups.list",
|
||||
)
|
||||
usergroups_list = sc.usergroups_list()
|
||||
except SlackAPIException as e:
|
||||
if e.response["error"] == "not_allowed_token_type":
|
||||
# Trying same request with access token. It is required due to migration to granular permissions
|
||||
# and can be removed after clients reinstall their bots
|
||||
try:
|
||||
sc_with_access_token = SlackClientWithErrorHandling(slack_team_identity.access_token)
|
||||
usergroups_list = sc_with_access_token.api_call(
|
||||
"usergroups.list",
|
||||
)
|
||||
usergroups_list = sc_with_access_token.usergroups_list()
|
||||
bot_access_token_accepted = False
|
||||
except SlackAPIException as err:
|
||||
if err.response["error"] == "missing_scope":
|
||||
|
|
@ -159,16 +150,10 @@ class SlackUserGroup(models.Model):
|
|||
if usergroup["id"] == slack_id:
|
||||
try:
|
||||
if bot_access_token_accepted:
|
||||
usergroups_users = sc.api_call(
|
||||
"usergroups.users.list",
|
||||
usergroup=usergroup["id"],
|
||||
)
|
||||
usergroups_users = sc.usergroups_users_list(usergroup=usergroup["id"])
|
||||
else:
|
||||
sc_with_access_token = SlackClientWithErrorHandling(slack_team_identity.access_token)
|
||||
usergroups_users = sc_with_access_token.api_call(
|
||||
"usergroups.users.list",
|
||||
usergroup=usergroup["id"],
|
||||
)
|
||||
usergroups_users = sc_with_access_token.usergroups_users_list(usergroup=usergroup["id"])
|
||||
except SlackAPIException as e:
|
||||
if e.response["error"] == "no_such_subteam":
|
||||
logger.info("User group does not exist")
|
||||
|
|
|
|||
|
|
@ -66,11 +66,7 @@ class OpenAlertAppearanceDialogStep(AlertGroupActionsMixin, scenario_step.Scenar
|
|||
"private_metadata": json.dumps(private_metadata),
|
||||
}
|
||||
|
||||
self._slack_client.api_call(
|
||||
"views.open",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
)
|
||||
self._slack_client.views_open(trigger_id=payload["trigger_id"], view=view)
|
||||
|
||||
|
||||
class UpdateAppearanceStep(scenario_step.ScenarioStep):
|
||||
|
|
@ -90,8 +86,7 @@ class UpdateAppearanceStep(scenario_step.ScenarioStep):
|
|||
attachments = alert_group.render_slack_attachments()
|
||||
blocks = alert_group.render_slack_blocks()
|
||||
|
||||
self._slack_client.api_call(
|
||||
"chat.update",
|
||||
self._slack_client.chat_update(
|
||||
channel=alert_group.slack_message.channel_id,
|
||||
ts=alert_group.slack_message.slack_id,
|
||||
attachments=attachments,
|
||||
|
|
|
|||
|
|
@ -15,16 +15,16 @@ from apps.alerts.models import Alert, AlertGroup, AlertGroupLogRecord, AlertRece
|
|||
from apps.alerts.tasks import custom_button_result
|
||||
from apps.alerts.utils import render_curl_command
|
||||
from apps.api.permissions import RBACPermission
|
||||
from apps.slack.constants import CACHE_UPDATE_INCIDENT_SLACK_MESSAGE_LIFETIME, SLACK_RATE_LIMIT_DELAY
|
||||
from apps.slack.scenarios import scenario_step
|
||||
from apps.slack.scenarios.slack_renderer import AlertGroupLogSlackRenderer
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import (
|
||||
from apps.slack.client import (
|
||||
SlackAPIChannelArchivedException,
|
||||
SlackAPIException,
|
||||
SlackAPIRateLimitException,
|
||||
SlackAPITokenException,
|
||||
SlackClientWithErrorHandling,
|
||||
)
|
||||
from apps.slack.constants import CACHE_UPDATE_INCIDENT_SLACK_MESSAGE_LIFETIME, SLACK_RATE_LIMIT_DELAY
|
||||
from apps.slack.scenarios import scenario_step
|
||||
from apps.slack.scenarios.slack_renderer import AlertGroupLogSlackRenderer
|
||||
from apps.slack.slack_formatter import SlackFormatter
|
||||
from apps.slack.tasks import (
|
||||
post_or_update_log_report_message_task,
|
||||
|
|
@ -133,9 +133,7 @@ class AlertShootingStep(scenario_step.ScenarioStep):
|
|||
return
|
||||
|
||||
try:
|
||||
result = self._slack_client.api_call(
|
||||
"chat.postMessage", channel=channel_id, attachments=attachments, blocks=blocks
|
||||
)
|
||||
result = self._slack_client.chat_postMessage(channel=channel_id, attachments=attachments, blocks=blocks)
|
||||
|
||||
alert_group.slack_messages.create(
|
||||
slack_id=result["ts"],
|
||||
|
|
@ -147,8 +145,7 @@ class AlertShootingStep(scenario_step.ScenarioStep):
|
|||
# If alert was made out of a message:
|
||||
if alert_group.channel.integration == AlertReceiveChannel.INTEGRATION_SLACK_CHANNEL:
|
||||
channel = json.loads(alert.integration_unique_data)["channel"]
|
||||
result = self._slack_client.api_call(
|
||||
"chat.postMessage",
|
||||
result = self._slack_client.chat_postMessage(
|
||||
channel=channel,
|
||||
thread_ts=json.loads(alert.integration_unique_data)["ts"],
|
||||
text=":rocket: <{}|Incident registered!>".format(alert_group.slack_message.permalink),
|
||||
|
|
@ -200,8 +197,7 @@ class AlertShootingStep(scenario_step.ScenarioStep):
|
|||
blocks: Block.AnyBlocks = []
|
||||
text = "Escalations are silenced due to Debug mode"
|
||||
blocks.append({"type": "section", "text": {"type": "mrkdwn", "text": text}})
|
||||
self._slack_client.api_call(
|
||||
"chat.postMessage",
|
||||
self._slack_client.chat_postMessage(
|
||||
channel=channel_id,
|
||||
text=text,
|
||||
attachments=[],
|
||||
|
|
@ -394,11 +390,7 @@ class SelectAttachGroupStep(AlertGroupActionsMixin, scenario_step.ScenarioStep):
|
|||
},
|
||||
}
|
||||
)
|
||||
self._slack_client.api_call(
|
||||
"views.open",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
)
|
||||
self._slack_client.views_open(trigger_id=payload["trigger_id"], view=view)
|
||||
|
||||
def get_select_incidents_blocks(self, alert_group: AlertGroup) -> Block.AnyBlocks:
|
||||
collected_options: typing.List[CompositionObjectOption] = []
|
||||
|
|
@ -482,8 +474,7 @@ class AttachGroupStep(AlertGroupActionsMixin, scenario_step.ScenarioStep):
|
|||
slack_user_identity = log_record.author.slack_user_identity
|
||||
|
||||
if slack_user_identity:
|
||||
self._slack_client.api_call(
|
||||
"chat.postEphemeral",
|
||||
self._slack_client.chat_postEphemeral(
|
||||
user=slack_user_identity.slack_id,
|
||||
channel=alert_group.slack_message.channel_id,
|
||||
text="{}{}".format(ephemeral_text[:1].upper(), ephemeral_text[1:]),
|
||||
|
|
@ -757,8 +748,7 @@ class UnAcknowledgeGroupStep(AlertGroupActionsMixin, scenario_step.ScenarioStep)
|
|||
)
|
||||
if alert_group.slack_message.ack_reminder_message_ts:
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"chat.update",
|
||||
self._slack_client.chat_update(
|
||||
channel=channel_id,
|
||||
ts=alert_group.slack_message.ack_reminder_message_ts,
|
||||
text=text,
|
||||
|
|
@ -803,17 +793,11 @@ class AcknowledgeConfirmationStep(AcknowledgeGroupStep):
|
|||
if self.user == alert_group.acknowledged_by_user:
|
||||
user_verbal = alert_group.acknowledged_by_user.get_username_with_slack_verbal()
|
||||
text = f"{user_verbal} confirmed that the Alert Group is still acknowledged."
|
||||
self._slack_client.api_call(
|
||||
"chat.update",
|
||||
channel=channel,
|
||||
ts=message_ts,
|
||||
text=text,
|
||||
)
|
||||
self._slack_client.chat_update(channel=channel, ts=message_ts, text=text)
|
||||
alert_group.acknowledged_by_confirmed = datetime.utcnow()
|
||||
alert_group.save(update_fields=["acknowledged_by_confirmed"])
|
||||
else:
|
||||
self._slack_client.api_call(
|
||||
"chat.postEphemeral",
|
||||
self._slack_client.chat_postEphemeral(
|
||||
channel=channel,
|
||||
user=slack_user_identity.slack_id,
|
||||
text="This Alert Group is acknowledged by another user. Acknowledge it yourself first.",
|
||||
|
|
@ -821,22 +805,12 @@ class AcknowledgeConfirmationStep(AcknowledgeGroupStep):
|
|||
elif alert_group.acknowledged_by == AlertGroup.SOURCE:
|
||||
user_verbal = self.user.get_username_with_slack_verbal()
|
||||
text = f"{user_verbal} confirmed that the Alert Group is still acknowledged."
|
||||
self._slack_client.api_call(
|
||||
"chat.update",
|
||||
channel=channel,
|
||||
ts=message_ts,
|
||||
text=text,
|
||||
)
|
||||
self._slack_client.chat_update(channel=channel, ts=message_ts, text=text)
|
||||
alert_group.acknowledged_by_confirmed = datetime.utcnow()
|
||||
alert_group.save(update_fields=["acknowledged_by_confirmed"])
|
||||
else:
|
||||
self._slack_client.api_call(
|
||||
"chat.delete",
|
||||
channel=channel,
|
||||
ts=message_ts,
|
||||
)
|
||||
self._slack_client.api_call(
|
||||
"chat.postEphemeral",
|
||||
self._slack_client.chat_delete(channel=channel, ts=message_ts)
|
||||
self._slack_client.chat_postEphemeral(
|
||||
channel=channel,
|
||||
user=slack_user_identity.slack_id,
|
||||
text="This Alert Group is already unacknowledged.",
|
||||
|
|
@ -877,8 +851,7 @@ class AcknowledgeConfirmationStep(AcknowledgeGroupStep):
|
|||
}
|
||||
]
|
||||
try:
|
||||
response = self._slack_client.api_call(
|
||||
"chat.postMessage",
|
||||
response = self._slack_client.chat_postMessage(
|
||||
channel=channel_id,
|
||||
text=text,
|
||||
attachments=attachments,
|
||||
|
|
@ -944,11 +917,7 @@ class DeleteGroupStep(scenario_step.ScenarioStep):
|
|||
|
||||
for message_ts in bot_messages_ts:
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"chat.delete",
|
||||
channel=channel_id,
|
||||
ts=message_ts,
|
||||
)
|
||||
self._slack_client.chat_delete(channel=channel_id, ts=message_ts)
|
||||
except SlackAPITokenException as e:
|
||||
logger.error(
|
||||
f"Unable to delete messages in slack. Message ts: {message_ts}"
|
||||
|
|
@ -981,11 +950,7 @@ class DeleteGroupStep(scenario_step.ScenarioStep):
|
|||
sc_with_access_token = SlackClientWithErrorHandling(
|
||||
self.slack_team_identity.access_token
|
||||
) # used access_token instead of bot_access_token
|
||||
sc_with_access_token.api_call(
|
||||
"chat.delete",
|
||||
channel=channel_id,
|
||||
ts=message_ts,
|
||||
)
|
||||
sc_with_access_token.chat_delete(channel=channel_id, ts=message_ts)
|
||||
else:
|
||||
raise e
|
||||
|
||||
|
|
@ -994,12 +959,7 @@ class DeleteGroupStep(scenario_step.ScenarioStep):
|
|||
message.added_to_resolution_note = False
|
||||
message.save(update_fields=["added_to_resolution_note"])
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"reactions.remove",
|
||||
channel=message.slack_channel_id,
|
||||
name="memo",
|
||||
timestamp=message.ts,
|
||||
)
|
||||
self._slack_client.reactions_remove(channel=message.slack_channel_id, name="memo", timestamp=message.ts)
|
||||
except SlackAPITokenException as e:
|
||||
logger.warning(
|
||||
f"Unable to delete resolution note reaction in slack. "
|
||||
|
|
@ -1030,8 +990,8 @@ class UpdateLogReportMessageStep(scenario_step.ScenarioStep):
|
|||
if slack_log_message is None:
|
||||
logger.debug(f"Start posting new log message for alert_group {alert_group.pk}")
|
||||
try:
|
||||
result = self._slack_client.api_call(
|
||||
"chat.postMessage", channel=slack_message.channel_id, thread_ts=slack_message.slack_id, text=text
|
||||
result = self._slack_client.chat_postMessage(
|
||||
channel=slack_message.channel_id, thread_ts=slack_message.slack_id, text=text
|
||||
)
|
||||
except SlackAPITokenException as e:
|
||||
print(e)
|
||||
|
|
@ -1090,8 +1050,7 @@ class UpdateLogReportMessageStep(scenario_step.ScenarioStep):
|
|||
f"Update log message for alert_group {alert_group.pk}, slack_log_message {slack_log_message.pk}"
|
||||
)
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"chat.update",
|
||||
self._slack_client.chat_update(
|
||||
channel=slack_message.channel_id,
|
||||
text="Alert Group log",
|
||||
ts=slack_log_message.slack_id,
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import typing
|
|||
|
||||
from django.utils import timezone
|
||||
|
||||
from apps.slack.client import SlackClientWithErrorHandling
|
||||
from apps.slack.scenarios import scenario_step
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.types import EventPayload, EventType, PayloadType, ScenarioRoute
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
|
|
@ -24,7 +24,7 @@ class InvitedToChannelStep(scenario_step.ScenarioStep):
|
|||
if payload["event"]["user"] == slack_team_identity.bot_user_id:
|
||||
channel_id = payload["event"]["channel"]
|
||||
slack_client = SlackClientWithErrorHandling(slack_team_identity.bot_access_token)
|
||||
channel = slack_client.api_call("conversations.info", channel=channel_id)["channel"]
|
||||
channel = slack_client.conversations_info(channel=channel_id)["channel"]
|
||||
|
||||
slack_team_identity.cached_channels.update_or_create(
|
||||
slack_id=channel["id"],
|
||||
|
|
|
|||
|
|
@ -46,11 +46,7 @@ class StartManageResponders(AlertGroupActionsMixin, scenario_step.ScenarioStep):
|
|||
return
|
||||
|
||||
view = render_dialog(alert_group)
|
||||
self._slack_client.api_call(
|
||||
"views.open",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
)
|
||||
self._slack_client.views_open(trigger_id=payload["trigger_id"], view=view)
|
||||
|
||||
|
||||
class ManageRespondersUserChange(scenario_step.ScenarioStep):
|
||||
|
|
@ -77,11 +73,7 @@ class ManageRespondersUserChange(scenario_step.ScenarioStep):
|
|||
ManageRespondersConfirmUserChange.routing_uid(),
|
||||
json.dumps({USER_DATA_KEY: selected_user.id, ALERT_GROUP_DATA_KEY: alert_group.pk}),
|
||||
)
|
||||
self._slack_client.api_call(
|
||||
"views.push",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
)
|
||||
self._slack_client.views_push(trigger_id=payload["trigger_id"], view=view)
|
||||
else:
|
||||
try:
|
||||
# no warnings, proceed with paging
|
||||
|
|
@ -96,8 +88,7 @@ class ManageRespondersUserChange(scenario_step.ScenarioStep):
|
|||
except DirectPagingAlertGroupResolvedError:
|
||||
view = render_dialog(alert_group, alert_group_resolved_warning=True)
|
||||
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
self._slack_client.views_update(
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["id"],
|
||||
|
|
@ -129,8 +120,7 @@ class ManageRespondersConfirmUserChange(scenario_step.ScenarioStep):
|
|||
except DirectPagingAlertGroupResolvedError:
|
||||
view = render_dialog(alert_group, alert_group_resolved_warning=True)
|
||||
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
self._slack_client.views_update(
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["previous_view_id"],
|
||||
|
|
@ -162,8 +152,7 @@ class ManageRespondersScheduleChange(scenario_step.ScenarioStep):
|
|||
except DirectPagingAlertGroupResolvedError:
|
||||
view = render_dialog(alert_group, alert_group_resolved_warning=True)
|
||||
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
self._slack_client.views_update(
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["id"],
|
||||
|
|
@ -185,8 +174,7 @@ class ManageRespondersRemoveUser(scenario_step.ScenarioStep):
|
|||
|
||||
unpage_user(alert_group, selected_user, from_user)
|
||||
view = render_dialog(alert_group)
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
self._slack_client.views_update(
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["id"],
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ from uuid import uuid4
|
|||
from django.conf import settings
|
||||
|
||||
from apps.alerts.models import AlertReceiveChannel, ChannelFilter
|
||||
from apps.slack.client import SlackAPIException
|
||||
from apps.slack.constants import DIVIDER
|
||||
from apps.slack.scenarios import scenario_step
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException
|
||||
from apps.slack.types import (
|
||||
Block,
|
||||
BlockActionType,
|
||||
|
|
@ -68,11 +68,7 @@ class StartCreateIncidentFromSlashCommand(scenario_step.ScenarioStep):
|
|||
FinishCreateIncidentFromSlashCommand.routing_uid(), blocks, json.dumps(private_metadata)
|
||||
)
|
||||
|
||||
self._slack_client.api_call(
|
||||
"views.open",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
)
|
||||
self._slack_client.views_open(trigger_id=payload["trigger_id"], view=view)
|
||||
|
||||
|
||||
class FinishCreateIncidentFromSlashCommand(scenario_step.ScenarioStep):
|
||||
|
|
@ -115,16 +111,14 @@ class FinishCreateIncidentFromSlashCommand(scenario_step.ScenarioStep):
|
|||
author_username = slack_user_identity.slack_verbal
|
||||
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"chat.postEphemeral",
|
||||
self._slack_client.chat_postEphemeral(
|
||||
channel=channel_id,
|
||||
user=slack_user_identity.slack_id,
|
||||
text=":white_check_mark: Alert *{}* successfully submitted".format(title),
|
||||
)
|
||||
except SlackAPIException as e:
|
||||
if e.response["error"] == "channel_not_found":
|
||||
self._slack_client.api_call(
|
||||
"chat.postEphemeral",
|
||||
self._slack_client.chat_postEphemeral(
|
||||
channel=slack_user_identity.im_channel_id,
|
||||
user=slack_user_identity.slack_id,
|
||||
text=":white_check_mark: Alert *{}* successfully submitted".format(title),
|
||||
|
|
@ -201,8 +195,7 @@ class OnOrgChange(scenario_step.ScenarioStep):
|
|||
if with_title_and_message_inputs:
|
||||
blocks.extend([_get_title_input(payload), _get_message_input(payload)])
|
||||
view = _get_manual_incident_form_view(submit_routing_uid, blocks, json.dumps(new_private_metadata))
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
self._slack_client.views_update(
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["id"],
|
||||
|
|
@ -249,8 +242,7 @@ class OnTeamChange(scenario_step.ScenarioStep):
|
|||
if with_title_and_message_inputs:
|
||||
blocks.extend([_get_title_input(payload), _get_message_input(payload)])
|
||||
view = _get_manual_incident_form_view(submit_routing_uid, blocks, json.dumps(new_private_metadata))
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
self._slack_client.views_update(
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["id"],
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import typing
|
||||
|
||||
from apps.slack.client import SlackAPIException, SlackAPITokenException
|
||||
from apps.slack.scenarios import scenario_step
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException, SlackAPITokenException
|
||||
from apps.slack.types import Block
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
|
|
@ -72,8 +72,7 @@ class NotificationDeliveryStep(scenario_step.ScenarioStep):
|
|||
]
|
||||
try:
|
||||
# TODO: slack-onprem, check exceptions
|
||||
self._slack_client.api_call(
|
||||
"chat.postMessage",
|
||||
self._slack_client.chat_postMessage(
|
||||
channel=channel,
|
||||
text=text,
|
||||
blocks=blocks,
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ from apps.alerts.paging import (
|
|||
check_user_availability,
|
||||
direct_paging,
|
||||
)
|
||||
from apps.slack.client import SlackAPIException
|
||||
from apps.slack.constants import DIVIDER, PRIVATE_METADATA_MAX_LENGTH
|
||||
from apps.slack.scenarios import scenario_step
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException
|
||||
from apps.slack.types import (
|
||||
Block,
|
||||
BlockActionType,
|
||||
|
|
@ -147,8 +147,7 @@ class StartDirectPaging(scenario_step.ScenarioStep):
|
|||
}
|
||||
initial_payload = {"view": {"private_metadata": json.dumps(private_metadata)}}
|
||||
view = render_dialog(slack_user_identity, slack_team_identity, initial_payload, initial=True)
|
||||
self._slack_client.api_call(
|
||||
"views.open",
|
||||
self._slack_client.views_open(
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
)
|
||||
|
|
@ -203,16 +202,14 @@ class FinishDirectPaging(scenario_step.ScenarioStep):
|
|||
text = ":white_check_mark: Alert group *{}* created: {}".format(title, alert_group.web_link)
|
||||
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"chat.postEphemeral",
|
||||
self._slack_client.chat_postEphemeral(
|
||||
channel=channel_id,
|
||||
user=slack_user_identity.slack_id,
|
||||
text=text,
|
||||
)
|
||||
except SlackAPIException as e:
|
||||
if e.response["error"] == "channel_not_found":
|
||||
self._slack_client.api_call(
|
||||
"chat.postEphemeral",
|
||||
self._slack_client.chat_postEphemeral(
|
||||
channel=slack_user_identity.im_channel_id,
|
||||
user=slack_user_identity.slack_id,
|
||||
text=text,
|
||||
|
|
@ -235,8 +232,7 @@ class OnPagingOrgChange(scenario_step.ScenarioStep):
|
|||
) -> None:
|
||||
updated_payload = reset_items(payload)
|
||||
view = render_dialog(slack_user_identity, slack_team_identity, updated_payload)
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
self._slack_client.views_update(
|
||||
trigger_id=updated_payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=updated_payload["view"]["id"],
|
||||
|
|
@ -253,8 +249,7 @@ class OnPagingTeamChange(scenario_step.ScenarioStep):
|
|||
payload: EventPayload,
|
||||
) -> None:
|
||||
view = render_dialog(slack_user_identity, slack_team_identity, payload)
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
self._slack_client.views_update(
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["id"],
|
||||
|
|
@ -290,11 +285,7 @@ class OnPagingUserChange(scenario_step.ScenarioStep):
|
|||
if availability_warnings:
|
||||
# display warnings and require additional confirmation
|
||||
view = _display_availability_warnings(payload, availability_warnings, selected_organization, selected_user)
|
||||
self._slack_client.api_call(
|
||||
"views.push",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
)
|
||||
self._slack_client.views_push(trigger_id=payload["trigger_id"], view=view)
|
||||
else:
|
||||
# user is available to be paged
|
||||
error_msg = None
|
||||
|
|
@ -304,8 +295,7 @@ class OnPagingUserChange(scenario_step.ScenarioStep):
|
|||
updated_payload = payload
|
||||
error_msg = "Cannot add user, maximum responders exceeded"
|
||||
view = render_dialog(slack_user_identity, slack_team_identity, updated_payload, error_msg=error_msg)
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
self._slack_client.views_update(
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["id"],
|
||||
|
|
@ -338,12 +328,7 @@ class OnPagingItemActionChange(scenario_step.ScenarioStep):
|
|||
error_msg = "Cannot update policy, maximum responders exceeded"
|
||||
|
||||
view = render_dialog(slack_user_identity, slack_team_identity, updated_payload, error_msg=error_msg)
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["id"],
|
||||
)
|
||||
self._slack_client.views_update(trigger_id=payload["trigger_id"], view=view, view_id=payload["view"]["id"])
|
||||
|
||||
|
||||
class OnPagingConfirmUserChange(scenario_step.ScenarioStep):
|
||||
|
|
@ -380,8 +365,7 @@ class OnPagingConfirmUserChange(scenario_step.ScenarioStep):
|
|||
updated_payload = payload
|
||||
error_msg = "Cannot add user, maximum responders exceeded"
|
||||
view = render_dialog(slack_user_identity, slack_team_identity, updated_payload, error_msg=error_msg)
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
self._slack_client.views_update(
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["previous_view_id"],
|
||||
|
|
@ -412,12 +396,7 @@ class OnPagingScheduleChange(scenario_step.ScenarioStep):
|
|||
updated_payload = payload
|
||||
error_msg = "Cannot add schedule, maximum responders exceeded"
|
||||
view = render_dialog(slack_user_identity, slack_team_identity, updated_payload, error_msg=error_msg)
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["id"],
|
||||
)
|
||||
self._slack_client.views_update(trigger_id=payload["trigger_id"], view=view, view_id=payload["view"]["id"])
|
||||
|
||||
|
||||
# slack view/blocks rendering helpers
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import typing
|
|||
from django.db.models import Q
|
||||
|
||||
from apps.api.permissions import RBACPermission
|
||||
from apps.slack.client import SlackAPIException
|
||||
from apps.slack.constants import DIVIDER
|
||||
from apps.slack.scenarios import scenario_step
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException
|
||||
from apps.slack.types import (
|
||||
Block,
|
||||
BlockActionType,
|
||||
|
|
@ -69,7 +69,7 @@ class AddToResolutionNoteStep(scenario_step.ScenarioStep):
|
|||
alert_group = slack_message.alert_group
|
||||
if not alert_group:
|
||||
self.open_warning_window(payload, warning_text)
|
||||
print(
|
||||
logger.exception(
|
||||
f"Exception: tried to add message from thread to Resolution Note: "
|
||||
f"Slack Team Identity pk: {self.slack_team_identity.pk}, "
|
||||
f"Slack Message id: {slack_message.slack_id}"
|
||||
|
|
@ -80,11 +80,7 @@ class AddToResolutionNoteStep(scenario_step.ScenarioStep):
|
|||
message_ts = payload["message_ts"]
|
||||
thread_ts = payload["message"]["thread_ts"]
|
||||
|
||||
result = self._slack_client.api_call(
|
||||
"chat.getPermalink",
|
||||
channel=channel_id,
|
||||
message_ts=message_ts,
|
||||
)
|
||||
result = self._slack_client.chat_getPermalink(channel=channel_id, message_ts=message_ts)
|
||||
permalink = None
|
||||
if result["permalink"] is not None:
|
||||
permalink = result["permalink"]
|
||||
|
|
@ -155,8 +151,7 @@ class AddToResolutionNoteStep(scenario_step.ScenarioStep):
|
|||
else:
|
||||
resolution_note.recreate()
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"reactions.add",
|
||||
self._slack_client.reactions_add(
|
||||
channel=channel_id,
|
||||
name="memo",
|
||||
timestamp=resolution_note_slack_message.ts,
|
||||
|
|
@ -189,8 +184,7 @@ class UpdateResolutionNoteStep(scenario_step.ScenarioStep):
|
|||
resolution_note_slack_message.save(update_fields=["added_to_resolution_note"])
|
||||
if resolution_note_slack_message.posted_by_bot:
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"chat.delete",
|
||||
self._slack_client.chat_delete(
|
||||
channel=resolution_note_slack_message.slack_channel_id,
|
||||
ts=resolution_note_slack_message.ts,
|
||||
)
|
||||
|
|
@ -240,8 +234,7 @@ class UpdateResolutionNoteStep(scenario_step.ScenarioStep):
|
|||
|
||||
if resolution_note_slack_message is None:
|
||||
try:
|
||||
result = self._slack_client.api_call(
|
||||
"chat.postMessage",
|
||||
result = self._slack_client.chat_postMessage(
|
||||
channel=alert_group_slack_message.channel_id,
|
||||
thread_ts=alert_group_slack_message.slack_id,
|
||||
text=resolution_note.text,
|
||||
|
|
@ -270,8 +263,7 @@ class UpdateResolutionNoteStep(scenario_step.ScenarioStep):
|
|||
raise e
|
||||
else:
|
||||
message_ts = result["message"]["ts"]
|
||||
result_permalink = self._slack_client.api_call(
|
||||
"chat.getPermalink",
|
||||
result_permalink = self._slack_client.chat_getPermalink(
|
||||
channel=alert_group_slack_message.channel_id,
|
||||
message_ts=message_ts,
|
||||
)
|
||||
|
|
@ -295,8 +287,7 @@ class UpdateResolutionNoteStep(scenario_step.ScenarioStep):
|
|||
resolution_note.save(update_fields=["resolution_note_slack_message"])
|
||||
elif resolution_note_slack_message.posted_by_bot:
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"chat.update",
|
||||
self._slack_client.chat_update(
|
||||
channel=alert_group_slack_message.channel_id,
|
||||
ts=resolution_note_slack_message.ts,
|
||||
text=resolution_note_slack_message.text,
|
||||
|
|
@ -345,25 +336,23 @@ class UpdateResolutionNoteStep(scenario_step.ScenarioStep):
|
|||
|
||||
def add_resolution_note_reaction(self, slack_thread_message: "ResolutionNoteSlackMessage"):
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"reactions.add",
|
||||
self._slack_client.reactions_add(
|
||||
channel=slack_thread_message.slack_channel_id,
|
||||
name="memo",
|
||||
timestamp=slack_thread_message.ts,
|
||||
)
|
||||
except SlackAPIException as e:
|
||||
print(e) # TODO:770: log instead of print
|
||||
logger.exception(e)
|
||||
|
||||
def remove_resolution_note_reaction(self, slack_thread_message: "ResolutionNoteSlackMessage") -> None:
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"reactions.remove",
|
||||
self._slack_client.reactions_remove(
|
||||
channel=slack_thread_message.slack_channel_id,
|
||||
name="memo",
|
||||
timestamp=slack_thread_message.ts,
|
||||
)
|
||||
except SlackAPIException as e:
|
||||
print(e)
|
||||
logger.exception(e)
|
||||
|
||||
def get_resolution_note_blocks(self, resolution_note: "ResolutionNote") -> Block.AnyBlocks:
|
||||
blocks: Block.AnyBlocks = []
|
||||
|
|
@ -453,8 +442,7 @@ class ResolutionNoteModalStep(AlertGroupActionsMixin, scenario_step.ScenarioStep
|
|||
|
||||
if "update" in resolution_note_window_action:
|
||||
try:
|
||||
self._slack_client.api_call(
|
||||
"views.update",
|
||||
self._slack_client.views_update(
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
view_id=payload["view"]["id"],
|
||||
|
|
@ -470,11 +458,7 @@ class ResolutionNoteModalStep(AlertGroupActionsMixin, scenario_step.ScenarioStep
|
|||
else:
|
||||
raise
|
||||
else:
|
||||
self._slack_client.api_call(
|
||||
"views.open",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
)
|
||||
self._slack_client.views_open(trigger_id=payload["trigger_id"], view=view)
|
||||
|
||||
def get_resolution_notes_blocks(
|
||||
self, alert_group: "AlertGroup", resolution_note_window_action: str, action_resolve: bool
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import logging
|
|||
import typing
|
||||
|
||||
from apps.slack.alert_group_slack_service import AlertGroupSlackService
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.client import SlackClientWithErrorHandling
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from apps.slack.models import SlackTeamIdentity, SlackUserIdentity
|
||||
|
|
@ -77,8 +77,4 @@ class ScenarioStep(object):
|
|||
},
|
||||
],
|
||||
}
|
||||
self._slack_client.api_call(
|
||||
"views.open",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
)
|
||||
self._slack_client.views_open(trigger_id=payload["trigger_id"], view=view)
|
||||
|
|
|
|||
|
|
@ -61,11 +61,7 @@ class EditScheduleShiftNotifyStep(scenario_step.ScenarioStep):
|
|||
"private_metadata": json.dumps(private_metadata),
|
||||
}
|
||||
|
||||
self._slack_client.api_call(
|
||||
"views.open",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
)
|
||||
self._slack_client.views_open(trigger_id=payload["trigger_id"], view=view)
|
||||
|
||||
def set_selected_value(self, slack_user_identity: "SlackUserIdentity", payload: EventPayload) -> None:
|
||||
action = payload["actions"][0]
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ class BaseShiftSwapRequestStep(scenario_step.ScenarioStep):
|
|||
organization = self.organization
|
||||
|
||||
blocks = self._generate_blocks(shift_swap_request)
|
||||
result = self._slack_client.api_call("chat.postMessage", channel=channel_id, blocks=blocks)
|
||||
result = self._slack_client.chat_postMessage(channel=channel_id, blocks=blocks)
|
||||
|
||||
return SlackMessage.objects.create(
|
||||
slack_id=result["ts"],
|
||||
|
|
@ -166,9 +166,7 @@ class BaseShiftSwapRequestStep(scenario_step.ScenarioStep):
|
|||
)
|
||||
|
||||
def update_message(self, shift_swap_request: "ShiftSwapRequest") -> None:
|
||||
# TODO: better error handling here...
|
||||
self._slack_client.api_call(
|
||||
"chat.update",
|
||||
self._slack_client.chat_update(
|
||||
channel=shift_swap_request.slack_channel_id,
|
||||
ts=shift_swap_request.slack_message.slack_id,
|
||||
blocks=self._generate_blocks(shift_swap_request),
|
||||
|
|
@ -229,8 +227,7 @@ class ShiftSwapRequestFollowUp(scenario_step.ScenarioStep):
|
|||
]
|
||||
|
||||
def post_message(self, shift_swap_request: "ShiftSwapRequest") -> None:
|
||||
self._slack_client.api_call(
|
||||
"chat.postMessage",
|
||||
self._slack_client.chat_postMessage(
|
||||
channel=shift_swap_request.slack_message.channel_id,
|
||||
thread_ts=shift_swap_request.slack_message.slack_id,
|
||||
reply_broadcast=True,
|
||||
|
|
|
|||
|
|
@ -75,18 +75,13 @@ class SlackChannelMessageEventStep(scenario_step.ScenarioStep):
|
|||
# SlackMessage instances without alert_group set (e.g., SSR Slack messages)
|
||||
return
|
||||
|
||||
result = self._slack_client.api_call(
|
||||
"chat.getPermalink",
|
||||
channel=channel,
|
||||
message_ts=message_ts,
|
||||
)
|
||||
result = self._slack_client.chat_getPermalink(channel=channel, message_ts=message_ts)
|
||||
permalink = None
|
||||
if result["permalink"] is not None:
|
||||
permalink = result["permalink"]
|
||||
|
||||
if len(text) > 2900:
|
||||
self._slack_client.api_call(
|
||||
"chat.postEphemeral",
|
||||
self._slack_client.chat_postEphemeral(
|
||||
channel=channel,
|
||||
user=slack_user_identity.slack_id,
|
||||
text=":warning: Unable to show the <{}|message> in Resolution Note: the message is too long ({}). "
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
from .slack_client import SlackClientWithErrorHandling # noqa: F401
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
class SlackAPIException(Exception):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.response = {}
|
||||
if "response" in kwargs:
|
||||
self.response = kwargs["response"]
|
||||
super().__init__(*args)
|
||||
|
||||
|
||||
class SlackAPITokenException(SlackAPIException):
|
||||
pass
|
||||
|
||||
|
||||
class SlackAPIChannelArchivedException(SlackAPIException):
|
||||
pass
|
||||
|
||||
|
||||
class SlackAPIRateLimitException(SlackAPIException):
|
||||
pass
|
||||
|
||||
|
||||
class SlackClientException(Exception):
|
||||
pass
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
import json
|
||||
|
||||
from slackclient.server import Server
|
||||
|
||||
from .exceptions import SlackClientException
|
||||
|
||||
|
||||
class SlackClientServer(Server):
|
||||
def api_call(self, token, request="?", timeout=None, **kwargs):
|
||||
"""
|
||||
This method is rewritten because we want to handle JSONDecodeError and add more information about response
|
||||
"""
|
||||
response = self.api_requester.do(token, request, kwargs, timeout=timeout)
|
||||
response_json = {"headers": dict(response.headers)}
|
||||
resp_text = response.text
|
||||
try:
|
||||
response_json.update(json.loads(resp_text))
|
||||
except json.JSONDecodeError:
|
||||
response_json["response_text"] = resp_text
|
||||
exception_text = (
|
||||
f"Slack API Call Error: unexpected response from Slack \n"
|
||||
f"Status: {response.status_code}\nArgs: ('{request}',) \nKwargs: {kwargs} \n"
|
||||
f"Response: {response_json}"
|
||||
)
|
||||
raise SlackClientException(exception_text)
|
||||
return json.dumps(response_json)
|
||||
|
|
@ -10,10 +10,9 @@ from django.utils import timezone
|
|||
|
||||
from apps.alerts.tasks.compare_escalations import compare_escalations
|
||||
from apps.slack.alert_group_slack_service import AlertGroupSlackService
|
||||
from apps.slack.client import SlackAPIException, SlackAPITokenException, SlackClientWithErrorHandling
|
||||
from apps.slack.constants import CACHE_UPDATE_INCIDENT_SLACK_MESSAGE_LIFETIME, SLACK_BOT_ID
|
||||
from apps.slack.scenarios.scenario_step import ScenarioStep
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException, SlackAPITokenException
|
||||
from apps.slack.utils import (
|
||||
get_cache_key_update_incident_slack_message,
|
||||
get_populate_slack_channel_task_id_key,
|
||||
|
|
@ -371,9 +370,7 @@ def populate_slack_usergroups_for_team(slack_team_identity_id):
|
|||
usergroups_list = None
|
||||
bot_access_token_accepted = True
|
||||
try:
|
||||
usergroups_list = sc.api_call(
|
||||
"usergroups.list",
|
||||
)
|
||||
usergroups_list = sc.usergroups_list()
|
||||
except SlackAPITokenException as e:
|
||||
logger.info(f"token revoked\n{e}")
|
||||
except SlackAPIException as e:
|
||||
|
|
@ -382,9 +379,7 @@ def populate_slack_usergroups_for_team(slack_team_identity_id):
|
|||
# Trying same request with access token. It is required due to migration to granular permissions
|
||||
# and can be removed after clients reinstall their bots
|
||||
sc_with_access_token = SlackClientWithErrorHandling(slack_team_identity.access_token)
|
||||
usergroups_list = sc_with_access_token.api_call(
|
||||
"usergroups.list",
|
||||
)
|
||||
usergroups_list = sc_with_access_token.usergroups_list()
|
||||
bot_access_token_accepted = False
|
||||
except SlackAPIException as err:
|
||||
handle_usergroups_list_slack_api_exception(err)
|
||||
|
|
@ -402,16 +397,10 @@ def populate_slack_usergroups_for_team(slack_team_identity_id):
|
|||
continue
|
||||
try:
|
||||
if bot_access_token_accepted:
|
||||
usergroups_users = sc.api_call(
|
||||
"usergroups.users.list",
|
||||
usergroup=usergroup["id"],
|
||||
)
|
||||
usergroups_users = sc.usergroups_users_list(usergroup=usergroup["id"])
|
||||
else:
|
||||
sc_with_access_token = SlackClientWithErrorHandling(slack_team_identity.access_token)
|
||||
usergroups_users = sc_with_access_token.api_call(
|
||||
"usergroups.users.list",
|
||||
usergroup=usergroup["id"],
|
||||
)
|
||||
usergroups_users = sc_with_access_token.usergroups_users_list(usergroup=usergroup["id"])
|
||||
except SlackAPIException as e:
|
||||
if e.response["error"] == "no_such_subteam":
|
||||
logger.info("User group does not exist")
|
||||
|
|
@ -549,11 +538,13 @@ def populate_slack_channels_for_team(slack_team_identity_id: int, cursor: Option
|
|||
return start_populate_slack_channels_for_team(slack_team_identity_id, delay)
|
||||
try:
|
||||
response, cursor, rate_limited = sc.paginated_api_call_with_ratelimit(
|
||||
"conversations.list",
|
||||
types="public_channel,private_channel",
|
||||
"conversations_list",
|
||||
paginated_key="channels",
|
||||
limit=1000,
|
||||
cursor=cursor,
|
||||
json={
|
||||
"types": "public_channel,private_channel",
|
||||
"limit": 1000,
|
||||
"cursor": cursor,
|
||||
},
|
||||
)
|
||||
except SlackAPITokenException as e:
|
||||
logger.info(f"token revoked\n{e}")
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from unittest.mock import patch
|
|||
import pytest
|
||||
from django.utils import timezone
|
||||
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.client import SlackClientWithErrorHandling
|
||||
from apps.slack.tasks import populate_slack_channels_for_team
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -801,9 +801,14 @@ def test_step_format_alert(
|
|||
assert mock_slack_api_call.call_args.args == ("views.open",)
|
||||
|
||||
|
||||
@patch("apps.slack.models.SlackTeamIdentity.get_conversation_members")
|
||||
@pytest.mark.django_db
|
||||
def test_step_resolution_note(
|
||||
make_organization_and_user_with_slack_identities, make_alert_receive_channel, make_alert_group, make_alert
|
||||
mock_get_conversation_members,
|
||||
make_organization_and_user_with_slack_identities,
|
||||
make_alert_receive_channel,
|
||||
make_alert_group,
|
||||
make_alert,
|
||||
):
|
||||
organization, user, slack_team_identity, slack_user_identity = make_organization_and_user_with_slack_identities()
|
||||
|
||||
|
|
@ -811,6 +816,7 @@ def test_step_resolution_note(
|
|||
alert_group = make_alert_group(alert_receive_channel)
|
||||
make_alert(alert_group, raw_request_data={})
|
||||
|
||||
channel_id = "RANDOM_CHANNEL_ID"
|
||||
payload = {
|
||||
"trigger_id": "RANDOM_TRIGGER_ID",
|
||||
"actions": [
|
||||
|
|
@ -825,14 +831,15 @@ def test_step_resolution_note(
|
|||
),
|
||||
}
|
||||
],
|
||||
"channel": {"id": "RANDOM_CHANNEL_ID"},
|
||||
"channel": {"id": channel_id},
|
||||
"message": {"ts": "RANDOM_MESSAGE_TS"},
|
||||
}
|
||||
|
||||
step_class = ScenarioStep.get_step("resolution_note", "ResolutionNoteModalStep")
|
||||
step = step_class(organization=organization, user=user, slack_team_identity=slack_team_identity)
|
||||
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_open") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.open",)
|
||||
mock_slack_api_call.assert_called_once()
|
||||
mock_get_conversation_members.assert_called_once_with(step._slack_client, channel_id)
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ from unittest.mock import patch
|
|||
import pytest
|
||||
|
||||
from apps.alerts.models import AlertGroup
|
||||
from apps.slack.client import SlackAPIException
|
||||
from apps.slack.models import SlackMessage
|
||||
from apps.slack.scenarios.scenario_step import ScenarioStep
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
|
|
|||
|
|
@ -94,10 +94,9 @@ def test_initial_state(manage_responders_setup):
|
|||
organization, user, slack_team_identity, slack_user_identity = manage_responders_setup
|
||||
|
||||
step = StartManageResponders(slack_team_identity, organization, user)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_open") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.open",)
|
||||
metadata = json.loads(mock_slack_api_call.call_args.kwargs["view"]["private_metadata"])
|
||||
assert metadata[ALERT_GROUP_DATA_KEY] == ALERT_GROUP_ID
|
||||
|
||||
|
|
@ -137,11 +136,9 @@ def test_add_user_no_warning(manage_responders_setup, make_schedule, make_on_cal
|
|||
payload = make_slack_payload(user=user)
|
||||
|
||||
step = ManageRespondersUserChange(slack_team_identity, organization, user)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
|
||||
# check there's a delete button for the user
|
||||
assert mock_slack_api_call.call_args.kwargs["view"]["blocks"][0]["accessory"]["value"] == str(user.pk)
|
||||
|
||||
|
|
@ -153,10 +150,9 @@ def test_add_user_raise_warning(manage_responders_setup):
|
|||
payload = make_slack_payload(user=user)
|
||||
|
||||
step = ManageRespondersUserChange(slack_team_identity, organization, user)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_push") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.push",)
|
||||
assert mock_slack_api_call.call_args.kwargs["view"]["callback_id"] == "ManageRespondersConfirmUserChange"
|
||||
text_from_blocks = "".join(
|
||||
b["text"]["text"] for b in mock_slack_api_call.call_args.kwargs["view"]["blocks"] if b["type"] == "section"
|
||||
|
|
@ -188,10 +184,9 @@ def test_add_schedule(manage_responders_setup, make_schedule, make_on_call_shift
|
|||
payload = make_slack_payload(schedule=schedule)
|
||||
|
||||
step = ManageRespondersScheduleChange(slack_team_identity, organization, user)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
assert mock_slack_api_call.call_args.kwargs["view"]["blocks"][0]["accessory"]["value"] == str(user.pk)
|
||||
|
||||
|
||||
|
|
@ -221,10 +216,9 @@ def test_add_schedule_alert_group_resolved(
|
|||
payload = make_slack_payload(schedule=schedule)
|
||||
|
||||
step = ManageRespondersScheduleChange(slack_team_identity, organization, user)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
assert (
|
||||
DirectPagingAlertGroupResolvedError.DETAIL
|
||||
in mock_slack_api_call.call_args.kwargs["view"]["blocks"][0]["text"]["text"]
|
||||
|
|
@ -237,10 +231,9 @@ def test_remove_user(manage_responders_setup):
|
|||
|
||||
payload = make_slack_payload(actions=[{"value": user.pk}])
|
||||
step = ManageRespondersRemoveUser(slack_team_identity, organization, user)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
# check there's no list of users in the view
|
||||
assert mock_slack_api_call.call_args.kwargs["view"]["blocks"][0]["accessory"]["type"] != "button"
|
||||
|
||||
|
|
|
|||
|
|
@ -89,14 +89,13 @@ def make_slack_payload(
|
|||
def test_initial_state(
|
||||
make_organization_and_user_with_slack_identities,
|
||||
):
|
||||
organization, user, slack_team_identity, slack_user_identity = make_organization_and_user_with_slack_identities()
|
||||
_, _, slack_team_identity, slack_user_identity = make_organization_and_user_with_slack_identities()
|
||||
payload = {"channel_id": "123", "trigger_id": "111"}
|
||||
|
||||
step = StartDirectPaging(slack_team_identity)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_open") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.open",)
|
||||
metadata = json.loads(mock_slack_api_call.call_args.kwargs["view"]["private_metadata"])
|
||||
assert metadata[DataKey.USERS] == {}
|
||||
assert metadata[DataKey.SCHEDULES] == {}
|
||||
|
|
@ -138,10 +137,9 @@ def test_add_user_no_warning(
|
|||
payload = make_slack_payload(organization=organization, user=user)
|
||||
|
||||
step = OnPagingUserChange(slack_team_identity)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
metadata = json.loads(mock_slack_api_call.call_args.kwargs["view"]["private_metadata"])
|
||||
assert metadata[DataKey.USERS] == {str(user.pk): Policy.DEFAULT}
|
||||
|
||||
|
|
@ -183,10 +181,9 @@ def test_add_user_maximum_exceeded(
|
|||
|
||||
step = OnPagingUserChange(slack_team_identity)
|
||||
with patch("apps.slack.scenarios.paging.PRIVATE_METADATA_MAX_LENGTH", 100):
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
view_data = mock_slack_api_call.call_args.kwargs["view"]
|
||||
metadata = json.loads(view_data["private_metadata"])
|
||||
# metadata unchanged, ignoring the prefix
|
||||
|
|
@ -210,10 +207,9 @@ def test_add_user_raise_warning(make_organization_and_user_with_slack_identities
|
|||
payload = make_slack_payload(organization=organization, user=user)
|
||||
|
||||
step = OnPagingUserChange(slack_team_identity)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_push") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.push",)
|
||||
assert mock_slack_api_call.call_args.kwargs["view"]["callback_id"] == "OnPagingConfirmUserChange"
|
||||
text_from_blocks = "".join(
|
||||
b["text"]["text"] for b in mock_slack_api_call.call_args.kwargs["view"]["blocks"] if b["type"] == "section"
|
||||
|
|
@ -232,10 +228,9 @@ def test_change_user_policy(make_organization_and_user_with_slack_identities):
|
|||
)
|
||||
|
||||
step = OnPagingItemActionChange(slack_team_identity)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
metadata = json.loads(mock_slack_api_call.call_args.kwargs["view"]["private_metadata"])
|
||||
assert metadata[DataKey.USERS] == {str(user.pk): Policy.IMPORTANT}
|
||||
|
||||
|
|
@ -249,10 +244,9 @@ def test_remove_user(make_organization_and_user_with_slack_identities):
|
|||
)
|
||||
|
||||
step = OnPagingItemActionChange(slack_team_identity)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
metadata = json.loads(mock_slack_api_call.call_args.kwargs["view"]["private_metadata"])
|
||||
assert metadata[DataKey.USERS] == {}
|
||||
|
||||
|
|
@ -324,10 +318,9 @@ def test_add_schedule(make_organization_and_user_with_slack_identities, make_sch
|
|||
)
|
||||
|
||||
step = OnPagingScheduleChange(slack_team_identity)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
metadata = json.loads(mock_slack_api_call.call_args.kwargs["view"]["private_metadata"])
|
||||
assert metadata[DataKey.SCHEDULES] == {str(schedule.pk): Policy.DEFAULT}
|
||||
assert metadata[DataKey.USERS] == {str(user.pk): Policy.IMPORTANT}
|
||||
|
|
@ -345,10 +338,9 @@ def test_add_schedule_responders_exceeded(make_organization_and_user_with_slack_
|
|||
|
||||
step = OnPagingScheduleChange(slack_team_identity)
|
||||
with patch("apps.slack.scenarios.paging.PRIVATE_METADATA_MAX_LENGTH", 100):
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
view_data = mock_slack_api_call.call_args.kwargs["view"]
|
||||
metadata = json.loads(view_data["private_metadata"])
|
||||
# metadata unchanged, ignoring the prefix
|
||||
|
|
@ -376,10 +368,9 @@ def test_change_schedule_policy(make_organization_and_user_with_slack_identities
|
|||
)
|
||||
|
||||
step = OnPagingItemActionChange(slack_team_identity)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
metadata = json.loads(mock_slack_api_call.call_args.kwargs["view"]["private_metadata"])
|
||||
assert metadata[DataKey.SCHEDULES] == {str(schedule.pk): Policy.IMPORTANT}
|
||||
assert metadata[DataKey.USERS] == {str(user.pk): Policy.DEFAULT}
|
||||
|
|
@ -396,10 +387,9 @@ def test_remove_schedule(make_organization_and_user_with_slack_identities, make_
|
|||
)
|
||||
|
||||
step = OnPagingItemActionChange(slack_team_identity)
|
||||
with patch.object(step._slack_client, "api_call") as mock_slack_api_call:
|
||||
with patch.object(step._slack_client, "views_update") as mock_slack_api_call:
|
||||
step.process_scenario(slack_user_identity, slack_team_identity, payload)
|
||||
|
||||
assert mock_slack_api_call.call_args.args == ("views.update",)
|
||||
metadata = json.loads(mock_slack_api_call.call_args.kwargs["view"]["private_metadata"])
|
||||
assert metadata[DataKey.SCHEDULES] == {}
|
||||
assert metadata[DataKey.USERS] == {str(user.pk): Policy.DEFAULT}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ from unittest.mock import patch
|
|||
|
||||
import pytest
|
||||
|
||||
from apps.slack.client import SlackAPIException, SlackClientWithErrorHandling
|
||||
from apps.slack.scenarios.scenario_step import ScenarioStep
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException
|
||||
from common.api_helpers.utils import create_engine_url
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -146,13 +146,13 @@ class TestBaseShiftSwapRequestStep:
|
|||
step = scenarios.BaseShiftSwapRequestStep(slack_team_identity, organization)
|
||||
|
||||
with patch.object(step, "_slack_client") as mock_slack_client:
|
||||
mock_slack_client.api_call.return_value = {"ts": ts}
|
||||
mock_slack_client.chat_postMessage.return_value = {"ts": ts}
|
||||
|
||||
slack_message = step.create_message(ssr)
|
||||
|
||||
mock_generate_blocks.assert_called_once_with(ssr)
|
||||
mock_slack_client.api_call.assert_called_once_with(
|
||||
"chat.postMessage", channel=ssr.slack_channel_id, blocks=mock_generate_blocks.return_value
|
||||
mock_slack_client.chat_postMessage.assert_called_once_with(
|
||||
channel=ssr.slack_channel_id, blocks=mock_generate_blocks.return_value
|
||||
)
|
||||
|
||||
assert slack_message.slack_id == ts
|
||||
|
|
@ -179,8 +179,8 @@ class TestBaseShiftSwapRequestStep:
|
|||
step.update_message(ssr)
|
||||
|
||||
mock_generate_blocks.assert_called_once_with(ssr)
|
||||
mock_slack_client.api_call.assert_called_once_with(
|
||||
"chat.update", channel=ssr.slack_channel_id, ts=ts, blocks=mock_generate_blocks.return_value
|
||||
mock_slack_client.chat_update.assert_called_once_with(
|
||||
channel=ssr.slack_channel_id, ts=ts, blocks=mock_generate_blocks.return_value
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from unittest.mock import Mock, call, patch
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
@ -237,7 +237,7 @@ class TestSlackChannelMessageEventStep:
|
|||
|
||||
step = SlackChannelMessageEventStep(slack_team_identity, organization, user)
|
||||
step._slack_client = Mock()
|
||||
step._slack_client.api_call.side_effect = [{"permalink": mock_permalink}, None]
|
||||
step._slack_client.chat_getPermalink.return_value = {"permalink": mock_permalink}
|
||||
|
||||
payload = {
|
||||
"event": {
|
||||
|
|
@ -250,21 +250,15 @@ class TestSlackChannelMessageEventStep:
|
|||
|
||||
step.save_thread_message_for_resolution_note(slack_user_identity, payload)
|
||||
|
||||
step._slack_client.api_call.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
"chat.getPermalink",
|
||||
channel=payload["event"]["channel"],
|
||||
message_ts=payload["event"]["ts"],
|
||||
),
|
||||
call(
|
||||
"chat.postEphemeral",
|
||||
channel=payload["event"]["channel"],
|
||||
user=slack_user_identity.slack_id,
|
||||
text=":warning: Unable to show the <{}|message> in Resolution Note: the message is too long ({}). "
|
||||
"Max length - 2900 symbols.".format(mock_permalink, len(payload["event"]["text"])),
|
||||
),
|
||||
]
|
||||
step._slack_client.chat_getPermalink.assert_called_once_with(
|
||||
channel=payload["event"]["channel"],
|
||||
message_ts=payload["event"]["ts"],
|
||||
)
|
||||
step._slack_client.chat_postEphemeral.assert_called_once_with(
|
||||
channel=payload["event"]["channel"],
|
||||
user=slack_user_identity.slack_id,
|
||||
text=":warning: Unable to show the <{}|message> in Resolution Note: the message is too long ({}). "
|
||||
"Max length - 2900 symbols.".format(mock_permalink, len(payload["event"]["text"])),
|
||||
)
|
||||
MockResolutionNoteSlackMessage.objects.get_or_create.assert_not_called()
|
||||
|
||||
|
|
@ -306,7 +300,7 @@ class TestSlackChannelMessageEventStep:
|
|||
|
||||
step = SlackChannelMessageEventStep(slack_team_identity, organization, user)
|
||||
step._slack_client = Mock()
|
||||
step._slack_client.api_call.side_effect = [{"permalink": mock_permalink}, None]
|
||||
step._slack_client.chat_getPermalink.side_effect = [{"permalink": mock_permalink}, None]
|
||||
|
||||
payload = {
|
||||
"event": {
|
||||
|
|
@ -319,14 +313,9 @@ class TestSlackChannelMessageEventStep:
|
|||
|
||||
step.save_thread_message_for_resolution_note(slack_user_identity, payload)
|
||||
|
||||
step._slack_client.api_call.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
"chat.getPermalink",
|
||||
channel=payload["event"]["channel"],
|
||||
message_ts=payload["event"]["ts"],
|
||||
),
|
||||
]
|
||||
step._slack_client.chat_getPermalink.assert_called_once_with(
|
||||
channel=payload["event"]["channel"],
|
||||
message_ts=payload["event"]["ts"],
|
||||
)
|
||||
|
||||
if resolution_note_slack_message_already_exists:
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ from unittest.mock import PropertyMock, patch
|
|||
import pytest
|
||||
|
||||
from apps.schedules.models.on_call_schedule import OnCallScheduleQuerySet
|
||||
from apps.slack.client import SlackClientWithErrorHandling
|
||||
from apps.slack.models import SlackUserGroup
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import enum
|
|||
import typing
|
||||
from datetime import datetime
|
||||
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException
|
||||
from apps.slack.client import SlackAPIException, SlackClientWithErrorHandling
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from apps.user_management.models import Organization
|
||||
|
|
@ -65,7 +64,7 @@ def post_message_to_channel(organization: "Organization", channel_id: str, text:
|
|||
if organization.slack_team_identity:
|
||||
slack_client = SlackClientWithErrorHandling(organization.slack_team_identity.bot_access_token)
|
||||
try:
|
||||
slack_client.api_call("chat.postMessage", channel=channel_id, text=text)
|
||||
slack_client.chat_postMessage(channel=channel_id, text=text)
|
||||
except SlackAPIException as e:
|
||||
if e.response["error"] == "channel_not_found":
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from rest_framework.views import APIView
|
|||
from apps.api.permissions import RBACPermission
|
||||
from apps.auth_token.auth import PluginAuthentication
|
||||
from apps.base.utils import live_settings
|
||||
from apps.slack.client import SlackAPIException, SlackAPITokenException, SlackClientWithErrorHandling
|
||||
from apps.slack.scenarios.alertgroup_appearance import STEPS_ROUTING as ALERTGROUP_APPEARANCE_ROUTING
|
||||
|
||||
# Importing routes from scenarios
|
||||
|
|
@ -34,8 +35,6 @@ from apps.slack.scenarios.shift_swap_requests import STEPS_ROUTING as SHIFT_SWAP
|
|||
from apps.slack.scenarios.slack_channel import STEPS_ROUTING as CHANNEL_ROUTING
|
||||
from apps.slack.scenarios.slack_channel_integration import STEPS_ROUTING as SLACK_CHANNEL_INTEGRATION_ROUTING
|
||||
from apps.slack.scenarios.slack_usergroup import STEPS_ROUTING as SLACK_USERGROUP_UPDATE_ROUTING
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.slack_client.exceptions import SlackAPIException, SlackAPITokenException
|
||||
from apps.slack.tasks import clean_slack_integration_leftovers, unpopulate_slack_user_identities
|
||||
from apps.slack.types import EventPayload, EventType, MessageEventSubtype, PayloadType, ScenarioRoute
|
||||
from apps.user_management.models import Organization
|
||||
|
|
@ -195,10 +194,7 @@ class SlackEventApiEndpointView(APIView):
|
|||
if slack_team_identity.detected_token_revoked is not None:
|
||||
# check if token is still invalid
|
||||
try:
|
||||
sc.api_call(
|
||||
"auth.test",
|
||||
team=slack_team_identity,
|
||||
)
|
||||
sc.auth_test(team=slack_team_identity)
|
||||
except SlackAPITokenException:
|
||||
logger.info(f"Team {slack_team_identity.slack_id} has revoked token, dropping request.")
|
||||
return Response(status=200)
|
||||
|
|
@ -223,7 +219,7 @@ class SlackEventApiEndpointView(APIView):
|
|||
elif (
|
||||
payload_event_bot_id and slack_team_identity and payload_event_channel_type == EventType.MESSAGE_CHANNEL
|
||||
):
|
||||
response = sc.api_call("bots.info", bot=payload_event_bot_id)
|
||||
response = sc.bots_info(bot=payload_event_bot_id)
|
||||
bot_user_id = response.get("bot", {}).get("user_id", "")
|
||||
|
||||
# Don't react on own bot's messages.
|
||||
|
|
@ -537,11 +533,7 @@ class SlackEventApiEndpointView(APIView):
|
|||
"text": "One more step!",
|
||||
},
|
||||
}
|
||||
slack_client.api_call(
|
||||
"views.open",
|
||||
trigger_id=payload["trigger_id"],
|
||||
view=view,
|
||||
)
|
||||
slack_client.views_open(trigger_id=payload["trigger_id"], view=view)
|
||||
|
||||
|
||||
class ResetSlackView(APIView):
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ from apps.schedules.tests.factories import (
|
|||
OnCallScheduleICalFactory,
|
||||
ShiftSwapRequestFactory,
|
||||
)
|
||||
from apps.slack.slack_client import SlackClientWithErrorHandling
|
||||
from apps.slack.client import SlackClientWithErrorHandling
|
||||
from apps.slack.tests.factories import (
|
||||
SlackChannelFactory,
|
||||
SlackMessageFactory,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
django==3.2.20
|
||||
djangorestframework==3.12.4
|
||||
slackclient==1.3.0
|
||||
slack_sdk==3.21.3
|
||||
whitenoise==5.3.0
|
||||
twilio~=6.37.0
|
||||
phonenumbers==8.10.0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue