serverwatcher 5.17.5__tar.gz → 5.18__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.17.5/src/serverwatcher.egg-info → serverwatcher-5.18}/PKG-INFO +1 -1
- {serverwatcher-5.17.5 → serverwatcher-5.18}/pyproject.toml +1 -1
- serverwatcher-5.18/src/serverwatcher/configclasses/config.py +64 -0
- serverwatcher-5.18/src/serverwatcher/configclasses/messages.py +116 -0
- serverwatcher-5.18/src/serverwatcher/configclasses/watcher.py +60 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher/defaultconfigs/config.yaml +3 -3
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher/defaultconfigs/messages.yaml +40 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher/validator.py +35 -27
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher/watcher.py +7 -5
- {serverwatcher-5.17.5 → serverwatcher-5.18/src/serverwatcher.egg-info}/PKG-INFO +1 -1
- serverwatcher-5.17.5/src/serverwatcher/configclasses/config.py +0 -34
- serverwatcher-5.17.5/src/serverwatcher/configclasses/messages.py +0 -66
- serverwatcher-5.17.5/src/serverwatcher/configclasses/watcher.py +0 -32
- {serverwatcher-5.17.5 → serverwatcher-5.18}/LICENSE +0 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/README.md +0 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/setup.cfg +0 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher/__init__.py +0 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher/__main__.py +0 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher/configclasses/__init__.py +0 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher/defaultconfigs/watcher.yaml +0 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher.egg-info/SOURCES.txt +0 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher.egg-info/dependency_links.txt +0 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher.egg-info/requires.txt +0 -0
- {serverwatcher-5.17.5 → serverwatcher-5.18}/src/serverwatcher.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from hungerlib import datamap, datamap_api
|
|
2
|
+
|
|
3
|
+
@datamap(syntax=datamap_api.braces, mode='config')
|
|
4
|
+
class GlobalConfig:
|
|
5
|
+
__user_config_path__ = 'config/config.yaml'
|
|
6
|
+
__default_config_path__ = 'defaultconfigs/config.yaml'
|
|
7
|
+
|
|
8
|
+
timezone: str = 'timezone'
|
|
9
|
+
|
|
10
|
+
panel_name: str = 'panel.name'
|
|
11
|
+
panel_url: str = 'panel.url'
|
|
12
|
+
panel_api_key: str = 'panel.api_key'
|
|
13
|
+
|
|
14
|
+
origin_server_id: str = 'origin.server_id'
|
|
15
|
+
|
|
16
|
+
server_name: str = 'server.name'
|
|
17
|
+
server_id: str = 'server.server_id'
|
|
18
|
+
server_domain: str = 'server.domain'
|
|
19
|
+
server_port: int = 'server.port'
|
|
20
|
+
|
|
21
|
+
tps_command: str = 'server.tps_command'
|
|
22
|
+
|
|
23
|
+
bridge_token: str = 'hungerbridge.token'
|
|
24
|
+
bridge_port: int = 'hungerbridge.port'
|
|
25
|
+
|
|
26
|
+
enable_logging: bool = 'logger.enabled'
|
|
27
|
+
logger_name: str = 'logger.name'
|
|
28
|
+
log_path: str = 'logger.log_path'
|
|
29
|
+
|
|
30
|
+
info_prefix: str = 'logger.prefixes.info'
|
|
31
|
+
warn_prefix: str = 'logger.prefixes.warn'
|
|
32
|
+
error_prefix: str = 'logger.prefixes.error'
|
|
33
|
+
|
|
34
|
+
clear_terminal: bool = 'terminal.enable_clearing'
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class fallbacks:
|
|
38
|
+
timezone = 'America/Chicago'
|
|
39
|
+
|
|
40
|
+
panel_name = 'My Panel'
|
|
41
|
+
panel_url = 'https://example.com'
|
|
42
|
+
panel_api_key = 'CHANGE_ME'
|
|
43
|
+
|
|
44
|
+
origin_server_id = 'CHANGE_ME'
|
|
45
|
+
|
|
46
|
+
server_name = 'My SMP'
|
|
47
|
+
server_id = 'CHANGE_ME'
|
|
48
|
+
server_domain = 'mc.example.com'
|
|
49
|
+
server_port = 25565
|
|
50
|
+
|
|
51
|
+
tps_command = 'ticks'
|
|
52
|
+
|
|
53
|
+
bridge_token = 'CHANGE_ME'
|
|
54
|
+
bridge_port = 1913
|
|
55
|
+
|
|
56
|
+
enable_logging = True
|
|
57
|
+
logger_name = 'Server Watcher'
|
|
58
|
+
log_path = '/home/container/logs/'
|
|
59
|
+
|
|
60
|
+
info_prefix = '<white>[INFO]: '
|
|
61
|
+
warn_prefix = '<yellow>[WARN]: '
|
|
62
|
+
error_prefix = '<red>[ERROR]: '
|
|
63
|
+
|
|
64
|
+
clear_terminal = True
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
from hungerlib import datamap, datamap_api
|
|
2
|
+
|
|
3
|
+
@datamap(syntax=datamap_api.braces, mode='config')
|
|
4
|
+
class MessagesConfig:
|
|
5
|
+
__user_config_path__ = 'config/messages.yaml'
|
|
6
|
+
__default_config_path__ = 'defaultconfigs/messages.yaml'
|
|
7
|
+
|
|
8
|
+
prefix: str = 'prefix'
|
|
9
|
+
bullet: str = 'bullet'
|
|
10
|
+
|
|
11
|
+
broadcast_restart_at: str = 'broadcast_restart_at'
|
|
12
|
+
|
|
13
|
+
minute_120: str = 'broadcast_minutes.120'
|
|
14
|
+
minute_60: str = 'broadcast_minutes.60'
|
|
15
|
+
minute_45: str = 'broadcast_minutes.45'
|
|
16
|
+
minute_30: str = 'broadcast_minutes.30'
|
|
17
|
+
minute_15: str = 'broadcast_minutes.15'
|
|
18
|
+
minute_5: str = 'broadcast_minutes.5'
|
|
19
|
+
minute_1: str = 'broadcast_minutes.1'
|
|
20
|
+
|
|
21
|
+
second_10: str = 'broadcast_seconds.10'
|
|
22
|
+
second_9: str = 'broadcast_seconds.9'
|
|
23
|
+
second_8: str = 'broadcast_seconds.8'
|
|
24
|
+
second_7: str = 'broadcast_seconds.7'
|
|
25
|
+
second_6: str = 'broadcast_seconds.6'
|
|
26
|
+
second_5: str = 'broadcast_seconds.5'
|
|
27
|
+
second_4: str = 'broadcast_seconds.4'
|
|
28
|
+
second_3: str = 'broadcast_seconds.3'
|
|
29
|
+
second_2: str = 'broadcast_seconds.2'
|
|
30
|
+
second_1: str = 'broadcast_seconds.1'
|
|
31
|
+
|
|
32
|
+
startup: str = 'logging.startup'
|
|
33
|
+
status_check: str = 'logging.status_check'
|
|
34
|
+
validation_fail: str = 'logging.validation_fail'
|
|
35
|
+
validation_ok: str = 'logging.validation_ok'
|
|
36
|
+
shutdown: str = 'logging.shutdown'
|
|
37
|
+
immediate_restart: str = 'logging.immediate_restart'
|
|
38
|
+
no_restart: str = 'logging.no_restart'
|
|
39
|
+
scheduled: str = 'logging.scheduled'
|
|
40
|
+
gap_low: str = 'logging.gap_low'
|
|
41
|
+
gap_high: str = 'logging.gap_high'
|
|
42
|
+
|
|
43
|
+
pro_restart_splash: str = 'reasons.pro_splash'
|
|
44
|
+
anti_restart_splash: str = 'reasons.anti_splash'
|
|
45
|
+
|
|
46
|
+
reason_restart_soon: str = 'reasons.restart_soon'
|
|
47
|
+
reason_ram: str = 'reasons.ram'
|
|
48
|
+
reason_cpu: str = 'reasons.cpu'
|
|
49
|
+
reason_uptime: str = 'reasons.uptime'
|
|
50
|
+
reason_tps: str = 'reasons.tps'
|
|
51
|
+
reason_low_uptime: str = 'reasons.low_uptime'
|
|
52
|
+
reason_players: str = 'reasons.players'
|
|
53
|
+
|
|
54
|
+
pro_restart_number: str = 'reasons.pro_restart_number'
|
|
55
|
+
anti_restart_number: str = 'reasons.anti_restart_number'
|
|
56
|
+
|
|
57
|
+
restart_action_sent: str = 'restarts.restart_action_sent'
|
|
58
|
+
server_back_online: str = 'restarts.back_online'
|
|
59
|
+
server_back_online_broadcast: str = 'restarts.back_online_broadcast'
|
|
60
|
+
server_failed_restart: str = 'restarts.failed_restart'
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class fallbacks:
|
|
64
|
+
prefix = '<aqua>[Server Watcher]'
|
|
65
|
+
bullet = '-'
|
|
66
|
+
|
|
67
|
+
broadcast_restart_at = '{prefix} The server will restart at {time} CDT.'
|
|
68
|
+
|
|
69
|
+
minute_120 = '{prefix} The server will restart in 2 hours.'
|
|
70
|
+
minute_60 = '{prefix} The server will restart in 1 hour.'
|
|
71
|
+
minute_45 = '{prefix} The server will restart in 45 minutes.'
|
|
72
|
+
minute_30 = '{prefix} The server will restart in 30 minutes.'
|
|
73
|
+
minute_15 = '{prefix} The server will restart in 15 minutes.'
|
|
74
|
+
minute_5 = '{prefix} The server will restart in 5 minutes.'
|
|
75
|
+
minute_1 = '{prefix} The server will restart in 1 minute.'
|
|
76
|
+
|
|
77
|
+
second_10 = '{prefix} <red>The server is restarting in 10 seconds!'
|
|
78
|
+
second_9 = '{prefix} <red>The server is restarting in 9 seconds!'
|
|
79
|
+
second_8 = '{prefix} <red>The server is restarting in 8 seconds!'
|
|
80
|
+
second_7 = '{prefix} <red>The server is restarting in 7 seconds!'
|
|
81
|
+
second_6 = '{prefix} <red>The server is restarting in 6 seconds!'
|
|
82
|
+
second_5 = '{prefix} <red>The server is restarting in 5 seconds!'
|
|
83
|
+
second_4 = '{prefix} <red>The server is restarting in 4 seconds!'
|
|
84
|
+
second_3 = '{prefix} <red>The server is restarting in 3 seconds!'
|
|
85
|
+
second_2 = '{prefix} <red>The server is restarting in 2 seconds!'
|
|
86
|
+
second_1 = '{prefix} <red>The server is restarting in 1 second!'
|
|
87
|
+
|
|
88
|
+
startup = 'ServerWatcher is running!'
|
|
89
|
+
status_check = 'Checking server status...'
|
|
90
|
+
validation_fail = 'Validation FAILED.'
|
|
91
|
+
validation_ok = 'All validation checks succeeded.'
|
|
92
|
+
shutdown = 'Shutting down ServerWatcher.'
|
|
93
|
+
immediate_restart = 'Restarting immediately.'
|
|
94
|
+
no_restart = 'The server does not need to restart.'
|
|
95
|
+
scheduled = 'Restart needed, but anti-restart factors outweigh it.'
|
|
96
|
+
gap_low = 'Gap {gap}. Scheduling restart in 2 hours.'
|
|
97
|
+
gap_high = 'Gap {gap}. Scheduling restart in 1 hour.'
|
|
98
|
+
|
|
99
|
+
pro_restart_splash = 'PRO-RESTART REASONS:'
|
|
100
|
+
anti_restart_splash = 'ANTI-RESTART REASONS:'
|
|
101
|
+
|
|
102
|
+
reason_restart_soon = 'The server is set to restart soon'
|
|
103
|
+
reason_ram = 'RAM usage ({ram}) is higher than {threshold} GB'
|
|
104
|
+
reason_cpu = 'CPU usage ({cpu}) is higher than {threshold}%'
|
|
105
|
+
reason_uptime = 'Uptime {uptime} exceeds {threshold}h'
|
|
106
|
+
reason_tps = 'TPS {tps} is lower than {threshold}'
|
|
107
|
+
reason_low_uptime = 'Uptime {uptime} is shorter than 30m'
|
|
108
|
+
reason_players = 'There {verb} {count} {plural} online'
|
|
109
|
+
|
|
110
|
+
pro_restart_number = 'Pro-restart: '
|
|
111
|
+
anti_restart_number = 'Anti-restart:'
|
|
112
|
+
|
|
113
|
+
restart_action_sent = 'Restart action sent. Waiting...'
|
|
114
|
+
server_back_online = 'Server is back online!'
|
|
115
|
+
server_back_online_broadcast = '{prefix} <green>Restart successful!'
|
|
116
|
+
server_failed_restart = 'Server failed to restart!'
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from hungerlib import datamap, datamap_api
|
|
2
|
+
|
|
3
|
+
@datamap(mode='config')
|
|
4
|
+
class WatcherConfig:
|
|
5
|
+
__user_config_path__ = 'config/watcher.yaml'
|
|
6
|
+
__default_config_path__ = 'defaultconfigs/watcher.yaml'
|
|
7
|
+
|
|
8
|
+
watch_interval: int = 'watch_interval'
|
|
9
|
+
|
|
10
|
+
schedule_control: bool = 'schedule_control.enabled'
|
|
11
|
+
restart_soon_id: int = 'schedule_control.restart_soon_id'
|
|
12
|
+
|
|
13
|
+
threshold_ram: int = 'thresholds.ram'
|
|
14
|
+
threshold_cpu: int = 'thresholds.cpu'
|
|
15
|
+
threshold_uptime: int = 'thresholds.uptime'
|
|
16
|
+
threshold_tps: float = 'thresholds.tps'
|
|
17
|
+
|
|
18
|
+
weight_restart_soon: int = 'weights.restart_soon'
|
|
19
|
+
weight_ram: int = 'weights.ram'
|
|
20
|
+
weight_cpu: int = 'weights.cpu'
|
|
21
|
+
weight_uptime: int = 'weights.uptime'
|
|
22
|
+
weight_tps: int = 'weights.tps'
|
|
23
|
+
|
|
24
|
+
weight_low_uptime: int = 'weights.low_uptime'
|
|
25
|
+
weight_per_player: int = 'weights.per_player'
|
|
26
|
+
|
|
27
|
+
low_gap_minutes: int = 'gaps.low_gap_minutes'
|
|
28
|
+
high_gap_minutes: int = 'gaps.high_gap_minutes'
|
|
29
|
+
|
|
30
|
+
restart_wait_seconds: int = 'restart.wait_seconds'
|
|
31
|
+
restart_timeout: int = 'restart.online_timeout'
|
|
32
|
+
restart_online_interval: int = 'restart.online_interval'
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class fallbacks:
|
|
36
|
+
watch_interval = 300
|
|
37
|
+
|
|
38
|
+
schedule_control = False
|
|
39
|
+
restart_soon_id = 0
|
|
40
|
+
|
|
41
|
+
threshold_ram = 6
|
|
42
|
+
threshold_cpu = 150
|
|
43
|
+
threshold_uptime = 12
|
|
44
|
+
threshold_tps = 19.5
|
|
45
|
+
|
|
46
|
+
weight_restart_soon = 3
|
|
47
|
+
weight_ram = 1
|
|
48
|
+
weight_cpu = 1
|
|
49
|
+
weight_uptime = 1
|
|
50
|
+
weight_tps = 1
|
|
51
|
+
|
|
52
|
+
weight_low_uptime = 5
|
|
53
|
+
weight_per_player = 1
|
|
54
|
+
|
|
55
|
+
low_gap_minutes = 120
|
|
56
|
+
high_gap_minutes = 60
|
|
57
|
+
|
|
58
|
+
restart_wait_seconds = 30
|
|
59
|
+
restart_timeout = 120
|
|
60
|
+
restart_online_interval = 2
|
|
@@ -25,9 +25,9 @@ logger:
|
|
|
25
25
|
log_path: '/home/container/logs/'
|
|
26
26
|
|
|
27
27
|
prefixes:
|
|
28
|
-
info: "<white>[INFO]: "
|
|
29
|
-
warn: "<yellow>[WARN]: "
|
|
30
|
-
error: "<red>[ERROR]: "
|
|
28
|
+
info: "<white>[%hh%:%mm%:%ss%] [INFO]: "
|
|
29
|
+
warn: "<yellow>[%hh%:%mm%:%ss%] [WARN]: "
|
|
30
|
+
error: "<red>[%hh%:%mm%:%ss%] [ERROR]: "
|
|
31
31
|
|
|
32
32
|
terminal:
|
|
33
33
|
enable_clearing: True
|
|
@@ -1,3 +1,43 @@
|
|
|
1
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
# MAP USAGE GUIDE
|
|
3
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
# The maps below provide different kinds of placeholders.
|
|
5
|
+
#
|
|
6
|
+
# 1. ColorMap (static)
|
|
7
|
+
# Provides color codes. Syntax: <color>
|
|
8
|
+
# Examples:
|
|
9
|
+
# <red> <green> <yellow> <reset>
|
|
10
|
+
#
|
|
11
|
+
# 2. GlobalConfig (config)
|
|
12
|
+
# Provides server-wide configuration values. Syntax: {field}
|
|
13
|
+
# Examples:
|
|
14
|
+
# {server_name}
|
|
15
|
+
# {panel_url}
|
|
16
|
+
#
|
|
17
|
+
# 3. MessagesConfig (keys)
|
|
18
|
+
# Provides message templates. Syntax: {field}
|
|
19
|
+
# Examples:
|
|
20
|
+
# {prefix}
|
|
21
|
+
# {broadcast_restart_at}
|
|
22
|
+
#
|
|
23
|
+
# 4. WatcherConfig (config)
|
|
24
|
+
# Provides thresholds, weights, and timing values. Syntax: {field}
|
|
25
|
+
# Examples:
|
|
26
|
+
# {threshold_ram}
|
|
27
|
+
# {low_gap_minutes}
|
|
28
|
+
#
|
|
29
|
+
# 5. TimeMap (dynamic)
|
|
30
|
+
# Provides live timestamps. Syntax: %field%
|
|
31
|
+
# Examples:
|
|
32
|
+
# %hh% hour (00–23)
|
|
33
|
+
# %mm% minute (00–59)
|
|
34
|
+
# %ss% second (00–59)
|
|
35
|
+
# %ms% millisecond (000–999)
|
|
36
|
+
# %YYYY% year
|
|
37
|
+
# %MM% month
|
|
38
|
+
# %DD% day
|
|
39
|
+
# %weekday%
|
|
40
|
+
|
|
1
41
|
prefix: '<aqua>[Server Watcher]'
|
|
2
42
|
bullet: '-'
|
|
3
43
|
|
|
@@ -9,7 +9,7 @@ from serverwatcher.configclasses.watcher import WatcherConfig
|
|
|
9
9
|
utils.clearTerminal()
|
|
10
10
|
|
|
11
11
|
def deep_get_attr(obj, dotted):
|
|
12
|
-
parts = dotted.split(
|
|
12
|
+
parts = dotted.split('.')
|
|
13
13
|
cur = obj
|
|
14
14
|
for p in parts:
|
|
15
15
|
if not hasattr(cur, p):
|
|
@@ -19,15 +19,15 @@ def deep_get_attr(obj, dotted):
|
|
|
19
19
|
|
|
20
20
|
def validate_type(name, value, expected_type, errors):
|
|
21
21
|
if not isinstance(value, expected_type):
|
|
22
|
-
errors.append(f
|
|
22
|
+
errors.append(f'{name}: expected {expected_type.__name__}, got {type(value).__name__}')
|
|
23
23
|
|
|
24
24
|
def validate_positive(name, value, errors):
|
|
25
25
|
if isinstance(value, (int, float)) and value < 0:
|
|
26
|
-
errors.append(f
|
|
26
|
+
errors.append(f'{name}: must be >= 0 (got {value})')
|
|
27
27
|
|
|
28
28
|
def validate_nonempty(name, value, errors):
|
|
29
|
-
if isinstance(value, str) and value.strip() ==
|
|
30
|
-
errors.append(f
|
|
29
|
+
if isinstance(value, str) and value.strip() == '':
|
|
30
|
+
errors.append(f'{name}: cannot be empty')
|
|
31
31
|
|
|
32
32
|
def validate_dataclass(config_obj, schema, errors):
|
|
33
33
|
for f in fields(schema):
|
|
@@ -45,53 +45,60 @@ def validate_dataclass(config_obj, schema, errors):
|
|
|
45
45
|
|
|
46
46
|
def validate_global_config(config, errors):
|
|
47
47
|
if config.server_port <= 0 or config.server_port > 65535:
|
|
48
|
-
errors.append(f
|
|
48
|
+
errors.append(f'server_port: must be 1–65535 (got {config.server_port})')
|
|
49
49
|
|
|
50
50
|
if config.bridge_port <= 0 or config.bridge_port > 65535:
|
|
51
|
-
errors.append(f
|
|
51
|
+
errors.append(f'bridge_port: must be 1–65535 (got {config.bridge_port})')
|
|
52
52
|
|
|
53
53
|
def validate_watcher_config(watcherconfig, errors):
|
|
54
54
|
if watcherconfig.restart_wait_seconds < 1:
|
|
55
|
-
errors.append(f
|
|
55
|
+
errors.append(f'restart_wait_seconds: must be >= 1 (got {watcherconfig.restart_wait_seconds})')
|
|
56
56
|
|
|
57
57
|
if watcherconfig.threshold_cpu <= 0:
|
|
58
|
-
errors.append(f
|
|
58
|
+
errors.append(f'threshold_cpu: must not be less than 1 (got {watcherconfig.threshold_cpu})')
|
|
59
59
|
|
|
60
60
|
if watcherconfig.threshold_ram <= 0:
|
|
61
|
-
errors.append(f
|
|
61
|
+
errors.append(f'threshold_ram: must be > 0 (got {watcherconfig.threshold_ram})')
|
|
62
62
|
|
|
63
63
|
if watcherconfig.threshold_tps <= 0 or watcherconfig.threshold_tps > 20:
|
|
64
|
-
errors.append(f
|
|
64
|
+
errors.append(f'threshold_tps: must be 1–20 (got {watcherconfig.threshold_tps})')
|
|
65
65
|
|
|
66
66
|
def validate_messages_config(messages, errors):
|
|
67
67
|
for f in fields(MessagesConfig):
|
|
68
68
|
value = getattr(messages, f.name)
|
|
69
|
-
if isinstance(value, str) and
|
|
69
|
+
if isinstance(value, str) and '{prefix}' not in value:
|
|
70
70
|
pass
|
|
71
71
|
|
|
72
|
+
|
|
73
|
+
# fallback detection
|
|
72
74
|
def ensure_no_global_defaults(config, defaults):
|
|
73
|
-
|
|
75
|
+
fb = config.fallbacks
|
|
76
|
+
|
|
77
|
+
if config.panel_url == fb.panel_url:
|
|
74
78
|
defaults.append('panel_url')
|
|
75
|
-
|
|
76
|
-
if config.panel_api_key ==
|
|
79
|
+
|
|
80
|
+
if config.panel_api_key == fb.panel_api_key:
|
|
77
81
|
defaults.append('panel_api_key')
|
|
78
82
|
|
|
79
|
-
if config.origin_server_id ==
|
|
83
|
+
if config.origin_server_id == fb.origin_server_id:
|
|
80
84
|
defaults.append('origin_server_id')
|
|
81
85
|
|
|
82
|
-
if config.server_id ==
|
|
86
|
+
if config.server_id == fb.server_id:
|
|
83
87
|
defaults.append('server_id')
|
|
84
88
|
|
|
85
|
-
if config.server_domain ==
|
|
89
|
+
if config.server_domain == fb.server_domain:
|
|
86
90
|
defaults.append('server_domain')
|
|
87
91
|
|
|
88
|
-
if config.bridge_token ==
|
|
92
|
+
if config.bridge_token == fb.bridge_token:
|
|
89
93
|
defaults.append('bridge_token')
|
|
90
94
|
|
|
91
95
|
def ensure_no_watcher_defaults(watcherconfig, defaults):
|
|
92
|
-
|
|
96
|
+
fb = watcherconfig.fallbacks
|
|
97
|
+
|
|
98
|
+
if watcherconfig.schedule_control and watcherconfig.restart_soon_id == fb.restart_soon_id:
|
|
93
99
|
defaults.append('restart_soon_id')
|
|
94
100
|
|
|
101
|
+
# main validation entrypoint
|
|
95
102
|
def validate_all():
|
|
96
103
|
errors = []
|
|
97
104
|
defaults = []
|
|
@@ -112,20 +119,21 @@ def validate_all():
|
|
|
112
119
|
ensure_no_watcher_defaults(watcher, defaults)
|
|
113
120
|
|
|
114
121
|
if len(defaults) >= 5:
|
|
115
|
-
print(
|
|
122
|
+
print('❌ CONFIG VALIDATION FAILED:\nIt looks like you haven\'t configured this yet! Please change these defaults:')
|
|
116
123
|
for d in defaults:
|
|
117
|
-
print(
|
|
124
|
+
print(' -', d)
|
|
118
125
|
sys.exit(1)
|
|
119
126
|
|
|
120
127
|
if errors or defaults:
|
|
121
|
-
print(
|
|
128
|
+
print('❌ CONFIG VALIDATION FAILED:')
|
|
122
129
|
for e in errors:
|
|
123
|
-
print(
|
|
130
|
+
print(' -', e)
|
|
124
131
|
for d in defaults:
|
|
125
|
-
print(
|
|
132
|
+
print(' -', d, ': must not be left default')
|
|
126
133
|
sys.exit(1)
|
|
127
134
|
|
|
128
|
-
print(
|
|
135
|
+
print('✅ All configs are valid.')
|
|
136
|
+
|
|
129
137
|
|
|
130
|
-
if __name__ ==
|
|
138
|
+
if __name__ == '__main__':
|
|
131
139
|
validate_all()
|
|
@@ -18,9 +18,10 @@ class ServerWatcher:
|
|
|
18
18
|
|
|
19
19
|
datamap_api.setGlobalMaps(
|
|
20
20
|
utils.ASCII_COLOR_MAP,
|
|
21
|
+
utils.TIME_MAP(self.config.timezone),
|
|
21
22
|
self.config,
|
|
22
23
|
self.messages,
|
|
23
|
-
self.watcherconfig
|
|
24
|
+
self.watcherconfig,
|
|
24
25
|
)
|
|
25
26
|
|
|
26
27
|
self.panel = servers.Panel(
|
|
@@ -53,10 +54,11 @@ class ServerWatcher:
|
|
|
53
54
|
Servers=[self.server],
|
|
54
55
|
log_path=self.config.log_path,
|
|
55
56
|
|
|
56
|
-
origin_maps = [utils.ASCII_COLOR_MAP, self.config, self.messages, self.watcherconfig],
|
|
57
|
-
destination_maps = [utils.ASCII_COLOR_MAP, self.config, self.messages, self.watcherconfig],
|
|
58
|
-
broadcast_maps = [utils.MC_COLOR_MAP, self.config, self.messages, self.watcherconfig],
|
|
59
|
-
file_maps = [utils.STRIP_COLOR_MAP, self.config, self.messages, self.watcherconfig],
|
|
57
|
+
origin_maps = [utils.ASCII_COLOR_MAP, utils.TIME_MAP(self.config.timezone), self.config, self.messages, self.watcherconfig],
|
|
58
|
+
destination_maps = [utils.ASCII_COLOR_MAP, utils.TIME_MAP(self.config.timezone), self.config, self.messages, self.watcherconfig],
|
|
59
|
+
broadcast_maps = [utils.MC_COLOR_MAP, utils.TIME_MAP(self.config.timezone), self.config, self.messages, self.watcherconfig],
|
|
60
|
+
file_maps = [utils.STRIP_COLOR_MAP, utils.TIME_MAP(self.config.timezone), self.config, self.messages, self.watcherconfig],
|
|
61
|
+
prefix_maps = [utils.ASCII_COLOR_MAP, utils.TIME_MAP(self.config.timezone)],
|
|
60
62
|
|
|
61
63
|
info_prefix=self.config.info_prefix,
|
|
62
64
|
warn_prefix=self.config.warn_prefix,
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
from hungerlib import datamap, datamap_api
|
|
2
|
-
|
|
3
|
-
@datamap(syntax=datamap_api.braces, mode='config')
|
|
4
|
-
class GlobalConfig:
|
|
5
|
-
__user_config_path__ = 'config/config.yaml'
|
|
6
|
-
__default_config_path__ = 'defaultconfigs/config.yaml'
|
|
7
|
-
|
|
8
|
-
timezone: str = ('timezone', 'America/Chicago')
|
|
9
|
-
|
|
10
|
-
panel_name: str = ('panel.name', 'My Panel')
|
|
11
|
-
panel_url: str = ('panel.url', 'https://example.com')
|
|
12
|
-
panel_api_key: str = ('panel.api_key', 'CHANGE_ME')
|
|
13
|
-
|
|
14
|
-
origin_server_id: str = ('origin.server_id', 'CHANGE_ME')
|
|
15
|
-
|
|
16
|
-
server_name: str = ('server.name', 'My SMP')
|
|
17
|
-
server_id: str = ('server.server_id', 'CHANGE_ME')
|
|
18
|
-
server_domain: str = ('server.domain', 'mc.example.com')
|
|
19
|
-
server_port: int = ('server.port', 25565)
|
|
20
|
-
|
|
21
|
-
tps_command: str = ('server.tps_command', 'ticks')
|
|
22
|
-
|
|
23
|
-
bridge_token: str = ('hungerbridge.token', 'CHANGE_ME')
|
|
24
|
-
bridge_port: int = ('hungerbridge.port', 1913)
|
|
25
|
-
|
|
26
|
-
enable_logging: bool = ('logger.enabled', True)
|
|
27
|
-
logger_name: str = ('logger.name', 'Server Watcher')
|
|
28
|
-
log_path: str = ('logger.log_path', '/home/container/logs/')
|
|
29
|
-
|
|
30
|
-
info_prefix: str = ('logger.prefixes.info', '<white>[INFO]: ')
|
|
31
|
-
warn_prefix: str = ('logger.prefixes.warn', '<yellow>[WARN]: ')
|
|
32
|
-
error_prefix: str = ('logger.prefixes.error', '<red>[ERROR]: ')
|
|
33
|
-
|
|
34
|
-
clear_terminal: bool = ('terminal.enable_clearing', True)
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
from hungerlib import datamap, datamap_api
|
|
2
|
-
|
|
3
|
-
@datamap(syntax=datamap_api.braces, mode='config')
|
|
4
|
-
class MessagesConfig:
|
|
5
|
-
__user_config_path__ = 'config/messages.yaml'
|
|
6
|
-
__default_config_path__ = 'defaultconfigs/messages.yaml'
|
|
7
|
-
|
|
8
|
-
prefix: str = ('prefix', '<aqua>[Server Watcher]')
|
|
9
|
-
bullet: str = ('bullet', '-')
|
|
10
|
-
|
|
11
|
-
broadcast_restart_at: str = ('broadcast_restart_at', '{prefix} The server will restart at {time} CDT.')
|
|
12
|
-
|
|
13
|
-
# minute countdowns
|
|
14
|
-
minute_120: str = ('broadcast_minutes.120', '{prefix} The server will restart in 2 hours.')
|
|
15
|
-
minute_60: str = ('broadcast_minutes.60', '{prefix} The server will restart in 1 hour.')
|
|
16
|
-
minute_45: str = ('broadcast_minutes.45', '{prefix} The server will restart in 45 minutes.')
|
|
17
|
-
minute_30: str = ('broadcast_minutes.30', '{prefix} The server will restart in 30 minutes.')
|
|
18
|
-
minute_15: str = ('broadcast_minutes.15', '{prefix} The server will restart in 15 minutes.')
|
|
19
|
-
minute_5: str = ('broadcast_minutes.5', '{prefix} The server will restart in 5 minutes.')
|
|
20
|
-
minute_1: str = ('broadcast_minutes.1', '{prefix} The server will restart in 1 minute.')
|
|
21
|
-
|
|
22
|
-
# second countdowns
|
|
23
|
-
second_10: str = ('broadcast_seconds.10', '{prefix} <red>The server is restarting in 10 seconds!')
|
|
24
|
-
second_9: str = ('broadcast_seconds.9', '{prefix} <red>The server is restarting in 9 seconds!')
|
|
25
|
-
second_8: str = ('broadcast_seconds.8', '{prefix} <red>The server is restarting in 8 seconds!')
|
|
26
|
-
second_7: str = ('broadcast_seconds.7', '{prefix} <red>The server is restarting in 7 seconds!')
|
|
27
|
-
second_6: str = ('broadcast_seconds.6', '{prefix} <red>The server is restarting in 6 seconds!')
|
|
28
|
-
second_5: str = ('broadcast_seconds.5', '{prefix} <red>The server is restarting in 5 seconds!')
|
|
29
|
-
second_4: str = ('broadcast_seconds.4', '{prefix} <red>The server is restarting in 4 seconds!')
|
|
30
|
-
second_3: str = ('broadcast_seconds.3', '{prefix} <red>The server is restarting in 3 seconds!')
|
|
31
|
-
second_2: str = ('broadcast_seconds.2', '{prefix} <red>The server is restarting in 2 seconds!')
|
|
32
|
-
second_1: str = ('broadcast_seconds.1', '{prefix} <red>The server is restarting in 1 second!')
|
|
33
|
-
|
|
34
|
-
# logging
|
|
35
|
-
startup: str = ('logging.startup', 'ServerWatcher is running!')
|
|
36
|
-
status_check: str = ('logging.status_check', 'Checking server status...')
|
|
37
|
-
validation_fail: str = ('logging.validation_fail', 'Validation FAILED.')
|
|
38
|
-
validation_ok: str = ('logging.validation_ok', 'All validation checks succeeded.')
|
|
39
|
-
shutdown: str = ('logging.shutdown', 'Shutting down ServerWatcher.')
|
|
40
|
-
immediate_restart: str = ('logging.immediate_restart', 'Restarting immediately.')
|
|
41
|
-
no_restart: str = ('logging.no_restart', 'The server does not need to restart.')
|
|
42
|
-
scheduled: str = ('logging.scheduled', 'Restart needed, but anti-restart factors outweigh it.')
|
|
43
|
-
gap_low: str = ('logging.gap_low', 'Gap {gap}. Scheduling restart in 2 hours.')
|
|
44
|
-
gap_high: str = ('logging.gap_high', 'Gap {gap}. Scheduling restart in 1 hour.')
|
|
45
|
-
|
|
46
|
-
# reason splashes
|
|
47
|
-
pro_restart_splash: str = ('reasons.pro_splash', 'PRO-RESTART REASONS:')
|
|
48
|
-
anti_restart_splash: str = ('reasons.anti_splash', 'ANTI-RESTART REASONS:')
|
|
49
|
-
|
|
50
|
-
# individual reasons
|
|
51
|
-
reason_restart_soon: str = ('reasons.restart_soon', 'The server is set to restart soon')
|
|
52
|
-
reason_ram: str = ('reasons.ram', 'RAM usage ({ram}) is higher than {threshold} GB')
|
|
53
|
-
reason_cpu: str = ('reasons.cpu', 'CPU usage ({cpu}) is higher than {threshold}%')
|
|
54
|
-
reason_uptime: str = ('reasons.uptime', 'Uptime {uptime} exceeds {threshold}h')
|
|
55
|
-
reason_tps: str = ('reasons.tps', 'TPS {tps} is lower than {threshold}')
|
|
56
|
-
reason_low_uptime: str = ('reasons.low_uptime', 'Uptime {uptime} is shorter than 30m')
|
|
57
|
-
reason_players: str = ('reasons.players', 'There {verb} {count} {plural} online')
|
|
58
|
-
|
|
59
|
-
pro_restart_number: str = ('reasons.pro_restart_number', 'Pro-restart: ')
|
|
60
|
-
anti_restart_number: str = ('reasons.anti_restart_number', 'Anti-restart:')
|
|
61
|
-
|
|
62
|
-
# restart events
|
|
63
|
-
restart_action_sent: str = ('restarts.restart_action_sent', 'Restart action sent. Waiting...')
|
|
64
|
-
server_back_online: str = ('restarts.back_online', 'Server is back online!')
|
|
65
|
-
server_back_online_broadcast: str = ('restarts.back_online_broadcast', '{prefix} <green>Restart successful!')
|
|
66
|
-
server_failed_restart: str = ('restarts.failed_restart', 'Server failed to restart!')
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from hungerlib import datamap, datamap_api
|
|
2
|
-
|
|
3
|
-
@datamap(syntax=datamap_api.braces, mode='config')
|
|
4
|
-
class WatcherConfig:
|
|
5
|
-
__user_config_path__ = 'config/watcher.yaml'
|
|
6
|
-
__default_config_path__ = 'defaultconfigs/watcher.yaml'
|
|
7
|
-
|
|
8
|
-
watch_interval: int = ('watch_interval', 300)
|
|
9
|
-
|
|
10
|
-
schedule_control: bool = ('schedule_control.enabled', False)
|
|
11
|
-
restart_soon_id: int = ('schedule_control.restart_soon_id', 0)
|
|
12
|
-
|
|
13
|
-
threshold_ram: int = ('thresholds.ram', 6)
|
|
14
|
-
threshold_cpu: int = ('thresholds.cpu', 150)
|
|
15
|
-
threshold_uptime: int = ('thresholds.uptime', 12)
|
|
16
|
-
threshold_tps: float = ('thresholds.tps', 19.5)
|
|
17
|
-
|
|
18
|
-
weight_restart_soon: int = ('weights.restart_soon', 3)
|
|
19
|
-
weight_ram: int = ('weights.ram', 1)
|
|
20
|
-
weight_cpu: int = ('weights.cpu', 1)
|
|
21
|
-
weight_uptime: int = ('weights.uptime', 1)
|
|
22
|
-
weight_tps: int = ('weights.tps', 1)
|
|
23
|
-
|
|
24
|
-
weight_low_uptime: int = ('weights.low_uptime', 5)
|
|
25
|
-
weight_per_player: int = ('weights.per_player', 1)
|
|
26
|
-
|
|
27
|
-
low_gap_minutes: int = ('gaps.low_gap_minutes', 120)
|
|
28
|
-
high_gap_minutes: int = ('gaps.high_gap_minutes', 60)
|
|
29
|
-
|
|
30
|
-
restart_wait_seconds: int = ('restart.wait_seconds', 30)
|
|
31
|
-
restart_timeout: int = ('restart.online_timeout', 120)
|
|
32
|
-
restart_online_interval: int = ('restart.online_interval', 2)
|
|
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
|