serverwatcher 2.1.2__tar.gz → 2.2.3__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-2.1.2/src/serverwatcher.egg-info → serverwatcher-2.2.3}/PKG-INFO +1 -1
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/pyproject.toml +1 -1
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/src/serverwatcher/messages.py +2 -1
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/src/serverwatcher/watcher.py +116 -21
- {serverwatcher-2.1.2 → serverwatcher-2.2.3/src/serverwatcher.egg-info}/PKG-INFO +1 -1
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/LICENSE +0 -0
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/README.md +0 -0
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/setup.cfg +0 -0
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/src/serverwatcher/__init__.py +0 -0
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/src/serverwatcher/config.py +0 -0
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/src/serverwatcher.egg-info/SOURCES.txt +0 -0
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/src/serverwatcher.egg-info/dependency_links.txt +0 -0
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/src/serverwatcher.egg-info/requires.txt +0 -0
- {serverwatcher-2.1.2 → serverwatcher-2.2.3}/src/serverwatcher.egg-info/top_level.txt +0 -0
|
@@ -18,7 +18,8 @@ class WatcherMessages:
|
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
broadcast_second: dict = field(default_factory=lambda: {
|
|
21
|
-
s: "{prefix} Restart in " + str(s) + " seconds!"
|
|
21
|
+
s: "{prefix} Restart in " + str(s) + " seconds!"
|
|
22
|
+
for s in range(10, 0, -1)
|
|
22
23
|
})
|
|
23
24
|
|
|
24
25
|
# log messages
|
|
@@ -1,23 +1,90 @@
|
|
|
1
1
|
import time
|
|
2
2
|
from zoneinfo import ZoneInfo
|
|
3
3
|
|
|
4
|
+
from hungerlib import Panel, HungerLogger
|
|
5
|
+
from hungerlib.servers import MinecraftServer, GenericServer
|
|
4
6
|
from hungerlib.addons import (
|
|
7
|
+
clearTerminal,
|
|
5
8
|
Snapshot,
|
|
6
9
|
snapSchedule,
|
|
7
10
|
waitForOnline,
|
|
8
11
|
validateAll,
|
|
9
|
-
runCountdownEvents
|
|
12
|
+
runCountdownEvents,
|
|
10
13
|
)
|
|
14
|
+
from hungerlib.addons import configloader
|
|
15
|
+
|
|
16
|
+
from .config import WatcherConfig
|
|
17
|
+
from .messages import WatcherMessages
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
DEFAULT_CONFIG = {
|
|
21
|
+
"panel": {
|
|
22
|
+
"name": "My Panel",
|
|
23
|
+
"url": "https://example.com",
|
|
24
|
+
"api_key": "CHANGE_ME",
|
|
25
|
+
},
|
|
26
|
+
"origin": {
|
|
27
|
+
"server_id": "CHANGE_ME",
|
|
28
|
+
},
|
|
29
|
+
"server": {
|
|
30
|
+
"name": "My SMP",
|
|
31
|
+
"server_id": "CHANGE_ME",
|
|
32
|
+
"domain": "example.com",
|
|
33
|
+
"port": 25565,
|
|
34
|
+
"rcon_port": 25575,
|
|
35
|
+
"rcon_password": "password",
|
|
36
|
+
"tps_command": "ticks",
|
|
37
|
+
},
|
|
38
|
+
"watcher": {},
|
|
39
|
+
"messages": {},
|
|
40
|
+
}
|
|
11
41
|
|
|
12
42
|
|
|
13
43
|
class ServerWatcher:
|
|
14
|
-
def __init__(self,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
self.
|
|
44
|
+
def __init__(self, config_path: str = "config.yaml"):
|
|
45
|
+
# ensure config exists, then load it
|
|
46
|
+
ensure_yaml(config_path, DEFAULT_CONFIG)
|
|
47
|
+
raw = load_yaml(config_path)
|
|
48
|
+
|
|
49
|
+
# map watcher + messages sections into your dataclasses
|
|
50
|
+
self.cfg: WatcherConfig = map_to_dataclass(raw.get("watcher", {}), WatcherConfig)
|
|
51
|
+
self.msg: WatcherMessages = map_to_dataclass(
|
|
52
|
+
raw.get("messages", {}), WatcherMessages
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# panel / origin / server wiring from YAML
|
|
56
|
+
p = raw["panel"]
|
|
57
|
+
self.panel = Panel(
|
|
58
|
+
name=p["name"],
|
|
59
|
+
url=p["url"],
|
|
60
|
+
api_key=p["api_key"],
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
o = raw["origin"]
|
|
64
|
+
self.origin = GenericServer(
|
|
65
|
+
name="Origin",
|
|
66
|
+
panel=self.panel,
|
|
67
|
+
server_id=o["server_id"],
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
s = raw["server"]
|
|
71
|
+
self.server = MinecraftServer(
|
|
72
|
+
name=s["name"],
|
|
73
|
+
panel=self.panel,
|
|
74
|
+
server_id=s["server_id"],
|
|
75
|
+
server_domain=s["domain"],
|
|
76
|
+
server_port=s["port"],
|
|
77
|
+
rcon_port=s["rcon_port"],
|
|
78
|
+
rcon_password=s["rcon_password"],
|
|
79
|
+
tpsCommand=s["tps_command"],
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
self.log = HungerLogger(
|
|
83
|
+
name=f"ServerWatcher-{s['name']}",
|
|
84
|
+
server=self.server,
|
|
85
|
+
log_path="/home/container/logs/",
|
|
86
|
+
console_backspaces=8,
|
|
87
|
+
)
|
|
21
88
|
|
|
22
89
|
def fmt(self, template: str, **kwargs):
|
|
23
90
|
return template.format(prefix=self.msg.prefix, **kwargs)
|
|
@@ -36,12 +103,12 @@ class ServerWatcher:
|
|
|
36
103
|
alive = waitForOnline(
|
|
37
104
|
self.server,
|
|
38
105
|
timeout=self.cfg.restart_online_timeout,
|
|
39
|
-
interval=self.cfg.restart_online_interval
|
|
106
|
+
interval=self.cfg.restart_online_interval,
|
|
40
107
|
)
|
|
41
108
|
|
|
42
109
|
if alive:
|
|
43
110
|
self.log.info("Server is back online!")
|
|
44
|
-
self.server.sendBroadcast(f
|
|
111
|
+
self.server.sendBroadcast(f"{self.msg.prefix}<green>Restart successful!")
|
|
45
112
|
self.origin.enableSchedule(self.cfg.origin_disable_schedule_id)
|
|
46
113
|
else:
|
|
47
114
|
self.log.error("Server failed to restart!")
|
|
@@ -58,21 +125,19 @@ class ServerWatcher:
|
|
|
58
125
|
)
|
|
59
126
|
|
|
60
127
|
minute_callbacks = {
|
|
61
|
-
m: (lambda msg=self.fmt(self.msg.broadcast_minute[m]):
|
|
62
|
-
self.server.sendBroadcast(msg))
|
|
128
|
+
m: (lambda msg=self.fmt(self.msg.broadcast_minute[m]): self.server.sendBroadcast(msg))
|
|
63
129
|
for m in self.msg.broadcast_minute
|
|
64
130
|
}
|
|
65
131
|
|
|
66
132
|
second_callbacks = {
|
|
67
|
-
s: (lambda msg=self.fmt(self.msg.broadcast_second[s]):
|
|
68
|
-
self.server.sendBroadcast(msg))
|
|
133
|
+
s: (lambda msg=self.fmt(self.msg.broadcast_second[s]): self.server.sendBroadcast(msg))
|
|
69
134
|
for s in self.msg.broadcast_second
|
|
70
135
|
}
|
|
71
136
|
|
|
72
137
|
runCountdownEvents(
|
|
73
138
|
target_time=scheduled,
|
|
74
139
|
minute_callbacks=minute_callbacks,
|
|
75
|
-
second_callbacks=second_callbacks
|
|
140
|
+
second_callbacks=second_callbacks,
|
|
76
141
|
)
|
|
77
142
|
|
|
78
143
|
def evaluate(self):
|
|
@@ -97,32 +162,51 @@ class ServerWatcher:
|
|
|
97
162
|
|
|
98
163
|
if snap.ram >= self.cfg.ram_threshold:
|
|
99
164
|
restart_reasons.append(
|
|
100
|
-
self.fmt(
|
|
165
|
+
self.fmt(
|
|
166
|
+
self.msg.reason_ram,
|
|
167
|
+
ram=snap.ram,
|
|
168
|
+
threshold=self.cfg.ram_threshold,
|
|
169
|
+
)
|
|
101
170
|
)
|
|
102
171
|
pro += round(snap.ram, 0) - 5
|
|
103
172
|
|
|
104
173
|
if snap.cpu >= self.cfg.cpu_threshold:
|
|
105
174
|
restart_reasons.append(
|
|
106
|
-
self.fmt(
|
|
175
|
+
self.fmt(
|
|
176
|
+
self.msg.reason_cpu,
|
|
177
|
+
cpu=snap.cpu,
|
|
178
|
+
threshold=self.cfg.cpu_threshold,
|
|
179
|
+
)
|
|
107
180
|
)
|
|
108
181
|
pro += self.cfg.weight_cpu
|
|
109
182
|
|
|
110
183
|
if snap.uptime // 3600 >= self.cfg.uptime_hours_threshold:
|
|
111
184
|
restart_reasons.append(
|
|
112
|
-
self.fmt(
|
|
185
|
+
self.fmt(
|
|
186
|
+
self.msg.reason_uptime,
|
|
187
|
+
uptime=snap.uptime_formatted,
|
|
188
|
+
threshold=self.cfg.uptime_hours_threshold,
|
|
189
|
+
)
|
|
113
190
|
)
|
|
114
191
|
pro += self.cfg.weight_uptime
|
|
115
192
|
|
|
116
193
|
if snap.tps <= self.cfg.tps_threshold:
|
|
117
194
|
restart_reasons.append(
|
|
118
|
-
self.fmt(
|
|
195
|
+
self.fmt(
|
|
196
|
+
self.msg.reason_tps,
|
|
197
|
+
tps=snap.tps,
|
|
198
|
+
threshold=self.cfg.tps_threshold,
|
|
199
|
+
)
|
|
119
200
|
)
|
|
120
201
|
pro += self.cfg.weight_tps
|
|
121
202
|
|
|
122
203
|
# ANTI-RESTART
|
|
123
204
|
if snap.uptime // 60 < 30:
|
|
124
205
|
no_restart_reasons.append(
|
|
125
|
-
self.fmt(
|
|
206
|
+
self.fmt(
|
|
207
|
+
self.msg.reason_low_uptime,
|
|
208
|
+
uptime=snap.uptime_formatted,
|
|
209
|
+
)
|
|
126
210
|
)
|
|
127
211
|
anti += self.cfg.weight_low_uptime
|
|
128
212
|
|
|
@@ -130,7 +214,12 @@ class ServerWatcher:
|
|
|
130
214
|
verb = "are" if snap.players != 1 else "is"
|
|
131
215
|
plural = "players" if snap.players != 1 else "player"
|
|
132
216
|
no_restart_reasons.append(
|
|
133
|
-
self.fmt(
|
|
217
|
+
self.fmt(
|
|
218
|
+
self.msg.reason_players,
|
|
219
|
+
verb=verb,
|
|
220
|
+
count=snap.players,
|
|
221
|
+
plural=plural,
|
|
222
|
+
)
|
|
134
223
|
)
|
|
135
224
|
anti += snap.players * self.cfg.weight_per_player
|
|
136
225
|
|
|
@@ -164,3 +253,9 @@ class ServerWatcher:
|
|
|
164
253
|
self.schedule_restart(self.cfg.high_gap_minutes)
|
|
165
254
|
|
|
166
255
|
self.restart_and_wait()
|
|
256
|
+
|
|
257
|
+
def run(self):
|
|
258
|
+
clearTerminal()
|
|
259
|
+
while True:
|
|
260
|
+
self.evaluate()
|
|
261
|
+
time.sleep(60)
|
|
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
|