<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://kit.fontawesome.com/64d58efce2.js" crossorigin="anonymous"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
<link rel="stylesheet" href="https://guardianofc.github.io/css/bootstrap.min.css">
<script type="text/javascript"
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe"
crossorigin="anonymous"></script>
<title>Guardian</title>
<style>
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700;800&display=swap");
:root {
/*Editar background*/
--bg: #fff;
--bg-img: url(https://i.ibb.co/2qnXWZs/20230728-173338.png);
/*Editar o modal*/
--btn-modal: #0000003f;
--btn-modal-border: 50px;
--modal-shadow: #ffffff;
--modal-bg: #431F65;
--config-color: #0000003f;
--category-color: #0000003f;
--text-color: #ffffff;
/*Editar os t铆tulos e container*/
--title: #fff;
--title-2: #fff;
--container-linear: linear-gradient(-45deg, #4481eb 0%, #04befe 100%);
/*Editar a box (user/password)*/
--box-color: #fff;
--box-text: #fff;
--box-border: 55px;
--box-icon: #fff;
--box-typing: #fff;
/*Editar os 铆cones*/
--icon: #fff;
--icon-border: 50px;
--icon-border-color: 1px solid #fff;
--icon-pressed: #aaa;
/*Editar os bot茫o start*/
--btn-color: #5995fd;
--btn-border: 50px;
--btn-text: #fff;
--btn-pressed: #4d84e2;
--btn-transparent: 2px solid #fff;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
body,
input {
font-family: "Poppins", sans-serif;
}
.container {
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100vw;
position: relative;
/*background: var(--bg-img) center center / cover rgb(32, 32, 32);*/
background: var(--bg-img) center center / cover rgb(32, 32, 32);
overflow: hidden;
}
.forms-container {
position: absolute;
width: 100%;
height: 100vh;
top: -3%;
left: 0;
}
.signin-signup {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
left: 75%;
width: 50%;
transition: 1s 0.7s ease-in-out;
display: grid;
grid-template-columns: 1fr;
z-index: 5;
}
form {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0rem 5rem;
transition: all 0.2s 0.7s;
overflow: hidden;
grid-column: 1 / 2;
grid-row: 1 / 2;
}
form.sign-up-form {
opacity: 0;
z-index: 1;
}
form.sign-in-form {
z-index: 2;
}
.title {
font-size: 1.5rem;
color: var(--title);
margin-bottom: 10px;
}
.bg-input {
width: 100%;
background-color: transparent;
margin: 10px 0;
height: 55px;
border-radius: var(--box-border);
border: 3px solid #fff;
grid-template-columns: 15% 85%;
padding: 0 0.4rem;
}
input {
width: 100%;
background: transparent;
border: none;
outline: none;
color: var(--box-typing);
line-height: 1;
font-weight: 600;
font-size: 1.1rem;
}
.bg-input i.icon {
color: var(--box-icon);
}
.bg-input input::placeholder {
color: #fff;
font-weight: 500;
}
.social-text {
color: #fff;
padding: 0.7rem 0;
font-size: 1rem;
}
.social-media {
display: flex;
justify-content: center;
}
.social-icon {
height: 46px;
width: 46px;
display: flex;
justify-content: center;
align-items: center;
margin: 0 0.45rem;
color: var(--icon);
border-radius: var(--icon-border);
border: var(--icon-border-color);
text-decoration: none;
font-size: 1.1rem;
transition: 0.3s;
}
.social-icon:hover {
color: var(--icon-pressed);
border-color: var(--icon-pressed);
}
.btn {
width: 150px;
border: none;
outline: none;
height: 49px;
border-radius: var(--btn-border);
color: var(--btn-text);
text-transform: uppercase;
font-weight: 600;
margin: 20px 0;
cursor: pointer;
transition: 0.5s;
}
.btn:hover {
background-color: var(--btn-pressed);
}
.panels-container {
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.container:before {
content: "";
position: absolute;
height: 2000px;
width: 2000px;
top: -10%;
right: 48%;
transform: translateY(-50%);
background-image: var(--container-linear);
/*background-color: var(container-color)*/
transition: 1.8s ease-in-out;
border-radius: 50%;
z-index: 6;
}
.image {
width: 100%;
transition: transform 1.1s ease-in-out;
transition-delay: 0.4s;
}
.panel {
display: flex;
flex-direction: column;
align-items: flex-end;
justify-content: space-around;
text-align: center;
z-index: 6;
}
.left-panel {
pointer-events: all;
padding: 3rem 17% 2rem 12%;
}
.right-panel {
pointer-events: none;
padding: 3rem 12% 2rem 17%;
}
.panel .content {
color: var(--title-2);
transition: transform 0.9s ease-in-out;
transition-delay: 0.6s;
}
.panel h3 {
font-weight: 600;
line-height: 1;
font-size: 1.5rem;
}
.panel p {
font-size: 0.95rem;
padding: 0.7rem 0;
}
.btn.transparent {
margin: 0;
background: none;
border: var(--btn-transparent);
width: 130px;
height: 41px;
font-weight: 600;
font-size: 0.8rem;
}
.right-panel .image,
.right-panel .content {
transform: translateX(800px);
}
.container.sign-up-mode:before {
transform: translate(100%, -50%);
right: 52%;
}
.container.sign-up-mode .left-panel .image,
.container.sign-up-mode .left-panel .content {
transform: translateX(-800px);
}
.container.sign-up-mode .signin-signup {
left: 25%;
}
.container.sign-up-mode form.sign-up-form {
opacity: 1;
z-index: 2;
}
.container.sign-up-mode form.sign-in-form {
opacity: 0;
z-index: 1;
}
.container.sign-up-mode .right-panel .image,
.container.sign-up-mode .right-panel .content {
transform: translateX(0%);
}
.container.sign-up-mode .left-panel {
pointer-events: none;
}
.container.sign-up-mode .right-panel {
pointer-events: all;
}
@media (max-width: 870px) {
.container {
min-height: 800px;
height: 100vh;
}
.signin-signup {
width: 100%;
top: 95%;
transform: translate(-50%, -100%);
transition: 1s 0.8s ease-in-out;
}
.signin-signup,
.container.sign-up-mode .signin-signup {
left: 50%;
}
.panels-container {
grid-template-columns: 1fr;
grid-template-rows: 1fr 2fr 1fr;
}
.panel {
flex-direction: row;
justify-content: space-around;
align-items: center;
padding: 2.5rem 8%;
grid-column: 1 / 2;
}
.right-panel {
grid-row: 3 / 4;
}
.left-panel {
grid-row: 1 / 2;
}
.image {
width: 200px;
transition: transform 0.9s ease-in-out;
transition-delay: 0.6s;
}
.panel .content {
padding-right: 15%;
transition: transform 0.9s ease-in-out;
transition-delay: 0.8s;
}
.panel h3 {
font-size: 1.2rem;
}
.panel p {
font-size: 0.7rem;
padding: 0.5rem 0;
}
.btn.transparent {
width: 110px;
height: 35px;
margin-top: 5px;
margin-bottom: 15px;
font-size: 0.7rem;
}
.container:before {
width: 1500px;
height: 1500px;
transform: translateX(-50%);
left: 30%;
bottom: 68%;
right: initial;
top: initial;
transition: 2s ease-in-out;
}
.container.sign-up-mode:before {
transform: translate(-50%, 100%);
bottom: 32%;
right: initial;
}
.container.sign-up-mode .left-panel .image,
.container.sign-up-mode .left-panel .content {
transform: translateY(-300px);
}
.container.sign-up-mode .right-panel .image,
.container.sign-up-mode .right-panel .content {
transform: translateY(0px);
}
.right-panel .image,
.right-panel .content {
transform: translateY(300px);
}
.container.sign-up-mode .signin-signup {
top: 5%;
transform: translate(-50%, 0);
}
}
@media (max-width: 570px) {
form {
padding: 0 1.5rem;
}
.image {
display: none;
}
.panel .content {
padding: 0.5rem 1rem;
}
.container {
padding: 1.5rem;
}
.container:before {
bottom: 72%;
left: 50%;
}
.container.sign-up-mode:before {
bottom: 28%;
left: 50%;
}
}
.modal {
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
}
.modal-content {
border: none;
background: var(--modal-bg);
box-shadow: 0 5px 10px var(--modal-shadow);
color: var(--text-color);
}
.modal-dialog {
padding: 0 0.5rem;
}
.bg-category {
background: var(--category-color);
}
.bg-config {
background: var(--config-color);
}
.bt {
width: 150px;
background-color: var(--btn-modal);
border: none;
outline: none;
height: 49px;
border-radius: var(--btn-modal-border);
text-transform: uppercase;
font-weight: 600;
margin: 10px 0;
cursor: pointer;
transition: 0.5s;
}
.d-flex {
margin: 10px 15px;
justify-content: center;
align-items: center;
}
.ms-2 {
margin-left: 0.5rem;
}
.btn {
background: linear-gradient(-45deg, #8D4ED1, #431F65);
background-size: 400% 400%;
animation: gradient 10s ease infinite;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.container:before {
background: linear-gradient(70deg, #8D4ED1, #431F65);
background-size: 100% 100%;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.titulo {
margin-top: 10px;
}
h4 {
font-size: 1rem;
}
.img {
margin: -90px;
}
</style>
</head>
<body>
<div class="container">
<div class="forms-container">
<div class="signin-signup">
<form class="sign-in-form">
<div class="img">
<img src="https://i.ibb.co/MM1Pw2B/20230724-165647.png" alt=""
style="width: 260px; height: 260px;">
</div>
<div class="d-flex gap-2 justify-content-center align-items-center bg-input" id="config-area">
<i class="icon fa fa-cogs"></i>
<input type="text" placeholder="CONFIG." disabled id="config">
<i class="icon fa fa-angle-double-down"></i>
</div>
<div class="d-flex gap-2 justify-content-center align-items-center bg-input">
<i class="icon fa fa-user"></i>
<input type="text" placeholder="Nome de usuario" id="username">
</div>
<div class="d-flex gap-2 justify-content-center align-items-center bg-input">
<i class="icon fa fa-lock"></i>
<input type="text" placeholder="Senha" id="password">
<i class="icon fa fa-eye"
onclick="password.type==`text`?password.type = `password`:password.type = `text`"></i>
</div>
<div class="d-flex gap-2 justify-content-center align-items-center bg-input">
<i class="icon fa fa-lock"></i>
<input type="text" placeholder="V2ray UUID" id="uuid">
<i class="icon fa fa-eye"
onclick="uuid.type==`text`?uuid.type = `password`:uuid.type = `text`"></i>
</div>
<button type="button" class="btn solid" id="start-stop">INICIAR</button>
<p class="social-text" id="state" style="color: #fff;"></p>
<div class="social-media">
<a class="social-icon" id="sync" onclick="DtStartAppUpdate.execute()">
<i class="bi bi-arrow-repeat"></i>
</a>
<a class="social-icon" id="logger">
<i class="bi bi-file-earmark-text"></i>
</a>
<a class="social-icon" id="checkUser" onclick="DtStartCheckUser.execute()">
<i class="bi bi-calendar2-day"></i>
</a>
</div>
</form>
<form class="sign-up-form">
<h2 class="title">DESFRUTE</h2>
<p class="social-text">Aqui est茫o algumas ferramentas 煤teis</p>
<div class="social-media">
<a class="social-icon" data-bs-target="#speedTestModal" data-bs-toggle="modal">
<i class="bi bi-speedometer"></i>
</a>
<a class="social-icon" onclick="DtIgnoreBatteryOptimizations.execute()">
<i class="bi bi-battery-full"></i>
</a>
<a class="social-icon" onclick="toggleHotSpot()">
<i id="hotspotIcon" class="bi bi-wifi"></i>
</a>
<a class="social-icon" onclick="DtStartWebViewActivity.execute('https://pshnet.online')">
<i class="bi bi-globe"></i>
</a>
<a class="social-icon" onclick="DtCleanApp.execute()">
<i class="bi bi-trash3"></i>
</a>
</div>
</form>
</div>
</div>
<div class="panels-container">
<div class="panel left-panel">
<div class="content">
<span class="bi bi-wifi" id="name"> TIM:</span>
<span id="ip">127.0.0.1</span>
<h3 class="titulo">Mais Ferramentas</h3>
<button class="btn transparent" id="sign-up-btn">
<i class="bi bi-gear"></i>
</button>
<div class="d-flex">
<h4 class="bi bi-person ms-2" id="total">00</h4>
</div>
</div>
<img src="https://i.imgur.com/bqqPxCH.png" class="image" alt="" />
</div>
<div class="panel right-panel">
<div class="content">
<h3>VOLTE PARA HOME</h3>
<p>
<i class="bi bi-arrow-down-circle-fill"></i>
</p>
<button class="btn transparent bi bi-house" id="sign-in-btn">
</button>
</div>
<img src="https://i.imgur.com/bqqPxCH.png" class="image" alt="" />
</div>
</div>
</div>
<div class="modal fade" id="checkUserModal">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content rounded-3 shadow">
<div class="modal-header border-bottom-0 pb-0">
<h1 class="modal-title fs-5 chk-title text-light"></h1>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body text-center">
<p class="fs-5 mb-0 chk-message text-light"></p>
</div>
</div>
</div>
</div>
<div class="modal fade" id="errorModal">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content rounded-3 shadow">
<div class="modal-header border-bottom-0 pb-0">
<h1 class="modal-title fs-5 err-title text-light"></h1>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body text-center">
<p class="fs-5 mb-0 err-message text-light"></p>
</div>
</div>
</div>
</div>
<div class="modal fade" id="loggerModal">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content rounded-3 shadow">
<div class="modal-body p-1 text-center">
<ul class="list-group bg-transparent overflow-y-auto logger-content" style="max-height: 600px;">
</ul>
</div>
<div class="modal-footer flex-nowrap p-0">
<button type="button" class="bt btn-lg btn-dark text-light w-100 clear-logger">LIMPAR</button>
<button type="button" class="bt btn-lg btn-dark text-light w-100"
data-bs-dismiss="modal">FECHAR</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="configModal">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content rounded-3 shadow">
<div class="modal-header border-bottom-0 pb-0">
<h1 class="modal-title fs-5 text-white">CONFIGURA脟脮ES</h1>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body p-1 text-center">
<ul class="list-group bg-transparent overflow-y-auto config-body" style="max-height: 600px;">
<li class="list-group-item bg-transparent text-white border-0">
<p>CATEGORIA</p>
<ul class="list-group bg-transparent overflow-y-auto text-start">
<li
class="list-group-item d-flex bg-transparent text-white border-0 border-bottom rounded-0">
<img src="https://cdn-icons-png.flaticon.com/512/3686/3686811.png" width="40"
height="40">
<div class="d-flex flex-column ms-2 w-100">
<span>CONFIG 01</span>
<span>DESC 01</span>
</div>
<div class="d-flex flex-column ms-2 w-100">
<span class="text-end">CONFIG_MODE</span>
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="modal fade" id="speedTestModal">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content rounded-3 shadow">
<div class="modal-header border-bottom-0 py-3">
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body ratio rounded-bottom-3" style="height: 600px;">
<div class="spinner d-flex w-100 h-100 align-items-center justify-content-center">
<div class="spinner-border text-light p-5" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<iframe class="rounded-bottom-3" id="speedFrame"></iframe>
</div>
</div>
</div>
</div>
<script>
const sign_in_btn = document.querySelector("#sign-in-btn");
const sign_up_btn = document.querySelector("#sign-up-btn");
const container = document.querySelector(".container");
sign_up_btn.addEventListener("click", () => {
container.classList.add("sign-up-mode");
});
sign_in_btn.addEventListener("click", () => {
container.classList.remove("sign-up-mode");
});
</script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
<script>
const configArea = document.querySelector('#config-area')
const config = document.querySelector('#config')
const username = document.querySelector('#username')
const password = document.querySelector('#password')
const uuid = document.querySelector('#uuid')
const logger = document.querySelector('#logger')
const startStopVpn = document.querySelector('#start-stop')
const stateStatus = document.querySelector('#state')
const loggerModal = new bootstrap.Modal(document.querySelector('#loggerModal'))
const checkUserModal = new bootstrap.Modal(document.querySelector('#checkUserModal'))
const errorModal = new bootstrap.Modal(document.querySelector('#errorModal'))
const configModal = new bootstrap.Modal(document.querySelector('#configModal'))
const clearLogger = document.querySelector('.clear-logger')
const speedTestModal = new bootstrap.Modal(document.querySelector('#speedTestModal'))
const toggleHotSpot = () => {
const hotSpotStatus = window?.DtGetStatusHotSpotService?.execute() ?? 'STOPPED';
hotSpotStatus == 'RUNNING' ? stopHotSpot() : startHotSpot();
}
const startHotSpot = () => DtStartHotSpotService.execute();
const stopHotSpot = () => DtStopHotSpotService.execute();
configArea.addEventListener('click', e => showConfigsModal())
username.addEventListener('input', e => DtUsername.set(e.target.value))
password.addEventListener('input', e => DtPassword.set(e.target.value))
uuid.addEventListener('input', e => DtUuid.set(e.target.value))
logger.addEventListener('click', e => loggerModal.show())
startStopVpn.addEventListener('click', (e) => {
if (DtGetVpnState.execute() != 'DISCONNECTED') {
DtExecuteVpnStop.execute()
} else {
DtExecuteVpnStart.execute()
}
})
clearLogger.addEventListener('click', () => DtClearLogs.execute())
speedTestModal._element.addEventListener('shown.bs.modal', () => {
const iframe = document.querySelector('#speedFrame');
if (!iframe.src) {
iframe.src = 'https://fast.com'
iframe.addEventListener('load', () => {
mp3Modal._element.querySelector('.spinner').classList.add('d-none')
})
}
})
speedTestModal._element.addEventListener('hide.bs.modal', () => {
const iframe = document.querySelector('#speedFrame');
iframe.src = '';
})
Object.defineProperty(String.prototype, 't', {
value: function t() {
return window?.DtTranslateText?.execute('' + this) ?? '' + this
},
writable: true,
configurable: true,
})
const dtConfigClickListener = () => {
const data = JSON.parse(window?.DtGetDefaultConfig?.execute() || `{ "auth": {"username": ""} }`)
const isV2ray = data?.mode?.toLowerCase()?.startsWith('v2ray');
config.placeholder = data.name ?? 'Escolha um servidor';
username.parentElement.style.setProperty('display', !data?.auth?.username && !isV2ray ? 'flex' : 'none', 'important')
password.parentElement.style.setProperty('display', !data?.auth?.password && !isV2ray ? 'flex' : 'none', 'important')
uuid.parentElement.style.setProperty('display', !data?.auth?.v2ray_uuid && isV2ray ? 'flex' : 'none', 'important')
}
const dtVpnStateListener = state => {
const isRunning = state != 'DISCONNECTED';
stateStatus.innerHTML = ('LBL_STATE_' + state).t()
startStopVpn.innerHTML = isRunning ? 'LBL_BTN_STOP'.t() : 'LBL_BTN_START'.t()
if (isRunning) {
username.setAttribute('readonly', 'true')
password.setAttribute('readonly', 'true')
} else {
username.removeAttribute('readonly')
password.removeAttribute('readonly')
}
if (state == 'CONNECTING') dtShowSuccessToastListener('Conectado...')
}
const dtCheckUserStartedListener = () => {
const data = JSON.parse(window?.DtGetDefaultConfig?.execute() || `{}`)
const isV2ray = data?.mode?.toLowerCase()?.startsWith('v2ray');
if (isV2ray) return;
const html = `
<div class="d-flex justify-content-center">
<div class="spinner-border p-4" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
`
checkUserModal._element.querySelector('.chk-title').textContent = 'CHECK USER'
checkUserModal._element.querySelector('.chk-message').innerHTML = html;
checkUserModal.show()
}
const dtCheckUserModelListener = model => {
const data = JSON.parse(model ?? `{"username": "test"}`)
const html = `
<div class="d-flex flex-column text-white">
<span>USU脕RIO:<br><font color="#00BFFFF"><u>${data.username}</u></font></span>
<span>VALIDADE:<br><font color="#00BFFFF">${data.expiration_date}</font></span>
<span>DIAS RESTANTES:<br><font color="#00BFFFF">${data.expiration_days}</font></span>
<span>CONEX脮ES:<br><font color="#00BFFFF"> ${data.count_connections}</font></span><br>
</div>
`
checkUserModal._element.querySelector('.chk-title').textContent = ''
checkUserModal._element.querySelector('.chk-message').innerHTML = html;
checkUserModal.show()
}
const dtMessageErrorListener = message => {
const data = JSON.parse(message)
errorModal._element.querySelector('.err-title').textContent = data.title;
errorModal._element.querySelector('.err-message').innerHTML = data.content;
errorModal.show()
}
const dtOnNewLogListener = () => {
const mock = [];
for (let i = 0; i < 30; i++) {
mock.push({ 'TIME': 'MESSAGE ' + i })
}
const log = window?.DtGetLogs?.execute() || JSON.stringify(mock)
const data = JSON.parse(log)
let content = '';
data.forEach(item => {
content += '<li class="list-group-item bg-transparent p-0 border-0 text-start ms-2 text-wrap" style="font-size: 12px; color: var(--text-color);">';
content += Object.keys(item)[0] + " " + item[Object.keys(item)]
content += '</li>';
})
loggerModal._element.querySelector('.logger-content').innerHTML = content;
const listGroup = loggerModal._element.querySelector('.list-group')
listGroup.scrollTo(0, listGroup.scrollHeight)
}
const dtVpnStartedSuccessListener = () => dtShowSuccessToastListener('Conectado com sucesso')
const dtVpnStoppedSuccessListener = () => dtShowSuccessToastListener('Desconectado com sucesso')
const dtShowSuccessToastListener = text => {
Toastify({
text: text,
close: true,
style: {
background: 'linear-gradient(to right, #00b09b, #96c93d)',
marginTop: '35px',
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center',
}
}).showToast()
}
const dtShowErrorToastListener = text => {
Toastify({
text: text,
close: true,
style: {
background: 'linear-gradient(to right, #ff5c33, #e69900)',
marginTop: '35px',
}
}).showToast()
}
const showConfigsModal = () => {
const mock = '[{"sorter":6,"color":"#6D08041C","name":"CONFIG","id":1393,"items":[{"mode":"V2RAY - VLESS","sorter":4,"tlsVersion":"TLSv1.2","name":"CONFIG 01","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":11803,"status":"ACTIVE"},{"mode":"SSH_DIRECT","sorter":2,"tlsVersion":"TLSv1.2","name":"CONFIG 02","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":28627,"status":"ACTIVE"},{"mode":"OVPN_PROXY","sorter":23,"tlsVersion":"TLSv1.2","name":"CONFIG 03","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":30001,"status":"ACTIVE"}]},{"sorter":2,"color":"#6D08041C","name":"CONFIG 2","id":1846,"items":[{"mode":"SSH_PROXY","sorter":1,"tlsVersion":"TLSv1.2","name":"CONFIG 01","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":26295,"status":"ACTIVE"}]},{"sorter":4,"color":"#80000000","name":"CONFIG 3","id":3310,"items":[{"mode":"SSH_PROXY","sorter":1,"tlsVersion":"TLSv1.2","name":"CONFIG. TEST","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":29997,"status":"ACTIVE"},{"mode":"OVPN_PROXY","sorter":1,"tlsVersion":"TLSv1.2","name":"CONFIG. TEST 2","icon":"https://cdn-icons-png.flaticon.com/512/8187/8187143.png","id":29998,"status":"ACTIVE"}]}]'
const data = JSON.parse(window?.DtGetConfigs?.execute() || mock)
data.sort((a, b) => a.sorter - b.sorter)
data.forEach(item => item.items.sort((a, b) => a.sorter - b.sorter))
const body = configModal._element.querySelector('.config-body')
body.innerHTML = ''
data.forEach(category => {
const categoryElement = document.createElement('li')
categoryElement.className = 'list-group-item bg-transparent border-0 mb-1 rounded-1 px-1'
categoryElement.style.color = 'var(--text-color)'
categoryElement.innerHTML = `<span class="fw-bold w-100 d-block p-1 rounded-1 mb-1 bg-category">${category.name}</span>`
const configUlElement = document.createElement('ul')
configUlElement.className = 'list-group overflow-y-auto'
category.items.forEach(item => {
const configElement = document.createElement('li')
configElement.className = 'list-group-item d-flex border-0 bg-config rounded-2 px-1 py-2 mb-1'
configElement.style.color = 'var(--text-color)'
configElement.innerHTML = `
<img src="${item.icon}" width="40" height="40">
<div class="text-start d-flex flex-column ms-2 w-100 text-truncate">
<span class="fw-bold text-uppercase" style="font-size: 0.8rem;">${item.name}</span>
<span class="fst-italic fw-bold text-uppercase" style="font-size: 0.7rem;">${item.description || ''}</span>
</div>
<div class="d-flex flex-column ms-2">
</div>
</li>
`
configElement.addEventListener('click', e => {
window?.DtSetConfig?.execute(item.id)
configModal.hide()
})
configUlElement.appendChild(configElement)
})
categoryElement.appendChild(configUlElement)
body.appendChild(categoryElement)
})
configModal.show()
}
username.value = window?.DtUsername?.get() ?? ''
password.value = window?.DtPassword?.get() ?? ''
uuid.value = window?.DtUuid?.get() ?? ''
username.placeholder = 'LBL_USERNAME'.t()
password.placeholder = 'LBL_PASSWORD'.t()
uuid.placeholder = 'LBL_UUID'.t()
dtOnNewLogListener()
dtVpnStateListener(window?.DtGetVpnState?.execute() ?? 'DISCONNECTED')
dtConfigClickListener()
console.log('DTunnel layout ready!馃殌')
</script>
<script>
class AndroidMock {
static getLocalIP() {
return '192.168.0.1';
}
static getConfig() {
return JSON.stringify({
urlCheckUser: 'URLAQUI'
});
}
static getNetworkName() {
return 'REDE';
}
static openRadioInfo() {
console.log('openRadioInfo');
}
}
</script>
<script>
function showLocalIP(android) {
console.log(android.getNetworkName());
document.getElementById('name').innerHTML = ' ' + android.getNetworkName() + ':';
document.getElementById('ip').innerHTML = android.getLocalIP();
setInterval(() => {
document.getElementById('name').innerHTML =
' ' + android.getNetworkName() + ':';
document.getElementById('ip').innerHTML = android.getLocalIP();
}, 2000)
}
function showCheckUser(android) {
const config = JSON.parse(window?.DtGetDefaultConfig?.execute() ?? android.getConfig());
const urlCheckUser = new URL(config.urlCheckUser);
urlCheckUser.protocol = 'ws:';
const socket = new WebSocket(urlCheckUser);
socket.onopen = function (e) {
socket.send(JSON.stringify({
action: 'all',
data: {}
}));
};
socket.onmessage = function (event) {
const data = JSON.parse(event.data);
if (data.total === undefined)
return;
const total = data.total;
document.getElementById('total').innerHTML = ' ' + String(total).padStart(2, '0');
socket.close();
};
}
window.onload = function () {
const android = window.Android || AndroidMock;
showLocalIP(android);
showCheckUser(android);
}
</script>
</body>
</html>