hungerlib 2.0.5.dev0__tar.gz → 2.1.1.dev0__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.
- {hungerlib-2.0.5.dev0/src/hungerlib.egg-info → hungerlib-2.1.1.dev0}/PKG-INFO +1 -1
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/pyproject.toml +1 -1
- hungerlib-2.1.1.dev0/src/hungerlib/config.py +52 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/logger.py +4 -4
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/panel.py +16 -23
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/servers/_generic.py +30 -82
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/servers/minecraft.py +21 -41
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0/src/hungerlib.egg-info}/PKG-INFO +1 -1
- hungerlib-2.0.5.dev0/src/hungerlib/config.py +0 -22
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/LICENSE +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/README.md +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/setup.cfg +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/__init__.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/addons/_generic.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/addons/colormap.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/addons/minecraft.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/api/__init__.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/api/backups.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/api/command.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/api/databases.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/api/filemanager.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/api/schedule.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/api/startup.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/mchelpers.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib/scheduler.py +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib.egg-info/SOURCES.txt +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib.egg-info/dependency_links.txt +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib.egg-info/requires.txt +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/hungerlib.egg-info/top_level.txt +0 -0
- {hungerlib-2.0.5.dev0 → hungerlib-2.1.1.dev0}/src/tests/test_imports.py +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# =====================================
|
|
2
|
+
# CORE CONFIG SYSTEM
|
|
3
|
+
# =====================================
|
|
4
|
+
# The variables in this file can be used to control many things in Hungerlib's functions.
|
|
5
|
+
# It helps keep track of constants and serves as an easy-to-use configuration system.
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from hungerlib.addons.colormap import *
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class Config:
|
|
13
|
+
# panel defaults
|
|
14
|
+
panel_name: str | None = None
|
|
15
|
+
panel_url: str | None = None
|
|
16
|
+
panel_api_key: str | None = None
|
|
17
|
+
panel_headers: dict | None = None
|
|
18
|
+
|
|
19
|
+
# generic server defaults
|
|
20
|
+
gs_name: str | None = None
|
|
21
|
+
gs_panel_url: str | None = None
|
|
22
|
+
gs_panel_api_key: str | None = None
|
|
23
|
+
gs_server_id: str | None = None
|
|
24
|
+
|
|
25
|
+
# minecraft server defaults
|
|
26
|
+
mc_name: str | None = None
|
|
27
|
+
mc_panel_url: str | None = None
|
|
28
|
+
mc_panel_api_key: str | None = None
|
|
29
|
+
mc_server_id: str | None = None
|
|
30
|
+
mc_server_domain: str | None = None
|
|
31
|
+
mc_server_port: int = 25565
|
|
32
|
+
mc_rcon_port: int = 25575
|
|
33
|
+
mc_rcon_password: str | None = None
|
|
34
|
+
mc_tpsCommand: str = 'tt20 tps'
|
|
35
|
+
|
|
36
|
+
# Color maps
|
|
37
|
+
file_color_map: dict | None = None
|
|
38
|
+
origin_color_map: dict = field(default_factory=lambda: ASCI_COLOR_MAP.copy())
|
|
39
|
+
destination_color_map: dict = field(default_factory=lambda: ASCI_COLOR_MAP.copy())
|
|
40
|
+
mc_color_map: dict = field(default_factory=lambda: MC_COLOR_MAP.copy())
|
|
41
|
+
|
|
42
|
+
# Prefixes
|
|
43
|
+
info_prefix: str = '<white>[INFO]: '
|
|
44
|
+
warn_prefix: str = '<yellow>[WARN]: '
|
|
45
|
+
error_prefix: str = '<red>[ERROR]: '
|
|
46
|
+
console_backspaces: int = 8
|
|
47
|
+
|
|
48
|
+
log_path: Path = Path("/home/container/logs")
|
|
49
|
+
log_destination_method: str = 'rcon'
|
|
50
|
+
|
|
51
|
+
# built-in default configuration
|
|
52
|
+
DefaultConfig = Config()
|
|
@@ -16,7 +16,7 @@ class HungerLogger:
|
|
|
16
16
|
self,
|
|
17
17
|
loggerName,
|
|
18
18
|
Config=DefaultConfig,
|
|
19
|
-
|
|
19
|
+
console_backspaces=0,
|
|
20
20
|
logDir=None,
|
|
21
21
|
server=None
|
|
22
22
|
):
|
|
@@ -26,7 +26,7 @@ class HungerLogger:
|
|
|
26
26
|
If no Config class is defined, DefaultConfig is used.
|
|
27
27
|
'''
|
|
28
28
|
self.loggerName = loggerName
|
|
29
|
-
self.
|
|
29
|
+
self.console_backspaces = '\b' * console_backspaces
|
|
30
30
|
self.config = Config
|
|
31
31
|
self.server = server
|
|
32
32
|
|
|
@@ -79,9 +79,9 @@ class HungerLogger:
|
|
|
79
79
|
return
|
|
80
80
|
colored = self._apply_colors(msg, self.config.destination_color_map)
|
|
81
81
|
if self.log_destination_method == 'rcon':
|
|
82
|
-
self.server._rcon_send(f'logtellraw targetless \"{self.
|
|
82
|
+
self.server._rcon_send(f'logtellraw targetless \"{self.console_backspaces}{colored}\"')
|
|
83
83
|
if self.log_destination_method == 'api':
|
|
84
|
-
self.server.sendConsoleCommand(f'logtellraw targetless \"{self.
|
|
84
|
+
self.server.sendConsoleCommand(f'logtellraw targetless \"{self.console_backspaces}{colored}\"')
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
def _log(self, level, msg, destination, origin, logs):
|
|
@@ -6,22 +6,18 @@ from hungerlib.api.filemanager import FileManagerAPI
|
|
|
6
6
|
from hungerlib.api.backups import BackupsAPI
|
|
7
7
|
from hungerlib.api.databases import DatabasesAPI
|
|
8
8
|
from hungerlib.api.startup import StartupAPI
|
|
9
|
+
from hungerlib.config import DefaultConfig
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class Panel:
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- HTTP helpers
|
|
16
|
-
- authentication
|
|
17
|
-
- panel-wide utilities
|
|
18
|
-
- API module accessors
|
|
19
|
-
"""
|
|
13
|
+
"""High-level panel object"""
|
|
14
|
+
def __init__(self, name=None, url=None, api_key=None, Config=DefaultConfig):
|
|
15
|
+
self.Config = Config
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
self.name = name
|
|
23
|
-
self.url = url.rstrip("/")
|
|
24
|
-
self.api_key = api_key
|
|
17
|
+
# If Config is provided, use its defaults
|
|
18
|
+
self.name = name or Config.panel_name
|
|
19
|
+
self.url = (url or Config.panel_url).rstrip("/")
|
|
20
|
+
self.api_key = api_key or Config.panel_api_key
|
|
25
21
|
|
|
26
22
|
# API modules
|
|
27
23
|
self.schedules = ScheduleAPI(self)
|
|
@@ -31,29 +27,28 @@ class Panel:
|
|
|
31
27
|
self.startup = StartupAPI(self)
|
|
32
28
|
self.commands = CommandAPI(self)
|
|
33
29
|
|
|
30
|
+
|
|
34
31
|
def __str__(self):
|
|
35
32
|
return f"Panel name: {self.name}\nURL: {self.url}\nAPI key: {self.api_key}"
|
|
36
33
|
|
|
37
|
-
#
|
|
38
|
-
# HTTP CORE
|
|
39
|
-
# ------------------------------------------------------------
|
|
34
|
+
# http core
|
|
40
35
|
@property
|
|
41
36
|
def headers(self):
|
|
37
|
+
if self.Config and self.Config.panel_headers:
|
|
38
|
+
return self.Config.panel_headers
|
|
39
|
+
|
|
40
|
+
|
|
42
41
|
return {
|
|
43
42
|
"Authorization": f"Bearer {self.api_key}",
|
|
44
43
|
"Accept": "application/json",
|
|
45
44
|
"Content-Type": "application/json",
|
|
46
45
|
}
|
|
47
|
-
|
|
48
46
|
def get(self, path, timeout=5):
|
|
49
47
|
return requests.get(f"{self.url}{path}", headers=self.headers, timeout=timeout)
|
|
50
|
-
|
|
51
48
|
def post(self, path, json=None, timeout=5):
|
|
52
49
|
return requests.post(f"{self.url}{path}", headers=self.headers, json=json, timeout=timeout)
|
|
53
|
-
|
|
54
50
|
def delete(self, path, timeout=5):
|
|
55
51
|
return requests.delete(f"{self.url}{path}", headers=self.headers, timeout=timeout)
|
|
56
|
-
|
|
57
52
|
def patch(self, path, json=None, timeout=5):
|
|
58
53
|
return requests.patch(f"{self.url}{path}", headers=self.headers, json=json, timeout=timeout)
|
|
59
54
|
|
|
@@ -65,16 +60,14 @@ class Panel:
|
|
|
65
60
|
files=file_data
|
|
66
61
|
)
|
|
67
62
|
|
|
68
|
-
|
|
69
|
-
#
|
|
70
|
-
# ------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
# panel health
|
|
71
65
|
def ping(self):
|
|
72
66
|
try:
|
|
73
67
|
r = self.get("/api/client")
|
|
74
68
|
return r.status_code == 200
|
|
75
69
|
except:
|
|
76
70
|
return False
|
|
77
|
-
|
|
78
71
|
def validateAPI(self):
|
|
79
72
|
r = self.get("/api/client/account")
|
|
80
73
|
return r.status_code == 200
|
|
@@ -1,87 +1,74 @@
|
|
|
1
1
|
# Universal server class
|
|
2
|
-
import time
|
|
3
|
-
import re
|
|
4
|
-
import mcrcon
|
|
5
2
|
from hungerlib.panel import Panel
|
|
6
|
-
from hungerlib.config import
|
|
3
|
+
from hungerlib.config import DefaultConfig
|
|
7
4
|
|
|
8
5
|
|
|
9
6
|
class GenericServer:
|
|
10
7
|
def __init__(
|
|
11
8
|
self,
|
|
12
|
-
name,
|
|
13
|
-
panel
|
|
14
|
-
server_id,
|
|
15
|
-
|
|
16
|
-
server_port,
|
|
17
|
-
rcon_port,
|
|
18
|
-
rcon_password,
|
|
19
|
-
Config: Config
|
|
9
|
+
name=None,
|
|
10
|
+
panel=None,
|
|
11
|
+
server_id=None,
|
|
12
|
+
Config=DefaultConfig
|
|
20
13
|
):
|
|
21
|
-
'''
|
|
22
|
-
self.name = name
|
|
23
|
-
self.panel = panel
|
|
24
|
-
self.server_id = server_id
|
|
25
|
-
self.server_domain = server_domain
|
|
26
|
-
self.server_port = server_port
|
|
27
|
-
self.rcon_port = rcon_port
|
|
28
|
-
self.rcon_password = rcon_password
|
|
14
|
+
'''Generic server class'''
|
|
29
15
|
self.Config = Config
|
|
30
|
-
self._cached_resources = None
|
|
31
16
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
17
|
+
# name
|
|
18
|
+
self.name = name or Config.gs_name or "Unnamed Server"
|
|
19
|
+
|
|
20
|
+
# panel (must be explicit)
|
|
21
|
+
self.panel = panel
|
|
22
|
+
if not isinstance(self.panel, Panel):
|
|
23
|
+
raise TypeError("GenericServer requires a Panel instance")
|
|
24
|
+
|
|
25
|
+
# server_id (must be explicit or valid default)
|
|
26
|
+
self.server_id = server_id or Config.gs_server_id
|
|
27
|
+
if not isinstance(self.server_id, str):
|
|
28
|
+
raise TypeError("GenericServer requires a server_id string")
|
|
35
29
|
|
|
30
|
+
self._cached_resources = None
|
|
31
|
+
|
|
32
|
+
# internal helpers
|
|
36
33
|
def _translate_mc_colors(self, msg):
|
|
37
34
|
for tag, code in self.Config.mc_color_map.items():
|
|
38
35
|
msg = msg.replace(tag, code)
|
|
39
36
|
return msg
|
|
40
37
|
|
|
41
|
-
#
|
|
42
|
-
# RESOURCE & STATUS
|
|
43
|
-
# ============================================================
|
|
44
|
-
|
|
38
|
+
# resource and status
|
|
45
39
|
def refresh(self):
|
|
46
40
|
r = self.panel.get(f"/api/client/servers/{self.server_id}/resources")
|
|
47
41
|
self._cached_resources = r.json().get("attributes", {}).get("resources", {})
|
|
48
42
|
return self._cached_resources
|
|
49
|
-
|
|
50
43
|
def resources(self):
|
|
51
44
|
return self._cached_resources or self.refresh()
|
|
52
|
-
|
|
53
45
|
def getRAM(self, rounding=2, gb=False):
|
|
54
46
|
mem = self.resources().get("memory_bytes")
|
|
55
47
|
if mem is None:
|
|
56
48
|
return None
|
|
57
49
|
div = 1024 * 1024 * (1024 if gb else 1)
|
|
58
50
|
return round(mem / div, rounding)
|
|
59
|
-
|
|
60
51
|
def getCPU(self, rounding=2):
|
|
61
52
|
cpu = self.resources().get("cpu_absolute")
|
|
62
53
|
return round(cpu, rounding) if cpu is not None else None
|
|
63
|
-
|
|
64
54
|
def getDisk(self, rounding=2, gb=False):
|
|
65
55
|
disk = self.resources().get("disk_bytes")
|
|
66
56
|
if disk is None:
|
|
67
57
|
return None
|
|
68
58
|
div = 1024 * 1024 * (1024 if gb else 1)
|
|
69
59
|
return round(disk / div, rounding)
|
|
70
|
-
|
|
71
60
|
def getNetworkIn(self, rounding=2, gb=False):
|
|
72
61
|
rx = self.resources().get("network_rx_bytes")
|
|
73
62
|
if rx is None:
|
|
74
63
|
return None
|
|
75
64
|
div = 1024 * 1024 * (1024 if gb else 1)
|
|
76
65
|
return round(rx / div, rounding)
|
|
77
|
-
|
|
78
66
|
def getNetworkOut(self, rounding=2, gb=False):
|
|
79
67
|
tx = self.resources().get("network_tx_bytes")
|
|
80
68
|
if tx is None:
|
|
81
69
|
return None
|
|
82
70
|
div = 1024 * 1024 * (1024 if gb else 1)
|
|
83
71
|
return round(tx / div, rounding)
|
|
84
|
-
|
|
85
72
|
def getUptime(self, formatted=False):
|
|
86
73
|
uptime = self.resources().get("uptime")
|
|
87
74
|
if uptime is None:
|
|
@@ -98,25 +85,19 @@ class GenericServer:
|
|
|
98
85
|
return f"{minutes}m {secs}s"
|
|
99
86
|
else:
|
|
100
87
|
return f"{secs}s"
|
|
101
|
-
|
|
102
88
|
def getStatus(self):
|
|
103
89
|
r = self.panel.get(f"/api/client/servers/{self.server_id}/resources")
|
|
104
90
|
return r.json().get("attributes", {}).get("current_state")
|
|
105
91
|
|
|
106
|
-
# ============================================================
|
|
107
|
-
# STATE HELPERS
|
|
108
|
-
# ============================================================
|
|
109
92
|
|
|
93
|
+
# state helpers
|
|
110
94
|
def isOnline(self):
|
|
111
95
|
return self.getStatus() == "running"
|
|
112
|
-
|
|
113
96
|
def isOffline(self):
|
|
114
97
|
return self.getStatus() == "offline"
|
|
115
98
|
|
|
116
|
-
# ============================================================
|
|
117
|
-
# POWER ACTIONS
|
|
118
|
-
# ============================================================
|
|
119
99
|
|
|
100
|
+
# power actions
|
|
120
101
|
def powerAction(self, action):
|
|
121
102
|
valid = {"start", "restart", "stop", "kill"}
|
|
122
103
|
if action not in valid:
|
|
@@ -124,111 +105,78 @@ class GenericServer:
|
|
|
124
105
|
payload = {"signal": action}
|
|
125
106
|
r = self.panel.post(f"/api/client/servers/{self.server_id}/power", json=payload)
|
|
126
107
|
return r.status_code, r.text
|
|
127
|
-
|
|
128
108
|
def start(self): return self.powerAction("start")
|
|
129
109
|
def restart(self): return self.powerAction("restart")
|
|
130
110
|
def stop(self): return self.powerAction("stop")
|
|
131
111
|
def kill(self): return self.powerAction("kill")
|
|
132
112
|
|
|
133
|
-
# ============================================================
|
|
134
|
-
# FILE MANAGER
|
|
135
|
-
# ============================================================
|
|
136
113
|
|
|
114
|
+
# file manager
|
|
137
115
|
def listFiles(self, directory="/"):
|
|
138
116
|
return self.panel.files.list(self.server_id, directory)
|
|
139
|
-
|
|
140
117
|
def downloadFile(self, path):
|
|
141
118
|
return self.panel.files.download(self.server_id, path)
|
|
142
|
-
|
|
143
119
|
def uploadFile(self, directory, file_data):
|
|
144
120
|
return self.panel.files.upload(self.server_id, directory, file_data)
|
|
145
|
-
|
|
146
121
|
def deleteFiles(self, root, files):
|
|
147
122
|
return self.panel.files.delete(self.server_id, root, files)
|
|
148
|
-
|
|
149
123
|
def renameFiles(self, root, files):
|
|
150
124
|
return self.panel.files.rename(self.server_id, root, files)
|
|
151
|
-
|
|
152
125
|
def copyFiles(self, root, files):
|
|
153
126
|
return self.panel.files.copy(self.server_id, root, files)
|
|
154
|
-
|
|
155
127
|
def moveFiles(self, root, files):
|
|
156
128
|
return self.panel.files.move(self.server_id, root, files)
|
|
157
|
-
|
|
158
129
|
def createFolder(self, directory, name):
|
|
159
130
|
return self.panel.files.create_folder(self.server_id, directory, name)
|
|
160
|
-
|
|
161
131
|
def compress(self, root, files):
|
|
162
132
|
return self.panel.files.compress(self.server_id, root, files)
|
|
163
|
-
|
|
164
133
|
def decompress(self, file_path):
|
|
165
134
|
return self.panel.files.decompress(self.server_id, file_path)
|
|
166
135
|
|
|
167
|
-
# ============================================================
|
|
168
|
-
# BACKUPS
|
|
169
|
-
# ============================================================
|
|
170
136
|
|
|
137
|
+
# backup manager
|
|
171
138
|
def listBackups(self):
|
|
172
139
|
return self.panel.backups.list(self.server_id)
|
|
173
|
-
|
|
174
140
|
def createBackup(self, name="Auto Backup"):
|
|
175
141
|
return self.panel.backups.create(self.server_id, name)
|
|
176
|
-
|
|
177
142
|
def deleteBackup(self, backup_id):
|
|
178
143
|
return self.panel.backups.delete(self.server_id, backup_id)
|
|
179
|
-
|
|
180
144
|
def downloadBackup(self, backup_id):
|
|
181
145
|
return self.panel.backups.download(self.server_id, backup_id)
|
|
182
146
|
|
|
183
|
-
# ============================================================
|
|
184
|
-
# DATABASES
|
|
185
|
-
# ============================================================
|
|
186
147
|
|
|
148
|
+
# database manager
|
|
187
149
|
def listDatabases(self):
|
|
188
150
|
return self.panel.databases.list(self.server_id)
|
|
189
|
-
|
|
190
151
|
def createDatabase(self, name, remote="%", host=None):
|
|
191
152
|
return self.panel.databases.create(self.server_id, name, remote, host)
|
|
192
|
-
|
|
193
153
|
def rotateDatabasePassword(self, db_id):
|
|
194
154
|
return self.panel.databases.rotate_password(self.server_id, db_id)
|
|
195
|
-
|
|
196
155
|
def deleteDatabase(self, db_id):
|
|
197
156
|
return self.panel.databases.delete(self.server_id, db_id)
|
|
198
157
|
|
|
199
|
-
# ============================================================
|
|
200
|
-
# STARTUP VARIABLES
|
|
201
|
-
# ============================================================
|
|
202
158
|
|
|
159
|
+
# startup variables
|
|
203
160
|
def getStartupVariables(self):
|
|
204
161
|
return self.panel.startup.list(self.server_id)
|
|
205
|
-
|
|
206
162
|
def updateStartupVariable(self, key, value):
|
|
207
163
|
return self.panel.startup.update(self.server_id, key, value)
|
|
208
164
|
|
|
209
|
-
# ============================================================
|
|
210
|
-
# SCHEDULES
|
|
211
|
-
# ============================================================
|
|
212
165
|
|
|
166
|
+
# schedules
|
|
213
167
|
def listSchedules(self):
|
|
214
168
|
return self.panel.schedules.list(self.server_id)
|
|
215
|
-
|
|
216
169
|
def createSchedule(self, payload):
|
|
217
170
|
return self.panel.schedules.create(self.server_id, payload)
|
|
218
|
-
|
|
219
171
|
def updateSchedule(self, schedule_id, payload):
|
|
220
172
|
return self.panel.schedules.update(self.server_id, schedule_id, payload)
|
|
221
|
-
|
|
222
173
|
def deleteSchedule(self, schedule_id):
|
|
223
174
|
return self.panel.schedules.delete(self.server_id, schedule_id)
|
|
224
|
-
|
|
225
175
|
def runSchedule(self, schedule_id):
|
|
226
176
|
return self.panel.schedules.run(self.server_id, schedule_id)
|
|
227
177
|
|
|
228
|
-
# ============================================================
|
|
229
|
-
# HEALTH SNAPSHOT
|
|
230
|
-
# ============================================================
|
|
231
178
|
|
|
179
|
+
# health snapshot
|
|
232
180
|
def snapshot(self):
|
|
233
181
|
return {
|
|
234
182
|
"ram": self.getRAM(),
|
|
@@ -3,44 +3,37 @@ import time
|
|
|
3
3
|
import re
|
|
4
4
|
import mcrcon
|
|
5
5
|
from hungerlib.panel import Panel
|
|
6
|
-
from hungerlib.config import
|
|
6
|
+
from hungerlib.config import DefaultConfig
|
|
7
7
|
from hungerlib.servers._generic import GenericServer
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class MinecraftServer(GenericServer):
|
|
11
11
|
def __init__(
|
|
12
12
|
self,
|
|
13
|
-
name,
|
|
14
|
-
panel,
|
|
15
|
-
server_id,
|
|
16
|
-
server_domain,
|
|
17
|
-
server_port,
|
|
18
|
-
Config,
|
|
13
|
+
name=None,
|
|
14
|
+
panel=None,
|
|
15
|
+
server_id=None,
|
|
16
|
+
server_domain=None,
|
|
17
|
+
server_port=None,
|
|
19
18
|
rcon_port=None,
|
|
20
19
|
rcon_password=None,
|
|
21
|
-
tpsCommand=
|
|
20
|
+
tpsCommand=None,
|
|
21
|
+
Config=DefaultConfig
|
|
22
22
|
):
|
|
23
|
-
|
|
24
|
-
A highly configurable server class for Minecraft servers.
|
|
25
|
-
Supports Rcon.
|
|
26
|
-
'''
|
|
27
|
-
super().__init__(
|
|
28
|
-
name,
|
|
29
|
-
panel,
|
|
30
|
-
server_id,
|
|
31
|
-
server_domain,
|
|
32
|
-
server_port,
|
|
33
|
-
rcon_port,
|
|
34
|
-
rcon_password,
|
|
35
|
-
Config
|
|
36
|
-
)
|
|
37
|
-
self.tpsCommand = tpsCommand
|
|
23
|
+
super().__init__(name, panel, server_id, Config)
|
|
38
24
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
25
|
+
self.server_domain = server_domain or Config.mc_server_domain
|
|
26
|
+
self.server_port = server_port or Config.mc_server_port
|
|
27
|
+
self.rcon_port = rcon_port or Config.mc_rcon_port
|
|
28
|
+
self.rcon_password = rcon_password or Config.mc_rcon_password
|
|
29
|
+
self.tpsCommand = tpsCommand or Config.mc_tpsCommand
|
|
42
30
|
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# rcon handler
|
|
43
34
|
def _rcon_send(self, command):
|
|
35
|
+
if not self.server_domain or not self.rcon_password:
|
|
36
|
+
return None
|
|
44
37
|
try:
|
|
45
38
|
with mcrcon.MCRcon(self.server_domain, self.rcon_password, port=self.rcon_port) as m:
|
|
46
39
|
resp1 = m.command(command)
|
|
@@ -51,21 +44,13 @@ class MinecraftServer(GenericServer):
|
|
|
51
44
|
print("RCON error:", e)
|
|
52
45
|
return None
|
|
53
46
|
|
|
54
|
-
#
|
|
55
|
-
# PLAYERS
|
|
56
|
-
# ============================================================
|
|
57
|
-
|
|
47
|
+
# getter methods
|
|
58
48
|
def getPlayers(self):
|
|
59
49
|
output = self._rcon_send("list")
|
|
60
50
|
if not output:
|
|
61
51
|
return None
|
|
62
52
|
m = re.search(r"There are (\d+)", output)
|
|
63
53
|
return int(m.group(1)) if m else None
|
|
64
|
-
|
|
65
|
-
# ============================================================
|
|
66
|
-
# TPS PARSER
|
|
67
|
-
# ============================================================
|
|
68
|
-
|
|
69
54
|
def getTPS(self, type="raw", rounding=10):
|
|
70
55
|
'''
|
|
71
56
|
This has limitations and is not yet complete. It currently ONLY parses TT20's tps command.
|
|
@@ -82,20 +67,15 @@ class MinecraftServer(GenericServer):
|
|
|
82
67
|
)
|
|
83
68
|
if not m:
|
|
84
69
|
return None
|
|
85
|
-
|
|
86
70
|
raw, avg, acc = map(float, m.groups())
|
|
87
71
|
table = {"raw": raw, "avg": avg, "acc": acc}
|
|
88
72
|
value = table.get(type, avg)
|
|
89
|
-
|
|
90
73
|
return round(value, rounding) if rounding else value
|
|
91
74
|
|
|
92
|
-
# ============================================================
|
|
93
|
-
# COMMANDS
|
|
94
|
-
# ============================================================
|
|
95
75
|
|
|
76
|
+
# commands
|
|
96
77
|
def sendConsoleCommand(self, command):
|
|
97
78
|
return self.panel.commands.send(self.server_id, command)
|
|
98
|
-
|
|
99
79
|
def sendBroadcast(self, message):
|
|
100
80
|
translated = self._translate_mc_colors(message)
|
|
101
81
|
safe = translated.replace('"', '\\"')
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# HungerLib's core config system
|
|
2
|
-
|
|
3
|
-
from dataclasses import dataclass, field
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from hungerlib.addons.colormap import *
|
|
6
|
-
|
|
7
|
-
@dataclass
|
|
8
|
-
class Config:
|
|
9
|
-
file_color_map: dict | None = None
|
|
10
|
-
origin_color_map: dict = field(default_factory=lambda: ASCI_COLOR_MAP.copy())
|
|
11
|
-
destination_color_map: dict = field(default_factory=lambda: ASCI_COLOR_MAP.copy())
|
|
12
|
-
mc_color_map: dict = field(default_factory=lambda: MC_COLOR_MAP.copy())
|
|
13
|
-
|
|
14
|
-
info_prefix: str = '<white>[INFO]: '
|
|
15
|
-
warn_prefix: str = '<yellow>[WARN]: '
|
|
16
|
-
error_prefix: str = '<red>[ERROR]: '
|
|
17
|
-
backspaces: int = 8
|
|
18
|
-
|
|
19
|
-
log_path: Path = Path("/home/container/logs")
|
|
20
|
-
log_destination_method: str = 'rcon'
|
|
21
|
-
|
|
22
|
-
DefaultConfig = Config()
|
|
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
|
|
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
|