forked from mehdiBezahaf/intent-deploy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnotifiers.py
81 lines (57 loc) · 2.02 KB
/
notifiers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
from __future__ import annotations
import logging
from dataclasses import dataclass
from typing import Callable, Optional, Protocol, Type, TYPE_CHECKING
import httpx
from yarl import URL
from intent_deployer.config import get_settings, telegram_url
log: logging.Logger = logging.getLogger(__name__)
if TYPE_CHECKING:
# BUG: in py3.9.7 data classes that inherit from typing.Protocol break so
# only actually use Protocol for type checking, use a plain class otherwise
class Notifier(Protocol):
@classmethod
def parse(cls, body: dict) -> Notifier:
...
async def send(self, msg: str):
...
else:
class Notifier:
pass
_notifiers: dict[str, Type[Notifier]] = {}
def register_notifier(name: str) -> Callable[[Type[Notifier]], Type[Notifier]]:
if name in _notifiers:
log.warning("The notifier type %s has already been registered", name)
def wrapper(notifier: Type[Notifier]) -> Type[Notifier]:
_notifiers[name] = notifier
return notifier
return wrapper
def get_notifier(name: str, body: dict) -> Optional[Notifier]:
klass = _notifiers.get(name)
if klass is None:
return None
return klass.parse(body)
@register_notifier("telegram")
@dataclass
class Telegram(Notifier):
url: URL
@classmethod
def parse(cls, body: dict) -> Telegram:
chat_id = body["data"]["chat"]["id"]
token = get_settings().telegram_token
if token is None:
raise Exception(
"Tried to create a telegram notifier, but no TELEGRAM_TOKEN was provided"
)
url = telegram_url / f"bot{token}" / "sendMessage" % {"chat_id": chat_id}
return cls(url)
async def send(self, msg: str):
url = self.url % {"text": msg}
async with httpx.AsyncClient() as client:
await client.post(str(url))
class NullNotifier(Notifier):
@classmethod
def parse(cls, body: dict) -> NullNotifier:
return cls()
async def send(self, msg: str):
pass