Files
amayo/README/FEATURE_FLAGS_COMANDOS.md

312 lines
7.1 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🎮 Feature Flags - Uso en Comandos Slash y Mensajes
## 🚀 Uso Universal
El sistema funciona **idénticamente** para comandos slash y comandos de mensaje.
---
## 📦 3 Formas de Usar
### 1⃣ Wrapper (Recomendado - Más Limpio)
```typescript
import { withFeatureFlag } from "@/core/lib/featureFlagCommandWrapper";
import { CommandSlash } from "@/core/types/commands";
// COMANDO SLASH
export const command: CommandSlash = {
name: 'shop',
description: 'Abre la tienda',
type: 'slash',
cooldown: 10,
run: withFeatureFlag('new_shop_system', async (interaction, client) => {
// Tu código aquí - solo se ejecuta si el flag está enabled
await interaction.reply('🛒 Tienda!');
}, {
fallbackMessage: '🔧 Tienda en mantenimiento'
})
};
// COMANDO DE MENSAJE
export const command: CommandMessage = {
name: 'shop',
type: 'message',
cooldown: 10,
run: withFeatureFlag('new_shop_system', async (message, args, client) => {
// Mismo código, funciona igual
await message.reply('🛒 Tienda!');
}, {
fallbackMessage: '🔧 Tienda en mantenimiento'
})
};
```
### 2⃣ Guard (Respuesta Automática)
```typescript
import { guardFeatureFlag } from "@/core/lib/featureFlagCommandWrapper";
// COMANDO SLASH
export const command: CommandSlash = {
name: 'mine',
description: 'Minea recursos',
type: 'slash',
cooldown: 10,
run: async (interaction, client) => {
// Guard responde automáticamente si está disabled
if (!await guardFeatureFlag('new_mining', interaction)) {
return; // Ya respondió al usuario
}
// Tu código aquí
await interaction.reply('⛏️ Minando...');
}
};
// COMANDO DE MENSAJE - EXACTAMENTE IGUAL
export const command: CommandMessage = {
name: 'mine',
type: 'message',
cooldown: 10,
run: async (message, args, client) => {
// Mismo guard funciona para mensajes
if (!await guardFeatureFlag('new_mining', message)) {
return;
}
await message.reply('⛏️ Minando...');
}
};
```
### 3⃣ Check Manual (Más Control)
```typescript
import { checkFeatureFlag } from "@/core/lib/featureFlagCommandWrapper";
// COMANDO SLASH
export const command: CommandSlash = {
name: 'inventory',
description: 'Tu inventario',
type: 'slash',
cooldown: 5,
run: async (interaction, client) => {
const useNewUI = await checkFeatureFlag('inventory_v2', interaction);
if (useNewUI) {
await interaction.reply('📦 Inventario v2');
} else {
await interaction.reply('📦 Inventario v1');
}
}
};
// COMANDO DE MENSAJE - IGUAL
export const command: CommandMessage = {
name: 'inventory',
type: 'message',
cooldown: 5,
run: async (message, args, client) => {
const useNewUI = await checkFeatureFlag('inventory_v2', message);
if (useNewUI) {
await message.reply('📦 Inventario v2');
} else {
await message.reply('📦 Inventario v1');
}
}
};
```
---
## 🔥 A/B Testing
```typescript
import { abTestCommand } from "@/core/lib/featureFlagCommandWrapper";
// COMANDO SLASH
export const command: CommandSlash = {
name: 'attack',
description: 'Ataca',
type: 'slash',
cooldown: 10,
run: async (interaction, client) => {
await abTestCommand('new_combat', interaction, {
variant: async () => {
// Nueva versión (50% usuarios)
await interaction.reply('⚔️ Daño nuevo: 100');
},
control: async () => {
// Versión antigua (50% usuarios)
await interaction.reply('⚔️ Daño viejo: 50');
}
});
}
};
// COMANDO DE MENSAJE - IGUAL
export const command: CommandMessage = {
name: 'attack',
type: 'message',
cooldown: 10,
run: async (message, args, client) => {
await abTestCommand('new_combat', message, {
variant: async () => {
await message.reply('⚔️ Daño nuevo: 100');
},
control: async () => {
await message.reply('⚔️ Daño viejo: 50');
}
});
}
};
```
---
## 💡 Ejemplo Real: Comando Universal
```typescript
import { checkFeatureFlag } from "@/core/lib/featureFlagCommandWrapper";
import { CommandSlash, CommandMessage } from "@/core/types/commands";
// Función de negocio (reutilizable)
async function executeShop(source: any) {
const useNewShop = await checkFeatureFlag('new_shop_system', source);
const items = useNewShop
? ['⚔️ Espada Legendaria', '🛡️ Escudo Épico']
: ['Espada', 'Escudo'];
const response = `🛒 **Tienda**\n${items.join('\n')}`;
// Detectar tipo y responder
if ('options' in source) {
await source.reply(response);
} else {
await source.reply(response);
}
}
// COMANDO SLASH
export const shopSlash: CommandSlash = {
name: 'shop',
description: 'Tienda',
type: 'slash',
cooldown: 10,
run: async (interaction, client) => {
await executeShop(interaction);
}
};
// COMANDO DE MENSAJE
export const shopMessage: CommandMessage = {
name: 'shop',
type: 'message',
cooldown: 10,
run: async (message, args, client) => {
await executeShop(message);
}
};
```
---
## 📊 Configurar Flags
```bash
# Crear flag
/featureflags create name:new_shop_system status:disabled target:global
# Habilitar
/featureflags update flag:new_shop_system status:enabled
# Rollout 25% de usuarios
/featureflags rollout flag:new_shop_system strategy:percentage percentage:25
# A/B testing (50/50)
/featureflags rollout flag:new_combat strategy:percentage percentage:50
# Ver estadísticas
/featureflags stats flag:new_shop_system
```
---
## ✨ Ventajas del Sistema
**Un solo código** para ambos tipos de comandos
**No rompe** comandos existentes
**Rollouts progresivos** sin redeploys
**Kill switches** instantáneos
**A/B testing** automático
**Estadísticas** de uso en tiempo real
---
## 🎯 Casos de Uso
### Migración Gradual
```typescript
run: async (interaction, client) => {
const useNew = await checkFeatureFlag('new_system', interaction);
if (useNew) {
await newSystem(interaction);
} else {
await oldSystem(interaction);
}
}
```
### Kill Switch
```bash
# Si hay un bug crítico
/featureflags update flag:problematic_feature status:maintenance
# Inmediatamente deshabilitado sin redeploy
```
### Beta Testing
```bash
# Solo para guilds específicos
/featureflags create name:beta_features status:rollout target:guild
/featureflags rollout flag:beta_features strategy:whitelist
# Luego añadir IDs de guilds en el config
```
### Eventos Temporales
```typescript
// Crear con fechas
await featureFlagService.setFlag({
name: 'halloween_event',
status: 'enabled',
startDate: new Date('2025-10-25'),
endDate: new Date('2025-11-01')
});
// Se auto-desactiva el 1 de noviembre
```
---
## 🔧 Integración en tu Bot
Simplemente usa los helpers en cualquier comando:
```typescript
import { withFeatureFlag } from '@/core/lib/featureFlagCommandWrapper';
export const command: CommandSlash = {
name: 'tu_comando',
description: 'Descripción',
type: 'slash',
cooldown: 10,
run: withFeatureFlag('tu_flag', async (interaction, client) => {
// Tu código existente aquí
})
};
```
**Eso es todo.** El sistema funciona transparentemente para ambos tipos de comandos. 🎮