Módulo User Panel
El Módulo User Panel (@zumito-team/user-panel-module) proporciona un dashboard web donde los usuarios de Discord pueden gestionar sus servidores, ver información de cuenta y acceder a páginas específicas de módulos (como colas de música). Incluye autenticación OAuth2 de Discord, soporte multi-idioma y una barra lateral dinámica que otros módulos pueden extender.
Instalación
Sección titulada «Instalación»npm install @zumito-team/user-panel-moduleAgrega a tu zumito.config.ts:
bundles: ['@zumito-team/user-panel-module']Qué proporciona
Sección titulada «Qué proporciona»Dashboard
Sección titulada «Dashboard»Una interfaz web completa en /panel que muestra:
- Lista de servidores — todas las guilds donde el usuario tiene permisos de Administrador, ManageGuild o es propietario.
- Dashboard específico por guild en
/panel/:guildIdcon secciones de barra lateral extensibles. - Soporte multi-idioma con detección automática mediante cookies o cabeceras
Accept-Language.
Autenticación
Sección titulada «Autenticación»Flujo de login basado en OAuth2 de Discord mediante el módulo compartido discord-auth:
- El usuario visita
/panel/login→ redirigido a autorización de Discord (scopeidentify). - Discord redirige de vuelta a
/panel/login/callback. - Se emite un JWT (
panel_token,purpose: 'panel') con el perfil completo de Discord, almacenado en cookie httpOnly con 30 días de expiración. - Todas las rutas del panel validan este token mediante
UserPanelAuthService(que extiendeDiscordAuthService). - Los tokens emitidos para otros módulos (ej. Admin) son rechazados gracias al claim
purpose.
Servicios
Sección titulada «Servicios»| Servicio | Propósito |
|---|---|---|
| UserPanelNavigationService | Registrar elementos en la barra lateral del panel de usuario. |
| UserPanelViewService | Renderizar páginas dentro del layout del panel (plantillas EJS). |
| UserPanelAuthService | Extiende DiscordAuthService. Valida tokens JWT con purpose: 'panel' y extrae datos del usuario de Discord. |
| UserPanelLanguageManager | Resolver idioma desde cookies o cabeceras, proporcionar funciones de traducción. |
| UserPanelColorsService | Gestionar la paleta de colores del panel. |
| Método | Ruta | Descripción |
|---|---|---|
GET | /panel | Dashboard principal con lista de servidores. |
GET | /panel/:guildId | Dashboard específico de guild. |
GET | /panel/login | Redirige a OAuth2 de Discord. |
GET | /panel/login/callback | Manejador del callback OAuth2. |
GET | /panel/logout | Limpia la cookie de autenticación y redirige a /panel. |
Elementos de navegación por defecto
Sección titulada «Elementos de navegación por defecto»El módulo registra estas entradas iniciales:
- Volver — Enlace a
/panel. - Dashboard — Resumen de guild en
/panel/:guildIdcon una seccióngeneral.
Configuración
Sección titulada «Configuración»Variables de entorno
Sección titulada «Variables de entorno»| Variable | Requerida | Descripción |
|---|---|---|
DISCORD_CLIENT_ID | Sí | Client ID de la aplicación Discord. |
DISCORD_CLIENT_SECRET | Sí | Client Secret de la aplicación Discord. |
SECRET_KEY | Sí | Clave secreta para firma JWT. |
HOST | Sí | URL del host del bot. |
FRONTEND_URL | Sí | URL del frontend para redirecciones. |
USER_PANEL_COLORS_FILE | No | Ruta a archivo JSON con colores personalizados. |
USER_PANEL_COLORS | No | String JSON con colores personalizados. |
Paleta de colores
Sección titulada «Paleta de colores»Misma estructura que el módulo admin. Configurable mediante USER_PANEL_COLORS o archivo JSON:
{ "primary": "#5865f2", "accent": "#5865f2", "success": "#57f287", "warning": "#fee75c", "danger": "#ed4245", "foreground": "#ffffff", "dark": { "100": "#36393f", "200": "#2f3136", "300": "#292b2f", "400": "#202225" }}Extender el panel de usuario
Sección titulada «Extender el panel de usuario»Agregar elementos de navegación
Sección titulada «Agregar elementos de navegación»Otros módulos pueden registrar elementos en la barra lateral consumiendo UserPanelNavigationService:
import { ServiceContainer } from 'zumito-framework';
const nav = ServiceContainer.getService('UserPanelNavigationService');
// Registrar un elemento de navegación principalnav.registerItem({ id: 'mi-funcionalidad', label: 'Mi Funcionalidad', icon: 'star', link: '/panel/mi-funcionalidad'});
// Registrar sub-elementos bajo una sección de un padre existentenav.registerSubItems('dashboard', 'general', [ { id: 'mi-sub-pagina', label: 'Mi Sub Página', icon: 'settings', link: '/panel/:guildId/mi-pagina' }]);Agregar rutas
Sección titulada «Agregar rutas»Crea tus propias clases de ruta que usen UserPanelViewService.render():
import { Route, RouteMethod, ServiceContainer } from 'zumito-framework';
class MiRutaPanel extends Route { method = RouteMethod.get; path = '/panel/:guildId/mi-pagina';
async execute(req, res) { const auth = ServiceContainer.getService('UserPanelAuthService'); const { isValid, data } = await auth.isLoginValid(req);
if (!isValid) return res.redirect('/panel/login');
const view = ServiceContainer.getService('UserPanelViewService'); const html = await view.render({ content: '<h1>Mi Página Personalizada</h1>', reqPath: req.path, req, res });
res.send(html); }}Declaración de requisitos del módulo
Sección titulada «Declaración de requisitos del módulo»Tu módulo debe declarar la dependencia al extender el panel:
class MiModulo extends Module { requirements = { services: ['UserPanelNavigationService'] };
async initialize() { const nav = ServiceContainer.getService('UserPanelNavigationService'); nav.registerSubItems('dashboard', 'general', [ { id: 'mi-pagina', label: 'Mi Página', link: '/panel/:guildId/mi-pagina' } ]); }}Soporte de idiomas
Sección titulada «Soporte de idiomas»El panel detecta automáticamente el idioma del usuario. Usa UserPanelLanguageManager para acceder a traducciones:
const langManager = ServiceContainer.getService('UserPanelLanguageManager');const { t, lang } = langManager.getLanguageVariables(req, res);
const greeting = t('mensaje_bienvenida'); // Devuelve string traducidoconst idiomasDisponibles = langManager.getAvailableLanguages(); // ['en', 'es', ...]Comparación de arquitectura con Admin
Sección titulada «Comparación de arquitectura con Admin»Ambos módulos comparten la misma base de autenticación mediante discord-auth, con diferentes configuraciones:
| Funcionalidad | Admin | User Panel |
|---|---|---|
| Servicio de autenticación | AdminAuthService → DiscordAuthService | UserPanelAuthService → DiscordAuthService |
| Servicio de vistas | AdminViewService | UserPanelViewService |
| Servicio de navegación | NavigationService | UserPanelNavigationService |
| Servicio de colores | AdminColorsService | UserPanelColorsService |
| Nombre de cookie | admin_token | panel_token |
| Propósito JWT | 'admin' | 'panel' |
| Clave de sub-elemento | sectionLabel | sectionId |
Dependencias
Sección titulada «Dependencias»discord-auth— Servicio compartido de autenticación OAuth2 de Discord.ejs— Renderizado de plantillas para páginas del panel.jose— Verificación y firma de JWT.zumito-framework
Módulos relacionados
Sección titulada «Módulos relacionados»- Módulo DisTube — Registra una página de cola de música en la barra lateral del panel de usuario.
- Módulo Admin — Arquitectura similar para dashboards de nivel administrador.