dotflow 0.14.1.dev1__tar.gz → 0.14.1.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/PKG-INFO +2 -2
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/README.md +1 -1
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/__init__.py +1 -1
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/abc/notify.py +2 -2
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/task.py +1 -1
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/providers/__init__.py +2 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/providers/notify_default.py +1 -1
- dotflow-0.14.1.dev2/dotflow/providers/notify_discord.py +112 -0
- dotflow-0.14.1.dev2/dotflow/providers/notify_telegram.py +109 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/pyproject.toml +2 -2
- dotflow-0.14.1.dev1/dotflow/providers/notify_telegram.py +0 -59
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/LICENSE +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/abc/__init__.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/abc/api.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/abc/file.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/abc/flow.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/abc/http.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/abc/log.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/abc/scheduler.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/abc/storage.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/abc/tcp.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/cli/__init__.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/cli/command.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/cli/commands/__init__.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/cli/commands/init.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/cli/commands/log.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/cli/commands/schedule.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/cli/commands/start.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/cli/setup.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/cli/validators/__init__.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/cli/validators/start.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/__init__.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/action.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/config.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/context.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/decorators/__init__.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/decorators/time.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/dotflow.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/exception.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/execution.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/module.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/serializers/__init__.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/serializers/task.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/serializers/transport.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/serializers/workflow.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/types/__init__.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/types/execution.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/types/overlap.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/types/status.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/types/storage.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/types/workflow.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/core/workflow.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/logging.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/main.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/providers/api_default.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/providers/log_default.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/providers/scheduler_cron.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/providers/scheduler_default.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/providers/storage_default.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/providers/storage_file.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/providers/storage_gcs.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/providers/storage_s3.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/settings.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/storage.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/types.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/utils/__init__.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/utils/basic_functions.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/utils/error_handler.py +0 -0
- {dotflow-0.14.1.dev1 → dotflow-0.14.1.dev2}/dotflow/utils/tools.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dotflow
|
|
3
|
-
Version: 0.14.1.
|
|
3
|
+
Version: 0.14.1.dev2
|
|
4
4
|
Summary: 🎲 Dotflow turns an idea into flow! Lightweight Python library for execution pipelines with retry, parallel, cron and async support.
|
|
5
5
|
License: MIT License
|
|
6
6
|
|
|
@@ -648,7 +648,7 @@ Extend Dotflow by implementing the abstract base classes:
|
|
|
648
648
|
| ABC | Methods | Purpose |
|
|
649
649
|
|-----|---------|---------|
|
|
650
650
|
| `Storage` | `post`, `get`, `key` | Custom storage backends |
|
|
651
|
-
| `Notify` | `
|
|
651
|
+
| `Notify` | `hook_status_task` | Custom notification channels |
|
|
652
652
|
| `Log` | `info`, `error` | Custom logging |
|
|
653
653
|
| `Scheduler` | `start`, `stop` | Custom scheduling strategies |
|
|
654
654
|
|
|
@@ -587,7 +587,7 @@ Extend Dotflow by implementing the abstract base classes:
|
|
|
587
587
|
| ABC | Methods | Purpose |
|
|
588
588
|
|-----|---------|---------|
|
|
589
589
|
| `Storage` | `post`, `get`, `key` | Custom storage backends |
|
|
590
|
-
| `Notify` | `
|
|
590
|
+
| `Notify` | `hook_status_task` | Custom notification channels |
|
|
591
591
|
| `Log` | `info`, `error` | Custom logging |
|
|
592
592
|
| `Scheduler` | `start`, `stop` | Custom scheduling strategies |
|
|
593
593
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from dotflow.providers.log_default import LogDefault
|
|
4
4
|
from dotflow.providers.notify_default import NotifyDefault
|
|
5
|
+
from dotflow.providers.notify_discord import NotifyDiscord
|
|
5
6
|
from dotflow.providers.notify_telegram import NotifyTelegram
|
|
6
7
|
from dotflow.providers.scheduler_default import SchedulerDefault
|
|
7
8
|
from dotflow.providers.storage_default import StorageDefault
|
|
@@ -10,6 +11,7 @@ from dotflow.providers.storage_file import StorageFile
|
|
|
10
11
|
__all__ = [
|
|
11
12
|
"LogDefault",
|
|
12
13
|
"NotifyDefault",
|
|
14
|
+
"NotifyDiscord",
|
|
13
15
|
"NotifyTelegram",
|
|
14
16
|
"SchedulerCron",
|
|
15
17
|
"SchedulerDefault",
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""Notify Discord"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from json import dumps
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from requests import post
|
|
9
|
+
|
|
10
|
+
from dotflow.abc.notify import Notify
|
|
11
|
+
from dotflow.core.types.status import TypeStatus
|
|
12
|
+
from dotflow.logging import logger
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class NotifyDiscord(Notify):
|
|
16
|
+
"""
|
|
17
|
+
Import:
|
|
18
|
+
You can import the **NotifyDiscord** class with:
|
|
19
|
+
|
|
20
|
+
from dotflow.providers import NotifyDiscord
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
`class` dotflow.providers.notify_discord.NotifyDiscord
|
|
24
|
+
|
|
25
|
+
from dotflow import Config, DotFlow
|
|
26
|
+
from dotflow.providers import NotifyDiscord
|
|
27
|
+
from dotflow.core.types.status import TypeStatus
|
|
28
|
+
|
|
29
|
+
config = Config(
|
|
30
|
+
notify=NotifyDiscord(
|
|
31
|
+
webhook_url="https://discord.com/api/webhooks/...",
|
|
32
|
+
notification_type=TypeStatus.FAILED,
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
workflow = DotFlow(config=config)
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
webhook_url (str): Discord webhook URL.
|
|
40
|
+
|
|
41
|
+
notification_type (Optional[TypeStatus]): Filter notifications
|
|
42
|
+
by task status. If None, all statuses are notified.
|
|
43
|
+
|
|
44
|
+
show_result (bool): Include task result in the notification.
|
|
45
|
+
Defaults to False.
|
|
46
|
+
|
|
47
|
+
timeout (float): Request timeout in seconds.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
COLORS = {
|
|
51
|
+
TypeStatus.COMPLETED: 0x4CAF50,
|
|
52
|
+
TypeStatus.FAILED: 0xF44336,
|
|
53
|
+
TypeStatus.RETRY: 0xFF9800,
|
|
54
|
+
TypeStatus.IN_PROGRESS: 0x2196F3,
|
|
55
|
+
TypeStatus.NOT_STARTED: 0x9E9E9E,
|
|
56
|
+
TypeStatus.PAUSED: 0x607D8B,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
def __init__(
|
|
60
|
+
self,
|
|
61
|
+
webhook_url: str,
|
|
62
|
+
notification_type: TypeStatus | None = None,
|
|
63
|
+
show_result: bool = False,
|
|
64
|
+
timeout: float = 1.5,
|
|
65
|
+
):
|
|
66
|
+
self.webhook_url = webhook_url
|
|
67
|
+
self.notification_type = notification_type
|
|
68
|
+
self.show_result = show_result
|
|
69
|
+
self.timeout = timeout
|
|
70
|
+
|
|
71
|
+
def hook_status_task(self, task: Any) -> None:
|
|
72
|
+
if self.notification_type and self.notification_type != task.status:
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
response = post(
|
|
77
|
+
url=self.webhook_url,
|
|
78
|
+
headers={"Content-Type": "application/json"},
|
|
79
|
+
data=dumps({"embeds": [self._build_embed(task)]}),
|
|
80
|
+
timeout=self.timeout,
|
|
81
|
+
)
|
|
82
|
+
response.raise_for_status()
|
|
83
|
+
except Exception as error:
|
|
84
|
+
logger.error(
|
|
85
|
+
"Internal problem sending notification on Discord: %s",
|
|
86
|
+
str(error),
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
def _build_embed(self, task: Any) -> dict:
|
|
90
|
+
embed = {
|
|
91
|
+
"title": f"{TypeStatus.get_symbol(task.status)} {task.status}",
|
|
92
|
+
"color": self.COLORS.get(task.status, 0x9E9E9E),
|
|
93
|
+
"description": f"`{task.workflow_id}` — Task {task.task_id}",
|
|
94
|
+
"fields": [],
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if self.show_result:
|
|
98
|
+
embed["fields"].append(
|
|
99
|
+
{
|
|
100
|
+
"name": "Result",
|
|
101
|
+
"value": f"```json\n{task.result(max=1024)}```",
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
if task.status == TypeStatus.FAILED and task.errors:
|
|
106
|
+
last_error = task.errors[-1]
|
|
107
|
+
error_value = f"`{last_error.exception}`: {last_error.message}"
|
|
108
|
+
embed["fields"].append(
|
|
109
|
+
{"name": "Error", "value": error_value[:1024]}
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
return embed
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Notify Telegram"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from json import dumps
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from requests import post
|
|
9
|
+
|
|
10
|
+
from dotflow.abc.notify import Notify
|
|
11
|
+
from dotflow.core.types.status import TypeStatus
|
|
12
|
+
from dotflow.logging import logger
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class NotifyTelegram(Notify):
|
|
16
|
+
"""
|
|
17
|
+
Import:
|
|
18
|
+
You can import the **NotifyTelegram** class with:
|
|
19
|
+
|
|
20
|
+
from dotflow.providers import NotifyTelegram
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
`class` dotflow.providers.notify_telegram.NotifyTelegram
|
|
24
|
+
|
|
25
|
+
from dotflow import Config, DotFlow
|
|
26
|
+
from dotflow.providers import NotifyTelegram
|
|
27
|
+
from dotflow.core.types.status import TypeStatus
|
|
28
|
+
|
|
29
|
+
config = Config(
|
|
30
|
+
notify=NotifyTelegram(
|
|
31
|
+
token="YOUR_BOT_TOKEN",
|
|
32
|
+
chat_id=123456789,
|
|
33
|
+
notification_type=TypeStatus.FAILED,
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
workflow = DotFlow(config=config)
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
token (str): Telegram bot token from BotFather.
|
|
41
|
+
|
|
42
|
+
chat_id (int): Telegram chat ID to send messages to.
|
|
43
|
+
|
|
44
|
+
notification_type (Optional[TypeStatus]): Filter notifications
|
|
45
|
+
by task status. If None, all statuses are notified.
|
|
46
|
+
|
|
47
|
+
show_result (bool): Include task result in the notification.
|
|
48
|
+
Defaults to False.
|
|
49
|
+
|
|
50
|
+
timeout (float): Request timeout in seconds.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
API_URL = "https://api.telegram.org/bot{token}/sendMessage"
|
|
54
|
+
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
token: str,
|
|
58
|
+
chat_id: int,
|
|
59
|
+
notification_type: TypeStatus | None = None,
|
|
60
|
+
show_result: bool = False,
|
|
61
|
+
timeout: float = 1.5,
|
|
62
|
+
):
|
|
63
|
+
self.token = token
|
|
64
|
+
self.chat_id = chat_id
|
|
65
|
+
self.notification_type = notification_type
|
|
66
|
+
self.show_result = show_result
|
|
67
|
+
self.timeout = timeout
|
|
68
|
+
|
|
69
|
+
def hook_status_task(self, task: Any) -> None:
|
|
70
|
+
if self.notification_type and self.notification_type != task.status:
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
response = post(
|
|
75
|
+
url=self.API_URL.format(token=self.token),
|
|
76
|
+
headers={"Content-Type": "application/json"},
|
|
77
|
+
data=dumps(
|
|
78
|
+
{
|
|
79
|
+
"chat_id": self.chat_id,
|
|
80
|
+
"text": self._build_message(task),
|
|
81
|
+
"parse_mode": "markdown",
|
|
82
|
+
}
|
|
83
|
+
),
|
|
84
|
+
timeout=self.timeout,
|
|
85
|
+
)
|
|
86
|
+
response.raise_for_status()
|
|
87
|
+
except Exception as error:
|
|
88
|
+
logger.error(
|
|
89
|
+
"Internal problem sending notification on Telegram: %s",
|
|
90
|
+
str(error),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def _build_message(self, task: Any) -> str:
|
|
94
|
+
symbol = TypeStatus.get_symbol(task.status)
|
|
95
|
+
header = f"{symbol} {task.status}"
|
|
96
|
+
footer = f"`{task.workflow_id}` — Task {task.task_id}"
|
|
97
|
+
|
|
98
|
+
parts = [header]
|
|
99
|
+
|
|
100
|
+
if self.show_result:
|
|
101
|
+
parts.append(f"```json\n{task.result(max=4000)}```")
|
|
102
|
+
|
|
103
|
+
if task.status == TypeStatus.FAILED and task.errors:
|
|
104
|
+
last_error = task.errors[-1]
|
|
105
|
+
parts.append(f"`{last_error.exception}`: {last_error.message}")
|
|
106
|
+
|
|
107
|
+
parts.append(footer)
|
|
108
|
+
|
|
109
|
+
return "\n".join(parts)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dotflow"
|
|
3
|
-
version = "0.14.1.
|
|
3
|
+
version = "0.14.1.dev2"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name="Fernando Celmer", email="email@fernandocelmer.com" },
|
|
6
6
|
]
|
|
@@ -60,7 +60,7 @@ scheduler = ["croniter"]
|
|
|
60
60
|
|
|
61
61
|
[tool.poetry]
|
|
62
62
|
name = "dotflow"
|
|
63
|
-
version = "0.14.1.
|
|
63
|
+
version = "0.14.1.dev2"
|
|
64
64
|
description = "🎲 Dotflow turns an idea into flow! Lightweight Python library for execution pipelines with retry, parallel, cron and async support."
|
|
65
65
|
authors = ["Fernando Celmer <email@fernandocelmer.com>"]
|
|
66
66
|
readme = "README.md"
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"""Notify Default"""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from json import dumps
|
|
6
|
-
from typing import Any
|
|
7
|
-
|
|
8
|
-
from requests import post
|
|
9
|
-
|
|
10
|
-
from dotflow.abc.notify import Notify
|
|
11
|
-
from dotflow.core.types.status import TypeStatus
|
|
12
|
-
from dotflow.logging import logger
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class NotifyTelegram(Notify):
|
|
16
|
-
MESSAGE = "{symbol} {status}\n```json\n{task}```\n{workflow_id}-{task_id}"
|
|
17
|
-
API_TELEGRAM = "https://api.telegram.org/bot{token}/sendMessage"
|
|
18
|
-
|
|
19
|
-
def __init__(
|
|
20
|
-
self,
|
|
21
|
-
token: str,
|
|
22
|
-
chat_id: int,
|
|
23
|
-
notification_type: TypeStatus | None = None,
|
|
24
|
-
timeout: int = 1.5,
|
|
25
|
-
):
|
|
26
|
-
self.token = token
|
|
27
|
-
self.chat_id = chat_id
|
|
28
|
-
self.notification_type = notification_type
|
|
29
|
-
self.timeout = timeout
|
|
30
|
-
|
|
31
|
-
def send(self, task: Any) -> None:
|
|
32
|
-
if not self.notification_type or self.notification_type == task.status:
|
|
33
|
-
data = {
|
|
34
|
-
"chat_id": self.chat_id,
|
|
35
|
-
"text": self._get_text(task=task),
|
|
36
|
-
"parse_mode": "markdown",
|
|
37
|
-
}
|
|
38
|
-
try:
|
|
39
|
-
response = post(
|
|
40
|
-
url=self.API_TELEGRAM.format(token=self.token),
|
|
41
|
-
headers={"Content-Type": "application/json"},
|
|
42
|
-
data=dumps(data),
|
|
43
|
-
timeout=self.timeout,
|
|
44
|
-
)
|
|
45
|
-
response.raise_for_status()
|
|
46
|
-
except Exception as error:
|
|
47
|
-
logger.error(
|
|
48
|
-
"Internal problem sending notification on Telegram: %s",
|
|
49
|
-
str(error),
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
def _get_text(self, task: Any) -> str:
|
|
53
|
-
return self.MESSAGE.format(
|
|
54
|
-
symbol=TypeStatus.get_symbol(task.status),
|
|
55
|
-
status=task.status,
|
|
56
|
-
workflow_id=task.workflow_id,
|
|
57
|
-
task_id=task.task_id,
|
|
58
|
-
task=task.result(max=4000),
|
|
59
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|