MVP funcional de chat aleatorio anónimo para Telegram con:
- Registro 18+ y perfil.
- Preferencia de género.
- Búsqueda global.
- Búsqueda por cercanía con ubicación voluntaria.
- Emparejamiento compatible.
- Relay anónimo de mensajes con
copyMessage. - Finalizar / siguiente.
- Likes y Super Interés.
- Bloqueos y reportes.
- PostgreSQL para datos persistentes.
- Redis para cola, sesión de chat y límites.
- Monetización con Telegram Stars (
XTR):- FreXo Premium: 199 Stars / 30 días.
- Boost 30 min: 25 Stars.
- Super Interés: 10 Stars.
- Reconectar: 15 Stars.
/paysupport.
Crea el bot con @BotFather y copia el token.
cp .env.example .env
nano .envConfigura al menos:
BOT_TOKEN=...
SUPPORT_USERNAME=@TuSoportedocker compose up -d --buildVer logs:
docker compose logs -f botNecesitas PostgreSQL y Redis activos.
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python main.pyEn Windows:
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
python main.pyapp/
├── handlers/ # Updates de Telegram
├── services/ # Matchmaking, relay y pagos
├── config.py
├── database.py
├── keyboards.py
├── models.py
├── redis_client.py
├── repositories.py
└── states.py
El bot no entrega automáticamente usernames o IDs del compañero.
La ubicación compartida se usa sólo para calcular distancia. No se reenvía al compañero.
Bloqueos y reportes son gratuitos. Ningún producto Premium puede evitar un bloqueo.
- Edición completa de perfil.
- Rango de edad y radio de distancia desde UI.
- Filtro por país / Travel Mode.
- Reconexión real usando historial elegible.
- Vista de personas que dieron Like para Premium.
- Panel administrativo.
- Moderación avanzada y antiflood.
- Referral system.
- Alembic para migraciones versionadas.
- Webhook + Nginx cuando se requiera escalar.
- Métricas de conversión, retención e ingresos.
Incluye:
- Edición de alias.
- Descripción/Bio de hasta 300 caracteres.
- Foto de perfil mediante Telegram
file_id. - Actualización de ubicación.
- Vista del perfil de la pareja durante una conversación.
- Distancia aproximada sin revelar coordenadas.
- Cambio de preferencia de género.
- Filtro Premium de rango de edad.
- Filtro Premium de radio: 5, 10, 25, 50 o 100 km.
- El usuario gratuito conserva búsqueda cercana hasta 100 km.
- Alias y edad visibles para todos como datos básicos de confianza.
- Usuario gratuito: perfil básico (alias, edad y género).
- Premium: foto, bio y distancia aproximada desde el inicio.
👀 Conocer más: si ambos aceptan, se desbloquea el perfil completo incluso sin Premium.📲 Compartir Telegram: sólo se revela después de doble consentimiento.❤️ Likes recibidos: gratis ve la cantidad; Premium ve quiénes son.- Premium puede devolver interés desde la lista de Likes.
- Reconexión real usando créditos comprados con Stars.
- La reconexión requiere aceptación del otro usuario.
- Nunca se permite reconectar tras bloqueo/reporte.
- Solicitudes de reconexión expiran en 24 horas.
Los mensajes retransmitidos desde otra persona muestran:
👤 Tu conexión
Hola, ¿cómo estás?
Los avisos internos usan el estilo:
🤖 FreXo
Conversación terminada.
Para fotografías, videos, documentos y contenido con caption, FreXo intenta integrar
la etiqueta 👤 Tu conexión en el propio caption. Para stickers, video notas y
contenidos sin caption, envía una cabecera inmediatamente antes.
- Antiflood de mensajes.
- Cooldown progresivo por spam.
- Límite de uso excesivo de
Siguiente. - Límite de búsquedas por ráfaga.
- Límite diario de reportes.
- Restricciones temporales y permanentes.
- Registro de acciones administrativas.
- Los baneos interrumpen el chat activo.
- Opción
PROTECT_RELAYED_CONTENT=true.
Configura ADMIN_IDS en .env y utiliza:
/admin
/userinfo TELEGRAM_ID
/ban TELEGRAM_ID 24 motivo
/ban TELEGRAM_ID perm motivo
/unban TELEGRAM_ID
El panel incluye estadísticas y revisión de reportes.
Cada usuario obtiene un enlace:
https://t.me/TU_BOT?start=ref_CODIGO
El referido no se considera válido por iniciar el bot. Se califica cuando logra su primer match, reduciendo abuso con cuentas vacías.
Recompensas:
- Cada referido calificado: 1 Super Interés.
- 3 calificados: 1 Travel Pass + 1 Spotlight.
- 5 calificados: 1 Boost gratis + 3 Super Intereses.
- Producto: 15 Stars.
- Añade 1 Travel Pass.
- El usuario selecciona un país.
- Matchmaking filtra candidatos del país objetivo durante 24 h.
- El país de origen se configura desde
🌎 Explorar.
- Producto: 50 Stars.
- Crédito activable cuando el usuario quiera.
- Duración: 3 horas.
- Añade +175 puntos a la puntuación de matchmaking.
- 30 minutos: 25 Stars.
- 60 minutos: 45 Stars.
- Los Boost de pago se activan inmediatamente.
- Los Boost ganados por referidos quedan como crédito activable.
Durante un chat:
- Rosa: 5 Stars.
- Café: 10 Stars.
- Flores: 25 Stars.
- Diamante: 100 Stars.
Los regalos no transfieren dinero al receptor y no revelan su Telegram. Quedan registrados como objetos sociales en el perfil FreXo.
El panel /admin agrega 📈 Conversión con:
- nuevos usuarios 30 días;
- matches;
- compras;
- compradores únicos;
- Stars cobradas;
- conversión usuario → comprador;
- ingresos por producto.
Los usuarios nuevos seleccionan su país antes de la ubicación opcional. Esto permite
que Travel Mode tenga suficientes perfiles clasificables desde el comienzo.
Los usuarios existentes pueden definirlo desde 🌎 Explorar.
- Paneles principales incluyen
🏠 Inicio. - Subpaneles incluyen
⬅️ Atrás. - Volver a inicio limpia estados FSM incompletos.
- Si existe una conversación activa,
Iniciono la oculta: FreXo vuelve a mostrar el panel de conversación.
Al comenzar un match, FreXo crea:
🧭 CONVERSACIÓN ACTIVA
👤 Andrea
🎂 24 años
🚻 Mujer
📍 A menos de 10 km
📌 Este panel queda fijado arriba.
- Se fija automáticamente en el chat privado.
- Se actualiza si ambos aceptan
Conocer más. - Se desfija al terminar, bloquear o reportar.
- Puede recuperarse con
🧭 Panel de chat. - No depende de desplazarse entre cientos de mensajes.
Durante una conversación, el teclado inferior cambia a:
🧭 Panel de chat 👤 Mi conexión
❤️ Me interesa 🎁 Regalo
🔄 Siguiente ❌ Terminar
Al terminar, vuelve automáticamente al menú principal.
En 🎁 Recompensas aparece una racha diaria.
Reglas:
- Reclamable cada 20 horas.
- Hasta 48 horas para conservar la racha.
- Ciclo de 7 recompensas:
- Super Interés
- Super Interés
- Boost 30 min
- 2 Super Intereses
- Travel Pass
- 2 Super Intereses
- Spotlight 3 h
Nueva tabla: retention_profiles.
Durante una conversación el teclado persistente usa dos páginas.
Página 1:
🧭 Panel de chat 👤 Mi conexión
❤️ Me interesa 👀 Conocer más
🔄 Siguiente ❌ Terminar
➡️ Más opciones
Página 2:
💘 Super Interés 📲 Compartir Telegram
🎁 Regalo ⭐ Guardar favorito
🚫 Bloquear 🚨 Reportar
🔄 Siguiente ❌ Terminar
⬅️ Acciones principales
Siguiente y Terminar están disponibles en ambas páginas para no ocultar
acciones críticas de la conversación.
- Gratis: últimas 5 conexiones.
- Premium: últimas 20 conexiones.
- Muestra alias, edad, fecha, motivo de cierre y actividad reciente dentro de FreXo.
- Los bloqueos/reportes siguen impidiendo reconexiones aunque aparezcan como historial.
- La conexión actual puede guardarse como favorita desde la página 2 del teclado.
- Existe un panel
⭐ Favoritosen el menú principal. - Guardar un favorito es privado y no notifica a la otra persona.
El usuario puede elegir hasta 6 intereses desde 👤 Mi perfil → 🎯 Mis intereses.
También se sugieren al terminar el onboarding.
Catálogo inicial:
- Música, viajes, videojuegos, deportes, cine/series, lectura.
- Fitness, comida, naturaleza, tecnología, mascotas, arte.
- Baile, fotografía, negocios e idiomas.
Los intereses:
- aparecen en el perfil;
- añaden puntos al matchmaking;
- muestran intereses compartidos;
- generan un rompehielo en el panel fijado de conversación.
FreXo muestra un porcentaje aproximado propio combinando:
- preferencias compatibles;
- diferencia de edad;
- distancia cuando existe ubicación;
- intereses en común.
No representa una garantía de afinidad; es únicamente un indicador del algoritmo de FreXo.
La Bot API no expone al bot el last seen/online real de la cuenta de Telegram.
Por eso FreXo sólo muestra actividad dentro del propio bot:
🟢 Activo recientemente en FreXo
⚪ Sin actividad reciente en FreXo
⚪ Actividad oculta
La preferencia puede apagarse desde ⚙️ Preferencias.
Cuando una persona compatible comienza a buscar y no encuentra match inmediatamente, FreXo puede avisar de forma oportunista a usuarios compatibles que tengan esta función activa.
Protecciones:
- máximo 2 avisos por día por destinatario;
- deduplicación entre la misma pareja durante 6 horas;
- no se avisa a personas en conversación o ya buscando;
- score mínimo de compatibilidad;
- botón para desactivar los avisos inmediatamente.
user_interestsfavoritesexperience_preferences
Estas son tablas nuevas, por lo que el create_all() actual puede crearlas sin borrar
los usuarios, pagos, conversaciones ni información existente.
La otra persona recibe una notificación explícita antes del menú:
🤖 FreXo
👋 Tu conexión terminó la conversación.
Ya puedes buscar otra persona cuando quieras.
Siguiente, bloqueos, reportes e inactividad tienen mensajes diferenciados.
Tras Terminar, Siguiente o cierre por inactividad:
👍 Buena 😐 Normal 👎 Mala
El feedback sirve para analítica de calidad. Una valoración mala aislada no sanciona.
Nueva tabla conversation_quality:
- mensajes enviados por cada integrante;
- último remitente;
- cantidad de mensajes consecutivos;
- último mensaje;
- recordatorio de inactividad.
Si alguien envía demasiados mensajes seguidos sin respuesta, FreXo muestra un recordatorio suave. No genera una sanción automática.
- Después de
GHOSTING_NUDGE_MINUTES(15 por defecto), se recuerda al último remitente que dé tiempo a la conexión. - Después de
CONVERSATION_IDLE_CLOSE_HOURS(24 h por defecto), una conversación abandonada se cierra automáticamente y libera ambos usuarios. - El monitor se ejecuta dentro del proceso del bot cada 5 minutos.
Botón persistente 💡 Sugerencia.
Si existen intereses compartidos, FreXo genera una pregunta relacionada.
Si no, utiliza rompehielos generales.
Cada favorito ofrece ↩️ Solicitar reconexión.
Consume un crédito de Reconexión y siempre requiere aprobación de la otra persona.
- 3 matches → 💘 2 Super Intereses
- 25 mensajes → 🚀 Boost 30 min
- 3 recompensas diarias → 🌎 Travel Pass
- Reclamar las tres → 🔥 Spotlight 3 h
Desde 👤 Mi perfil → 📊 Mis estadísticas:
- conexiones;
- mensajes enviados (el contador técnico comenzó a persistirse en v1.8);
- intereses enviados/recibidos;
- favoritos;
- regalos;
- rachas.
Nuevas tablas:
conversation_qualityconversation_feedbackweekly_progress
FreXo v1.9 congela el desarrollo de funciones grandes y endurece operación:
- Alembic 1.19.1; el bot ya no crea/modifica esquema con
create_all()al arrancar. - Baseline de adopción para instalaciones v1.8.x existentes.
entrypoint.shejecutaalembic upgrade headantes del bot.- PostgreSQL → Redis recovery para conversaciones activas tras reinicios.
- Cola efímera de matchmaking se limpia tras reinicio para evitar búsquedas fantasma.
- Endpoint local
/healthcon PostgreSQL + Redis + readiness. - Healthchecks Docker y rotación de logs.
- Logs JSON a stdout.
- Backups automáticos diarios, semanales y mensuales.
- Admin financiero de Telegram Stars: balance real y últimos movimientos.
- Reembolso auditado mediante
/refund CHARGE_ID motivo. - Estado de suscripción Premium con cancelar/reactivar renovación.
- Manejo del evento
subscriptionde Bot API 10.2. - Centro de ayuda, privacidad, términos, normas y eliminación/anominización de cuenta.
production_check.pyyload_test_redis.py.
Tu volumen PostgreSQL ya tiene una contraseña real. Cambiar POSTGRES_PASSWORD en
Docker Compose no cambia la contraseña dentro de una base ya inicializada.
En la primera actualización conserva las credenciales actuales.
Ejemplo para una instalación que todavía usa frexo/frexo:
POSTGRES_DB=frexo
POSTGRES_USER=frexo
POSTGRES_PASSWORD=frexo
DATABASE_URL=postgresql+asyncpg://frexo:frexo@postgres:5432/frexoLuego puedes rotarla de forma controlada.
cd /opt/frexo/frexo_telegram_bot
docker compose exec -T postgres \
pg_dump -U frexo frexo > backup_antes_v1.9.sql
# reemplazar archivos conservando .env
docker compose up -d --buildEl bot aplica automáticamente:
alembic upgrade headComprueba:
docker compose ps
docker compose logs --tail=200 bot
curl http://127.0.0.1:8080/health
docker compose exec bot alembic current
docker compose exec bot python scripts/production_check.pyGenera una contraseña:
openssl rand -hex 32Cámbiala dentro de PostgreSQL (sustituye NUEVA_PASSWORD):
docker compose exec postgres \
psql -U frexo -d frexo \
-c "ALTER USER frexo WITH PASSWORD 'NUEVA_PASSWORD';"Actualiza simultáneamente .env:
POSTGRES_PASSWORD=NUEVA_PASSWORD
DATABASE_URL=postgresql+asyncpg://frexo:NUEVA_PASSWORD@postgres:5432/frexoDespués:
docker compose up -d --force-recreate bot backupEl servicio backup guarda en ./backups:
- diarios: 7 días;
- semanales: ~5 semanas;
- mensuales: ~3 meses.
Comprueba:
find backups -type f -name '*.sql.gz' -lsEjecuta uno manual:
docker compose run --rm backup sh /scripts/backup_postgres.shPrueba restauración siempre en una base separada antes de confiar en el plan.
En /admin abre 💰 Finanzas. Consulta getMyStarBalance y
getStarTransactions directamente contra Telegram.
Reembolso:
/refund TELEGRAM_PAYMENT_CHARGE_ID motivo
Los textos legales incluidos son una base funcional para la beta y no sustituyen asesoría jurídica adaptada a los territorios donde FreXo se comercialice.
/admin incluye ahora 📅 Reporte de hoy.
El reporte utiliza la zona horaria definida por:
ADMIN_REPORT_TIMEZONE=America/Mexico_CityMuestra:
- usuarios nuevos;
- activos del día y últimos 15 minutos;
- búsquedas iniciadas;
- usuarios buscando actualmente;
- matches;
- mensajes;
- conversaciones activas;
- Likes/intereses;
- valoraciones de conversación;
- bloqueos y reportes;
- compras y compradores;
- conversión de activos a compradores;
- Premium vendidos y Premium activos;
- Stars brutas, reembolsos y Stars netas.
Las búsquedas se registran desde v1.9.1 mediante el evento
analytics_events.event_name = "search_started".
También existe el comando administrativo:
/daily
para abrir el mismo reporte directamente.
/admin → 📊 Estadísticas ahora incluye:
- usuarios registrados y perfiles completados;
- hombres, mujeres, otro y sin definir con cantidad y porcentaje;
- distribución de a qué género quieren conocer los usuarios;
- porcentaje de cada preferencia;
- preferencia mayoritaria destacada automáticamente;
- botón para actualizar sin generar mensajes duplicados.
Los porcentajes demográficos se calculan únicamente sobre usuarios con onboarding completado para no distorsionar los datos con registros abandonados.
Cuando FreXo crea una conversación, ambos usuarios reciben al final un aviso grande:
🎉 ¡MATCH ENCONTRADO!
✅ Ya encontraste una conexión y la búsqueda terminó.
💬 EMPIEZA A CHATEAR AHORA
⚠️ No necesitas pulsar ningún botón para escribir.
El aviso incluye alias, edad y un rompehielos sugerido según los intereses de ambos. El panel fijado y el teclado inferior siguen disponibles.
No requiere migración Alembic nueva.
Sección 1 (uso frecuente):
🎲 Buscar persona 📍 Personas cerca
❤️ Likes recibidos 👤 Mi perfil
🕘 Historial ⭐ Favoritos
📂 Más opciones
Sección 2:
🌎 Explorar 🎁 Recompensas
👑 Premium ⚙️ Preferencias
🛡️ Seguridad
⬅️ Volver al inicio
- Se envía después de unas horas si el usuario abandonó el onboarding.
- Botón
▶️ Continuar mi registroque intenta retomar desde el paso pendiente. - Cadencia configurable para evitar spam.
Para usuarios ya registrados se comprueba:
- foto;
- bio;
- al menos 3 intereses.
Si falta algo se muestra un progreso aproximado y acceso directo al perfil.
Si pasan varios minutos desde el match y un integrante todavía no ha enviado ningún mensaje, FreXo le recuerda que la conversación ya está activa.
Si la otra persona ya escribió, el recordatorio cambia a:
💬 Tu conexión ya te escribió
Sólo se envía una vez por usuario/conversación antes del primer mensaje. Además, si una conversación se queda esperando respuesta, el monitor de calidad recuerda al destinatario que puede responder directamente.
Variables opcionales:
PROFILE_REMINDER_HOURS=72
ONBOARDING_REMINDER_HOURS=48
ONBOARDING_REMINDER_DELAY_HOURS=2
ACTIVE_CHAT_REMINDER_MINUTES=10
REMINDER_SCAN_INTERVAL_SECONDS=600No requiere nuevas tablas ni migración Alembic.
/admin → 👥 Referidos permite introducir un Telegram ID y consultar:
- referidos totales;
- registros completados;
- referidos calificados por primer match;
- pendientes de primer match;
- porcentajes de conversión;
- enlace personal de referido.
También están disponibles:
/refstats TELEGRAM_ID
/userinfo TELEGRAM_ID
/userinfo incluye ahora el total y los referidos calificados.
/admin → 📣 Campañas permite crear enlaces con códigos personalizados, por ejemplo:
https://t.me/TU_BOT?start=camp_facebook_agosto
https://t.me/TU_BOT?start=camp_google_mx
https://t.me/TU_BOT?start=camp_canal_fenix
Por campaña se mide:
- inicios totales del bot desde el enlace;
- usuarios únicos que iniciaron;
- usuarios atribuidos a esa campaña;
- registros completados;
- usuarios que alcanzaron su primer match;
- conversiones entre las etapas.
Las campañas pueden pausarse y reactivarse desde /admin.
FreXo aplica atribución primaria única: un usuario nuevo no puede contarse a la vez como referido personal y como adquisición de campaña.
v1.9.4 agrega:
acquisition_campaignscampaign_touchescampaign_attributions
El entrypoint.sh ejecuta alembic upgrade head automáticamente.
En 🎁 Recompensas el usuario dispone ahora de:
📤 Compartir mi invitación
El botón abre el selector nativo de Telegram mediante:
https://t.me/share/url?url=...&text=...
Telegram permite al usuario elegir un chat, grupo, canal o Mensajes guardados.
La invitación incluye automáticamente el deep link personal ref_... y un
mensaje promocional editable antes de enviarlo.
No requiere cambios de base de datos ni migración Alembic.
/admin incluye ahora 📉 Embudo y también puede abrirse con /funnel.
El reporte trabaja por cohortes de nuevos usuarios de los últimos 7 o 30 días:
- Entraron al bot.
- Completaron el perfil.
- Iniciaron una búsqueda.
- Consiguieron match.
- Mandaron su primer mensaje.
- Obtuvieron una conversación real (ambos participantes escribieron).
Además muestra:
- retención D1 (retorno después de 24 horas, sólo entre usuarios ya elegibles);
- compradores y Stars generadas por la cohorte;
- mayor fuga entre pasos;
- filtros para todos, hombres, mujeres y campañas de adquisición.
El filtro por campaña utiliza la atribución campaign_attributions; no mezcla
usuarios de campañas distintas. No requiere nuevas tablas ni migración Alembic.
Mide usuarios únicos por etapa durante 7/30 días:
Paywall mostrado
→ Pulsó comprar
→ Factura preparada
→ Pre-checkout aprobado
→ Compra completada
También muestra rendimiento por trigger (Likes, filtro de edad, distancia, límite de búsquedas y menú Premium), Premium Preview otorgados y compradores por producto.
FreXo ya no depende únicamente de una tienda genérica. Los bloqueos Premium muestran la razón concreta por la que el usuario podría beneficiarse de pagar. No se inventan likes, urgencia ni escasez.
Después de la primera conversación real (ambos enviaron al menos un mensaje), un usuario elegible recibe una única prueba Premium por 24 horas.
Variables:
PREMIUM_PREVIEW_ENABLED=true
PREMIUM_PREVIEW_HOURS=24Nuevo producto frexo_pass_7d: 69 Stars, Premium por 7 días como compra única,
sin renovación automática.
No requiere migración Alembic nueva. Reutiliza analytics_events, orders,
order_contexts, star_transactions y users.premium_until.