215 lines
6.6 KiB
TypeScript
215 lines
6.6 KiB
TypeScript
"use client";
|
|
|
|
import React, { useEffect, useState, useRef } from "react";
|
|
|
|
import Stats from "./stats";
|
|
import ServerName from "./serverName";
|
|
import ServerControl from "./serverControl";
|
|
import ServerStatus from "./serverStatus";
|
|
import Navigation from "../ConsoleNavigation";
|
|
|
|
const Console = () => {
|
|
const [apiKey, setApiKey] = useState("");
|
|
const [url, setUrl] = useState("");
|
|
const [token, setToken] = useState("");
|
|
const [output, setOutput] = useState<string[]>([]);
|
|
const [input, setInput] = useState<string>("");
|
|
const [cpuStat, setCpuStat] = useState<number>(0);
|
|
const [ramStat, setRamStat] = useState<number>(0);
|
|
const [ramTotal, setRamTotal] = useState<number>(0);
|
|
const [diskUsage, setDiskUsage] = useState<number>(0);
|
|
const [diskTotal, setDiskTotal] = useState<number>(0);
|
|
const [network, setNetwork] = useState({ inbound: 0, outbound: 0 });
|
|
const [uptime, setUptime] = useState<number>(0);
|
|
const [serverStatus, setServerStatus] = useState<string>("N/A");
|
|
|
|
const websocketRef = useRef<WebSocket | null>(null); // Dodajemy ref do WebSocket
|
|
const textareaRef = useRef<HTMLTextAreaElement>(null); // Dodajemy referencję do textarea
|
|
|
|
const setCredentials = async () => {
|
|
setApiKey("ptlc_aDGU4VHNQuN5t6dyxNzVon3UZLR5ehuySmdR7xsUbMm");
|
|
};
|
|
|
|
const fetchData = async (apiKey: string) => {
|
|
console.log("Fetching data...");
|
|
console.log(apiKey);
|
|
try {
|
|
const response = await fetch(
|
|
"https://ptero.przeqpiciel.com/api/client/servers/0bf192ab/websocket",
|
|
{
|
|
method: "GET",
|
|
headers: {
|
|
Authorization: "Bearer " + apiKey.toString(),
|
|
"Content-Type": "application/json",
|
|
},
|
|
}
|
|
);
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
const data = await response.json();
|
|
setUrl(data.data.socket);
|
|
setToken(data.data.token);
|
|
} catch (error) {
|
|
console.error("Error fetching data:", error);
|
|
}
|
|
};
|
|
|
|
const fetchStats = async () => {
|
|
setDiskTotal(5);
|
|
};
|
|
|
|
useEffect(() => {
|
|
setCredentials();
|
|
fetchData(apiKey);
|
|
fetchStats();
|
|
}, [apiKey]);
|
|
|
|
useEffect(() => {
|
|
if (url && token) {
|
|
const websocket = new WebSocket(url);
|
|
websocketRef.current = websocket;
|
|
|
|
websocket.onopen = () => {
|
|
console.log("WebSocket connection established.");
|
|
websocket.send(`{"event":"auth","args":["${token}"]}`);
|
|
};
|
|
|
|
websocket.onmessage = (event) => {
|
|
const message = JSON.parse(event.data);
|
|
// console.log("Received message:", message.event);
|
|
|
|
switch (message.event) {
|
|
case "token expiring":
|
|
fetchData(apiKey);
|
|
websocket.send(`{"event":"auth","args":["${token}"]}`);
|
|
console.log("New token fetched");
|
|
break;
|
|
case "auth success":
|
|
console.log("Authenticated.");
|
|
break;
|
|
case "auth error":
|
|
console.error("Authentication error:", message.args[0]);
|
|
break;
|
|
case "stats":
|
|
let data = JSON.parse(JSON.parse(event.data).args[0]);
|
|
setCpuStat(data.cpu_absolute.toFixed(2));
|
|
setRamStat(
|
|
Number((data.memory_bytes / (1024 * 1024 * 1024)).toFixed(2))
|
|
);
|
|
setRamTotal(
|
|
Number(
|
|
(data.memory_limit_bytes / (1024 * 1024 * 1024)).toFixed(2)
|
|
)
|
|
);
|
|
setDiskUsage(
|
|
Number((data.disk_bytes / (1024 * 1024 * 1024)).toFixed(2))
|
|
);
|
|
setNetwork({
|
|
inbound: data.network.rx_bytes,
|
|
outbound: data.network.tx_bytes,
|
|
});
|
|
setUptime(data.uptime);
|
|
break;
|
|
case "status":
|
|
setServerStatus(message.args[0]);
|
|
break;
|
|
case "console output":
|
|
setOutput((prevOutput) => {
|
|
let tmpMessage = JSON.parse(event.data).args[0];
|
|
tmpMessage = tmpMessage.replace(/\u001b\[[0-9;]*m/g, "");
|
|
const newOutput = [...prevOutput, tmpMessage];
|
|
if (newOutput.length > 1000) {
|
|
return newOutput.slice(-1000);
|
|
}
|
|
return newOutput;
|
|
});
|
|
break;
|
|
}
|
|
};
|
|
|
|
websocket.onclose = () => {
|
|
console.log("WebSocket connection closed.");
|
|
};
|
|
|
|
websocket.onerror = (error) => {
|
|
console.error("WebSocket error:", error);
|
|
};
|
|
|
|
return () => {
|
|
websocket.close();
|
|
};
|
|
}
|
|
}, [url, token]);
|
|
|
|
useEffect(() => {
|
|
if (textareaRef.current) {
|
|
textareaRef.current.scrollTop = textareaRef.current.scrollHeight;
|
|
}
|
|
}, [output]);
|
|
|
|
const handleKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
if (e.key === "Enter" && websocketRef.current) {
|
|
console.log("Sending message:", input);
|
|
websocketRef.current.send(`{"event":"send command","args":["${input}"]}`);
|
|
setInput("");
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Navigation />
|
|
<section className="container mx-auto">
|
|
<div className="flex flex-col gap-4">
|
|
<div className="flex gap-4">
|
|
<div className="w-4/5 flex justify-self-auto justify-between items-center">
|
|
<ServerName serverName="asdf " />
|
|
<ServerStatus serverStatus={serverStatus} />
|
|
</div>
|
|
<div className="w-1/5 flex justify-between">
|
|
<ServerControl websocketRef={websocketRef} />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex gap-4">
|
|
<div className="w-4/5">
|
|
<div>
|
|
<textarea
|
|
className="textarea textarea-bordered text-yellow-200 w-full"
|
|
ref={textareaRef}
|
|
cols={110}
|
|
rows={20}
|
|
value={output.join("\n")}
|
|
readOnly
|
|
/>
|
|
</div>
|
|
<div>
|
|
<input
|
|
className="input input-bordered w-full text-yellow-200"
|
|
type="text"
|
|
value={input}
|
|
onChange={(e) => setInput(e.target.value)}
|
|
onKeyPress={handleKeyPress}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="w-1/5">
|
|
<Stats
|
|
cpu={cpuStat}
|
|
ramUsage={ramStat}
|
|
ramTotal={ramTotal}
|
|
diskUsage={diskUsage}
|
|
diskTotal={diskTotal}
|
|
network={network}
|
|
uptime={uptime}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default Console;
|