serverwatcher 5.8.dev4__py3-none-any.whl → 5.8.dev6__py3-none-any.whl

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/watcher.py CHANGED
@@ -1,4 +1,3 @@
1
- # serverwatcher.py
2
1
  import os
3
2
  import time
4
3
  import re
@@ -27,6 +26,7 @@ validate_all()
27
26
  _T_EXPR = re.compile(r"{([^{}]+)}")
28
27
 
29
28
  def t_eval(template: str, /, **ctx):
29
+ # evaluate inline expressions inside message templates
30
30
  def repl(match):
31
31
  expr = match.group(1).strip()
32
32
  try:
@@ -37,7 +37,6 @@ def t_eval(template: str, /, **ctx):
37
37
 
38
38
  class ServerWatcher:
39
39
  def __init__(self):
40
-
41
40
  self.config = loadConfig(
42
41
  "config/config.yaml",
43
42
  "/defaultconfigs/config.yaml",
@@ -79,10 +78,12 @@ class ServerWatcher:
79
78
  tpsCommand=self.config.tps_command,
80
79
  )
81
80
 
81
+ # formatted logger name
82
82
  logger_name = self.config.logger_name.format(
83
83
  server_name=self.config.server_name
84
84
  )
85
85
 
86
+ # initialize message router
86
87
  self.router = MessageRouter(
87
88
  name=logger_name,
88
89
  server=self.server,
@@ -91,27 +92,40 @@ class ServerWatcher:
91
92
  console_backspaces=self.config.console_backspaces,
92
93
  )
93
94
 
95
+ # timezone for scheduling
94
96
  self.tz = ZoneInfo(self.config.timezone)
95
97
 
96
98
  def fmt(self, template: str, **fmt):
99
+ # apply t-eval formatting to templates
97
100
  return t_eval(template, self=self, **fmt)
98
-
101
+
99
102
  def say(self, template, level="info", **fmt):
100
103
  if not template:
101
104
  return
102
- self.router.say(template, level=level, **fmt)
105
+ self.router.say(
106
+ template,
107
+ level=level,
108
+ log=self.config.enable_logging,
109
+ **fmt
110
+ )
111
+
112
+
103
113
 
104
114
  def shutdown(self):
105
115
  self.say(self.messages.shutdown)
106
116
  raise SystemExit
107
117
 
108
118
  def restart_and_wait(self):
119
+ # disable schedule if configured
109
120
  if self.watcherconfig.schedule_control:
110
121
  self.origin.disableSchedule(self.watcherconfig.restart_soon_id)
122
+
123
+ # send restart command
111
124
  self.server.restart()
112
125
  self.say(self.messages.restart_action_sent)
113
126
  time.sleep(self.watcherconfig.restart_wait_seconds)
114
127
 
128
+ # check server status
115
129
  self.say(self.messages.status_check, level="warn")
116
130
  alive = waitForOnline(
117
131
  self.server,
@@ -119,6 +133,7 @@ class ServerWatcher:
119
133
  interval=self.watcherconfig.restart_online_interval,
120
134
  )
121
135
 
136
+ # handle restart result
122
137
  if alive:
123
138
  self.say(self.messages.server_back_online)
124
139
  self.say(self.messages.server_back_online_broadcast, broadcast=True)
@@ -126,14 +141,18 @@ class ServerWatcher:
126
141
  self.say(self.messages.server_failed_restart, level="error")
127
142
 
128
143
  def schedule_restart(self, minutes):
144
+ # compute scheduled restart time
129
145
  info = snapSchedule(minimumMinutes=minutes)
130
146
  scheduled = info["scheduled"]
131
147
 
148
+ # format local time
132
149
  local_time = scheduled.astimezone(self.tz)
133
150
  time_str = local_time.strftime("%I:%M %p")
134
151
 
152
+ # broadcast restart time
135
153
  self.router.broadcast(self.fmt(self.messages.broadcast_restart_at, time=time_str))
136
154
 
155
+ # build minute callbacks
137
156
  minute_callbacks = {
138
157
  int(k.split("_")[1]): (
139
158
  lambda msg=self.fmt(getattr(self.messages, k)):
@@ -143,6 +162,7 @@ class ServerWatcher:
143
162
  if k.startswith("minute_")
144
163
  }
145
164
 
165
+ # build second callbacks
146
166
  second_callbacks = {
147
167
  int(k.split("_")[1]): (
148
168
  lambda msg=self.fmt(getattr(self.messages, k)):
@@ -152,6 +172,7 @@ class ServerWatcher:
152
172
  if k.startswith("second_")
153
173
  }
154
174
 
175
+ # run countdown events
155
176
  runCountdownEvents(
156
177
  target_time=scheduled,
157
178
  minute_callbacks=minute_callbacks,
@@ -159,32 +180,40 @@ class ServerWatcher:
159
180
  )
160
181
 
161
182
  def evaluate(self):
183
+ # announce evaluation start
162
184
  self.say(self.messages.startup)
163
185
 
186
+ # validate panel and server
164
187
  if not validateAll(self.panel, self.server):
165
188
  self.say(self.messages.validation_fail, level="error")
166
189
  self.shutdown()
167
190
 
191
+ # refresh server state
168
192
  self.server.refresh()
169
193
  snap = Snapshot(self.server, 2, True)
170
194
 
195
+ # scoring variables
171
196
  pro = 0
172
197
  anti = 0
173
198
  restart_reasons = []
174
199
  no_restart_reasons = []
175
200
 
201
+ # check schedule flag
176
202
  if self.watcherconfig.schedule_control and self.server.getSchedule(self.watcherconfig.restart_soon_id)["is_active"]:
177
203
  restart_reasons.append(self.messages.reason_restart_soon)
178
204
  pro += self.watcherconfig.weight_restart_soon
179
205
 
206
+ # check RAM threshold
180
207
  if snap.ram >= self.watcherconfig.threshold_ram:
181
208
  restart_reasons.append(self.fmt(self.messages.reason_ram, ram=snap.ram, threshold=self.watcherconfig.threshold_ram))
182
209
  pro += int(round(snap.ram, 0) - (self.watcherconfig.threshold_ram - 1))
183
210
 
211
+ # check CPU threshold
184
212
  if snap.cpu >= self.watcherconfig.threshold_cpu:
185
213
  restart_reasons.append(self.fmt(self.messages.reason_cpu, cpu=snap.cpu, threshold=self.watcherconfig.threshold_cpu))
186
214
  pro += self.watcherconfig.weight_cpu
187
215
 
216
+ # check uptime threshold
188
217
  if snap.uptime // 3600 >= self.watcherconfig.threshold_uptime:
189
218
  restart_reasons.append(
190
219
  self.fmt(self.messages.reason_uptime, uptime=snap.uptime_formatted,
@@ -192,46 +221,57 @@ class ServerWatcher:
192
221
  )
193
222
  pro += self.watcherconfig.weight_uptime
194
223
 
224
+ # check TPS threshold
195
225
  if (snap.tps if snap.tps is not None else 20) <= self.watcherconfig.threshold_tps:
196
226
  restart_reasons.append(self.fmt(self.messages.reason_tps, tps=snap.tps, threshold=self.watcherconfig.threshold_tps))
197
227
  pro += self.watcherconfig.weight_tps
198
228
 
229
+ # check low uptime penalty
199
230
  if snap.uptime // 60 < 30:
200
231
  no_restart_reasons.append(self.fmt(self.messages.reason_low_uptime, uptime=snap.uptime_formatted))
201
232
  anti += self.watcherconfig.weight_low_uptime
202
233
 
234
+ # check player count penalty
203
235
  if snap.players > 0:
204
236
  verb = "are" if snap.players != 1 else "is"
205
237
  plural = "players" if snap.players != 1 else "player"
206
238
  no_restart_reasons.append(self.fmt(self.messages.reason_players, verb=verb, count=snap.players, plural=plural))
207
239
  anti += snap.players * self.watcherconfig.weight_per_player
208
240
 
241
+ # output pro-restart reasons
209
242
  if restart_reasons:
210
243
  self.say(self.messages.pro_restart_splash, level="warn")
211
244
  for r in restart_reasons:
212
245
  self.say(f"{self.messages.bullet} {r}", level="warn")
213
246
 
247
+ # output anti-restart reasons
214
248
  if no_restart_reasons:
215
249
  self.say(self.messages.anti_restart_splash, level="warn")
216
250
  for r in no_restart_reasons:
217
251
  self.say(f"{self.messages.bullet} {r}", level="warn")
218
252
 
253
+ # output scores
219
254
  self.say(f"{self.messages.pro_restart_number} {pro}", level="warn")
220
255
  self.say(f"{self.messages.anti_restart_number} {anti}", level="warn")
221
256
 
257
+ # compute gap
222
258
  gap = abs(pro - anti)
223
259
 
260
+ # no restart case
224
261
  if pro == 0:
225
262
  self.say(self.messages.no_restart)
226
263
  return
227
264
 
265
+ # immediate restart case
228
266
  if pro > anti and snap.players == 0:
229
267
  self.say(self.messages.immediate_restart)
230
268
  self.restart_and_wait()
231
269
  return
232
270
 
271
+ # scheduled restart case
233
272
  self.say(self.messages.scheduled)
234
273
 
274
+ # choose schedule window
235
275
  if gap <= 2:
236
276
  self.say(self.messages.gap_low, level="warn", gap=gap)
237
277
  self.schedule_restart(self.watcherconfig.low_gap_minutes)
@@ -239,8 +279,11 @@ class ServerWatcher:
239
279
  self.say(self.messages.gap_high, level="warn", gap=gap)
240
280
  self.schedule_restart(self.watcherconfig.high_gap_minutes)
241
281
 
282
+ # perform restart
242
283
  self.restart_and_wait()
243
284
 
285
+
286
+ # main loop
244
287
  def run(self):
245
288
  if self.config.clear_terminal:
246
289
  clearTerminal()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: serverwatcher
3
- Version: 5.8.dev4
3
+ Version: 5.8.dev6
4
4
  Summary: A HungerLib-powered Minecraft server automation engine.
5
5
  Author: iFamished
6
6
  License: GPL-3.0
@@ -1,6 +1,6 @@
1
1
  serverwatcher/__init__.py,sha256=Q_afN0XU29n48d6Gf0-LT2lLo3RiTWlHRT6rC_fYbjw,486
2
2
  serverwatcher/validator.py,sha256=W1-RX8UQWeO2DKEe3vC1_U6xISe_WnAVXHYT0pf4uWc,4753
3
- serverwatcher/watcher.py,sha256=124sVNFQIKoPjH0OSxuMBqvXINvEq2PwDUhVw_8hvE0,8518
3
+ serverwatcher/watcher.py,sha256=t9NJ87eTQn0UUumkjudkwA9Z56G4RGciEpfqddtIYbw,9781
4
4
  serverwatcher/configclasses/__init__.py,sha256=YS0KhxtAJGdMcaiFstqTRNxIPLnR7s9v3Tkt5h2uKE4,182
5
5
  serverwatcher/configclasses/config.py,sha256=cnrRYaJ7W-SuUuVZI2tFgGWtmlLkMNNy51HxTud4tB8,1110
6
6
  serverwatcher/configclasses/messages.py,sha256=JZawv8_Kn9rns_bbuw0cuk5DhwinlueCao63NJIttXo,2770
@@ -8,8 +8,8 @@ serverwatcher/configclasses/watcher.py,sha256=urQvRr8b7OjK0sm5eovSg9S3vo0LWZxE0c
8
8
  serverwatcher/defaultconfigs/config.yaml,sha256=lq-eTwAG4QQKIJKniMeEj9eD_DG06zMNf-C7Scqa9KI,461
9
9
  serverwatcher/defaultconfigs/messages.yaml,sha256=Zft8a1XrZj2YcdVg1njQM55RZTCZdDWzaxi2raIPeOo,2090
10
10
  serverwatcher/defaultconfigs/watcher.yaml,sha256=1XUr7p5qRiaZkSccULVgEAGvHMFOM2IPNBRxdnG86NA,380
11
- serverwatcher-5.8.dev4.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
12
- serverwatcher-5.8.dev4.dist-info/METADATA,sha256=RyMVMgat_6CrMMIxE87oqXFpuLS7P7QwdnU2outl5Oc,1686
13
- serverwatcher-5.8.dev4.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
14
- serverwatcher-5.8.dev4.dist-info/top_level.txt,sha256=8DJAf8WmmglgtZHkp8aoTriRJ2YPcS4F3DfOIkytASo,14
15
- serverwatcher-5.8.dev4.dist-info/RECORD,,
11
+ serverwatcher-5.8.dev6.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
12
+ serverwatcher-5.8.dev6.dist-info/METADATA,sha256=2kN4aKYx5uS7eYWO5yc30Zrm4Yl-XRfvxwiApjKqFkY,1686
13
+ serverwatcher-5.8.dev6.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
14
+ serverwatcher-5.8.dev6.dist-info/top_level.txt,sha256=8DJAf8WmmglgtZHkp8aoTriRJ2YPcS4F3DfOIkytASo,14
15
+ serverwatcher-5.8.dev6.dist-info/RECORD,,