Update 1140
This commit is contained in:
317
readme.md
317
readme.md
@@ -212,6 +212,19 @@ DtUuid.get();
|
|||||||
DtUuid.set(value);
|
DtUuid.set(value);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `CakeApp.errors`
|
||||||
|
|
||||||
|
```js
|
||||||
|
CakeApp.errors.getLast(); // retorna string JSON com o último erro de conexão
|
||||||
|
```
|
||||||
|
|
||||||
|
Aliases equivalentes:
|
||||||
|
|
||||||
|
```js
|
||||||
|
DtGetLastConnectionError.execute();
|
||||||
|
DtGetConnectionError.execute();
|
||||||
|
```
|
||||||
|
|
||||||
### `CakeApp.system`
|
### `CakeApp.system`
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -271,7 +284,9 @@ function cleanBridgeValue(value) {
|
|||||||
| `DtExecuteVpnStart.execute()` | sem argumentos | void | Inicia/dispara o comando nativo da VPN. |
|
| `DtExecuteVpnStart.execute()` | sem argumentos | void | Inicia/dispara o comando nativo da VPN. |
|
||||||
| `DtExecuteVpnStop.execute()` | sem argumentos | void | Para a VPN. |
|
| `DtExecuteVpnStop.execute()` | sem argumentos | void | Para a VPN. |
|
||||||
| `DtGetNetworkDownloadBytes.execute()` | sem argumentos | string numérica | Retorna bytes baixados atuais da rede/app para verificação de tráfego. |
|
| `DtGetNetworkDownloadBytes.execute()` | sem argumentos | string numérica | Retorna bytes baixados atuais da rede/app para verificação de tráfego. |
|
||||||
| `DtGetLogs.execute()` | sem argumentos | string JSON | Retorna logs recentes de status/banner como array de objetos com timestamp. |
|
| `DtGetLogs.execute()` | sem argumentos | string JSON | Retorna logs recentes de status/banner/proxy como array de objetos com timestamp. |
|
||||||
|
| `DtGetLastConnectionError.execute()` | sem argumentos | string JSON | Retorna o último erro classificado de conexão, autenticação ou proxy. Retorna `{}` se não houver erro. |
|
||||||
|
| `DtGetConnectionError.execute()` | sem argumentos | string JSON | Alias de compatibilidade de `DtGetLastConnectionError.execute()`. |
|
||||||
| `DtShowLoggerDialog.execute()` | sem argumentos | void | Abre o diálogo nativo de logs. |
|
| `DtShowLoggerDialog.execute()` | sem argumentos | void | Abre o diálogo nativo de logs. |
|
||||||
|
|
||||||
Possíveis estados de `DtGetVpnState` / `DtVpnStateListener`:
|
Possíveis estados de `DtGetVpnState` / `DtVpnStateListener`:
|
||||||
@@ -286,6 +301,75 @@ Possíveis estados de `DtGetVpnState` / `DtVpnStateListener`:
|
|||||||
| `NO_NETWORK` | Aguardando rede. |
|
| `NO_NETWORK` | Aguardando rede. |
|
||||||
| `AUTH_FAILED` | Falha de autenticação. |
|
| `AUTH_FAILED` | Falha de autenticação. |
|
||||||
|
|
||||||
|
#### 5.3.1 Erros de conexão/autenticação/proxy
|
||||||
|
|
||||||
|
O patch expõe um bridge específico para o tema entender por que a conexão falhou, sem precisar depender apenas de texto solto no botão ou no status.
|
||||||
|
|
||||||
|
```js
|
||||||
|
function getLastConnectionError() {
|
||||||
|
try {
|
||||||
|
return JSON.parse(DtGetLastConnectionError.execute() || '{}');
|
||||||
|
} catch (e) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Formato retornado:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"state": "AUTH_FAILED",
|
||||||
|
"code": "LOGIN_INVALID",
|
||||||
|
"message": "Authentication failed",
|
||||||
|
"time": 1777290000000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Campos:
|
||||||
|
|
||||||
|
| Campo | Tipo | Significado |
|
||||||
|
|---|---|---|
|
||||||
|
| `state` | string | Estado nativo/mapeado no momento do erro. |
|
||||||
|
| `code` | string | Código normalizado para o tema tratar com UI própria. |
|
||||||
|
| `message` | string | Mensagem original limpa vinda do status/log/banner/proxy. |
|
||||||
|
| `time` | number | Timestamp em milissegundos. |
|
||||||
|
|
||||||
|
Códigos conhecidos nesta versão:
|
||||||
|
|
||||||
|
| Código | Quando aparece | Uso recomendado no tema |
|
||||||
|
|---|---|---|
|
||||||
|
| `LOGIN_EXPIRED` | Mensagens contendo acesso expirado/vencido. | Mostrar aviso de renovação. |
|
||||||
|
| `LOGIN_INVALID` | Falha de usuário/senha, HTTP 401 ou texto de login inválido. | Mostrar usuário/senha inválidos. |
|
||||||
|
| `LOGIN_LIMIT` | Mensagens de limite/conexões excedidas. | Mostrar limite de conexões atingido. |
|
||||||
|
| `PROXY_FORBIDDEN` | HTTP 403 ou `Forbidden`. | Mostrar proxy/bughost bloqueado. |
|
||||||
|
| `PROXY_BAD_REQUEST` | HTTP 400 ou `Bad Request`. | Mostrar payload/proxy inválido. |
|
||||||
|
| `PROXY_RATE_LIMITED` | HTTP 429 ou `Too Many Requests`. | Mostrar muitas tentativas/limite temporário. |
|
||||||
|
| `PROXY_SERVER_ERROR` | HTTP 500/502, `Bad Gateway` ou erro interno. | Mostrar falha no proxy/servidor remoto. |
|
||||||
|
| `AUTH_FAILED` | Falha de autenticação sem classificação mais específica. | Mostrar falha genérica de autenticação. |
|
||||||
|
|
||||||
|
Exemplo de uso direto:
|
||||||
|
|
||||||
|
```js
|
||||||
|
function renderLastError() {
|
||||||
|
const error = getLastConnectionError();
|
||||||
|
if (!error.code) return;
|
||||||
|
|
||||||
|
const messages = {
|
||||||
|
LOGIN_EXPIRED: 'Seu login expirou. Renove seu acesso.',
|
||||||
|
LOGIN_INVALID: 'Usuário ou senha inválidos.',
|
||||||
|
LOGIN_LIMIT: 'Limite de conexões atingido.',
|
||||||
|
PROXY_FORBIDDEN: 'Proxy/bughost bloqueou a conexão.',
|
||||||
|
PROXY_BAD_REQUEST: 'Payload ou proxy retornou Bad Request.',
|
||||||
|
PROXY_RATE_LIMITED: 'Muitas tentativas. Tente novamente mais tarde.',
|
||||||
|
PROXY_SERVER_ERROR: 'Proxy/servidor remoto retornou erro.',
|
||||||
|
AUTH_FAILED: 'Falha na autenticação.'
|
||||||
|
};
|
||||||
|
|
||||||
|
showError(messages[error.code] || error.message || 'Falha na conexão.');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 5.4 APIs de consulta de usuário/conta
|
### 5.4 APIs de consulta de usuário/conta
|
||||||
|
|
||||||
| API | Assinatura | Retorno | Finalidade |
|
| API | Assinatura | Retorno | Finalidade |
|
||||||
@@ -356,6 +440,27 @@ A porta padrão de proxy usada pelo tema existente é `6821`, mas o bridge em si
|
|||||||
const proxyAddress = `${DtGetLocalIP.execute()}:6821`;
|
const proxyAddress = `${DtGetLocalIP.execute()}:6821`;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Nesta versão do patch, `DtStartHotSpotService.execute()` não inicia mais o socket diretamente pelo `ProxyServer`. Ele dispara o `ProxyService` com `ACTION_START`, para que o Android mostre uma notificação foreground persistente do proxy, por exemplo:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Proxy ONLINE - 192.168.x.x:6821
|
||||||
|
```
|
||||||
|
|
||||||
|
Ao chamar `DtStopHotSpotService.execute()`, o app envia `ACTION_STOP` para o mesmo serviço e remove a notificação.
|
||||||
|
|
||||||
|
Em Android 13+ o app precisa da permissão `POST_NOTIFICATIONS`. O `OnlineConfigWebActivity` tenta pedir essa permissão ao abrir e também antes de iniciar o proxy. Se o usuário negar, o proxy não deve ser considerado iniciado pelo tema. Sempre confirme o status depois do comando:
|
||||||
|
|
||||||
|
```js
|
||||||
|
async function startLocalProxyAndRefresh() {
|
||||||
|
DtStartHotSpotService.execute();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const status = DtGetStatusHotSpotService.execute();
|
||||||
|
renderProxyStatus(status);
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 5.7 APIs de config visual/app
|
### 5.7 APIs de config visual/app
|
||||||
|
|
||||||
| API | Assinatura | Retorno | Finalidade |
|
| API | Assinatura | Retorno | Finalidade |
|
||||||
@@ -454,6 +559,50 @@ window.dtCheckUserModelListener = function(modelJson) {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `window.dtLogsUpdatedListener = function(logsJson) {}`
|
||||||
|
|
||||||
|
Chamado quando o app adiciona um log visível para o tema. Também existe o alias com inicial maiúscula `window.DtLogsUpdatedListener`.
|
||||||
|
|
||||||
|
```js
|
||||||
|
window.dtLogsUpdatedListener = function(logsJson) {
|
||||||
|
let rows = [];
|
||||||
|
try { rows = JSON.parse(logsJson || '[]'); } catch (e) {}
|
||||||
|
|
||||||
|
const text = rows.map(row => {
|
||||||
|
const time = Object.keys(row)[0] || '';
|
||||||
|
return `${time} ${row[time] || ''}`;
|
||||||
|
}).join('\n');
|
||||||
|
|
||||||
|
renderLogs(text);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### `window.dtConnectionErrorListener = function(error) {}`
|
||||||
|
|
||||||
|
Chamado quando o app classifica um erro de conexão/autenticação/proxy. Também existem estes aliases:
|
||||||
|
|
||||||
|
```js
|
||||||
|
window.DtConnectionErrorListener = function(error) {};
|
||||||
|
window.dtAuthErrorListener = function(error) {};
|
||||||
|
window.DtAuthErrorListener = function(error) {};
|
||||||
|
```
|
||||||
|
|
||||||
|
O argumento já chega como objeto JavaScript, não como string JSON.
|
||||||
|
|
||||||
|
```js
|
||||||
|
window.dtConnectionErrorListener = function(error) {
|
||||||
|
if (!error || !error.code) return;
|
||||||
|
|
||||||
|
if (error.code === 'LOGIN_EXPIRED') {
|
||||||
|
showError('Seu login expirou. Renove seu acesso.');
|
||||||
|
} else if (error.code === 'PROXY_FORBIDDEN') {
|
||||||
|
showError('Proxy/bughost bloqueou a conexão.');
|
||||||
|
} else {
|
||||||
|
showError(error.message || 'Falha na conexão.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. JSON de config retornado para o HTML
|
## 7. JSON de config retornado para o HTML
|
||||||
@@ -568,7 +717,7 @@ Ele varre todos os elementos `input`, `textarea` e `select`, e classifica eles p
|
|||||||
|
|
||||||
Ele detecta:
|
Ele detecta:
|
||||||
|
|
||||||
- Campos de UUID quando os metadados contêm `v2ray`, `uuid` ou `xray`.
|
- Campos de UUID quando os metadados contêm `v2ray`, `uuid`, `xray`, `vmess` ou `vless`.
|
||||||
- Campos de senha quando os metadados contêm `password`, `senha` ou `pass`.
|
- Campos de senha quando os metadados contêm `password`, `senha` ou `pass`.
|
||||||
- Campos de usuário quando os metadados contêm `username`, `usuario`, `login` ou tokens parecidos com usuário.
|
- Campos de usuário quando os metadados contêm `username`, `usuario`, `login` ou tokens parecidos com usuário.
|
||||||
|
|
||||||
@@ -595,31 +744,21 @@ HTML recomendado:
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Limitação importante desta versão
|
### Detecção V2Ray/Xray/VMess/VLess nesta versão
|
||||||
|
|
||||||
Nesta versão do `VOIDPRO.zip`, a função injetada de visibilidade considera V2Ray/Xray somente quando `mode` começa com `v2ray` ou `xray`.
|
No patch atual, a função injetada de visibilidade já considera `v2ray`, `xray`, `vmess` e `vless` no `mode` e também nos metadados do input.
|
||||||
|
|
||||||
Isto funciona:
|
Estes formatos são detectados como perfis baseados em UUID:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "mode": "V2RAY" }
|
{ "mode": "V2RAY" }
|
||||||
```
|
|
||||||
|
|
||||||
Isto funciona:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "mode": "XRAY" }
|
{ "mode": "XRAY" }
|
||||||
```
|
|
||||||
|
|
||||||
Estes podem não ser detectados pela função injetada, a não ser que o tema tenha sua própria lógica de visibilidade ou você aplique patch no Java:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "mode": "VMESS" }
|
{ "mode": "VMESS" }
|
||||||
{ "mode": "VLESS" }
|
{ "mode": "VLESS" }
|
||||||
{ "mode": "V2RAY - VMESS" }
|
{ "mode": "V2RAY - VMESS" }
|
||||||
```
|
```
|
||||||
|
|
||||||
Para builds atuais, prefira este formato de perfil no catálogo para configs baseadas em UUID:
|
Mesmo assim, o formato mais limpo para configs baseadas em UUID continua sendo:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -719,10 +858,23 @@ Exemplo:
|
|||||||
[
|
[
|
||||||
{ "14:03:55": "Connecting" },
|
{ "14:03:55": "Connecting" },
|
||||||
{ "14:03:56": "Authenticating" },
|
{ "14:03:56": "Authenticating" },
|
||||||
{ "14:03:57": "Server Message: welcome" }
|
{ "14:03:57": "Server Message: welcome" },
|
||||||
|
{ "14:03:58": "Proxy Status [HTTP_PROXY]: HTTP/1.1 101 Switching Protocols" },
|
||||||
|
{ "14:04:01": "Proxy Status [SSH_DIRECT]: HTTP/1.1 302 Found" }
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
O patch faz o bridge mostrar também respostas HTTP/proxy relevantes para o tema, incluindo:
|
||||||
|
|
||||||
|
- `Proxy Status [HTTP_PROXY]: HTTP/1.1 101 ...`
|
||||||
|
- `Proxy Status [HTTP_PROXY]: HTTP/1.1 302 ...`
|
||||||
|
- `Proxy Status [SSH_DIRECT]: HTTP/1.1 101 ...`
|
||||||
|
- `Proxy Status [SSH_DIRECT]: HTTP/1.1 302 ...`
|
||||||
|
- `HTTP/1.1 400`, `401`, `403`, `404`, `429`, `500`, `502`
|
||||||
|
- mensagens como `Unauthorized`, `Forbidden`, `Bad Request`, `Too Many Requests` e `Bad Gateway`
|
||||||
|
|
||||||
|
A diferença importante é o `SSH_DIRECT`: quando o campo de servidor SSH é usado como proxy/bughost e o servidor real está dentro do payload, o app agora faz uma leitura curta e segura da primeira resposta. Se vier HTTP, ele mostra o status para o HTML. Se vier banner SSH, ele preserva os bytes e não quebra o handshake.
|
||||||
|
|
||||||
Helper de renderização:
|
Helper de renderização:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -737,7 +889,23 @@ function readLogs() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
O buffer de logs nativo exposto ao HTML é limitado a entradas recentes de status e mensagens de banner do servidor. Ele não é o logcat/debug completo.
|
Listener ao vivo:
|
||||||
|
|
||||||
|
```js
|
||||||
|
window.dtLogsUpdatedListener = function(logsJson) {
|
||||||
|
let rows = [];
|
||||||
|
try { rows = JSON.parse(logsJson || '[]'); } catch (e) {}
|
||||||
|
|
||||||
|
const latest = rows.length ? Object.values(rows[rows.length - 1])[0] : '';
|
||||||
|
if (latest.includes('Proxy Status [SSH_DIRECT]')) {
|
||||||
|
showProxyStatus(latest);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLogs(readLogs());
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
O buffer de logs nativo exposto ao HTML é limitado a entradas recentes de status, mensagens de banner do servidor e mensagens úteis de proxy. Ele não é o logcat/debug completo.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -963,6 +1131,12 @@ if (!window.DtGetVpnState) {
|
|||||||
window.DtUuid = { get: () => '', set: (v) => console.log('uuid', v) };
|
window.DtUuid = { get: () => '', set: (v) => console.log('uuid', v) };
|
||||||
window.DtExecuteVpnStart = { execute: () => console.log('start') };
|
window.DtExecuteVpnStart = { execute: () => console.log('start') };
|
||||||
window.DtExecuteVpnStop = { execute: () => console.log('stop') };
|
window.DtExecuteVpnStop = { execute: () => console.log('stop') };
|
||||||
|
window.DtGetLogs = { execute: () => JSON.stringify([]) };
|
||||||
|
window.DtGetLastConnectionError = { execute: () => '{}' };
|
||||||
|
window.DtGetConnectionError = window.DtGetLastConnectionError;
|
||||||
|
window.DtGetStatusHotSpotService = { execute: () => 'STOPPED' };
|
||||||
|
window.DtStartHotSpotService = { execute: () => console.log('proxy start') };
|
||||||
|
window.DtStopHotSpotService = { execute: () => console.log('proxy stop') };
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -999,9 +1173,26 @@ Bom:
|
|||||||
usernameInput.value = cleanBridgeValue(DtUsername.get());
|
usernameInput.value = cleanBridgeValue(DtUsername.get());
|
||||||
```
|
```
|
||||||
|
|
||||||
### Erro: assumir que todos os modos V2Ray são detectados automaticamente pelo código de visibilidade injetado
|
### Erro: não tratar erros classificados do bridge
|
||||||
|
|
||||||
Use `mode: "V2RAY"` no catálogo/settings para este build, ou adicione um helper de visibilidade no tema que também verifique `vmess` e `vless`.
|
Ruim:
|
||||||
|
|
||||||
|
```js
|
||||||
|
window.DtVpnStateListener = function(state) {
|
||||||
|
if (state === 'AUTH_FAILED') alert('Falha');
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Bom:
|
||||||
|
|
||||||
|
```js
|
||||||
|
window.dtConnectionErrorListener = function(error) {
|
||||||
|
if (!error || !error.code) return;
|
||||||
|
showError(error.message || error.code);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `DtGetLastConnectionError.execute()` para recuperar o último erro quando a tela for recriada ou quando o tema carregar depois de uma falha.
|
||||||
|
|
||||||
### Erro: salvar autenticação somente no conectar
|
### Erro: salvar autenticação somente no conectar
|
||||||
|
|
||||||
@@ -1117,6 +1308,26 @@ const OnlineBridge = {
|
|||||||
this.set('DtUsername', username || '');
|
this.set('DtUsername', username || '');
|
||||||
this.set('DtPassword', password || '');
|
this.set('DtPassword', password || '');
|
||||||
this.set('DtUuid', uuid || '');
|
this.set('DtUuid', uuid || '');
|
||||||
|
},
|
||||||
|
|
||||||
|
readLogs() {
|
||||||
|
return this.jsonFromExec('DtGetLogs', []);
|
||||||
|
},
|
||||||
|
|
||||||
|
getLastError() {
|
||||||
|
return this.jsonFromExec('DtGetLastConnectionError', {});
|
||||||
|
},
|
||||||
|
|
||||||
|
getProxyStatus() {
|
||||||
|
return this.exec('DtGetStatusHotSpotService', 'STOPPED');
|
||||||
|
},
|
||||||
|
|
||||||
|
startProxy() {
|
||||||
|
this.command('DtStartHotSpotService');
|
||||||
|
},
|
||||||
|
|
||||||
|
stopProxy() {
|
||||||
|
this.command('DtStopHotSpotService');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@@ -1131,10 +1342,74 @@ Antes de publicar um tema, verifique:
|
|||||||
- Não mostra `Locked` para o usuário.
|
- Não mostra `Locked` para o usuário.
|
||||||
- Consegue fazer parse seguro de JSON vazio ou inválido.
|
- Consegue fazer parse seguro de JSON vazio ou inválido.
|
||||||
- Escuta `DtVpnStateListener`.
|
- Escuta `DtVpnStateListener`.
|
||||||
|
- Escuta `dtLogsUpdatedListener` se o tema mostra logs/proxy-status em tempo real.
|
||||||
|
- Escuta `dtConnectionErrorListener` ou lê `DtGetLastConnectionError.execute()` para mostrar erro correto.
|
||||||
- Chama `DtSetConfig.execute(id)` antes de iniciar um perfil selecionado.
|
- Chama `DtSetConfig.execute(id)` antes de iniciar um perfil selecionado.
|
||||||
- Salva usuário/senha/UUID antes de conectar.
|
- Salva usuário/senha/UUID antes de conectar.
|
||||||
- Trata `auth.username`, `auth.password` e `auth.v2ray_uuid`.
|
- Trata `auth.username`, `auth.password` e `auth.v2ray_uuid`.
|
||||||
- O campo UUID aparece para configs `mode: "V2RAY"` / `mode: "XRAY"`.
|
- O campo UUID aparece para configs `mode: "V2RAY"`, `"XRAY"`, `"VMESS"` e `"VLESS"`.
|
||||||
|
- Se usar proxy local, confirma `DtGetStatusHotSpotService.execute()` depois de chamar start/stop.
|
||||||
|
- Se usar proxy local em Android 13+, considera que a notificação pode depender da permissão `POST_NOTIFICATIONS`.
|
||||||
- Não depende de `DtGetPingResult` retornar ping real.
|
- Não depende de `DtGetPingResult` retornar ping real.
|
||||||
- Não coloca código de produção abaixo do marcador de mock.
|
- Não coloca código de produção abaixo do marcador de mock.
|
||||||
- Usa APIs nativas de altura das barras ou CSS safe areas para a navegação inferior não ficar cortada.
|
- Usa APIs nativas de altura das barras ou CSS safe areas para a navegação inferior não ficar cortada.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 21. Resumo dos bridges novos do patch V2/V3/V4
|
||||||
|
|
||||||
|
Esta versão do patch adiciona/atualiza estes pontos para temas HTML OnlineConfig:
|
||||||
|
|
||||||
|
| Item | Bridge/callback | O que muda para o tema |
|
||||||
|
|---|---|---|
|
||||||
|
| Último erro de conexão | `DtGetLastConnectionError.execute()` | Tema consegue saber se foi login expirado, login inválido, limite, proxy bloqueado, erro 400/403/429/500 etc. |
|
||||||
|
| Alias de erro | `DtGetConnectionError.execute()` | Mesmo retorno de `DtGetLastConnectionError.execute()`. |
|
||||||
|
| Helper limpo | `CakeApp.errors.getLast()` | Wrapper `CakeApp` para buscar o último erro. |
|
||||||
|
| Callback de erro | `dtConnectionErrorListener(error)` | Tema recebe o erro ao vivo como objeto JS. |
|
||||||
|
| Callback de auth/compatibilidade | `dtAuthErrorListener(error)` | Alias compatível para temas que tratam erro de autenticação separado. |
|
||||||
|
| Callback de logs | `dtLogsUpdatedListener(logsJson)` | Tema recebe logs recentes sempre que uma mensagem visível é adicionada. |
|
||||||
|
| Status de proxy HTTP | `DtGetLogs.execute()` | Logs agora incluem `Proxy Status [HTTP_PROXY]` e `Proxy Status [SSH_DIRECT]`. |
|
||||||
|
| SSH_DIRECT com payload/proxy | logs + erro classificado | Mesmo em SSH direto, o app tenta detectar resposta HTTP inicial do proxy sem quebrar banner SSH. |
|
||||||
|
| Proxy local foreground | `DtStartHotSpotService.execute()` | Inicia `ProxyService` com notificação foreground em vez de ligar apenas o socket interno. |
|
||||||
|
| Permissão de notificação | abertura do `OnlineConfigWebActivity` e start do proxy | Android 13+ pede `POST_NOTIFICATIONS`; se negar, o tema deve confirmar o status do proxy. |
|
||||||
|
| Detecção UUID | `CakeApp.applyAuthVisibility()` | Agora considera `v2ray`, `xray`, `vmess` e `vless`. |
|
||||||
|
|
||||||
|
Exemplo completo para tema tratar logs e erros:
|
||||||
|
|
||||||
|
```js
|
||||||
|
function parseBridgeJson(raw, fallback) {
|
||||||
|
try { return JSON.parse(raw || ''); } catch (e) { return fallback; }
|
||||||
|
}
|
||||||
|
|
||||||
|
window.dtLogsUpdatedListener = function(logsJson) {
|
||||||
|
const logs = parseBridgeJson(logsJson, []);
|
||||||
|
const text = logs.map(row => {
|
||||||
|
const time = Object.keys(row)[0] || '';
|
||||||
|
return `${time} ${row[time] || ''}`;
|
||||||
|
}).join('\n');
|
||||||
|
|
||||||
|
renderLogs(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.dtConnectionErrorListener = function(error) {
|
||||||
|
if (!error || !error.code) return;
|
||||||
|
|
||||||
|
const messageByCode = {
|
||||||
|
LOGIN_EXPIRED: 'Seu login expirou. Renove seu acesso.',
|
||||||
|
LOGIN_INVALID: 'Usuário ou senha inválidos.',
|
||||||
|
LOGIN_LIMIT: 'Limite de conexões atingido.',
|
||||||
|
PROXY_FORBIDDEN: 'Proxy/bughost bloqueou a conexão.',
|
||||||
|
PROXY_BAD_REQUEST: 'Payload ou proxy inválido.',
|
||||||
|
PROXY_RATE_LIMITED: 'Muitas tentativas no proxy.',
|
||||||
|
PROXY_SERVER_ERROR: 'Erro no proxy/servidor remoto.',
|
||||||
|
AUTH_FAILED: 'Falha de autenticação.'
|
||||||
|
};
|
||||||
|
|
||||||
|
renderError(messageByCode[error.code] || error.message || 'Falha na conexão.');
|
||||||
|
};
|
||||||
|
|
||||||
|
function restoreLastErrorOnLoad() {
|
||||||
|
const error = parseBridgeJson(DtGetLastConnectionError.execute(), {});
|
||||||
|
if (error.code) window.dtConnectionErrorListener(error);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user