From 703526ca16e7ba93df927321c6deb45e8c8d568b Mon Sep 17 00:00:00 2001 From: Polina Sheviakova Date: Mon, 27 Nov 2023 17:01:28 +0300 Subject: [PATCH 1/3] Added telegram message_thread_id option --- CHANGELOG.md | 2 +- docs/source/ruletypes.rst | 2 ++ elastalert/alerters/telegram.py | 4 +++- elastalert/schema.yaml | 1 + tests/alerters/telegram_test.py | 40 +++++++++++++++++++++++++++++++++ 5 files changed, 47 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dcbeceb..0cc6e624 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ - TBD ## New features -- TBD +- [Telegram] Added new telegram_thread_id setting for sending alerts to different threads of supergroup/forum. - [#???](https://github.com/jertel/elastalert2/pull/???) - @polshe-v ## Other changes - Update setup.py & requirements.txt & requirements-dev.txt - [#1316](https://github.com/jertel/elastalert2/pull/1316) - @nsano-rururu diff --git a/docs/source/ruletypes.rst b/docs/source/ruletypes.rst index 92ac80b2..e2455f69 100644 --- a/docs/source/ruletypes.rst +++ b/docs/source/ruletypes.rst @@ -3688,6 +3688,8 @@ Optional: ``telegram_parse_mode``: The Telegram parsing mode, which determines the format of the alert text body. Possible values are ``markdown``, ``markdownV2``, ``html``. Defaults to ``markdown``. +``telegram_thread_id``: Unique identifier for the target thread of supergroup/forum using telegram message_thread_id (Optional, positive integer value, no default). + Example usage:: alert: diff --git a/elastalert/alerters/telegram.py b/elastalert/alerters/telegram.py index 48632537..1e31ab9e 100644 --- a/elastalert/alerters/telegram.py +++ b/elastalert/alerters/telegram.py @@ -23,6 +23,7 @@ def __init__(self, rule): self.telegram_proxy_login = self.rule.get('telegram_proxy_login', None) self.telegram_proxy_password = self.rule.get('telegram_proxy_pass', None) self.telegram_parse_mode = self.rule.get('telegram_parse_mode', 'markdown') + self.telegram_thread_id = self.rule.get('telegram_thread_id', None) def alert(self, matches): if self.telegram_parse_mode != 'html': @@ -49,7 +50,8 @@ def alert(self, matches): 'chat_id': self.telegram_room_id, 'text': body, 'parse_mode': self.telegram_parse_mode, - 'disable_web_page_preview': True + 'disable_web_page_preview': True, + 'message_thread_id': self.self.telegram_thread_id } try: diff --git a/elastalert/schema.yaml b/elastalert/schema.yaml index a41c775d..666d06b0 100644 --- a/elastalert/schema.yaml +++ b/elastalert/schema.yaml @@ -773,6 +773,7 @@ properties: telegram_proxy_login: {type: string} telegram_proxy_pass: {type: string} telegram_parse_mode: {type: string, enum: ['markdown', 'markdownV2', 'html']} + telegram_thread_id: {type: number} ### Tencent SMS tencent_sms_secret_id: {type: string} diff --git a/tests/alerters/telegram_test.py b/tests/alerters/telegram_test.py index 66d0a1a4..404116ff 100644 --- a/tests/alerters/telegram_test.py +++ b/tests/alerters/telegram_test.py @@ -12,6 +12,46 @@ from elastalert.util import EAException +def test_telegram_thread_id(caplog): + caplog.set_level(logging.INFO) + rule = { + 'name': 'Test Telegram Rule', + 'type': 'any', + 'telegram_bot_token': 'xxxxx1', + 'telegram_room_id': 'xxxxx2', + 'telegram_thread_id': 2, + 'alert': [] + } + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = TelegramAlerter(rule) + match = { + '@timestamp': '2021-01-01T00:00:00', + 'somefield': 'foobarbaz' + } + with mock.patch('requests.post') as mock_post_request: + alert.alert([match]) + expected_data = { + 'chat_id': rule['telegram_room_id'], + 'text': '⚠ Test Telegram Rule ⚠ \nTest Telegram Rule\n\n@timestamp: 2021-01-01T00:00:00\nsomefield: foobarbaz\n', + 'parse_mode': 'markdown', + 'disable_web_page_preview': True, + 'message_thread_id' : 2 + } + + mock_post_request.assert_called_once_with( + 'https://api.telegram.org/botxxxxx1/sendMessage', + data=mock.ANY, + headers={'content-type': 'application/json'}, + proxies=None, + auth=None + ) + + actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) + assert expected_data == actual_data + assert ('elastalert', logging.INFO, 'Alert sent to Telegram room xxxxx2') == caplog.record_tuples[0] + + def test_telegram_markdown(caplog): caplog.set_level(logging.INFO) rule = { From af0f8a5ec1c998fad23a3dbf836ff72e1062a8a2 Mon Sep 17 00:00:00 2001 From: Polina Sheviakova Date: Mon, 27 Nov 2023 21:15:21 +0300 Subject: [PATCH 2/3] Fixed typo; Updated CHANGELOG PR number --- CHANGELOG.md | 2 +- elastalert/alerters/telegram.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cc6e624..d45e2708 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ - TBD ## New features -- [Telegram] Added new telegram_thread_id setting for sending alerts to different threads of supergroup/forum. - [#???](https://github.com/jertel/elastalert2/pull/???) - @polshe-v +- [Telegram] Added new telegram_thread_id setting for sending alerts to different threads of supergroup/forum. - [#1319](https://github.com/jertel/elastalert2/pull/1319) - @polshe-v ## Other changes - Update setup.py & requirements.txt & requirements-dev.txt - [#1316](https://github.com/jertel/elastalert2/pull/1316) - @nsano-rururu diff --git a/elastalert/alerters/telegram.py b/elastalert/alerters/telegram.py index 1e31ab9e..18c543c3 100644 --- a/elastalert/alerters/telegram.py +++ b/elastalert/alerters/telegram.py @@ -51,7 +51,7 @@ def alert(self, matches): 'text': body, 'parse_mode': self.telegram_parse_mode, 'disable_web_page_preview': True, - 'message_thread_id': self.self.telegram_thread_id + 'message_thread_id': self.telegram_thread_id } try: From 1b4e7c1c517dbd62c45c0df08b2ac2eca451f087 Mon Sep 17 00:00:00 2001 From: Polina Sheviakova Date: Mon, 27 Nov 2023 21:54:32 +0300 Subject: [PATCH 3/3] Fixed telegram tests --- tests/alerters/telegram_test.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tests/alerters/telegram_test.py b/tests/alerters/telegram_test.py index 404116ff..748c72bb 100644 --- a/tests/alerters/telegram_test.py +++ b/tests/alerters/telegram_test.py @@ -33,10 +33,10 @@ def test_telegram_thread_id(caplog): alert.alert([match]) expected_data = { 'chat_id': rule['telegram_room_id'], - 'text': '⚠ Test Telegram Rule ⚠ \nTest Telegram Rule\n\n@timestamp: 2021-01-01T00:00:00\nsomefield: foobarbaz\n', + 'text': '⚠ *Test Telegram Rule* ⚠ ```\nTest Telegram Rule\n\n@timestamp: 2021-01-01T00:00:00\nsomefield: foobarbaz\n ```', 'parse_mode': 'markdown', 'disable_web_page_preview': True, - 'message_thread_id' : 2 + 'message_thread_id': 2 } mock_post_request.assert_called_once_with( @@ -74,7 +74,8 @@ def test_telegram_markdown(caplog): 'chat_id': rule['telegram_room_id'], 'text': '⚠ *Test Telegram Rule* ⚠ ```\nTest Telegram Rule\n\n@timestamp: 2021-01-01T00:00:00\nsomefield: foobarbaz\n ```', 'parse_mode': 'markdown', - 'disable_web_page_preview': True + 'disable_web_page_preview': True, + 'message_thread_id': None } mock_post_request.assert_called_once_with( @@ -113,7 +114,8 @@ def test_telegram_html(caplog): 'chat_id': rule['telegram_room_id'], 'text': '⚠ Test Telegram Rule ⚠ \nTest Telegram Rule\n\n@timestamp: 2021-01-01T00:00:00\nsomefield: foobarbaz\n', 'parse_mode': 'html', - 'disable_web_page_preview': True + 'disable_web_page_preview': True, + 'message_thread_id': None } mock_post_request.assert_called_once_with( @@ -153,7 +155,8 @@ def test_telegram_proxy(): 'chat_id': rule['telegram_room_id'], 'text': '⚠ *Test Telegram Rule* ⚠ ```\nTest Telegram Rule\n\n@timestamp: 2021-01-01T00:00:00\nsomefield: foobarbaz\n ```', 'parse_mode': 'markdown', - 'disable_web_page_preview': True + 'disable_web_page_preview': True, + 'message_thread_id': None } mock_post_request.assert_called_once_with( @@ -190,7 +193,8 @@ def test_telegram_text_maxlength(): 'text': '⚠ *Test Telegram Rule' + ('a' * 3979) + '\n⚠ *message was cropped according to telegram limits!* ⚠ ```', 'parse_mode': 'markdown', - 'disable_web_page_preview': True + 'disable_web_page_preview': True, + 'message_thread_id': None } mock_post_request.assert_called_once_with( @@ -315,7 +319,8 @@ def test_telegram_matchs(): '----------------------------------------\n' + ' ```', 'parse_mode': 'markdown', - 'disable_web_page_preview': True + 'disable_web_page_preview': True, + 'message_thread_id': None } mock_post_request.assert_called_once_with(