from fastapi import FastAPI, HTTPException
from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles
import subprocess
import os
import json
from pathlib import Path
import asyncio
import time
from datetime import datetime
import re
app = FastAPI(title="Windows XP RDP")
# Informações sobre o container Windows
WINDOWS_CONTAINER_NAME = "windows-rdp"
WINDOWS_IMAGE = "dockurr/windows:latest"
def get_installation_progress():
"""Tenta detectar o progresso da instalação do Windows"""
progress = {
"stage": "unknown",
"percentage": 0,
"message": "Aguardando inicialização..."
}
# Verificar se há arquivos de log do Windows
storage_path = Path("/storage")
if storage_path.exists():
# Verificar se há arquivo de disco (indica que está criando)
disk_file = storage_path / "disk.qcow2"
if disk_file.exists():
size_mb = disk_file.stat().st_size / (1024 * 1024)
if size_mb < 100:
progress = {
"stage": "downloading",
"percentage": min(int(size_mb / 10), 10),
"message": f"Baixando ISO do Windows XP... ({size_mb:.1f} MB)"
}
elif size_mb < 2000:
progress = {
"stage": "creating_disk",
"percentage": min(10 + int((size_mb - 100) / 20), 30),
"message": f"Criando disco virtual... ({size_mb:.1f} MB)"
}
else:
progress = {
"stage": "installing",
"percentage": min(30 + int((size_mb - 2000) / 100), 90),
"message": f"Instalando Windows XP... ({size_mb:.1f} MB)"
}
# Verificar se a porta 8006 está respondendo (Windows iniciou)
try:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1)
result = sock.connect_ex(('localhost', 8006))
sock.close()
if result == 0:
progress = {
"stage": "ready",
"percentage": 100,
"message": "Windows XP está pronto!"
}
except:
pass
return progress
@app.get("/", response_class=HTMLResponse)
async def root():
"""Página inicial com logs em tempo real"""
html_content = """
Windows XP RDP
🖥️ Windows XP RDP
Aguardando inicialização...
Aguardando
📋 Informações de Conexão
Versão: Windows XP
Usuário RDP: Docker
Senha RDP: admin
Porta RDP: 3389
Web Viewer: Abrir Web Viewer
Status: Verificando...
ℹ️ Informações
- A instalação do Windows XP pode levar 20-40 minutos
- Você pode acompanhar o progresso acima
- O Web Viewer estará disponível quando o Windows iniciar
- Esta página atualiza automaticamente a cada 5 segundos
"""
return html_content
@app.get("/progress")
async def get_progress():
"""Retorna o progresso da instalação"""
progress = get_installation_progress()
return progress
@app.get("/status")
async def get_status():
"""Verifica o status do Windows (rodando no mesmo container)"""
try:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
result = sock.connect_ex(('localhost', 8006))
sock.close()
web_viewer_available = result == 0
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
result = sock.connect_ex(('localhost', 3389))
sock.close()
rdp_available = result == 0
running = web_viewer_available or rdp_available
return {
"running": running,
"web_viewer_available": web_viewer_available,
"rdp_available": rdp_available,
"mode": "direct"
}
except Exception as e:
return {
"running": True,
"web_viewer_available": False,
"rdp_available": False,
"mode": "direct",
"note": "Status não pôde ser verificado, mas o container está ativo"
}
@app.get("/logs-stream")
async def get_logs_stream():
"""Retorna logs do Windows em formato de texto"""
logs = []
# Tentar ler logs do FastAPI
try:
fastapi_log = Path("/tmp/fastapi.log")
if fastapi_log.exists():
with open(fastapi_log, 'r', encoding='utf-8', errors='ignore') as f:
lines = f.readlines()
logs.extend(lines[-50:]) # Últimas 50 linhas
except:
pass
# Tentar ler logs do sistema
try:
# Verificar processos relacionados ao Windows/QEMU
result = subprocess.run(
["ps", "aux"],
capture_output=True,
text=True,
timeout=2
)
if "qemu" in result.stdout.lower() or "windows" in result.stdout.lower():
logs.append("Windows/QEMU está rodando\n")
except:
pass
# Adicionar informações de progresso
progress = get_installation_progress()
logs.append(f"Status: {progress['message']} ({progress['percentage']}%)\n")
if not logs:
logs.append("Aguardando logs do Windows...\n")
return "".join(logs)
@app.get("/web-viewer")
async def web_viewer():
"""Redireciona para o web viewer do Windows"""
import socket
try:
hostname = socket.gethostname()
except:
hostname = "localhost"
return HTMLResponse(f"""
Windows XP Web Viewer
""")
@app.get("/info")
async def get_info():
"""Retorna informações sobre o ambiente"""
import socket
try:
hostname = socket.gethostname()
except:
hostname = "localhost"
status = await get_status()
progress = get_installation_progress()
hf_space_host = os.environ.get("SPACE_HOST", None)
return {
"hostname": hostname,
"hf_space_host": hf_space_host,
"status": status,
"progress": progress,
"mode": "direct",
"version": "Windows XP",
"rdp_info": {
"username": "Docker",
"password": "admin",
"port": 3389,
"host": "localhost"
},
"web_viewer": {
"url": "http://localhost:8006",
"note": "No HuggingFace Spaces, use o hostname do Space se localhost não funcionar"
}
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)