Skip to content

Commit 3fa9af4

Browse files
committed
Add server info retrieval and display functionality
- Implemented `get_server_info` method in API to fetch server details. - Updated `ServerInfo` interface to include `started_at` property. - Enhanced server page template to display Minecraft version, modloader version, RAM, and server start time. - Modified `load_data` function to populate server information on the page. - Added event handling for server start time in the server core and Minecraft server classes.
1 parent d4134a1 commit 3fa9af4

7 files changed

Lines changed: 117 additions & 1 deletion

File tree

client/src/scripts/api.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,22 @@ export default class API {
290290
}
291291
}
292292

293+
public static async get_server_info(server_name: string) {
294+
if (!Cookies.has('token')) {
295+
console.error('No token found in cookies');
296+
return null;
297+
}
298+
const {data, status} = await API.get(`/api/server/${server_name}`, {});
299+
if (status === 200) {
300+
return data as ServerInfo;
301+
}
302+
else if (status === 500) {
303+
console.error('Error getting server info:', data['message']);
304+
throw new Error('Error getting server info');
305+
}
306+
else{
307+
return null;
308+
}
309+
}
310+
293311
}

client/src/scripts/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ interface ServerInfo {
3232
mc_version: string;
3333
modloader_version: string;
3434
ram: number;
35+
started_at: Date | null; // Nullable to handle servers that haven't been started yet
3536
}
3637

3738
export { AccessLevel, User, ServerInfo, AccessLevelFromString };

client/src/server/index.template.html

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,22 @@
99
<body>
1010
{{ insert("header/header") }}
1111
<main>
12-
12+
<h1 id="server-name"></h1>
13+
<div>
14+
<span id="mc-version"></span>
15+
</div>
16+
<div>
17+
<span id="modloader-version"></span>
18+
</div>
19+
<div>
20+
<span id="ram"></span>
21+
</div>
22+
<div>
23+
<span id="started-at"></span>
24+
</div>
25+
<div>
26+
<span id="running-for"></span>
27+
</div>
1328
</main>
1429
<script type="module" src="server.js"></script>
1530
</body>

client/src/server/server.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,51 @@ if (!server_name) {
99
}
1010

1111
async function load_data(){
12+
API.get_server_info(server_name as string).then((server_info) => {
13+
if (!server_info) {
14+
window.location.href = "/app/dashboard";
15+
return;
16+
}
1217

18+
const serverNameElement = document.getElementById("server-name") as HTMLHeadingElement;
19+
serverNameElement.textContent = server_info.name;
20+
21+
const mcVersionElement = document.getElementById("mc-version") as HTMLSpanElement;
22+
mcVersionElement.textContent = `Minecraft Version: ${server_info.mc_version}`;
23+
24+
const modloaderVersionElement = document.getElementById("modloader-version") as HTMLSpanElement;
25+
modloaderVersionElement.textContent = `Modloader Version: ${server_info.modloader_version}`;
26+
27+
const ramElement = document.getElementById("ram") as HTMLSpanElement;
28+
ramElement.textContent = `RAM: ${server_info.ram} MB`;
29+
30+
const startedAtElement = document.getElementById("started-at") as HTMLSpanElement;
31+
startedAtElement.textContent = server_info.started_at ? `Started At: ${new Date(server_info.started_at).toLocaleString()}` : "Not Started";
32+
33+
const runningForElement = document.getElementById("running-for") as HTMLSpanElement;
34+
if (server_info.started_at) {
35+
const startedAt = new Date(server_info.started_at);
36+
37+
function updateRunningFor() {
38+
const now = new Date();
39+
const diff = Math.floor((now.getTime() - startedAt.getTime()) / 1000); // in seconds
40+
const hours = Math.floor(diff / 3600);
41+
const minutes = Math.floor((diff % 3600) / 60);
42+
const seconds = diff % 60;
43+
runningForElement.textContent = `Running For: ${hours}h ${minutes}m ${seconds}s`;
44+
}
45+
46+
updateRunningFor();
47+
setInterval(updateRunningFor, 1000);
48+
}
49+
else {
50+
runningForElement.textContent = "Not Running";
51+
}
52+
53+
}).catch((error) => {
54+
console.error("Error loading server info:", error);
55+
window.location.href = "/app/dashboard";
56+
});
1357
}
1458

1559
load_data();

server/src/bus/events.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,13 @@
157157
</args>
158158
<return type="None" />
159159
</event>
160+
<event name="STARTED_AT" id="0x0105">
161+
<args>
162+
<arg name="timestamp" type="datetime" id="0x01" />
163+
<arg name="server_name" type="str" id="0x02" />
164+
</args>
165+
<return type="datetime" />
166+
</event>
160167
</namespace>
161168
<namespace name="CONSOLE">
162169
<event name="MESSAGE_RECEIVED" id="0x0101">

server/src/core/core.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,11 @@ def on_server_info(self, timestamp : datetime, server_name: str) -> Dict[str, An
513513
"mc_version": Version.from_string(srv_info['mc_version']),
514514
"modloader_version": Version.from_string(srv_info['modloader_version']),
515515
"ram": srv_info['ram'],
516+
"started_at": self.__bus.trigger(
517+
Events['SERVER.STARTED_AT'],
518+
server_name=server_name,
519+
timeout=0.5 # Wait for 0.5 seconds for the server to respond
520+
),
516521
}
517522

518523
def on_get_version_minecraft(self, timestamp: datetime) -> list[Version]:

server/src/minecraft/Base_mc_server.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class BaseMcServer(ABC):
5252
"on_player_ban": "PLAYERS.BAN",
5353
"on_player_pardon": "PLAYERS.PARDON",
5454
"on_player_list": "PLAYERS.LIST",
55+
"on_started_at": "SERVER.STARTED_AT",
5556
}
5657

5758
def __init__(self, name : str, path : str, ram : int, mc_version : Version, bus_data : BusData):
@@ -61,6 +62,7 @@ def __init__(self, name : str, path : str, ram : int, mc_version : Version, bus_
6162
self.__name = name
6263
self.__path = path
6364
self._ServerStatus = ServerStatus.STOPPED
65+
self.__started_at : datetime = None
6466
self.__register_callbacks()
6567

6668
@property
@@ -85,6 +87,7 @@ def start(self) -> None:
8587
Logger.error(f"Server \"{self.name}\" failed to start.")
8688
return
8789
self.__bus.trigger(Events["SERVER.STARTED"], server_name = self.name)
90+
self.__started_at = datetime.now()
8891
self._after_start()
8992
Logger.info(f"Server \"{self.name}\" started")
9093
self.__wait_for_stop()
@@ -126,6 +129,7 @@ def stop(self) -> None:
126129
while self._ServerStatus not in (ServerStatus.STOPPED, ServerStatus.ERROR):
127130
time.sleep(0.2)
128131
self.__bus.trigger(Events["SERVER.STOPPED"], server_name = self.name)
132+
self.__started_at = None
129133
self.__bus.stop()
130134
Logger.info(f"Server \"{self.name}\" stopped with status: {self._ServerStatus.name}")
131135

@@ -143,6 +147,14 @@ def name(self) -> str:
143147
@property
144148
def path(self) -> str:
145149
return self.__path
150+
151+
@property
152+
def started_at(self) -> datetime:
153+
"""
154+
Get the datetime when the server was started.
155+
:return: The datetime when the server was started, or None if the server has not been started.
156+
"""
157+
return self.__started_at
146158

147159
def __on_ping(self, timestamp: datetime, server_name: str) -> str:
148160
"""
@@ -165,6 +177,20 @@ def __register_callbacks(self):
165177
# Register the ping callback
166178
self.__bus.register(Events["SERVER.PING"], self.__on_ping)
167179

180+
def on_started_at(self, timestamp: datetime, server_name: str) -> datetime:
181+
"""
182+
Callback for the STARTED_AT event.
183+
This method is called when the server starts and can be overridden by subclasses.
184+
:param timestamp: The timestamp when the server started.
185+
:param server_name: The name of the server.
186+
:return: The timestamp when the server started.
187+
"""
188+
if server_name == self.name:
189+
Logger.info(f"Server {self.name} started at {timestamp}.")
190+
return self.__started_at
191+
Logger.debug(f"Started at event received for server {server_name}, but this is not the current server ({self.name}). Ignoring.")
192+
return None
193+
168194

169195
def main():
170196
from datetime import datetime

0 commit comments

Comments
 (0)