1
0
forked from aidan/beesrv

feat: add webui, zip builder

This commit is contained in:
Aidan 2025-04-13 02:45:22 -04:00
parent 94040e020f
commit 4c71eef936
8 changed files with 813 additions and 6 deletions

97
create_zip.sh Executable file
View File

@ -0,0 +1,97 @@
version=$(grep "version=" module/module.prop | cut -d "=" -f 2)
echo "BeeSrv ZIP Builder"
echo "=================="
echo ""
# Check if zip is installed
if ! command -v zip &> /dev/null; then
echo "[!] zip is not installed"
exit 1
fi
# Check if bun is installed
if ! command -v bun &> /dev/null; then
echo "[!] bun is not installed"
exit 1
fi
# Check if filename to be created already exists
if [ -f "BeeSrv-$version.zip" ]; then
echo "[i] BeeSrv-$version.zip already exists, would you like to overwrite it? (y/n)"
read overwrite
if [ "$overwrite" != "y" ]; then
echo "[!] Aborting..."
exit 1
else
rm -rf BeeSrv-$version.zip
echo "[✔] Overwriting BeeSrv-$version.zip..."
fi
fi
# Check for leftover tmp dir
if [ -d "tmp" ]; then
echo "[i] tmp directory already exists, would you like to overwrite it? (y/n)"
read overwrite
if [ "$overwrite" != "y" ]; then
echo "[!] Aborting..."
exit 1
else
rm -rf tmp
fi
fi
# Copy module to tmp
cp -r module tmp
echo "[✔] Created working directory"
# Clean any unnecessary files
rm -rf tmp/module/webroot/dist
rm -rf tmp/module/webroot/.gitignore
rm -rf tmp/module/webroot/package-lock.json
echo "[✔] Completed cleanup"
# Build webroot
echo "[i] Building webroot..."
cd tmp/webroot
echo "[i] Installing dependencies..."
bun install
echo ""
echo "[✔] Installed dependencies"
echo ""
echo "[i] Building with parcel..."
echo ""
bunx parcel build src/index.html
echo ""
echo "[✔] Built webroot"
# Clean up for zip
rm -rf .parcel-cache
rm -rf src
rm -rf node_modules
rm bun.lock*
rm package*
rm .gitignore
echo "[✔] Completed cleanup"
# Move built files to webroot
cd ..
cp -r webroot/dist/* webroot
echo "[✔] Moved built files to webroot"
# Remove build dir
rm -rf webroot/dist
echo "[✔] Completed cleanup"
# Create zip
echo "[i] Creating zip..."
zip -r ../BeeSrv-$version.zip *
cd ..
echo "[✔] Created zip"
# Clean up
rm -rf tmp
echo "[✔] Completed cleanup"
echo ""
echo "BeeSrv-$version.zip created successfully!"

View File

@ -2,7 +2,8 @@ ui_print ""
ui_print "=== BEESRV ==="
ui_print "Version: $(grep_prop version $MODPATH/module.prop)"
ui_print "Made with ❤️ by ihatenodejs"
ui_print "================================"
ui_print "==========================="
ui_print ""
sleep 0.4
# Environment checks
@ -31,14 +32,33 @@ fi
# Create config
ui_print "[i] Creating config..."
mkdir -p /data/adb/beesrv
touch /data/adb/beesrv/config.txt
chmod 664 /data/adb/beesrv/config.txt
echo "SERVER=" >> /data/adb/beesrv/config.txt
# Check if config file exists, and check if required variables are set
config_modified=false
if [ ! -f "/data/adb/beesrv/config.txt" ]; then
echo "SERVER=" >> /data/adb/beesrv/config.txt
ui_print "[✔] Config created"
ui_print ""
else
ui_print "[i] Config file found, checking..."
ui_print "[✔] Config created"
# Check SERVER var
if ! grep -q "SERVER=" /data/adb/beesrv/config.txt; then
ui_print "[i] SERVER variable not found, adding..."
echo "SERVER=" >> /data/adb/beesrv/config.txt
config_modified=true
fi
if [ "$config_modified" = true ]; then
ui_print "[✔] Config modified successfully"
ui_print ""
else
ui_print "[✔] Config already valid, skipping update..."
ui_print ""
fi
fi
ui_print ""
ui_print "== INSTALLATION COMPLETE! =="
ui_print ""
ui_print "Join our Telegram channel: t.me/pontushub"
sleep 0.4

5
module/webroot/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.parcel-cache/
dist/
node_modules/
package-lock.json
bun.lock*

View File

@ -0,0 +1,25 @@
{
"name": "parcel-vanilla-starter",
"private": true,
"version": "0.0.0",
"source": "src/index.html",
"scripts": {
"start": "parcel",
"build": "bunx @tailwindcss/cli -i ./src/css/style-pre.css -o ./src/css/style.css && parcel build",
"build:css:watch": "bunx @tailwindcss/cli -i ./src/css/style-pre.css -o ./src/css/style.css --watch"
},
"dependencies": {
"@tailwindcss/cli": "^4.1.3",
"kernelsu": "^1.0.6",
"tailwindcss": "^4.1.3"
},
"devDependencies": {
"buffer": "^6.0.3",
"events": "^3.3.0",
"os-browserify": "^0.3.0",
"parcel": "^2.14.0",
"process": "^0.11.10",
"util": "^0.12.5",
"vm-browserify": "^1.1.2"
}
}

View File

@ -0,0 +1 @@
@import "tailwindcss";

View File

@ -0,0 +1,409 @@
/*! tailwindcss v4.1.3 | MIT License | https://tailwindcss.com */
@layer properties;
@layer theme, base, components, utilities;
@layer theme {
:root, :host {
--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
--color-red-400: oklch(70.4% 0.191 22.216);
--color-green-400: oklch(79.2% 0.209 151.711);
--color-blue-500: oklch(62.3% 0.214 259.815);
--color-slate-500: oklch(55.4% 0.046 257.417);
--color-slate-600: oklch(44.6% 0.043 257.281);
--color-slate-700: oklch(37.2% 0.044 257.287);
--color-gray-300: oklch(87.2% 0.01 258.338);
--color-gray-600: oklch(44.6% 0.03 256.802);
--color-gray-700: oklch(37.3% 0.034 259.733);
--color-gray-800: oklch(27.8% 0.033 256.848);
--color-gray-900: oklch(21% 0.034 264.665);
--color-white: #fff;
--spacing: 0.25rem;
--text-xl: 1.25rem;
--text-xl--line-height: calc(1.75 / 1.25);
--text-2xl: 1.5rem;
--text-2xl--line-height: calc(2 / 1.5);
--font-weight-semibold: 600;
--font-weight-bold: 700;
--radius-md: 0.375rem;
--animate-spin: spin 1s linear infinite;
--default-transition-duration: 150ms;
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
--default-font-family: var(--font-sans);
--default-mono-font-family: var(--font-mono);
}
}
@layer base {
*, ::after, ::before, ::backdrop, ::file-selector-button {
box-sizing: border-box;
margin: 0;
padding: 0;
border: 0 solid;
}
html, :host {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
tab-size: 4;
font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
font-feature-settings: var(--default-font-feature-settings, normal);
font-variation-settings: var(--default-font-variation-settings, normal);
-webkit-tap-highlight-color: transparent;
}
hr {
height: 0;
color: inherit;
border-top-width: 1px;
}
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
h1, h2, h3, h4, h5, h6 {
font-size: inherit;
font-weight: inherit;
}
a {
color: inherit;
-webkit-text-decoration: inherit;
text-decoration: inherit;
}
b, strong {
font-weight: bolder;
}
code, kbd, samp, pre {
font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
font-feature-settings: var(--default-mono-font-feature-settings, normal);
font-variation-settings: var(--default-mono-font-variation-settings, normal);
font-size: 1em;
}
small {
font-size: 80%;
}
sub, sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
table {
text-indent: 0;
border-color: inherit;
border-collapse: collapse;
}
:-moz-focusring {
outline: auto;
}
progress {
vertical-align: baseline;
}
summary {
display: list-item;
}
ol, ul, menu {
list-style: none;
}
img, svg, video, canvas, audio, iframe, embed, object {
display: block;
vertical-align: middle;
}
img, video {
max-width: 100%;
height: auto;
}
button, input, select, optgroup, textarea, ::file-selector-button {
font: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
letter-spacing: inherit;
color: inherit;
border-radius: 0;
background-color: transparent;
opacity: 1;
}
:where(select:is([multiple], [size])) optgroup {
font-weight: bolder;
}
:where(select:is([multiple], [size])) optgroup option {
padding-inline-start: 20px;
}
::file-selector-button {
margin-inline-end: 4px;
}
::placeholder {
opacity: 1;
}
@supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {
::placeholder {
color: currentcolor;
@supports (color: color-mix(in lab, red, red)) {
color: color-mix(in oklab, currentcolor 50%, transparent);
}
}
}
textarea {
resize: vertical;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-date-and-time-value {
min-height: 1lh;
text-align: inherit;
}
::-webkit-datetime-edit {
display: inline-flex;
}
::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}
::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
padding-block: 0;
}
:-moz-ui-invalid {
box-shadow: none;
}
button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {
appearance: button;
}
::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
height: auto;
}
[hidden]:where(:not([hidden="until-found"])) {
display: none !important;
}
}
@layer utilities {
.visible {
visibility: visible;
}
.mt-4 {
margin-top: calc(var(--spacing) * 4);
}
.mr-1 {
margin-right: calc(var(--spacing) * 1);
}
.mr-2 {
margin-right: calc(var(--spacing) * 2);
}
.mb-2 {
margin-bottom: calc(var(--spacing) * 2);
}
.mb-4 {
margin-bottom: calc(var(--spacing) * 4);
}
.ml-2 {
margin-left: calc(var(--spacing) * 2);
}
.block {
display: block;
}
.flex {
display: flex;
}
.hidden {
display: none;
}
.table {
display: table;
}
.h-4 {
height: calc(var(--spacing) * 4);
}
.h-5 {
height: calc(var(--spacing) * 5);
}
.w-4 {
width: calc(var(--spacing) * 4);
}
.w-5 {
width: calc(var(--spacing) * 5);
}
.w-full {
width: 100%;
}
.border-collapse {
border-collapse: collapse;
}
.transform {
transform: var(--tw-rotate-x) var(--tw-rotate-y) var(--tw-rotate-z) var(--tw-skew-x) var(--tw-skew-y);
}
.animate-spin {
animation: var(--animate-spin);
}
.resize {
resize: both;
}
.flex-wrap {
flex-wrap: wrap;
}
.items-center {
align-items: center;
}
.gap-2 {
gap: calc(var(--spacing) * 2);
}
.rounded-md {
border-radius: var(--radius-md);
}
.border {
border-style: var(--tw-border-style);
border-width: 1px;
}
.border-gray-600 {
border-color: var(--color-gray-600);
}
.bg-gray-700 {
background-color: var(--color-gray-700);
}
.bg-gray-800 {
background-color: var(--color-gray-800);
}
.bg-gray-900 {
background-color: var(--color-gray-900);
}
.bg-slate-500 {
background-color: var(--color-slate-500);
}
.bg-slate-600 {
background-color: var(--color-slate-600);
}
.p-2 {
padding: calc(var(--spacing) * 2);
}
.p-4 {
padding: calc(var(--spacing) * 4);
}
.px-3 {
padding-inline: calc(var(--spacing) * 3);
}
.px-4 {
padding-inline: calc(var(--spacing) * 4);
}
.py-1 {
padding-block: calc(var(--spacing) * 1);
}
.py-2 {
padding-block: calc(var(--spacing) * 2);
}
.text-center {
text-align: center;
}
.text-left {
text-align: left;
}
.text-2xl {
font-size: var(--text-2xl);
line-height: var(--tw-leading, var(--text-2xl--line-height));
}
.font-bold {
--tw-font-weight: var(--font-weight-bold);
font-weight: var(--font-weight-bold);
}
.font-semibold {
--tw-font-weight: var(--font-weight-semibold);
font-weight: var(--font-weight-semibold);
}
.text-gray-300 {
color: var(--color-gray-300);
}
.text-green-400 {
color: var(--color-green-400);
}
.text-red-400 {
color: var(--color-red-400);
}
.text-white {
color: var(--color-white);
}
.underline {
text-decoration-line: underline;
}
.outline {
outline-style: var(--tw-outline-style);
outline-width: 1px;
}
.transition-colors {
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
}
.hover\:bg-slate-600 {
&:hover {
@media (hover: hover) {
background-color: var(--color-slate-600);
}
}
}
.hover\:bg-slate-700 {
&:hover {
@media (hover: hover) {
background-color: var(--color-slate-700);
}
}
}
}
@property --tw-rotate-x {
syntax: "*";
inherits: false;
initial-value: rotateX(0);
}
@property --tw-rotate-y {
syntax: "*";
inherits: false;
initial-value: rotateY(0);
}
@property --tw-rotate-z {
syntax: "*";
inherits: false;
initial-value: rotateZ(0);
}
@property --tw-skew-x {
syntax: "*";
inherits: false;
initial-value: skewX(0);
}
@property --tw-skew-y {
syntax: "*";
inherits: false;
initial-value: skewY(0);
}
@property --tw-border-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@property --tw-font-weight {
syntax: "*";
inherits: false;
}
@property --tw-outline-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
@layer properties {
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
*, ::before, ::after, ::backdrop {
--tw-rotate-x: rotateX(0);
--tw-rotate-y: rotateY(0);
--tw-rotate-z: rotateZ(0);
--tw-skew-x: skewX(0);
--tw-skew-y: skewY(0);
--tw-border-style: solid;
--tw-font-weight: initial;
--tw-outline-style: solid;
}
}
}

View File

@ -0,0 +1,104 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BeeSrv WebUI</title>
<!-- Tailwind CSS -->
<link rel="stylesheet" href="css/style.css">
<script type="module" src="js/app.js"></script>
</head>
<body class="bg-gray-900 text-white">
<header class="bg-gray-800 p-4">
<h1 class="text-2xl font-bold">BeeSrv WebUI</h1>
</header>
<main class="p-4">
<h2 class="text-2xl font-bold mb-4">Self-Check</h2>
<table class="w-full bg-gray-700 border-collapse border border-gray-600 mb-4">
<tbody>
<tr>
<th class="border border-gray-600 p-2 text-left">Internet Connection</th>
<td class="border border-gray-600 p-2">
<button class="bg-slate-500 text-white px-3 py-1 rounded-md hover:bg-slate-600 transition-colors" id="checkConnection">
<span id="testBtn" class="flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-router-icon lucide-router w-4 h-4"><rect width="20" height="8" x="2" y="14" rx="2"/><path d="M6.01 18H6"/><path d="M10.01 18H10"/><path d="M15 10v4"/><path d="M17.84 7.17a4 4 0 0 0-5.66 0"/><path d="M20.66 4.34a8 8 0 0 0-11.31 0"/></svg>
Test
</span>
<span id="testBtnLoading" class="flex items-center gap-2 hidden">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-loader-icon lucide-loader w-4 h-4 animate-spin"><path d="M12 2v4"/><path d="m16.2 7.8 2.9-2.9"/><path d="M18 12h4"/><path d="m16.2 16.2 2.9 2.9"/><path d="M12 18v4"/><path d="m4.9 19.1 2.9-2.9"/><path d="M2 12h4"/><path d="m4.9 4.9 2.9 2.9"/></svg>
Testing...
</span>
</button>
<span id="connectionStatus" class="ml-2 text-green-400 flex items-center gap-2 hidden">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-icon lucide-check w-5 h-5"><path d="M20 6 9 17l-5-5"/></svg>
Connected
</span>
<span id="connectionError" class="ml-2 text-red-400 flex items-center gap-2 hidden">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x w-5 h-5"><path d="M18 6 6 18"/><path d="M6 6l12 12"/></svg>
Error
</span>
</td>
</tr>
</tbody>
</table>
<div id="errorBox" class="bg-gray-700 border border-gray-600 p-4 rounded-md mb-4 hidden">
<div class="flex items-center gap-2 text-red-400 mb-2">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-alert-triangle w-5 h-5"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>
<span class="font-semibold">Error</span>
</div>
<p id="errorMessage" class="text-gray-300">No error</p>
</div>
<h2 class="text-2xl font-bold mb-4">Module</h2>
<table class="w-full bg-gray-700 border-collapse border border-gray-600">
<tbody>
<tr>
<th class="border border-gray-600 p-2 text-left">Version</th>
<td class="border border-gray-600 p-2">
<span id="version" class="flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-loader-icon lucide-loader w-5 h-5 animate-spin" id="versionLoader"><path d="M12 2v4"/><path d="m16.2 7.8 2.9-2.9"/><path d="M18 12h4"/><path d="m16.2 16.2 2.9 2.9"/><path d="M12 18v4"/><path d="m4.9 19.1 2.9-2.9"/><path d="M2 12h4"/><path d="m4.9 4.9 2.9 2.9"/></svg>
<span id="versionText">Loading...</span>
</span>
</td>
</tr>
<tr>
<th class="border border-gray-600 p-2 text-left">Server</th>
<td class="border border-gray-600 p-2">
<span id="server" class="flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-loader-icon lucide-loader w-5 h-5 animate-spin" id="serverLoader"><path d="M12 2v4"/><path d="m16.2 7.8 2.9-2.9"/><path d="M18 12h4"/><path d="m16.2 16.2 2.9 2.9"/><path d="M12 18v4"/><path d="m4.9 19.1 2.9-2.9"/><path d="M2 12h4"/><path d="m4.9 4.9 2.9 2.9"/></svg>
<span id="serverText">Loading...</span>
</span>
</td>
</tr>
</tbody>
</table>
<h2 class="text-2xl font-bold mt-4">Join Us</h2>
<div class="flex flex-wrap gap-2 mt-4">
<a href="https://t.me/pontushub">
<button class="flex items-center bg-slate-600 text-white px-4 py-2 rounded-md hover:bg-slate-700 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-send-icon lucide-send mr-1 w-5 h-5"><path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"/><path d="m21.854 2.147-10.94 10.939"/></svg>
Telegram
</button>
</a>
<a href="https://t.me/pontushubchat">
<button class="flex items-center bg-slate-600 text-white px-4 py-2 rounded-md hover:bg-slate-700 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-circle-question-icon lucide-message-circle-question mr-1 w-5 h-5"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>
Support
</button>
</a>
<a href="https://donate.stripe.com/cN28yxe1wf5teC4dQS">
<button class="flex items-center bg-slate-600 text-white px-4 py-2 rounded-md hover:bg-slate-700 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hand-coins-icon lucide-hand-coins mr-1 w-5 h-5"><path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"/><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"/><path d="m2 16 6 6"/><circle cx="16" cy="9" r="2.9"/><circle cx="6" cy="5" r="3"/></svg>
Donate
</button>
</a>
</div>
<p class="mt-4 text-center">Made with ❤️ by ihatenodejs</p>
</main>
</body>
</html>

View File

@ -0,0 +1,146 @@
import { exec } from "kernelsu"
const modules_dir = "/data/adb/modules/BeeSrv"
const persist_dir = "/data/adb/beesrv"
function showError(message) {
const errorBox = document.getElementById("errorBox")
const errorMessage = document.getElementById("errorMessage")
errorMessage.textContent = message
errorBox.classList.remove("hidden")
}
function hideError() {
const errorBox = document.getElementById("errorBox")
errorBox.classList.add("hidden")
}
async function getVersion() {
try {
const { errno, stdout, stderr } = await exec(`cat ${modules_dir}/module.prop`)
if (errno !== 0) {
showError("Failed to read module version")
return "Unknown"
}
const version = stdout.split("\n").find(line => line.startsWith("version="))
if (!version) {
showError("Module version not found")
return "Unknown"
}
return version.split("=")[1]
} catch (error) {
showError("Error reading module version")
return "Unknown"
}
}
async function getServer() {
try {
const { errno, stdout, stderr } = await exec(`cat ${persist_dir}/config.txt`)
if (errno !== 0) {
showError("Failed to read server configuration")
return "Unknown"
}
const server = stdout.split("\n").find(line => line.startsWith("SERVER="))
if (!server) {
showError("Server configuration not found")
return "Unknown"
}
return server.split("=")[1]
} catch (error) {
showError("Error reading server configuration")
return "Unknown"
}
}
async function checkConnection() {
try {
const response = await fetch('https://httpbin.org/get', {
method: 'GET',
signal: AbortSignal.timeout(5000)
});
return response.ok;
} catch (error) {
if (error.name === 'AbortError') {
throw new Error('Connection check timed out. Please try again.');
} else if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {
throw new Error('Unable to reach the internet. Please check your network connection.');
} else {
throw new Error('Connection check failed. Please try again later.');
}
}
}
document.addEventListener("DOMContentLoaded", async () => {
const versionText = document.getElementById("versionText")
const serverText = document.getElementById("serverText")
const versionLoader = document.getElementById("versionLoader")
const serverLoader = document.getElementById("serverLoader")
try {
const version = await getVersion()
const server = await getServer()
versionLoader.classList.add("hidden")
serverLoader.classList.add("hidden")
versionText.textContent = version
serverText.textContent = server
} catch (error) {
versionLoader.classList.add("hidden")
serverLoader.classList.add("hidden")
versionText.textContent = "Error"
serverText.textContent = "Error"
}
const checkConnectionBtn = document.getElementById("checkConnection")
const testBtn = document.getElementById("testBtn")
const testBtnLoading = document.getElementById("testBtnLoading")
const connectionStatus = document.getElementById("connectionStatus")
const connectionError = document.getElementById("connectionError")
function resetButtonState() {
testBtnLoading.classList.add("hidden")
testBtn.classList.remove("hidden")
checkConnectionBtn.disabled = false
}
function setLoadingState() {
testBtn.classList.add("hidden")
testBtnLoading.classList.remove("hidden")
connectionStatus.classList.add("hidden")
connectionError.classList.add("hidden")
checkConnectionBtn.disabled = true
hideError()
}
function showSuccessState() {
connectionStatus.classList.remove("hidden")
connectionError.classList.add("hidden")
// Hide the button after successful test
checkConnectionBtn.classList.add("hidden")
}
function showErrorState(message) {
connectionStatus.classList.add("hidden")
connectionError.classList.remove("hidden")
showError(message)
checkConnectionBtn.classList.add("hidden")
}
checkConnectionBtn.addEventListener("click", async () => {
setLoadingState()
try {
const isConnected = await checkConnection()
resetButtonState()
if (isConnected) {
showSuccessState()
} else {
showErrorState("No internet connection detected")
}
} catch (error) {
resetButtonState()
showErrorState(error.message)
}
})
})