Skip to content

Commit 56e38c8

Browse files
committed
Add notifications module and update response scaffold for pattern notifications
1 parent 46b5b1e commit 56e38c8

File tree

5 files changed

+48
-6
lines changed

5 files changed

+48
-6
lines changed

src/notifications.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import asyncio
2+
import contextvars
3+
from typing import TYPE_CHECKING
4+
5+
if TYPE_CHECKING:
6+
from .telegram.telegram_context import TelegramContext
7+
8+
_ctx: contextvars.ContextVar["TelegramContext | None"] = contextvars.ContextVar(
9+
"telegram_context", default=None
10+
)
11+
12+
13+
def set_context(ctx: "TelegramContext") -> None:
14+
_ctx.set(ctx)
15+
16+
17+
def send(message: str) -> None:
18+
ctx = _ctx.get()
19+
if ctx:
20+
asyncio.create_task(ctx.send_message(message)) # noqa: RUF006

src/response_scaffold.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import re
22

3+
from . import notifications
34
from .scaffold_config import ScaffoldConfig
45

56

@@ -36,8 +37,10 @@ def _transform(self) -> str:
3637
return re.sub(r"\n{3,}", "\n\n", content).strip()
3738

3839
def _apply_replace_patterns(self, content: str) -> str:
39-
for pattern, replacement in self.config.replace_patterns.items():
40-
content = re.sub(pattern, replacement, content, flags=re.DOTALL)
40+
for rp in self.config.replace_patterns:
41+
if rp.notify and re.search(rp.pattern, content, flags=re.DOTALL):
42+
notifications.send(rp.notify)
43+
content = re.sub(rp.pattern, rp.replacement, content, flags=re.DOTALL)
4144
return content
4245

4346
def _validate_required_tags(self, content: str) -> None:

src/scaffold_config.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,34 @@
22
from typing import Any
33

44

5+
@dataclass
6+
class ReplacePattern:
7+
pattern: str
8+
replacement: str
9+
notify: str | None = None
10+
11+
512
@dataclass
613
class ScaffoldConfig:
714
require_tags: set[str] = field(default_factory=set)
815
delete_tags: set[str] = field(default_factory=set)
916
rename_tags: dict[str, str] = field(default_factory=dict)
10-
replace_patterns: dict[str, str] = field(default_factory=dict)
17+
replace_patterns: list[ReplacePattern] = field(default_factory=list)
1118

1219
@classmethod
1320
def from_dict(cls, data: dict[str, Any]) -> "ScaffoldConfig":
21+
raw_patterns = data.get("replace_patterns", [])
22+
patterns = [
23+
ReplacePattern(
24+
pattern=p["pattern"],
25+
replacement=p["replacement"],
26+
notify=p.get("notify"),
27+
)
28+
for p in raw_patterns
29+
]
1430
return cls(
1531
require_tags=set(data.get("require_tags", [])),
1632
delete_tags=set(data.get("delete_tags", [])),
1733
rename_tags=data.get("rename_tags", {}),
18-
replace_patterns=data.get("replace_patterns", {}),
34+
replace_patterns=patterns,
1935
)

src/telegram/message_handler.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import backoff
66
from telegram.error import TimedOut
77

8+
from .. import notifications
89
from .telegram_context import TelegramContext
910

1011

@@ -13,6 +14,7 @@ def message_handler(
1314
) -> Callable[..., Awaitable[Any]]:
1415
async def wrapper(self, update, context, *args, **kwargs) -> Any:
1516
ctx = TelegramContext(self.app, update, context)
17+
notifications.set_context(ctx)
1618
typing_task = asyncio.create_task(_loop_send_typing_action(ctx))
1719
try:
1820
await func(self, ctx, *args, **kwargs)

tests/unit/test_response_scaffold.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import pytest
22

33
from src.response_scaffold import ResponseScaffold
4-
from src.scaffold_config import ScaffoldConfig
4+
from src.scaffold_config import ReplacePattern, ScaffoldConfig
55

66

77
def test_deletes_tags():
@@ -38,7 +38,8 @@ def test_display_returns_content_outside_tags():
3838

3939

4040
def test_apply_replace_patterns():
41-
config = ScaffoldConfig(replace_patterns={r"foo\s+bar": "baz"})
41+
pattern = ReplacePattern(pattern=r"foo\s+bar", replacement="baz")
42+
config = ScaffoldConfig(replace_patterns=[pattern])
4243
content = "before foo bar after"
4344
scaffold = ResponseScaffold(content, config)
4445
assert scaffold.transformed_content == "before baz after"

0 commit comments

Comments
 (0)