Skip to content

Commit 04d0cbc

Browse files
authored
Merge branch 'main' into update-copyright
2 parents e5b0c0c + a1764b7 commit 04d0cbc

File tree

9 files changed

+151
-8
lines changed

9 files changed

+151
-8
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
python-version: ${{ matrix.python-version }}
3030
- name: Start MongoDB
3131
if: ${{ matrix.os == 'ubuntu-latest' }}
32-
uses: supercharge/mongodb-github-action@1.10.0
32+
uses: supercharge/mongodb-github-action@1.11.0
3333
with:
3434
mongodb-version: latest
3535
- name: Install dependencies
@@ -67,7 +67,7 @@ jobs:
6767

6868
- name: Test Summary
6969
id: test_summary
70-
uses: test-summary/action@v2.2
70+
uses: test-summary/action@v2.4
7171
if: always() # always run, even if tests fail
7272
with:
7373
paths: ".test-reports/*.xml"

.pre-commit-config.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ ci:
44

55
repos:
66
- repo: https://github.com/psf/black
7-
rev: 23.7.0
7+
rev: 24.10.0
88
hooks:
99
- id: black
1010
args:
1111
- --diff
1212
- --check
1313
- repo: https://github.com/PyCQA/flake8
14-
rev: 6.1.0
14+
rev: 7.1.1
1515
hooks:
1616
- id: flake8
1717
- repo: https://github.com/PyCQA/pylint
18-
rev: v3.0.0a6
18+
rev: v3.3.2
1919
hooks:
2020
- id: pylint
2121
name: pylint
@@ -25,18 +25,18 @@ repos:
2525
# run pylint across multiple cpu cores to speed it up-
2626
- --jobs=0 # See https://pylint.pycqa.org/en/latest/user_guide/run.html?#parallel-execution to know more
2727
- repo: https://github.com/pre-commit/mirrors-mypy
28-
rev: v1.4.1
28+
rev: v1.13.0
2929
hooks:
3030
- id: mypy
3131
exclude: ^tests/
3232
- repo: https://github.com/asottile/pyupgrade
33-
rev: v3.10.1
33+
rev: v3.19.0
3434
hooks:
3535
- id: pyupgrade
3636
args:
3737
- --py37-plus
3838
- repo: https://github.com/pycqa/isort
39-
rev: 5.12.0
39+
rev: 5.13.2
4040
hooks:
4141
- id: isort
4242
name: isort

ptbcontrib/log_forwarder/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Logging handler for python-telegram-bot
2+
Extension to forward application logs to specific Telegram chats through a `logging.Handler` class.
3+
4+
## Usage
5+
Initialize the log forwarder in a method that runs in the `post_init` hook of `Application`:
6+
7+
```python
8+
async def on_startup(app: Application):
9+
error_forwarder = LogForwarder(
10+
app.bot, [CHAT_ID], log_levels=["ERROR", "WARNING"]
11+
)
12+
# Add handler to the root logger to apply to all other loggers
13+
logging.getLogger().addHandler(error_forwarder)
14+
15+
application: Application = (
16+
ApplicationBuilder()
17+
.token("BOT_TOKEN")
18+
.post_init(on_startup)
19+
.build()
20+
)
21+
```
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# A library containing community-based extension for the python-telegram-bot library
2+
# Copyright (C) 2020-2024
3+
# The ptbcontrib developers
4+
#
5+
# This program is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU Lesser Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU Lesser Public License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser Public License
16+
# along with this program. If not, see [http://www.gnu.org/licenses/].
17+
"""
18+
This module contains a subclass for the `logging.Handler`
19+
that forwards specific logs to Telegram chats.
20+
"""
21+
22+
from .log_forwarder import LogForwarder
23+
24+
__all__ = [
25+
"LogForwarder",
26+
]
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# A library containing community-based extension for the python-telegram-bot library
2+
# Copyright (C) 2020-2024
3+
# The ptbcontrib developers
4+
#
5+
# This program is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU Lesser Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU Lesser Public License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser Public License
16+
# along with this program. If not, see [http://www.gnu.org/licenses/].
17+
"""This module contains LogForwarder class"""
18+
19+
from __future__ import annotations
20+
21+
import asyncio
22+
import logging
23+
from collections.abc import Iterable
24+
25+
from telegram.constants import ParseMode
26+
from telegram.ext import ExtBot
27+
28+
29+
class LogForwarder(logging.Handler):
30+
"""
31+
Logging handler to forward specific logs to Telegram chats.
32+
"""
33+
34+
def __init__(
35+
self,
36+
bot: ExtBot,
37+
chat_ids: Iterable[int],
38+
parse_mode: ParseMode = ParseMode.MARKDOWN_V2,
39+
log_levels: Iterable[str] = ("WARN", "ERROR"),
40+
):
41+
super().__init__()
42+
self._bot = bot
43+
self._chat_ids = chat_ids
44+
self._parse_mode = parse_mode
45+
self._log_levels = log_levels
46+
self._loop = asyncio.get_event_loop()
47+
48+
def format_tg_msg(self, text: str) -> str:
49+
"""
50+
Formats the log message to be sent to Telegram.
51+
Override this method to customize the message.
52+
The default implementation applies the handler's formatter
53+
and puts the result in a Markdown code block.
54+
"""
55+
56+
msg = "```\n" + text + "\n```"
57+
return msg
58+
59+
def emit(self, record: logging.LogRecord) -> None:
60+
try:
61+
formatted = self.format(record)
62+
msg = self.format_tg_msg(formatted)
63+
if record.levelname in self._log_levels:
64+
for chat_id in self._chat_ids:
65+
f = self._bot.send_message(
66+
chat_id=chat_id, text=msg, parse_mode=self._parse_mode
67+
)
68+
asyncio.run_coroutine_threadsafe(f, self._loop)
69+
except RecursionError: # https://bugs.python.org/issue36272
70+
raise
71+
except Exception: # pylint: disable=W0703
72+
self.handleError(record)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
python-telegram-bot>=20.0

ptbcontrib/ptb_jobstores/mongodb/mongodb.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/env python
2+
# pylint: disable=duplicate-code
23
#
34
# A library containing community-based extension for the python-telegram-bot library
45
# Copyright (C) 2020-2025

ptbcontrib/ptb_jobstores/sqlalchemy/sqlalchemy.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/env python
2+
# pylint: disable=duplicate-code
23
#
34
# A library containing community-based extension for the python-telegram-bot library
45
# Copyright (C) 2020-2025

tests/test_log_forwarder.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import logging
2+
from unittest.mock import MagicMock
3+
4+
from telegram.constants import ParseMode
5+
6+
from ptbcontrib.log_forwarder import LogForwarder
7+
8+
9+
async def test_log_forwarder():
10+
root_logger = logging.getLogger()
11+
chat_ids = [69420]
12+
bot = MagicMock()
13+
log_forwarder = LogForwarder(bot, chat_ids)
14+
root_logger.addHandler(log_forwarder)
15+
16+
logger = logging.getLogger("test_logger")
17+
logger.error("TEST")
18+
19+
bot.send_message.assert_called_with(
20+
chat_id=69420, text="```\nTEST\n```", parse_mode=ParseMode.MARKDOWN_V2
21+
)

0 commit comments

Comments
 (0)