Skip to content

Commit e2ed02d

Browse files
committed
add welcome message
1 parent 0c398a1 commit e2ed02d

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

modules/alert_bot.py

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
@dataclasses.dataclass
1212
class Alert:
1313
severity: str
14+
description: str
1415
text: str
1516
timeout: int
1617

@@ -29,75 +30,89 @@ def init_alerts():
2930
ALERTS = {
3031
"low_wallet_balance": Alert(
3132
"low",
32-
"Validator wallet {wallet} balance is low: {balance} TON.",
33+
"Validator's wallet balance is low",
34+
"Validator's wallet {wallet} balance is less than 10 TON: {balance} TON.",
3335
18 * HOUR
3436
),
3537
"db_usage_80": Alert(
3638
"high",
39+
"Node's db usage is more than 80%",
3740
"""TON DB usage > 80%. Clean the TON database:
3841
https://docs.ton.org/participate/nodes/node-maintenance-and-security#database-grooming
3942
or (and) set node\'s archive ttl to lower value.""",
4043
24 * HOUR
4144
),
4245
"db_usage_95": Alert(
4346
"critical",
47+
"Node's db usage is more than 95%",
4448
"""TON DB usage > 95%. Disk is almost full, clean the TON database immediately:
4549
https://docs.ton.org/participate/nodes/node-maintenance-and-security#database-grooming
4650
or (and) set node\'s archive ttl to lower value.""",
4751
6 * HOUR
4852
),
4953
"low_efficiency": Alert(
5054
"high",
51-
"""Validator efficiency is low: {efficiency}%.""",
55+
"Validator had low efficiency in the validation round",
56+
"""Validator efficiency is less than 90%: <b>{efficiency}%</b>.""",
5257
VALIDATION_PERIOD // 3
5358
),
5459
"out_of_sync": Alert(
5560
"critical",
56-
"Node is out of sync on {sync} sec.",
61+
"Validator had low efficiency in the round",
62+
"Node is out of sync on more than 20 sec: <b>{sync} sec</b>.",
5763
300
5864
),
5965
"service_down": Alert(
6066
"critical",
67+
"Node is not running (service is down)",
6168
"validator.service is down.",
6269
300
6370
),
6471
"adnl_connection_failed": Alert(
6572
"high",
73+
"Node is not answering to ADNL connection",
6674
"ADNL connection to node failed",
6775
3 * HOUR
6876
),
6977
"zero_block_created": Alert(
7078
"critical",
79+
"Validator has not created any blocks in the last few hours",
7180
"Validator has not created any blocks in the last {hours} hours.",
7281
VALIDATION_PERIOD // 3
7382
),
7483
"validator_slashed": Alert(
7584
"high",
85+
"Validator has been slashed in the previous validation round",
7686
"Validator has been slashed in previous round for {amount} TON",
7787
FREEZE_PERIOD
7888
),
7989
"stake_not_accepted": Alert(
8090
"high",
8191
"Validator's stake has not been accepted",
92+
"Validator's stake has not been accepted",
8293
ELECTIONS_START_BEFORE
8394
),
8495
"stake_accepted": Alert(
8596
"info",
97+
"Validator's stake has been accepted (info alert with no sound)",
8698
"Validator's stake {stake} TON has been accepted",
8799
ELECTIONS_START_BEFORE
88100
),
89101
"stake_returned": Alert(
90102
"info",
103+
"Validator's stake has been returned (info alert with no sound)",
91104
"Validator's stake {stake} TON has been returned on address {address}. The reward amount is {reward} TON.",
92105
60
93106
),
94107
"stake_not_returned": Alert(
95108
"high",
109+
"Validator's stake has not been returned",
96110
"Validator's stake has not been returned on address {address}.",
97111
60
98112
),
99113
"voting": Alert(
100114
"high",
115+
"There is an active network proposal that has many votes but is not voted by the validator",
101116
"Found proposals with hashes `{hashes}` that have significant amount of votes, but current validator didn't vote for them. Please check @tonstatus for more details.",
102117
VALIDATION_PERIOD
103118
),
@@ -120,14 +135,14 @@ def __init__(self, ton, local, *args, **kwargs):
120135
self.chat_id = None
121136
self.last_db_check = 0
122137

123-
def send_message(self, text: str, silent: bool = False):
138+
def send_message(self, text: str, silent: bool = False, disable_web_page_preview: bool = False):
124139
if self.token is None:
125140
raise Exception("send_message error: token is not initialized")
126141
if self.chat_id is None:
127142
raise Exception("send_message error: chat_id is not initialized")
128143
request_url = f"https://api.telegram.org/bot{self.token}/sendMessage"
129-
data = {'chat_id': self.chat_id, 'text': text, 'parse_mode': 'HTML', 'disable_notification': silent}
130-
response = requests.post(request_url, data=data, timeout=3)
144+
data = {'chat_id': self.chat_id, 'text': text, 'parse_mode': 'HTML', 'disable_notification': silent, 'link_preview_options': {'is_disabled': disable_web_page_preview}}
145+
response = requests.post(request_url, json=data, timeout=3)
131146
if response.status_code != 200:
132147
raise Exception(f"send_message error: {response.text}")
133148
response = response.json()
@@ -144,8 +159,7 @@ def send_alert(self, alert_name: str, *args, **kwargs):
144159
raise Exception(f"Alert {alert_name} not found")
145160
alert_name_readable = alert_name.replace('_', ' ').title()
146161
text = '🆘' if alert.severity != 'info' else ''
147-
text += f'''
148-
️ <b>Node {self.hostname}: {alert_name_readable} </b>
162+
text += f''' <b>Node {self.hostname}: {alert_name_readable} </b>
149163
150164
{alert.text.format(*args, **kwargs)}
151165
@@ -236,6 +250,39 @@ def test_alert(self, args):
236250
self.init()
237251
self.send_message('Test alert')
238252

253+
def send_welcome_message(self):
254+
message = """
255+
👋 Hello, this is alert bot.
256+
257+
I don't process any commands, I only send notifications.
258+
259+
Current notifications enabled:
260+
261+
"""
262+
for alert in ALERTS.values():
263+
message += f"- {alert.description}\n"
264+
265+
message += """
266+
If you want, you can disable some notifications in mytonctrl by the <a href="https://docs.ton.org/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-private-alerting#endisbling-alerts"> instruction </a>.
267+
268+
Full bot documentation <a href="https://docs.ton.org/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-private-alerting"> here</a>.
269+
"""
270+
self.send_message(text=message, disable_web_page_preview=True)
271+
272+
def on_set_chat_id(self, chat_id):
273+
self.token = self.ton.local.db.get("BotToken")
274+
if self.token is None:
275+
raise Exception("BotToken is not set")
276+
self.chat_id = chat_id
277+
init_alerts()
278+
try:
279+
self.send_welcome_message()
280+
return True
281+
except Exception as e:
282+
self.local.add_log(f"Error while sending welcome message: {e}", "error")
283+
self.local.add_log(f"If you want the bot to write to a multi-person chat group, make sure the bot is added to that chat group and has admin rights. If it is not - do it and run the command `set ChatId <ChatId>` again.", "info")
284+
return False
285+
239286
def check_db_usage(self):
240287
if time.time() - self.last_db_check < 600:
241288
return

mytonctrl/mytonctrl.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,7 @@ def GetSettings(ton, args):
879879
print(json.dumps(result, indent=2))
880880
#end define
881881

882-
def SetSettings(ton, args):
882+
def SetSettings(local, ton, args):
883883
try:
884884
name = args[0]
885885
value = args[1]
@@ -891,6 +891,10 @@ def SetSettings(ton, args):
891891
color_print(f"{{red}} Error: set {name} ... is deprecated and does not work {{endc}}."
892892
f"\nInstead, use {{bold}}enable_mode {mode_name}{{endc}}")
893893
return
894+
if name == 'ChatId':
895+
from modules.alert_bot import AlertBotModule
896+
if not AlertBotModule(ton, local).on_set_chat_id(value):
897+
return
894898
force = False
895899
if len(args) > 2:
896900
if args[2] == "--force":

0 commit comments

Comments
 (0)