Skip to content

Commit

Permalink
Refactored, fixed UI.
Browse files Browse the repository at this point in the history
  • Loading branch information
bia-pain-bache committed Nov 28, 2024
1 parent 7c5d839 commit 64817c2
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 64 deletions.
4 changes: 0 additions & 4 deletions src/authentication/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,4 @@ export async function login(request, env) {
if (auth) return Response.redirect(`${origin}/panel`, 302);
if (request.method === 'POST') return await generateJWTToken(request, env);
return await renderLoginPage(request, env);
}

export function checkSecrets(env) {
if (!env.UUID || !env.TROJAN_PASS) throw new Error("Please set UUID and Trojan password first.");
}
18 changes: 11 additions & 7 deletions src/helpers/init.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import { isValidUUID } from './helpers';
import { isValidUUID } from "./helpers";

const defaultProxyIP = 'bpb.yousef.isegaro.com';
let userID, dohURL, proxyIP, trojanPassword, defaultHttpPorts, defaultHttpsPorts, panelVersion, hostName, origin, client, pathName;

function initParams(request, env) {
const proxyIPs = env.PROXYIP?.split(',').map(proxyIP => proxyIP.trim());
userID = env.UUID;
if (!isValidUUID(userID)) throw new Error(`Invalid UUID: ${userID}`);
trojanPassword = env.TROJAN_PASS;
const url = new URL(request.url);
pathName = url.pathname;
if (pathName !== '/secrets') {
if (!userID || !trojanPassword) throw new Error("Please set UUID and Trojan password first.");
if (userID && !isValidUUID(userID)) throw new Error(`Invalid UUID: ${userID}`);
}
dohURL = env.DOH_URL || 'https://cloudflare-dns.com/dns-query';
proxyIP = proxyIPs ? proxyIPs[Math.floor(Math.random() * proxyIPs.length)] : defaultProxyIP;
trojanPassword = env.TROJAN_PASS;
defaultHttpPorts = ['80', '8080', '2052', '2082', '2086', '2095', '8880'];
defaultHttpsPorts = ['443', '8443', '2053', '2083', '2087', '2096'];
panelVersion = '2.7.6';
panelVersion = '2.7.7';
hostName = request.headers.get('Host');
const url = new URL(request.url);
const searchParams = new URLSearchParams(url.search);
client = searchParams.get('app');
origin = url.origin;
pathName = url.pathname;
}

export function initializeParams(request, env) {
export async function initializeParams(request, env) {
initParams(request, env);
return Promise.resolve();
}
Expand Down
123 changes: 82 additions & 41 deletions src/pages/secrets.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,66 @@ import { panelVersion, initializeParams } from "../helpers/init";

export async function renderSecretsPage (request, env) {
await initializeParams(request, env);
return `
const secretsPage = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>UUID and Password Generator</title>
<title>User Login</title>
<style>
:root {
--color: black;
--primary-color: #09639f;
--header-color: #09639f;
--background-color: #fff;
--container-background-color: #f9f9f9;
--text-color: #333;
--form-background-color: #f9f9f9;
--lable-text-color: #333;
--h2-color: #3b3b3b;
--border-color: #ddd;
--input-background-color: white;
--header-shadow: 2px 2px 4px rgba(0, 0, 0, 0.25);
}
html, body { height: 100%; margin: 0; }
body {
font-family: system-ui;
background-color: var(--background-color);
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
position: relative;
overflow: hidden;
text-align: center;
}
body.dark-mode {
--color: white;
--primary-color: #09639F;
--header-color: #3498DB;
--background-color: #121212;
--form-background-color: #121212;
--lable-text-color: #DFDFDF;
--h2-color: #D5D5D5;
--border-color: #353535;
--input-background-color: #252525;
--header-shadow: 2px 2px 4px rgba(255, 255, 255, 0.25);
}
html, body { height: 100%; margin: 0; }
.container {
background: var(--container-background-color);
padding: 20px;
border: 1px solid var(--border-color);
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
text-align: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90%;
max-width: 400px;
}
h1 { color: var(--primary-color); margin-bottom: 20px; }
h1 { font-size: 2.5rem; text-align: center; color: var(--header-color); margin: 0 auto 30px; text-shadow: var(--header-shadow); }
h2 { text-align: center; color: var(--h2-color) }
strong { color: var(--lable-text-color); }
.output-container {
display: flex;
align-items: center;
justify-content: space-between;
margin: 15px 0;
padding: 10px;
background-color: #e9e9e9;
background-color: var(--input-background-color);
color: var(--lable-text-color);
border: 1px solid var(--border-color);
border-radius: 5px;
font-family: monospace;
font-size: 1rem;
Expand All @@ -58,8 +75,17 @@ export async function renderSecretsPage (request, env) {
transition: color 0.2s;
}
.copy-icon:hover { color: #2980b9; }
.form-container {
background: var(--form-background-color);
border: 1px solid var(--border-color);
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
padding: 20px;
}
.form-control { margin-bottom: 15px; display: flex; align-items: center; }
button {
margin-top: 15px;
display: block;
width: 100%;
padding: 10px;
font-size: 16px;
font-weight: 600;
Expand All @@ -70,64 +96,79 @@ export async function renderSecretsPage (request, env) {
cursor: pointer;
transition: background-color 0.3s ease;
}
button:hover { background-color: #2980b9; }
.button:hover,
button:focus {
background-color: #2980b9;
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.3);
transform: translateY(-2px);
}
button.button:hover { color: white; }
.button:active { transform: translateY(1px); box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); }
@media only screen and (min-width: 768px) {
.container { width: 40%; }
}
</style>
</head>
<body>
<div class="container">
<h1>BPB Panel <span style="font-size: smaller;">${panelVersion}</span> 💦</h1>
<div>
<strong>Random UUID:</strong>
<div class="output-container">
<span id="uuid" class="output"></span>
<span class="copy-icon" onclick="copyToClipboard('uuid')">📋</span>
<div class="form-container">
<h2>Secrets generator</h2>
<div>
<strong>Random UUID</strong>
<div class="output-container">
<span id="uuid" class="output"></span>
<span class="copy-icon" onclick="copyToClipboard('uuid')">📋</span>
</div>
</div>
</div>
<div>
<strong>Random Trojan Password:</strong>
<div class="output-container">
<span id="trojan-password" class="output"></span>
<span class="copy-icon" onclick="copyToClipboard('trojan-password')">📋</span>
<div>
<strong>Random Trojan Password</strong>
<div class="output-container">
<span id="trojan-password" class="output"></span>
<span class="copy-icon" onclick="copyToClipboard('trojan-password')">📋</span>
</div>
</div>
<button class="button" onclick="generateCredentials()">Generate Again ♻️</button>
</div>
<button onclick="generateCredentials()">Generate Again</button>
</div>
<script>
localStorage.getItem('darkMode') === 'enabled' && document.body.classList.add('dark-mode');
function generateUUID() {
return crypto.randomUUID();
}
function generateStrongPassword(length = 16) {
function generateStrongPassword() {
const charset =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+[]{}|;:',.<>?";
let password = '';
const randomValues = new Uint8Array(length);
const randomValues = new Uint8Array(16);
crypto.getRandomValues(randomValues);
for (let i = 0; i < length; i++) {
for (let i = 0; i < 16; i++) {
password += charset[randomValues[i] % charset.length];
}
return password;
}
function generateCredentials() {
const uuid = generateUUID();
const password = generateStrongPassword();
document.getElementById('uuid').textContent = uuid;
document.getElementById('trojan-password').textContent = password;
}
function copyToClipboard(elementId) {
const textToCopy = document.getElementById(elementId).textContent;
navigator.clipboard.writeText(textToCopy)
.then(() => alert('✅ Copied to clipboard!'))
.catch(err => console.error('Failed to copy text:', err));
}
generateCredentials();
</script>
</body>
</html>`;

return new Response(secretsPage, { status: 200, headers: {'Content-Type': 'text/html'}});
}
14 changes: 2 additions & 12 deletions src/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { vlessOverWSHandler } from './protocols/vless';
import { trojanOverWSHandler } from './protocols/trojan';
import { updateWarpConfigs } from './kv/handlers';
import { logout, resetPassword, login, checkSecrets } from './authentication/auth';
import { logout, resetPassword, login } from './authentication/auth';
import { renderErrorPage } from './pages/error';
import { getXrayCustomConfigs, getXrayWarpConfigs } from './cores-configs/xray';
import { getSingBoxCustomConfig, getSingBoxWarpConfig } from './cores-configs/sing-box';
Expand All @@ -20,46 +20,37 @@ export default {
if (!upgradeHeader || upgradeHeader !== 'websocket') {
switch (pathName) {
case '/update-warp':
checkSecrets(env);
return await updateWarpConfigs(request, env);

case `/sub/${userID}`:
checkSecrets(env);
if (client === 'sfa') return await getSingBoxCustomConfig(request, env, false);
if (client === 'clash') return await getClashNormalConfig(request, env);
if (client === 'xray') return await getXrayCustomConfigs(request, env, false);
return await getNormalConfigs(request, env);

case `/fragsub/${userID}`:
checkSecrets(env);
return client === 'hiddify'
? await getSingBoxCustomConfig(request, env, true)
: await getXrayCustomConfigs(request, env, true);

case `/warpsub/${userID}`:
checkSecrets(env);
if (client === 'clash') return await getClashWarpConfig(request, env);
if (client === 'singbox' || client === 'hiddify') return await getSingBoxWarpConfig(request, env, client);
return await getXrayWarpConfigs(request, env, client);

case '/panel':
checkSecrets(env);
return await handlePanel(request, env);

case '/login':
checkSecrets(env);
return await login(request, env);

case '/logout':
checkSecrets(env);
case '/logout':
return logout();

case '/panel/password':
checkSecrets(env);
return await resetPassword(request, env);

case '/my-ip':
checkSecrets(env);
return await getMyIP(request);

case '/secrets':
Expand All @@ -69,7 +60,6 @@ export default {
return await fallback(request);
}
} else {
checkSecrets(env);
return pathName.startsWith('/tr')
? await trojanOverWSHandler(request, env)
: await vlessOverWSHandler(request, env);
Expand Down

0 comments on commit 64817c2

Please sign in to comment.