- Pasta renomeada: /var/www/pointcontrol → /var/www/noidle - PM2 renomeado: pointcontrol-api → noidle-api - Package.json backend atualizado - Package.json frontend atualizado - Todas as referências de código atualizadas - Documentação atualizada - Script de migração executado com sucesso - Backup criado em /tmp/ - Sistema testado e funcionando Resolução: Organização completa da estrutura bagunçada
6.5 KiB
Especificação Completa - Cliente Windows NoIdle
📋 Visão Geral
O cliente Windows deve monitorar e enviar para o servidor:
- Aplicativos ativos (window_title, application_name)
- Histórico de navegação (URLs do Chrome/Edge)
- Eventos de sessão (logon/logoff do Windows)
🔌 Endpoints da API
Base URL
https://admin.noidle.tech
1️⃣ Registrar Atividade (Aplicativos)
Endpoint: POST /api/activity/log
Frequência: A cada 5-10 segundos (quando há mudança de aplicativo/janela)
Headers:
Content-Type: application/json
Body:
{
"device_id": "DEV-1762999424206-0BJR2Q",
"window_title": "Documento - Word",
"application_name": "WINWORD.EXE",
"idle_time_seconds": 0,
"urls": [
{
"url": "https://example.com/page",
"title": "Example Page",
"browser": "Chrome"
}
]
}
Campos Obrigatórios:
device_id(string): ID único do dispositivowindow_title(string): Título da janela ativa (NÃO pode ser "System Idle" ou vazio)application_name(string): Nome do executável (ex: "chrome.exe", "WINWORD.EXE", "notepad.exe")idle_time_seconds(number): Tempo em segundos que o usuário está inativo (0 = ativo)
Campos Opcionais:
urls(array): Array de objetos com histórico de navegação (ver seção 2)
⚠️ IMPORTANTE:
- NÃO envie
window_title = "System Idle"ouapplication_name = "[IDLE]"quando o usuário está realmente usando um aplicativo - Se o usuário estiver inativo por mais de 30 segundos, aí sim pode enviar
idle_time_seconds > 0 - Capture o título real da janela e o executável real usando APIs do Windows
Exemplo de Resposta:
{
"success": true,
"message": "Atividade registrada"
}
2️⃣ Histórico de Navegação (Chrome/Edge)
Endpoint: POST /api/activity/log (mesmo endpoint, campo urls)
Frequência: A cada vez que uma nova URL é visitada no navegador
Como Capturar:
- Use a API do Chrome/Edge para monitorar abas abertas
- Capture URLs de todas as abas ativas
- Envie no array
urlsdentro do mesmo POST de atividade
Estrutura do Array urls:
{
"urls": [
{
"url": "https://www.google.com/search?q=exemplo",
"title": "exemplo - Pesquisa Google",
"browser": "Chrome"
},
{
"url": "https://github.com/user/repo",
"title": "user/repo · GitHub",
"browser": "Chrome"
}
]
}
Campos:
url(string): URL completa visitadatitle(string): Título da página/ababrowser(string): "Chrome" ou "Edge"
⚠️ IMPORTANTE:
- Envie URLs de TODAS as abas abertas, não apenas a ativa
- Atualize a lista sempre que uma nova aba for aberta ou fechada
- Não envie URLs vazias ou inválidas
3️⃣ Eventos de Sessão (Logon/Logoff)
Endpoint: POST /api/activity/session
Frequência: Imediatamente quando ocorre logon ou logoff
Headers:
Content-Type: application/json
Body para LOGON:
{
"device_id": "DEV-1762999424206-0BJR2Q",
"event_type": "logon",
"username": "Sergio.Dev"
}
Body para LOGOFF:
{
"device_id": "DEV-1762999424206-0BJR2Q",
"event_type": "logoff",
"username": "Sergio.Dev"
}
Campos Obrigatórios:
device_id(string): ID único do dispositivoevent_type(string): "logon" ou "logoff"username(string): Nome do usuário do Windows
Como Capturar:
- Use eventos do Windows:
SessionSwitch,SessionLock,SessionUnlock - Monitore o evento de logon do sistema operacional
- Capture o username do usuário logado
Exemplo de Resposta:
{
"success": true,
"message": "Evento logon registrado"
}
4️⃣ Heartbeat (Opcional mas Recomendado)
Endpoint: POST /api/devices/heartbeat
Frequência: A cada 30-60 segundos
Body:
{
"device_id": "DEV-1762999424206-0BJR2Q"
}
Nota: O heartbeat é opcional se você estiver enviando atividades regularmente, mas ajuda a manter o dispositivo marcado como ativo.
🔧 Implementação Técnica
Capturar Window Title e Application Name (C#/PowerShell)
using System;
using System.Runtime.InteropServices;
using System.Text;
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
// Obter janela ativa
IntPtr hwnd = GetForegroundWindow();
StringBuilder windowTitle = new StringBuilder(256);
GetWindowText(hwnd, windowTitle, 256);
// Obter processo
uint processId;
GetWindowThreadProcessId(hwnd, out processId);
Process process = Process.GetProcessById((int)processId);
string appName = process.ProcessName + ".exe";
Capturar URLs do Chrome (PowerShell)
# Usar Chrome DevTools Protocol ou ler histórico do Chrome
# Alternativa: usar extensão do Chrome que envia dados via API local
Capturar Eventos de Sessão (C#)
using Microsoft.Win32;
SystemEvents.SessionSwitch += (sender, e) => {
if (e.Reason == SessionSwitchReason.SessionLock) {
// Logoff ou bloqueio
} else if (e.Reason == SessionSwitchReason.SessionUnlock) {
// Logon ou desbloqueio
}
};
✅ Checklist de Implementação
- Cliente captura
window_titlereal (não "System Idle") - Cliente captura
application_namereal (exe do processo) - Cliente envia atividades a cada 5-10 segundos quando há mudança
- Cliente monitora e envia URLs do Chrome/Edge
- Cliente detecta eventos de logon/logoff do Windows
- Cliente envia eventos de sessão imediatamente
- Cliente trata erros de rede e faz retry
- Cliente valida dados antes de enviar
🐛 Troubleshooting
Problema: Apenas "System Idle" aparece nas atividades
Solução: Verifique se o código está capturando a janela ativa corretamente. Use GetForegroundWindow() e não confie em valores padrão.
Problema: URLs não aparecem
Solução: Verifique se o array urls está sendo enviado no POST /api/activity/log e se contém dados válidos.
Problema: Eventos de sessão não aparecem
Solução: Verifique se o cliente está escutando eventos do Windows corretamente e se está fazendo POST para /api/activity/session.
📞 Suporte
Para problemas técnicos, verifique:
- Logs do cliente (console/arquivo de log)
- Logs do servidor:
pm2 logs noidle-api - Resposta HTTP dos endpoints (status code, mensagem de erro)