From 64d91ceadbf01a329e9c16906d81fa1452f0c8fd Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Fri, 16 Aug 2024 15:15:40 -0300 Subject: [PATCH 1/4] Update msteams app refs to be for Grafana IRM (#4838) Update missing references to MSTeams OnCall app to now refer to Grafana IRM. --- docs/sources/manage/notify/ms-teams/index.md | 2 +- .../src/containers/MSTeams/MSTeamsInstructions.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/sources/manage/notify/ms-teams/index.md b/docs/sources/manage/notify/ms-teams/index.md index dd5dfd9d4d..e6fd9bd7cd 100644 --- a/docs/sources/manage/notify/ms-teams/index.md +++ b/docs/sources/manage/notify/ms-teams/index.md @@ -38,7 +38,7 @@ The following is required to connect to Microsoft Teams to Grafana OnCall: - You must have Admin permissions in your Grafana Cloud instance. - You must have Owner permissions in Microsoft Teams. -- Install the Grafana OnCall app from the [Microsoft Marketplace](https://appsource.microsoft.com/en-us/product/office/WA200004307). +- Install the Grafana IRM app from the [Microsoft Marketplace](https://appsource.microsoft.com/en-us/product/office/WA200004307). ## Install Microsoft Teams integration for Grafana OnCall diff --git a/grafana-plugin/src/containers/MSTeams/MSTeamsInstructions.tsx b/grafana-plugin/src/containers/MSTeams/MSTeamsInstructions.tsx index 1f188cf67e..de29a379d9 100644 --- a/grafana-plugin/src/containers/MSTeams/MSTeamsInstructions.tsx +++ b/grafana-plugin/src/containers/MSTeams/MSTeamsInstructions.tsx @@ -79,20 +79,20 @@ export const MSTeamsInstructions: FC = observer((props MS Teams marketplace {' '} - and add Grafana OnCall app to your MS Teams org workspace.{' '} + and add Grafana IRM app to your MS Teams org workspace.{' '} )} {!onCallisAdded ? 2 : 1}.{' '} {personalSettings ? ( - Send a direct message to the Grafana OnCall bot using ⁠linkUser command with + Send a direct message to the Grafana IRM bot using ⁠linkUser command with following code: ) : ( - Add OnCall bot to your team channel and send this code by{' '} - @Grafana OnCall linkTeam command + Add IRM bot to your team channel and send this code by @Grafana IRM linkTeam{' '} + command )} From 7112be811681264db541b89fa94523d940d95525 Mon Sep 17 00:00:00 2001 From: Dominik Broj Date: Fri, 16 Aug 2024 22:25:53 +0200 Subject: [PATCH 2/4] remove engine field (#4841) # What this PR does remove engine field so that `yarn install` works on different versions of Node.js ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- grafana-plugin/package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/grafana-plugin/package.json b/grafana-plugin/package.json index 84cbf8e352..73df3a5e92 100644 --- a/grafana-plugin/package.json +++ b/grafana-plugin/package.json @@ -126,9 +126,6 @@ "webpack-cli": "^5.1.4", "webpack-livereload-plugin": "^3.0.2" }, - "engines": { - "node": "20.x" - }, "dependencies": { "@dnd-kit/core": "^6.0.8", "@dnd-kit/modifiers": "^7.0.0", From f79445fbcbd5231dcb2b68c7b7e474a6ba537f79 Mon Sep 17 00:00:00 2001 From: Michael Derynck Date: Mon, 19 Aug 2024 07:59:01 -0600 Subject: [PATCH 3/4] Fix pagination behavior when page # exceeds search results (#4817) # What this PR does Change pagination to return last available page if the page number exceeds the pages available instead of returning 404. This came up from if the user is on a page other than the first and they enter a search and the number of search results are smaller than what would be needed to reach the current page number it would give a blank page and 404. ## Which issue(s) this PR closes Related to [issue link here] ## 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] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --------- Co-authored-by: Rares Mardare --- .../public_api/tests/test_alert_groups.py | 5 +-- engine/common/api_helpers/paginators.py | 39 +++++++++++++++++++ .../src/pages/integrations/Integrations.tsx | 8 ++-- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/engine/apps/public_api/tests/test_alert_groups.py b/engine/apps/public_api/tests/test_alert_groups.py index 51d074211d..9c88fec880 100644 --- a/engine/apps/public_api/tests/test_alert_groups.py +++ b/engine/apps/public_api/tests/test_alert_groups.py @@ -447,10 +447,9 @@ def test_pagination(settings, alert_group_public_api_setup): token, alert_groups, _, _ = alert_group_public_api_setup client = APIClient() - url = reverse("api-public:alert_groups-list") + url = "{}?perpage=1".format(reverse("api-public:alert_groups-list")) - with patch("common.api_helpers.paginators.PathPrefixedPagePagination.get_page_size", return_value=1): - response = client.get(url, HTTP_AUTHORIZATION=token) + response = client.get(url, HTTP_AUTHORIZATION=token) assert response.status_code == status.HTTP_200_OK result = response.json() diff --git a/engine/common/api_helpers/paginators.py b/engine/common/api_helpers/paginators.py index e85ed62a52..5c5b508cd3 100644 --- a/engine/common/api_helpers/paginators.py +++ b/engine/common/api_helpers/paginators.py @@ -1,5 +1,6 @@ import typing +from django.core.paginator import EmptyPage from rest_framework.pagination import BasePagination, CursorPagination, PageNumberPagination from rest_framework.response import Response @@ -54,6 +55,44 @@ def get_paginated_response_schema(self, schema): ) return paginated_schema + def paginate_queryset(self, queryset, request, view=None): + request.build_absolute_uri = lambda: create_engine_url(request.get_full_path()) + per_page = request.query_params.get(self.page_size_query_param, self.page_size) + try: + per_page = int(per_page) + except ValueError: + per_page = self.page_size + + if per_page < 1: + per_page = self.page_size + + paginator = self.django_paginator_class(queryset, per_page) + page_number = request.query_params.get(self.page_query_param, 1) + try: + page_number = int(page_number) + except ValueError: + page_number = 1 + + if page_number < 1: + page_number = 1 + + try: + self.page = self.get_page(page_number, paginator) + except EmptyPage: + self.page = paginator.page(paginator.num_pages) + + if paginator.num_pages > 1 and self.template is not None: + self.display_page_controls = True + + self.request = request + return list(self.page) + + def get_page(self, page_number, paginator): + try: + return paginator.page(page_number) + except EmptyPage: + return paginator.page(paginator.num_pages) + class PathPrefixedCursorPagination(BasePathPrefixedPagination, CursorPagination): def get_paginated_response(self, data: PaginatedData) -> Response: diff --git a/grafana-plugin/src/pages/integrations/Integrations.tsx b/grafana-plugin/src/pages/integrations/Integrations.tsx index fed1b4c317..1df6f1cc19 100644 --- a/grafana-plugin/src/pages/integrations/Integrations.tsx +++ b/grafana-plugin/src/pages/integrations/Integrations.tsx @@ -660,6 +660,7 @@ class _IntegrationsPage extends React.Component { const { store } = this.props; + return requestedPage !== store.filtersStore.currentTablePageNum[PAGE.Integrations]; }; @@ -696,6 +697,10 @@ class _IntegrationsPage extends React.Component { + store.filtersStore.currentTablePageNum[PAGE.Integrations] = newPage; + }); + await alertReceiveChannelStore.fetchPaginatedItems({ filters: this.getFiltersBasedOnCurrentTab(), page: newPage, @@ -703,9 +708,6 @@ class _IntegrationsPage extends React.Component this.invalidateRequestFn(newPage), }); - runInAction(() => { - store.filtersStore.currentTablePageNum[PAGE.Integrations] = newPage; - }); LocationHelper.update({ p: newPage }, 'partial'); }; From 0c96427cfc68dda6fddd3ab6fc05aea319fa6229 Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Mon, 19 Aug 2024 14:05:40 -0400 Subject: [PATCH 4/4] fix `apps.telegram.tasks.send_log_and_actions_message` retrying tasks (#4851) # What this PR does It _appears_ like Telegram may have changed one of the error messages they return for `telegram.error.BadRequest`. This _may_ be causing us to infinitely retry some of these tasks. Previously we were checking for two variants of the same type of error message: - "Message to reply not found" - "Replied message not found" _However_, if I search for the following [in the logs](https://ops.grafana-ops.net/goto/hMgBb8CSR?orgId=1): ```logql {namespace="amixr-prod"} |~ `(Message to be replied not found|Message to reply not found|Replied message not found)` ```` I _only_ see references to "Message to be replied not found". I have updated references to the former to this new error log message we are seeing. Also: - deduplicate some of the words we check for in `telegram.error.BadRequest` and `telegram.error.Unauthorized` into `apps.telegram.client.TelegramClient.BadRequestMessage` and `apps.telegram.client.TelegramClient.UnauthorizedMessage` respectively - deduplicate some of the wording we use in the `reason` arg passed to `TelegramToUserConnector.create_telegram_notification_error` into `apps.telegram.models.connectors.personal.TelegramToUserConnector.NotificationErrorReason` - standardize how we check the `message` attribute of `telegram.error.TelegramError`s into a new `error_message_is` static method on `apps.telegram.client.TelegramClient` - previously we would check these error messages in two different ways: ```python3 # style 1 if "error message to check" in e.message: # do something # style 2 if error.message == "error message to check": # do something ``` ## Which issue(s) this PR closes Closes https://github.com/grafana/oncall-private/issues/2868 ## 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] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- .nvmrc | 1 + engine/apps/telegram/client.py | 20 +++++++++- engine/apps/telegram/decorators.py | 6 +-- .../telegram/models/connectors/channel.py | 15 ++++---- .../telegram/models/connectors/personal.py | 38 +++++++++++-------- engine/apps/telegram/tasks.py | 21 +++++----- .../telegram/tests/test_personal_connector.py | 18 +++++---- engine/apps/telegram/tests/test_tasks.py | 6 ++- grafana-plugin/.nvmrc | 1 - 9 files changed, 78 insertions(+), 48 deletions(-) create mode 100644 .nvmrc delete mode 100644 grafana-plugin/.nvmrc diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000000..8ce7030825 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20.16.0 diff --git a/engine/apps/telegram/client.py b/engine/apps/telegram/client.py index e469e5e9fb..4271ae5f32 100644 --- a/engine/apps/telegram/client.py +++ b/engine/apps/telegram/client.py @@ -3,7 +3,7 @@ from django.conf import settings from telegram import Bot, InlineKeyboardMarkup, Message, ParseMode -from telegram.error import BadRequest, InvalidToken, Unauthorized +from telegram.error import BadRequest, InvalidToken, TelegramError, Unauthorized from telegram.utils.request import Request from apps.alerts.models import AlertGroup @@ -27,6 +27,18 @@ def __init__(self, token: Optional[str] = None): if self.token is None: raise InvalidToken() + class BadRequestMessage: + CHAT_NOT_FOUND = "Chat not found" + MESSAGE_IS_NOT_MODIFIED = "Message is not modified" + MESSAGE_TO_EDIT_NOT_FOUND = "Message to edit not found" + NEED_ADMIN_RIGHTS_IN_THE_CHANNEL = "Need administrator rights in the channel chat" + MESSAGE_TO_BE_REPLIED_NOT_FOUND = "Message to be replied not found" + + class UnauthorizedMessage: + BOT_WAS_BLOCKED_BY_USER = "Forbidden: bot was blocked by the user" + INVALID_TOKEN = "Invalid token" + USER_IS_DEACTIVATED = "Forbidden: user is deactivated" + @property def api_client(self) -> Bot: return Bot(self.token, request=Request(read_timeout=15)) @@ -96,7 +108,7 @@ def send_raw_message( disable_web_page_preview=False, ) except BadRequest as e: - logger.warning("Telegram BadRequest: {}".format(e.message)) + logger.warning(f"Telegram BadRequest: {e.message}") raise return message @@ -171,3 +183,7 @@ def _get_message_and_keyboard( raise Exception(f"_get_message_and_keyboard with type {message_type} is not implemented") return text, keyboard + + @staticmethod + def error_message_is(error: TelegramError, messages: list[str]) -> bool: + return error.message in messages diff --git a/engine/apps/telegram/decorators.py b/engine/apps/telegram/decorators.py index bfc29a7910..655e7e4fd8 100644 --- a/engine/apps/telegram/decorators.py +++ b/engine/apps/telegram/decorators.py @@ -42,7 +42,7 @@ def decorated(*args, **kwargs): try: return f(*args, **kwargs) except error.BadRequest as e: - if "Message is not modified" in e.message: + if TelegramClient.error_message_is(e, [TelegramClient.BadRequestMessage.MESSAGE_IS_NOT_MODIFIED]): logger.warning( f"Tried to change Telegram message, but update is identical to original message. " f"args: {args}, kwargs: {kwargs}" @@ -59,7 +59,7 @@ def decorated(*args, **kwargs): try: return f(*args, **kwargs) except error.BadRequest as e: - if "Message to edit not found" in e.message: + if TelegramClient.error_message_is(e, [TelegramClient.BadRequestMessage.MESSAGE_TO_EDIT_NOT_FOUND]): logger.warning( f"Tried to edit Telegram message, but message was deleted. args: {args}, kwargs: {kwargs}" ) @@ -75,7 +75,7 @@ def decorated(*args, **kwargs): try: return f(*args, **kwargs) except error.BadRequest as e: - if "Replied message not found" in e.message: + if TelegramClient.error_message_is(e, [TelegramClient.BadRequestMessage.MESSAGE_TO_BE_REPLIED_NOT_FOUND]): logger.warning( f"Tried to reply to Telegram message, but message was deleted. args: {args}, kwargs: {kwargs}" ) diff --git a/engine/apps/telegram/models/connectors/channel.py b/engine/apps/telegram/models/connectors/channel.py index 49168808b9..49b1191aee 100644 --- a/engine/apps/telegram/models/connectors/channel.py +++ b/engine/apps/telegram/models/connectors/channel.py @@ -123,15 +123,16 @@ def send_alert_group_message(self, alert_group: AlertGroup) -> None: chat_id=self.channel_chat_id, message_type=TelegramMessage.ALERT_GROUP_MESSAGE, alert_group=alert_group ) except error.BadRequest as e: - if e.message == "Need administrator rights in the channel chat": + if TelegramClient.error_message_is( + e, + [ + TelegramClient.BadRequestMessage.NEED_ADMIN_RIGHTS_IN_THE_CHANNEL, + TelegramClient.BadRequestMessage.CHAT_NOT_FOUND, + ], + ): logger.warning( f"Could not send alert group to Telegram channel with id {self.channel_chat_id} " - f"due to lack of admin rights. alert_group {alert_group.pk}" - ) - elif e.message == "Chat not found": - logger.warning( - f"Could not send alert group to Telegram channel with id {self.channel_chat_id} " - f"due to 'Chat not found'. alert_group {alert_group.pk}" + f"due to {e.message}. alert_group {alert_group.pk}" ) else: telegram_client.send_message( diff --git a/engine/apps/telegram/models/connectors/personal.py b/engine/apps/telegram/models/connectors/personal.py index ae006ed453..9726cb3e3d 100644 --- a/engine/apps/telegram/models/connectors/personal.py +++ b/engine/apps/telegram/models/connectors/personal.py @@ -25,6 +25,14 @@ class TelegramToUserConnector(models.Model): class Meta: unique_together = (("user", "telegram_chat_id"),) + class NotificationErrorReason: + USER_WAS_DISABLED = "Telegram user was disabled" + INVALID_TOKEN = "Invalid token" + BOT_BLOCKED_BY_USER = "Bot was blocked by the user" + FORMATTING_ERROR_IN_RENDERED_TEMPLATE = ( + "Notification sent but there was a formatting error in the rendered template" + ) + @classmethod def notify_user(cls, user: User, alert_group: AlertGroup, notification_policy: UserNotificationPolicy) -> None: try: @@ -98,7 +106,7 @@ def send_full_alert_group(self, alert_group: AlertGroup, notification_policy: Us self.user, notification_policy, UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_TELEGRAM_TOKEN_ERROR, - reason="Invalid token", + reason=self.NotificationErrorReason.INVALID_TOKEN, ) return @@ -123,7 +131,7 @@ def send_full_alert_group(self, alert_group: AlertGroup, notification_policy: Us self.user, notification_policy, UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_FORMATTING_ERROR, - reason="Notification sent but there was a formatting error in the rendered template", + reason=self.NotificationErrorReason.FORMATTING_ERROR_IN_RENDERED_TEMPLATE, ) telegram_client.send_message( chat_id=self.telegram_chat_id, @@ -131,29 +139,29 @@ def send_full_alert_group(self, alert_group: AlertGroup, notification_policy: Us alert_group=alert_group, ) except error.Unauthorized as e: - if e.message == "Forbidden: bot was blocked by the user": + if TelegramClient.error_message_is(e, [TelegramClient.UnauthorizedMessage.BOT_WAS_BLOCKED_BY_USER]): TelegramToUserConnector.create_telegram_notification_error( alert_group, self.user, notification_policy, UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_TELEGRAM_BOT_IS_DELETED, - reason="Bot was blocked by the user", + reason=self.NotificationErrorReason.BOT_BLOCKED_BY_USER, ) - elif e.message == "Invalid token": + elif TelegramClient.error_message_is(e, [TelegramClient.UnauthorizedMessage.INVALID_TOKEN]): TelegramToUserConnector.create_telegram_notification_error( alert_group, self.user, notification_policy, UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_TELEGRAM_TOKEN_ERROR, - reason="Invalid token", + reason=self.NotificationErrorReason.INVALID_TOKEN, ) - elif e.message == "Forbidden: user is deactivated": + elif TelegramClient.error_message_is(e, [TelegramClient.UnauthorizedMessage.USER_IS_DEACTIVATED]): TelegramToUserConnector.create_telegram_notification_error( alert_group, self.user, notification_policy, UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_TELEGRAM_USER_IS_DEACTIVATED, - reason="Telegram user was disabled", + reason=self.NotificationErrorReason.USER_WAS_DISABLED, ) else: raise e @@ -175,7 +183,7 @@ def send_link_to_channel_message(self, alert_group: AlertGroup, notification_pol self.user, notification_policy, UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_TELEGRAM_TOKEN_ERROR, - reason="Invalid token", + reason=self.NotificationErrorReason.INVALID_TOKEN, ) return @@ -193,29 +201,29 @@ def send_link_to_channel_message(self, alert_group: AlertGroup, notification_pol alert_group=alert_group, ) except error.Unauthorized as e: - if e.message == "Forbidden: bot was blocked by the user": + if TelegramClient.error_message_is(e, [TelegramClient.UnauthorizedMessage.BOT_WAS_BLOCKED_BY_USER]): TelegramToUserConnector.create_telegram_notification_error( alert_group, self.user, notification_policy, UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_TELEGRAM_BOT_IS_DELETED, - reason="Bot was blocked by the user", + reason=self.NotificationErrorReason.BOT_BLOCKED_BY_USER, ) - elif e.message == "Invalid token": + elif TelegramClient.error_message_is(e, [TelegramClient.UnauthorizedMessage.INVALID_TOKEN]): TelegramToUserConnector.create_telegram_notification_error( alert_group, self.user, notification_policy, UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_TELEGRAM_TOKEN_ERROR, - reason="Invalid token", + reason=self.NotificationErrorReason.INVALID_TOKEN, ) - elif e.message == "Forbidden: user is deactivated": + elif TelegramClient.error_message_is(e, [TelegramClient.UnauthorizedMessage.USER_IS_DEACTIVATED]): TelegramToUserConnector.create_telegram_notification_error( alert_group, self.user, notification_policy, UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_TELEGRAM_USER_IS_DEACTIVATED, - reason="Telegram user was disabled", + reason=self.NotificationErrorReason.USER_WAS_DISABLED, ) else: raise e diff --git a/engine/apps/telegram/tasks.py b/engine/apps/telegram/tasks.py index 5aeb9948e4..93e7e4f1b6 100644 --- a/engine/apps/telegram/tasks.py +++ b/engine/apps/telegram/tasks.py @@ -66,7 +66,7 @@ def edit_message(self, message_pk): try: telegram_client.edit_message(message=message) except error.BadRequest as e: - if "Message is not modified" in e.message: + if TelegramClient.error_message_is(e, [TelegramClient.BadRequestMessage.MESSAGE_IS_NOT_MODIFIED]): pass except (error.RetryAfter, error.TimedOut) as e: countdown = getattr(e, "retry_after", 3) @@ -165,20 +165,19 @@ def send_log_and_actions_message(self, channel_chat_id, group_chat_id, channel_m reply_to_message_id=reply_to_message_id, ) except error.BadRequest as e: - if e.message == "Chat not found": + if TelegramClient.error_message_is( + e, + [ + TelegramClient.BadRequestMessage.CHAT_NOT_FOUND, + TelegramClient.BadRequestMessage.MESSAGE_TO_BE_REPLIED_NOT_FOUND, + ], + ): logger.warning( f"Could not send log and actions messages to Telegram group with id {group_chat_id} " - f"due to 'Chat not found'. alert_group {alert_group.pk}" + f"due to '{e.message}'. alert_group {alert_group.pk}" ) return - elif e.message == "Message to reply not found": - logger.warning( - f"Could not send log and actions messages to Telegram group with id {group_chat_id} " - f"due to 'Message to reply not found'. alert_group {alert_group.pk}" - ) - return - else: - raise + raise @shared_dedicated_queue_retry_task( diff --git a/engine/apps/telegram/tests/test_personal_connector.py b/engine/apps/telegram/tests/test_personal_connector.py index 00a2dd7d3b..e9d4d19362 100644 --- a/engine/apps/telegram/tests/test_personal_connector.py +++ b/engine/apps/telegram/tests/test_personal_connector.py @@ -8,7 +8,11 @@ from apps.telegram.models import TelegramMessage, TelegramToUserConnector -@patch.object(TelegramClient, "send_raw_message", side_effect=error.BadRequest("Replied message not found")) +@patch.object( + TelegramClient, + "send_raw_message", + side_effect=error.BadRequest(TelegramClient.BadRequestMessage.MESSAGE_TO_BE_REPLIED_NOT_FOUND), +) @pytest.mark.django_db def test_personal_connector_replied_message_not_found( mock_send_message, @@ -53,19 +57,19 @@ def test_personal_connector_replied_message_not_found( "side_effect,notification_error_code,reason", [ ( - error.Unauthorized("Forbidden: bot was blocked by the user"), + error.Unauthorized(TelegramClient.UnauthorizedMessage.BOT_WAS_BLOCKED_BY_USER), UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_TELEGRAM_BOT_IS_DELETED, - "Bot was blocked by the user", + TelegramToUserConnector.NotificationErrorReason.BOT_BLOCKED_BY_USER, ), ( - error.Unauthorized("Invalid token"), + error.Unauthorized(TelegramClient.UnauthorizedMessage.INVALID_TOKEN), UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_TELEGRAM_TOKEN_ERROR, - "Invalid token", + TelegramToUserConnector.NotificationErrorReason.INVALID_TOKEN, ), ( - error.Unauthorized("Forbidden: user is deactivated"), + error.Unauthorized(TelegramClient.UnauthorizedMessage.USER_IS_DEACTIVATED), UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_TELEGRAM_USER_IS_DEACTIVATED, - "Telegram user was disabled", + TelegramToUserConnector.NotificationErrorReason.USER_WAS_DISABLED, ), ], ) diff --git a/engine/apps/telegram/tests/test_tasks.py b/engine/apps/telegram/tests/test_tasks.py index a3a7c2f810..fab8406878 100644 --- a/engine/apps/telegram/tests/test_tasks.py +++ b/engine/apps/telegram/tests/test_tasks.py @@ -7,8 +7,10 @@ from apps.telegram.models import TelegramMessage from apps.telegram.tasks import send_log_and_actions_message +bad_request_error_msg = TelegramClient.BadRequestMessage.MESSAGE_TO_BE_REPLIED_NOT_FOUND -@patch.object(TelegramClient, "send_raw_message", side_effect=error.BadRequest("Message to reply not found")) + +@patch.object(TelegramClient, "send_raw_message", side_effect=error.BadRequest(bad_request_error_msg)) @pytest.mark.django_db def test_send_log_and_actions_replied_message_not_found( mock_send_message, @@ -42,6 +44,6 @@ def test_send_log_and_actions_replied_message_not_found( expected_msg = ( f"Could not send log and actions messages to Telegram group with id group_chat_id " - f"due to 'Message to reply not found'. alert_group {alert_group.pk}" + f"due to '{bad_request_error_msg}'. alert_group {alert_group.pk}" ) assert expected_msg in caplog.text diff --git a/grafana-plugin/.nvmrc b/grafana-plugin/.nvmrc deleted file mode 100644 index 922f10a165..0000000000 --- a/grafana-plugin/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -20.x