serverwatcher 5.6.1__tar.gz → 5.8__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.
- {serverwatcher-5.6.1/src/serverwatcher.egg-info → serverwatcher-5.8}/PKG-INFO +1 -1
- {serverwatcher-5.6.1 → serverwatcher-5.8}/pyproject.toml +1 -1
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher/configclasses/config.py +5 -5
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher/configclasses/messages.py +23 -26
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher/configclasses/watcher.py +4 -2
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher/defaultconfigs/config.yaml +1 -2
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher/defaultconfigs/messages.yaml +4 -22
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher/defaultconfigs/watcher.yaml +2 -0
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher/validator.py +5 -18
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher/watcher.py +49 -67
- {serverwatcher-5.6.1 → serverwatcher-5.8/src/serverwatcher.egg-info}/PKG-INFO +1 -1
- {serverwatcher-5.6.1 → serverwatcher-5.8}/LICENSE +0 -0
- {serverwatcher-5.6.1 → serverwatcher-5.8}/README.md +0 -0
- {serverwatcher-5.6.1 → serverwatcher-5.8}/setup.cfg +0 -0
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher/__init__.py +0 -0
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher/configclasses/__init__.py +0 -0
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher.egg-info/SOURCES.txt +0 -0
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher.egg-info/dependency_links.txt +0 -0
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher.egg-info/requires.txt +0 -0
- {serverwatcher-5.6.1 → serverwatcher-5.8}/src/serverwatcher.egg-info/top_level.txt +0 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
from dataclasses import
|
|
1
|
+
from dataclasses import field
|
|
2
|
+
from hungerlib import datamap, datamap_api
|
|
2
3
|
|
|
3
4
|
def yaml_key(path: str, default=None):
|
|
4
5
|
return field(default=default, metadata={"yaml_key": path})
|
|
5
6
|
|
|
6
|
-
@
|
|
7
|
+
@datamap(syntax=datamap_api.braces)
|
|
7
8
|
class GlobalConfig:
|
|
8
|
-
|
|
9
|
+
timezone: str = yaml_key("timezone")
|
|
9
10
|
|
|
10
11
|
panel_name: str = yaml_key("panel.name")
|
|
11
12
|
panel_url: str = yaml_key("panel.url")
|
|
@@ -25,7 +26,6 @@ class GlobalConfig:
|
|
|
25
26
|
enable_logging: bool = yaml_key("logger.enabled")
|
|
26
27
|
logger_name: str = yaml_key("logger.name")
|
|
27
28
|
log_path: str = yaml_key("logger.log_path")
|
|
28
|
-
timezone: str = yaml_key("logger.timezone")
|
|
29
29
|
|
|
30
30
|
console_backspaces: int = yaml_key("terminal.backspaces")
|
|
31
|
-
clear_terminal: bool = yaml_key("terminal.enable_clearing")
|
|
31
|
+
clear_terminal: bool = yaml_key("terminal.enable_clearing")
|
|
@@ -1,36 +1,35 @@
|
|
|
1
|
-
from dataclasses import
|
|
1
|
+
from dataclasses import field
|
|
2
|
+
from hungerlib import datamap, datamap_api
|
|
2
3
|
|
|
3
4
|
def yaml_key(path: str, default=None):
|
|
4
5
|
return field(default=default, metadata={"yaml_key": path})
|
|
5
6
|
|
|
6
|
-
@
|
|
7
|
+
@datamap(syntax=datamap_api.braces)
|
|
7
8
|
class MessagesConfig:
|
|
8
|
-
prefix: str = yaml_key("prefix")
|
|
9
|
-
broadcast_restart_at: str = yaml_key("broadcast_restart_at")
|
|
9
|
+
prefix: str = yaml_key("prefix", "<aqua>[Server Watcher]")
|
|
10
10
|
bullet: str = yaml_key("bullet")
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
minute_120: str = yaml_key("broadcast_minutes.120")
|
|
14
|
-
minute_60: str = yaml_key("broadcast_minutes.60")
|
|
15
|
-
minute_45: str = yaml_key("broadcast_minutes.45")
|
|
16
|
-
minute_30: str = yaml_key("broadcast_minutes.30")
|
|
17
|
-
minute_15: str = yaml_key("broadcast_minutes.15")
|
|
18
|
-
minute_5: str = yaml_key("broadcast_minutes.5")
|
|
19
|
-
minute_1: str = yaml_key("broadcast_minutes.1")
|
|
12
|
+
broadcast_restart_at: str = yaml_key("broadcast_restart_at")
|
|
20
13
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
14
|
+
minute_120: str = yaml_key("broadcast_minutes.120", "{prefix} Restart in 2 hours!")
|
|
15
|
+
minute_60: str = yaml_key("broadcast_minutes.60", "{prefix} Restart in 1 hour!")
|
|
16
|
+
minute_45: str = yaml_key("broadcast_minutes.45", "{prefix} Restart in 45 minutes!")
|
|
17
|
+
minute_30: str = yaml_key("broadcast_minutes.30", "{prefix} Restart in 30 minutes!")
|
|
18
|
+
minute_15: str = yaml_key("broadcast_minutes.15", "{prefix} Restart in 15 minutes!")
|
|
19
|
+
minute_5: str = yaml_key("broadcast_minutes.5", "{prefix} Restart in 5 minutes!")
|
|
20
|
+
minute_1: str = yaml_key("broadcast_minutes.1", "{prefix} Restart in 1 minute!")
|
|
21
|
+
|
|
22
|
+
second_10: str = yaml_key("broadcast_seconds.10", "{prefix} Restart in 10 seconds!")
|
|
23
|
+
second_9: str = yaml_key("broadcast_seconds.9", "{prefix} Restart in 9 seconds!")
|
|
24
|
+
second_8: str = yaml_key("broadcast_seconds.8", "{prefix} Restart in 8 seconds!")
|
|
25
|
+
second_7: str = yaml_key("broadcast_seconds.7", "{prefix} Restart in 7 seconds!")
|
|
26
|
+
second_6: str = yaml_key("broadcast_seconds.6", "{prefix} Restart in 6 seconds!")
|
|
27
|
+
second_5: str = yaml_key("broadcast_seconds.5", "{prefix} Restart in 5 seconds!")
|
|
28
|
+
second_4: str = yaml_key("broadcast_seconds.4", "{prefix} Restart in 4 seconds!")
|
|
29
|
+
second_3: str = yaml_key("broadcast_seconds.3", "{prefix} Restart in 3 seconds!")
|
|
30
|
+
second_2: str = yaml_key("broadcast_seconds.2", "{prefix} Restart in 2 seconds!")
|
|
31
|
+
second_1: str = yaml_key("broadcast_seconds.1", "{prefix} Restart in 1 second!")
|
|
32
32
|
|
|
33
|
-
# logging
|
|
34
33
|
startup: str = yaml_key("logging.startup")
|
|
35
34
|
status_check: str = yaml_key("logging.status_check")
|
|
36
35
|
validation_fail: str = yaml_key("logging.validation_fail")
|
|
@@ -42,7 +41,6 @@ class MessagesConfig:
|
|
|
42
41
|
gap_low: str = yaml_key("logging.gap_low")
|
|
43
42
|
gap_high: str = yaml_key("logging.gap_high")
|
|
44
43
|
|
|
45
|
-
# reasons
|
|
46
44
|
pro_restart_splash: str = yaml_key("reasons.pro_splash")
|
|
47
45
|
anti_restart_splash: str = yaml_key("reasons.anti_splash")
|
|
48
46
|
|
|
@@ -57,7 +55,6 @@ class MessagesConfig:
|
|
|
57
55
|
pro_restart_number: str = yaml_key("reasons.pro_restart_number")
|
|
58
56
|
anti_restart_number: str = yaml_key("reasons.anti_restart_number")
|
|
59
57
|
|
|
60
|
-
# restarts
|
|
61
58
|
restart_action_sent: str = yaml_key("restarts.restart_action_sent")
|
|
62
59
|
server_back_online: str = yaml_key("restarts.back_online")
|
|
63
60
|
server_back_online_broadcast: str = yaml_key("restarts.back_online_broadcast")
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
from dataclasses import
|
|
1
|
+
from dataclasses import field
|
|
2
|
+
from hungerlib import datamap, datamap_api
|
|
2
3
|
|
|
3
4
|
def yaml_key(path: str, default=None):
|
|
4
5
|
return field(default=default, metadata={"yaml_key": path})
|
|
5
6
|
|
|
6
|
-
@
|
|
7
|
+
@datamap(syntax=datamap_api.braces)
|
|
7
8
|
class WatcherConfig:
|
|
9
|
+
watch_interval: int = yaml_key("watch_interval")
|
|
8
10
|
schedule_control: bool = yaml_key("schedule_control.enabled")
|
|
9
11
|
restart_soon_id: int = yaml_key("schedule_control.restart_soon_id")
|
|
10
12
|
|
|
@@ -1,28 +1,10 @@
|
|
|
1
1
|
prefix: '<aqua>[Server Watcher]'
|
|
2
|
-
|
|
3
|
-
broadcast_restart_at: '{prefix} The server will restart at {time} CDT.'
|
|
4
2
|
bullet: '-'
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
'120': '{prefix} Restart in 2 hours!'
|
|
8
|
-
'60': '{prefix} Restart in 1 hour!'
|
|
9
|
-
'45': '{prefix} Restart in 45 minutes!'
|
|
10
|
-
'30': '{prefix} Restart in 30 minutes!'
|
|
11
|
-
'15': '{prefix} Restart in 15 minutes!'
|
|
12
|
-
'5': '{prefix} Restart in 5 minutes!'
|
|
13
|
-
'1': '{prefix} Restart in 1 minute!'
|
|
4
|
+
broadcast_restart_at: '{prefix} The server will restart at {time} CDT.'
|
|
14
5
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
'9': '{prefix} Restart in 9 seconds!'
|
|
18
|
-
'8': '{prefix} Restart in 8 seconds!'
|
|
19
|
-
'7': '{prefix} Restart in 7 seconds!'
|
|
20
|
-
'6': '{prefix} Restart in 6 seconds!'
|
|
21
|
-
'5': '{prefix} Restart in 5 seconds!'
|
|
22
|
-
'4': '{prefix} Restart in 4 seconds!'
|
|
23
|
-
'3': '{prefix} Restart in 3 seconds!'
|
|
24
|
-
'2': '{prefix} Restart in 2 seconds!'
|
|
25
|
-
'1': '{prefix} Restart in 1 second!'
|
|
6
|
+
broadcast_minutes: {}
|
|
7
|
+
broadcast_seconds: {}
|
|
26
8
|
|
|
27
9
|
logging:
|
|
28
10
|
startup: 'ServerWatcher is running!'
|
|
@@ -46,7 +28,7 @@ reasons:
|
|
|
46
28
|
uptime: 'Uptime {uptime} exceeds {threshold}h'
|
|
47
29
|
tps: 'TPS {tps} is lower than {threshold}'
|
|
48
30
|
low_uptime: 'Uptime {uptime} is shorter than 30m'
|
|
49
|
-
players: 'There {verb} {count} {plural} online'
|
|
31
|
+
players: 'There {verb} {count} {plural} online' # produces: "There are 2 players online" or "There is 1 player online"
|
|
50
32
|
|
|
51
33
|
pro_restart_number: 'Pro-restart: '
|
|
52
34
|
anti_restart_number: 'Anti-restart:'
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
from dataclasses import fields
|
|
3
|
-
|
|
4
|
-
from hungerlib.addons import loadConfig
|
|
3
|
+
from hungerlib import utils, loadConfig
|
|
5
4
|
|
|
6
5
|
from serverwatcher.configclasses.config import GlobalConfig
|
|
7
6
|
from serverwatcher.configclasses.messages import MessagesConfig
|
|
8
7
|
from serverwatcher.configclasses.watcher import WatcherConfig
|
|
9
8
|
|
|
9
|
+
utils.clearTerminal()
|
|
10
10
|
|
|
11
11
|
def deep_get_attr(obj, dotted):
|
|
12
12
|
parts = dotted.split(".")
|
|
@@ -17,22 +17,18 @@ def deep_get_attr(obj, dotted):
|
|
|
17
17
|
cur = getattr(cur, p)
|
|
18
18
|
return cur
|
|
19
19
|
|
|
20
|
-
|
|
21
20
|
def validate_type(name, value, expected_type, errors):
|
|
22
21
|
if not isinstance(value, expected_type):
|
|
23
22
|
errors.append(f"{name}: expected {expected_type.__name__}, got {type(value).__name__}")
|
|
24
23
|
|
|
25
|
-
|
|
26
24
|
def validate_positive(name, value, errors):
|
|
27
25
|
if isinstance(value, (int, float)) and value < 0:
|
|
28
26
|
errors.append(f"{name}: must be >= 0 (got {value})")
|
|
29
27
|
|
|
30
|
-
|
|
31
28
|
def validate_nonempty(name, value, errors):
|
|
32
29
|
if isinstance(value, str) and value.strip() == "":
|
|
33
30
|
errors.append(f"{name}: cannot be empty")
|
|
34
31
|
|
|
35
|
-
|
|
36
32
|
def validate_dataclass(config_obj, schema, errors):
|
|
37
33
|
for f in fields(schema):
|
|
38
34
|
name = f.name
|
|
@@ -47,18 +43,13 @@ def validate_dataclass(config_obj, schema, errors):
|
|
|
47
43
|
if expected_type in (int, float):
|
|
48
44
|
validate_positive(name, value, errors)
|
|
49
45
|
|
|
50
|
-
|
|
51
46
|
def validate_global_config(config, errors):
|
|
52
|
-
if config.watch_interval < 1:
|
|
53
|
-
errors.append(f"watch_interval: must be >= 1 (got {config.watch_interval})")
|
|
54
|
-
|
|
55
47
|
if config.server_port <= 0 or config.server_port > 65535:
|
|
56
48
|
errors.append(f"server_port: must be 1–65535 (got {config.server_port})")
|
|
57
49
|
|
|
58
50
|
if config.rcon_port <= 0 or config.rcon_port > 65535:
|
|
59
51
|
errors.append(f"rcon_port: must be 1–65535 (got {config.rcon_port})")
|
|
60
52
|
|
|
61
|
-
|
|
62
53
|
def validate_watcher_config(watcherconfig, errors):
|
|
63
54
|
if watcherconfig.restart_wait_seconds < 1:
|
|
64
55
|
errors.append(f"restart_wait_seconds: must be >= 1 (got {watcherconfig.restart_wait_seconds})")
|
|
@@ -72,13 +63,12 @@ def validate_watcher_config(watcherconfig, errors):
|
|
|
72
63
|
if watcherconfig.threshold_tps <= 0 or watcherconfig.threshold_tps > 20:
|
|
73
64
|
errors.append(f"threshold_tps: must be 1–20 (got {watcherconfig.threshold_tps})")
|
|
74
65
|
|
|
75
|
-
|
|
76
66
|
def validate_messages_config(messages, errors):
|
|
77
|
-
for
|
|
67
|
+
for f in fields(MessagesConfig):
|
|
68
|
+
value = getattr(messages, f.name)
|
|
78
69
|
if isinstance(value, str) and "{prefix}" not in value:
|
|
79
70
|
pass
|
|
80
71
|
|
|
81
|
-
|
|
82
72
|
def ensure_no_global_defaults(config, defaults):
|
|
83
73
|
if config.panel_url == "https://example.com":
|
|
84
74
|
defaults.append('panel_url')
|
|
@@ -98,12 +88,10 @@ def ensure_no_global_defaults(config, defaults):
|
|
|
98
88
|
if config.rcon_password == 'password':
|
|
99
89
|
defaults.append('rcon_password')
|
|
100
90
|
|
|
101
|
-
|
|
102
91
|
def ensure_no_watcher_defaults(watcherconfig, defaults):
|
|
103
92
|
if watcherconfig.schedule_control and watcherconfig.restart_soon_id == 0:
|
|
104
93
|
defaults.append('restart_soon_id')
|
|
105
94
|
|
|
106
|
-
|
|
107
95
|
def validate_all():
|
|
108
96
|
errors = []
|
|
109
97
|
defaults = []
|
|
@@ -123,7 +111,7 @@ def validate_all():
|
|
|
123
111
|
ensure_no_global_defaults(config, defaults)
|
|
124
112
|
ensure_no_watcher_defaults(watcher, defaults)
|
|
125
113
|
|
|
126
|
-
if len(defaults) >=
|
|
114
|
+
if len(defaults) >= 5:
|
|
127
115
|
print("❌ CONFIG VALIDATION FAILED:\nIt looks like you haven't configured this yet! Please change these defaults:")
|
|
128
116
|
for d in defaults:
|
|
129
117
|
print(" -", d)
|
|
@@ -139,6 +127,5 @@ def validate_all():
|
|
|
139
127
|
|
|
140
128
|
print("✅ All configs are valid.")
|
|
141
129
|
|
|
142
|
-
|
|
143
130
|
if __name__ == "__main__":
|
|
144
131
|
validate_all()
|
|
@@ -1,48 +1,19 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import time
|
|
3
|
-
import re
|
|
4
3
|
from zoneinfo import ZoneInfo
|
|
5
4
|
|
|
6
|
-
from hungerlib import
|
|
7
|
-
from hungerlib.servers import MinecraftServer, GenericServer
|
|
8
|
-
from hungerlib.addons import (
|
|
9
|
-
clearTerminal,
|
|
10
|
-
Snapshot,
|
|
11
|
-
snapSchedule,
|
|
12
|
-
waitForOnline,
|
|
13
|
-
validateAll,
|
|
14
|
-
runCountdownEvents,
|
|
15
|
-
loadConfig,
|
|
16
|
-
)
|
|
5
|
+
from hungerlib import servers, MessageRouter, loadConfig, utils, datamap_api, mapit
|
|
17
6
|
|
|
18
7
|
from serverwatcher.configclasses.config import GlobalConfig
|
|
19
8
|
from serverwatcher.configclasses.messages import MessagesConfig
|
|
20
9
|
from serverwatcher.configclasses.watcher import WatcherConfig
|
|
21
|
-
|
|
22
10
|
from serverwatcher.validator import validate_all
|
|
23
11
|
|
|
24
12
|
validate_all()
|
|
25
13
|
|
|
26
|
-
_T_EXPR = re.compile(r"{([^{}]+)}")
|
|
27
|
-
|
|
28
|
-
def t_eval(template: str, /, **ctx):
|
|
29
|
-
"""
|
|
30
|
-
Evaluate a t-string-like template with Python expressions inside { }.
|
|
31
|
-
Example:
|
|
32
|
-
t_eval("CPU: {snap.cpu}%", snap=snap)
|
|
33
|
-
"""
|
|
34
|
-
def repl(match):
|
|
35
|
-
expr = match.group(1).strip()
|
|
36
|
-
try:
|
|
37
|
-
return str(eval(expr, {}, ctx))
|
|
38
|
-
except Exception as e:
|
|
39
|
-
return f"<err:{e}>"
|
|
40
|
-
|
|
41
|
-
return _T_EXPR.sub(repl, template)
|
|
42
14
|
|
|
43
15
|
class ServerWatcher:
|
|
44
16
|
def __init__(self):
|
|
45
|
-
|
|
46
17
|
self.config = loadConfig(
|
|
47
18
|
"config/config.yaml",
|
|
48
19
|
"/defaultconfigs/config.yaml",
|
|
@@ -61,19 +32,26 @@ class ServerWatcher:
|
|
|
61
32
|
WatcherConfig
|
|
62
33
|
)
|
|
63
34
|
|
|
64
|
-
|
|
35
|
+
datamap_api.set_default_maps(
|
|
36
|
+
utils.ASCII_COLOR_MAP,
|
|
37
|
+
self.config,
|
|
38
|
+
self.messages,
|
|
39
|
+
self.watcherconfig
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
self.panel = servers.Panel(
|
|
65
43
|
name=self.config.panel_name,
|
|
66
44
|
url=self.config.panel_url,
|
|
67
45
|
api_key=self.config.panel_api_key,
|
|
68
46
|
)
|
|
69
47
|
|
|
70
|
-
self.origin =
|
|
48
|
+
self.origin = servers.Generic(
|
|
71
49
|
name="Origin",
|
|
72
50
|
panel=self.panel,
|
|
73
51
|
server_id=self.config.origin_server_id
|
|
74
52
|
)
|
|
75
53
|
|
|
76
|
-
self.server =
|
|
54
|
+
self.server = servers.Minecraft(
|
|
77
55
|
name=self.config.server_name,
|
|
78
56
|
panel=self.panel,
|
|
79
57
|
server_id=self.config.server_id,
|
|
@@ -84,27 +62,31 @@ class ServerWatcher:
|
|
|
84
62
|
tpsCommand=self.config.tps_command,
|
|
85
63
|
)
|
|
86
64
|
|
|
87
|
-
logger_name = self.config.logger_name.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
self.log = HungerLogger(
|
|
92
|
-
name=self.config.logger_name,
|
|
65
|
+
logger_name = mapit(self.config.logger_name, server_name=self.config.server_name)
|
|
66
|
+
|
|
67
|
+
self.router = MessageRouter(
|
|
68
|
+
name=logger_name,
|
|
93
69
|
server=self.server,
|
|
94
70
|
log_path=self.config.log_path,
|
|
71
|
+
formatter=self._fmt,
|
|
95
72
|
console_backspaces=self.config.console_backspaces,
|
|
96
73
|
)
|
|
97
74
|
|
|
98
75
|
self.tz = ZoneInfo(self.config.timezone)
|
|
99
76
|
|
|
100
|
-
def
|
|
101
|
-
return
|
|
77
|
+
def _fmt(self, template: str, **ctx):
|
|
78
|
+
return mapit(template, **ctx)
|
|
102
79
|
|
|
103
|
-
def say(self, template, level="info", **
|
|
80
|
+
def say(self, template, level="info", **ctx):
|
|
104
81
|
if not template:
|
|
105
82
|
return
|
|
106
|
-
|
|
107
|
-
|
|
83
|
+
msg = mapit(template, **ctx)
|
|
84
|
+
self.router.say(
|
|
85
|
+
msg,
|
|
86
|
+
level=level,
|
|
87
|
+
log=self.config.enable_logging,
|
|
88
|
+
**ctx
|
|
89
|
+
)
|
|
108
90
|
|
|
109
91
|
def shutdown(self):
|
|
110
92
|
self.say(self.messages.shutdown)
|
|
@@ -113,12 +95,13 @@ class ServerWatcher:
|
|
|
113
95
|
def restart_and_wait(self):
|
|
114
96
|
if self.watcherconfig.schedule_control:
|
|
115
97
|
self.origin.disableSchedule(self.watcherconfig.restart_soon_id)
|
|
98
|
+
|
|
116
99
|
self.server.restart()
|
|
117
100
|
self.say(self.messages.restart_action_sent)
|
|
118
101
|
time.sleep(self.watcherconfig.restart_wait_seconds)
|
|
119
102
|
|
|
120
103
|
self.say(self.messages.status_check, level="warn")
|
|
121
|
-
alive = waitForOnline(
|
|
104
|
+
alive = utils.waitForOnline(
|
|
122
105
|
self.server,
|
|
123
106
|
timeout=self.watcherconfig.restart_timeout,
|
|
124
107
|
interval=self.watcherconfig.restart_online_interval,
|
|
@@ -126,7 +109,7 @@ class ServerWatcher:
|
|
|
126
109
|
|
|
127
110
|
if alive:
|
|
128
111
|
self.say(self.messages.server_back_online)
|
|
129
|
-
self.say(self.messages.server_back_online_broadcast)
|
|
112
|
+
self.say(self.messages.server_back_online_broadcast, broadcast=True)
|
|
130
113
|
else:
|
|
131
114
|
self.say(self.messages.server_failed_restart, level="error")
|
|
132
115
|
|
|
@@ -137,12 +120,12 @@ class ServerWatcher:
|
|
|
137
120
|
local_time = scheduled.astimezone(self.tz)
|
|
138
121
|
time_str = local_time.strftime("%I:%M %p")
|
|
139
122
|
|
|
140
|
-
self.
|
|
123
|
+
self.router.broadcast(mapit(self.messages.broadcast_restart_at, time=time_str))
|
|
141
124
|
|
|
142
125
|
minute_callbacks = {
|
|
143
126
|
int(k.split("_")[1]): (
|
|
144
|
-
lambda msg=
|
|
145
|
-
self.
|
|
127
|
+
lambda msg=mapit(getattr(self.messages, k)):
|
|
128
|
+
self.router.broadcast(msg)
|
|
146
129
|
)
|
|
147
130
|
for k in vars(self.messages)
|
|
148
131
|
if k.startswith("minute_")
|
|
@@ -150,8 +133,8 @@ class ServerWatcher:
|
|
|
150
133
|
|
|
151
134
|
second_callbacks = {
|
|
152
135
|
int(k.split("_")[1]): (
|
|
153
|
-
lambda msg=
|
|
154
|
-
self.
|
|
136
|
+
lambda msg=mapit(getattr(self.messages, k)):
|
|
137
|
+
self.router.broadcast(msg)
|
|
155
138
|
)
|
|
156
139
|
for k in vars(self.messages)
|
|
157
140
|
if k.startswith("second_")
|
|
@@ -166,12 +149,12 @@ class ServerWatcher:
|
|
|
166
149
|
def evaluate(self):
|
|
167
150
|
self.say(self.messages.startup)
|
|
168
151
|
|
|
169
|
-
if not validateAll(self.panel, self.server):
|
|
152
|
+
if not utils.validateAll(self.panel, self.server):
|
|
170
153
|
self.say(self.messages.validation_fail, level="error")
|
|
171
154
|
self.shutdown()
|
|
172
155
|
|
|
173
156
|
self.server.refresh()
|
|
174
|
-
snap = Snapshot(self.server, 2, True)
|
|
157
|
+
snap = utils.Snapshot(self.server, 2, True)
|
|
175
158
|
|
|
176
159
|
pro = 0
|
|
177
160
|
anti = 0
|
|
@@ -183,46 +166,45 @@ class ServerWatcher:
|
|
|
183
166
|
pro += self.watcherconfig.weight_restart_soon
|
|
184
167
|
|
|
185
168
|
if snap.ram >= self.watcherconfig.threshold_ram:
|
|
186
|
-
restart_reasons.append(
|
|
169
|
+
restart_reasons.append(mapit(self.messages.reason_ram, ram=snap.ram, threshold=self.watcherconfig.threshold_ram))
|
|
187
170
|
pro += int(round(snap.ram, 0) - (self.watcherconfig.threshold_ram - 1))
|
|
188
171
|
|
|
189
172
|
if snap.cpu >= self.watcherconfig.threshold_cpu:
|
|
190
|
-
restart_reasons.append(
|
|
173
|
+
restart_reasons.append(mapit(self.messages.reason_cpu, cpu=snap.cpu, threshold=self.watcherconfig.threshold_cpu))
|
|
191
174
|
pro += self.watcherconfig.weight_cpu
|
|
192
175
|
|
|
193
176
|
if snap.uptime // 3600 >= self.watcherconfig.threshold_uptime:
|
|
194
177
|
restart_reasons.append(
|
|
195
|
-
|
|
196
|
-
threshold=self.watcherconfig.threshold_uptime)
|
|
178
|
+
mapit(self.messages.reason_uptime, uptime=snap.uptime_formatted, threshold=self.watcherconfig.threshold_uptime)
|
|
197
179
|
)
|
|
198
180
|
pro += self.watcherconfig.weight_uptime
|
|
199
181
|
|
|
200
182
|
if (snap.tps if snap.tps is not None else 20) <= self.watcherconfig.threshold_tps:
|
|
201
|
-
restart_reasons.append(
|
|
183
|
+
restart_reasons.append(mapit(self.messages.reason_tps, tps=snap.tps, threshold=self.watcherconfig.threshold_tps))
|
|
202
184
|
pro += self.watcherconfig.weight_tps
|
|
203
185
|
|
|
204
186
|
if snap.uptime // 60 < 30:
|
|
205
|
-
no_restart_reasons.append(
|
|
187
|
+
no_restart_reasons.append(mapit(self.messages.reason_low_uptime, uptime=snap.uptime_formatted))
|
|
206
188
|
anti += self.watcherconfig.weight_low_uptime
|
|
207
189
|
|
|
208
190
|
if snap.players > 0:
|
|
209
191
|
verb = "are" if snap.players != 1 else "is"
|
|
210
192
|
plural = "players" if snap.players != 1 else "player"
|
|
211
|
-
no_restart_reasons.append(
|
|
193
|
+
no_restart_reasons.append(mapit(self.messages.reason_players, verb=verb, count=snap.players, plural=plural))
|
|
212
194
|
anti += snap.players * self.watcherconfig.weight_per_player
|
|
213
195
|
|
|
214
196
|
if restart_reasons:
|
|
215
197
|
self.say(self.messages.pro_restart_splash, level="warn")
|
|
216
198
|
for r in restart_reasons:
|
|
217
|
-
self.
|
|
199
|
+
self.say(f"{self.messages.bullet} {r}", level="warn")
|
|
218
200
|
|
|
219
201
|
if no_restart_reasons:
|
|
220
202
|
self.say(self.messages.anti_restart_splash, level="warn")
|
|
221
203
|
for r in no_restart_reasons:
|
|
222
|
-
self.
|
|
204
|
+
self.say(f"{self.messages.bullet} {r}", level="warn")
|
|
223
205
|
|
|
224
|
-
self.
|
|
225
|
-
self.
|
|
206
|
+
self.say(f"{self.messages.pro_restart_number} {pro}", level="warn")
|
|
207
|
+
self.say(f"{self.messages.anti_restart_number} {anti}", level="warn")
|
|
226
208
|
|
|
227
209
|
gap = abs(pro - anti)
|
|
228
210
|
|
|
@@ -248,9 +230,9 @@ class ServerWatcher:
|
|
|
248
230
|
|
|
249
231
|
def run(self):
|
|
250
232
|
if self.config.clear_terminal:
|
|
251
|
-
clearTerminal()
|
|
233
|
+
utils.clearTerminal()
|
|
252
234
|
while True:
|
|
253
235
|
if self.config.clear_terminal:
|
|
254
|
-
clearTerminal()
|
|
236
|
+
utils.clearTerminal()
|
|
255
237
|
self.evaluate()
|
|
256
|
-
time.sleep(self.
|
|
238
|
+
time.sleep(self.watcherconfig.watch_interval)
|
|
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
|