hungerlib 3.2.dev10__tar.gz → 3.2.dev12__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-3.2.dev10/src/hungerlib.egg-info → hungerlib-3.2.dev12}/PKG-INFO +1 -1
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/pyproject.toml +1 -1
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/__init__.py +5 -0
- hungerlib-3.2.dev12/src/hungerlib/bridgeclient.py +42 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/messagerouter.py +25 -4
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/servers/minecraft.py +34 -9
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12/src/hungerlib.egg-info}/PKG-INFO +1 -1
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib.egg-info/SOURCES.txt +1 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/LICENSE +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/README.md +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/setup.cfg +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/api/__init__.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/api/backups.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/api/command.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/api/databases.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/api/filemanager.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/api/schedule.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/api/startup.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/configloader.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/datamap.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/panel.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/servers/__init__.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/servers/generic.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/utils/__init__.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/utils/colormaps.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/utils/time.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib/utils/utils.py +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib.egg-info/dependency_links.txt +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib.egg-info/requires.txt +0 -0
- {hungerlib-3.2.dev10 → hungerlib-3.2.dev12}/src/hungerlib.egg-info/top_level.txt +0 -0
|
@@ -13,6 +13,7 @@ from .datamap import set_default_maps, get_default_maps, Syntax, DataMap, datama
|
|
|
13
13
|
from .messagerouter import MessageRouter
|
|
14
14
|
from .panel import Panel
|
|
15
15
|
from .servers import GenericServer, MinecraftServer
|
|
16
|
+
from .bridgeclient import health, ping, runCommand, log
|
|
16
17
|
from .utils import (
|
|
17
18
|
ColorMap,
|
|
18
19
|
ASCII_COLOR_MAP,
|
|
@@ -93,6 +94,10 @@ __all__ = [
|
|
|
93
94
|
'Snapshot',
|
|
94
95
|
'clearTerminal',
|
|
95
96
|
'validateAll',
|
|
97
|
+
'health',
|
|
98
|
+
'ping',
|
|
99
|
+
'runCommand',
|
|
100
|
+
'log',
|
|
96
101
|
|
|
97
102
|
# namespaces
|
|
98
103
|
'utils',
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
|
|
3
|
+
class HungerBridgeClient:
|
|
4
|
+
def __init__(self, base_url: str, token: str):
|
|
5
|
+
self.base = base_url.rstrip("/")
|
|
6
|
+
self.headers = {
|
|
7
|
+
"Authorization": f"Bearer {token}",
|
|
8
|
+
"Content-Type": "application/json"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
def _post(self, path: str, payload: dict):
|
|
12
|
+
r = requests.post(f"{self.base}{path}", headers=self.headers, json=payload)
|
|
13
|
+
if not r.ok:
|
|
14
|
+
raise RuntimeError(f"HungerBridge error {r.status_code}: {r.text}")
|
|
15
|
+
return r.json()
|
|
16
|
+
|
|
17
|
+
def _get(self, path: str):
|
|
18
|
+
r = requests.get(f"{self.base}{path}", headers=self.headers)
|
|
19
|
+
if not r.ok:
|
|
20
|
+
raise RuntimeError(f"HungerBridge error {r.status_code}: {r.text}")
|
|
21
|
+
return r.json()
|
|
22
|
+
|
|
23
|
+
# -----------------------------
|
|
24
|
+
# Public API
|
|
25
|
+
# -----------------------------
|
|
26
|
+
def health(self):
|
|
27
|
+
return self._get("/health")
|
|
28
|
+
|
|
29
|
+
def ping(self):
|
|
30
|
+
return self._get("/ping")
|
|
31
|
+
|
|
32
|
+
def runCommand(self, command: str, silent: bool = False):
|
|
33
|
+
return self._post("/run", {
|
|
34
|
+
"command": command,
|
|
35
|
+
"silent": silent
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
def log(self, message: str, level: str = "info"):
|
|
39
|
+
return self._post("/log", {
|
|
40
|
+
"level": level,
|
|
41
|
+
"message": message
|
|
42
|
+
})
|
|
@@ -2,6 +2,7 @@ import logging
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
|
|
5
|
+
|
|
5
6
|
class MessageRouter:
|
|
6
7
|
def __init__(
|
|
7
8
|
self,
|
|
@@ -48,13 +49,33 @@ class MessageRouter:
|
|
|
48
49
|
print(msg)
|
|
49
50
|
|
|
50
51
|
def destination(self, msg):
|
|
51
|
-
if not self.server
|
|
52
|
+
if not self.server:
|
|
52
53
|
return
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
)
|
|
54
|
+
|
|
55
|
+
# Prefer HungerBridge client if present
|
|
56
|
+
bridge = getattr(self.server, "bridge", None)
|
|
57
|
+
if bridge is not None:
|
|
58
|
+
try:
|
|
59
|
+
bridge.log(self.console_backspaces + msg, level="info")
|
|
60
|
+
return
|
|
61
|
+
except Exception as e:
|
|
62
|
+
print("Bridge destination error, falling back to RCON:", e)
|
|
63
|
+
|
|
64
|
+
# Fallback to RCON/logtellraw
|
|
65
|
+
if hasattr(self.server, "_rcon_send"):
|
|
66
|
+
self.server._rcon_send(
|
|
67
|
+
f'logtellraw targetless "{self.console_backspaces}{msg}"'
|
|
68
|
+
)
|
|
56
69
|
|
|
57
70
|
def log(self, msg, level="INFO"):
|
|
71
|
+
# Prefer HungerBridge client for server log
|
|
72
|
+
bridge = getattr(self.server, "bridge", None)
|
|
73
|
+
if bridge is not None:
|
|
74
|
+
try:
|
|
75
|
+
bridge.log(msg, level=level.lower())
|
|
76
|
+
except Exception as e:
|
|
77
|
+
print("Bridge log error, falling back to file log:", e)
|
|
78
|
+
|
|
58
79
|
{
|
|
59
80
|
"INFO": self.logger.info,
|
|
60
81
|
"WARN": self.logger.warning,
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import time
|
|
2
2
|
import re
|
|
3
3
|
import mcrcon
|
|
4
|
+
|
|
4
5
|
from hungerlib.panel import Panel
|
|
5
6
|
from hungerlib.utils.colormaps import MC_COLOR_MAP, ASCII_COLOR_MAP
|
|
6
7
|
from hungerlib.servers import GenericServer
|
|
8
|
+
from hungerlib.bridgeclient import HungerBridgeClient
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
class MinecraftServer(GenericServer):
|
|
10
12
|
def __init__(
|
|
11
13
|
self,
|
|
12
14
|
name,
|
|
13
|
-
panel,
|
|
15
|
+
panel: Panel,
|
|
14
16
|
server_id,
|
|
15
17
|
server_domain,
|
|
16
18
|
server_port,
|
|
17
19
|
rcon_port,
|
|
18
20
|
rcon_password,
|
|
21
|
+
bridge_url=None,
|
|
22
|
+
bridge_token=None,
|
|
19
23
|
mc_color_map=MC_COLOR_MAP,
|
|
20
24
|
ascii_color_map=ASCII_COLOR_MAP,
|
|
21
25
|
tpsCommand='tt20 tps',
|
|
@@ -31,7 +35,6 @@ class MinecraftServer(GenericServer):
|
|
|
31
35
|
else ascii_color_map
|
|
32
36
|
)
|
|
33
37
|
|
|
34
|
-
# Pass normalized maps to GenericServer
|
|
35
38
|
super().__init__(
|
|
36
39
|
name,
|
|
37
40
|
panel,
|
|
@@ -47,9 +50,12 @@ class MinecraftServer(GenericServer):
|
|
|
47
50
|
self.rcon_password = rcon_password
|
|
48
51
|
self.tpsCommand = tpsCommand
|
|
49
52
|
|
|
53
|
+
# Optional HungerBridge client
|
|
54
|
+
self.bridge: HungerBridgeClient | None = None
|
|
55
|
+
if bridge_url and bridge_token:
|
|
56
|
+
self.bridge = HungerBridgeClient(bridge_url, bridge_token)
|
|
50
57
|
|
|
51
|
-
|
|
52
|
-
# rcon handler
|
|
58
|
+
# rcon handler (fallback path)
|
|
53
59
|
def _rcon_send(self, command):
|
|
54
60
|
if not self.server_domain or not self.rcon_password:
|
|
55
61
|
return None
|
|
@@ -65,17 +71,19 @@ class MinecraftServer(GenericServer):
|
|
|
65
71
|
|
|
66
72
|
# getter methods
|
|
67
73
|
def getPlayers(self):
|
|
74
|
+
# Prefer bridge if we ever add an endpoint; for now still RCON
|
|
68
75
|
output = self._rcon_send("list")
|
|
69
76
|
if not output:
|
|
70
77
|
return None
|
|
71
78
|
m = re.search(r"There are (\d+)", output)
|
|
72
79
|
return int(m.group(1)) if m else None
|
|
80
|
+
|
|
73
81
|
def getTPS(self, type="raw", rounding=10):
|
|
74
|
-
|
|
82
|
+
"""
|
|
75
83
|
This has limitations and is not yet complete. It currently ONLY parses TT20's tps command.
|
|
76
84
|
Example: /tt20 tps
|
|
77
85
|
This parser WILL NOT WORK with other configurations!
|
|
78
|
-
|
|
86
|
+
"""
|
|
79
87
|
output = self._rcon_send(self.tpsCommand)
|
|
80
88
|
if not output:
|
|
81
89
|
return None
|
|
@@ -91,12 +99,29 @@ class MinecraftServer(GenericServer):
|
|
|
91
99
|
value = table.get(type, avg)
|
|
92
100
|
return round(value, rounding) if rounding else value
|
|
93
101
|
|
|
94
|
-
|
|
95
102
|
# commands
|
|
96
|
-
def sendConsoleCommand(self, command):
|
|
103
|
+
def sendConsoleCommand(self, command: str):
|
|
104
|
+
# Prefer HungerBridge
|
|
105
|
+
if self.bridge is not None:
|
|
106
|
+
try:
|
|
107
|
+
return self.bridge.runCommand(command)
|
|
108
|
+
except Exception as e:
|
|
109
|
+
print("Bridge command error, falling back to panel:", e)
|
|
110
|
+
|
|
111
|
+
# Fallback to panel (which may use RCON or other transport)
|
|
97
112
|
return self.panel.commands.send(self.server_id, command)
|
|
98
|
-
|
|
113
|
+
|
|
114
|
+
def sendBroadcast(self, message: str):
|
|
99
115
|
translated = self._translate_mc_colors(message)
|
|
100
116
|
safe = translated.replace('"', '\\"')
|
|
101
117
|
cmd = f'tellraw @a {{"text":"{safe}"}}'
|
|
118
|
+
|
|
119
|
+
# Prefer HungerBridge
|
|
120
|
+
if self.bridge is not None:
|
|
121
|
+
try:
|
|
122
|
+
return self.bridge.runCommand(cmd)
|
|
123
|
+
except Exception as e:
|
|
124
|
+
print("Bridge broadcast error, falling back to panel:", e)
|
|
125
|
+
|
|
126
|
+
# Fallback
|
|
102
127
|
return self.sendConsoleCommand(cmd)
|
|
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
|
|
File without changes
|