276 lines
10 KiB
Text
276 lines
10 KiB
Text
import logging
|
|
import json
|
|
import asyncio
|
|
import nest_asyncio
|
|
|
|
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
|
from telegram.ext import Application, CommandHandler, CallbackQueryHandler, ContextTypes
|
|
|
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
|
from apscheduler.triggers.cron import CronTrigger
|
|
from datetime import datetime
|
|
import pytz
|
|
|
|
# Aplica nest_asyncio para evitar problemas con el event loop
|
|
nest_asyncio.apply()
|
|
|
|
# Configuración del logging
|
|
logging.basicConfig(
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
level=logging.INFO
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# --------- DATOS DEL CUADRANTE ---------
|
|
CUADRANTE = [
|
|
{
|
|
"Planta Baja": "Feminismos",
|
|
"Villa Paloma": "OVT",
|
|
"Planta 2 (Escalera)": "Enrefugio"
|
|
},
|
|
{
|
|
"Planta Baja": "Kamanchaka",
|
|
"Villa Paloma": "F.F.F",
|
|
"Planta 2 (Escalera)": "Yoga"
|
|
},
|
|
{
|
|
"Planta Baja": "Warawas + F.L.O.R",
|
|
"Villa Paloma": "Circo",
|
|
"Planta 2 (Escalera)": "Asamblea"
|
|
},
|
|
{
|
|
"Planta Baja": "Autodefensa",
|
|
"Villa Paloma": "Hacklab",
|
|
"Planta 2 (Escalera)": "Fermentos + hongos"
|
|
}
|
|
]
|
|
|
|
# --- PON AQUÍ EL CHAT_ID DE TU GRUPO ---
|
|
GROUP_CHAT_ID = -1002113687479 # <--- Reemplaza por el ID de tu grupo
|
|
|
|
# Mensaje de bienvenida con emojis
|
|
WELCOME_MESSAGE = (
|
|
"👋 *Bienvenidos a La Enredadera*\n\n"
|
|
"🏠 Un centro social ubicado en *Tetuán, Madrid* 📍, en la Calle de la Coruña 5.\n\n"
|
|
"🤝 En La Enredadera trabajamos por la igualdad, el respeto y la solidaridad, "
|
|
"rechazando categóricamente la homofobia, la transfobia, la xenofobia y cualquier forma de discriminación. \n\n"
|
|
"💬 Aquí fomentamos la participación, el diálogo y la defensa de los derechos de todas las personas.\n\n"
|
|
"👉 *Selecciona una opción para saber más:*"
|
|
)
|
|
|
|
# Textos de respuesta para cada opción, con emojis añadidos
|
|
NUEVOS_COLECTIVOS = (
|
|
"📢 *NUEVOS COLECTIVOS*\n\n"
|
|
"📝 *Presentación:*\n"
|
|
"• Cómo se llama el proyecto/colectivo\n"
|
|
"• De qué tipo es (colectivo/asociación, etc.)\n"
|
|
"• Cuántas personas sois. (Abierto/Cerrado)\n"
|
|
"• Desde cuándo funcionáis\n\n"
|
|
"💡 *Valores y política:*\n"
|
|
"• Cuáles son los objetivos\n"
|
|
"• Valores y principios\n"
|
|
"• Cómo funcionáis internamente (asambleas, consensos, votación, líder…)\n"
|
|
"• ¿Estáis en conexión con alguna red/iniciativa/colectivo?\n\n"
|
|
"🚚 *Logística:*\n"
|
|
"• Actividad que queréis realizar\n"
|
|
"• Qué necesidades tenéis (material, espacio, etc.)\n"
|
|
"• Cuándo lo queréis realizar y cada cuánto\n\n"
|
|
"🤝 *Compromisos con la Enre:*\n"
|
|
"• Asistencia obligatoria a la asamblea de la Enre (todos los lunes a las 20:00)\n"
|
|
"• Limpieza del espacio una vez al mes 🧹\n"
|
|
"• Bienvenida a externos (todos los lunes de 19:00-20:00)\n"
|
|
"• Organización de una Kafeta Enre cada 3-4 meses\n"
|
|
"• Apoyo a otros colectivos\n"
|
|
"• Participación en el grupo de Telegram “Enredando colectives”\n"
|
|
"• Gestión de llaves de la Enre para necesidades puntuales 🔑\n\n"
|
|
"🚫 *Líneas rojas en colectivos/eventos:*\n"
|
|
"• Masculinidad exclusiva\n"
|
|
"• No toleramos actitudes violentas, discriminatorias o de exclusión (homofobia, transfobia, xenofobia, etc.)"
|
|
)
|
|
|
|
EVENTOS_EXTERNOS = (
|
|
"🎉 *EVENTOS EXTERNOS*\n\n"
|
|
"👥 *Información del colectivo:*\n"
|
|
"• Cómo se llama el colectivo\n"
|
|
"• Líneas políticas\n"
|
|
"• Organización interna\n"
|
|
"• Qué aportan al espacio\n\n"
|
|
"📅 *Información del evento:*\n"
|
|
"• Público objetivo, aforo y si es abierto\n"
|
|
"• Espacio y enseres necesarios\n"
|
|
"• Evitar solapes de eventos/actividades\n"
|
|
"• Horario (máximo hasta las 23:30)\n"
|
|
"• Bebida y comida a cargo del evento (si es necesario, la Enre gestiona la bebida: pedidos@distribucioneslavapies.es)\n"
|
|
"• Equipo de Scum: Contactar con Julita y tarifa de 20 € (o lo que se acuerde)\n\n"
|
|
"⚠️ *Líneas rojas en colectivos/eventos:*\n"
|
|
"• No a actitudes excluyentes o discriminatorias\n\n"
|
|
"🤝 *Compromisos con la Enre:*\n"
|
|
"• Asistencia a la asamblea previa al evento (entre las 19:00 y 20:00)\n"
|
|
"• Turno de puerta y barra durante el evento\n"
|
|
"• Limpieza posterior del espacio 🧼\n"
|
|
"• Aporte del 10% de lo recaudado para la Enre\n\n"
|
|
"🎶 *Eventos con música:*\n"
|
|
"• Música se para a las 23:00/23:30; se debe desalojar el espacio salvo para el personal de limpieza\n"
|
|
"• Conciertos/pinchadas en la planta baja (NO en Villa Paloma)\n"
|
|
"• Preferencia por conciertos por la tarde para evitar molestias nocturnas\n"
|
|
"• Respeto por los fines de semana\n\n"
|
|
"📞 *Desde la asamblea:*\n"
|
|
"• Contacto Enre: Persona asignada para confirmar y coordinar el evento\n"
|
|
"• Madrina: Acompaña y coordina el evento, se asigna dos semanas antes\n"
|
|
"• Protocolo policial a entregar y mediación en el evento\n"
|
|
"• Valoración posterior del evento"
|
|
)
|
|
|
|
KAFETAS_ENRE = (
|
|
"☕ *KAFETAS ENRE*\n\n"
|
|
"🎯 *Objetivo:*\n"
|
|
"• Punto de encuentro entre colectivos\n"
|
|
"• Recaudar fondos para el espacio\n\n"
|
|
"🔄 *Funcionamiento:*\n"
|
|
"• Bebida a cargo de la Enre, verificación de cantidad por el colectivo\n"
|
|
"• Recaudación destinada a la Enre\n"
|
|
"• Organización conjunta entre colectivos\n"
|
|
"• Posible presencia de comida, según recursos disponibles\n"
|
|
"• Frecuencia: Dos kafetas al mes\n\n"
|
|
"🛠 *Tareas durante la kafeta:*\n"
|
|
"• Turno de puerta\n"
|
|
"• Turno de barra\n"
|
|
"• Limpieza posterior del espacio 🧽"
|
|
)
|
|
|
|
# CUADRANTE LIMPIEZA FORMATO LISTA
|
|
CUADRANTE_LIMPIEZA = (
|
|
"*🧹 Cuadrante de Limpieza Semanal*\n\n"
|
|
"🏠 *Planta Baja*\n"
|
|
" • Semana 1: Feminismos\n"
|
|
" • Semana 2: Kamanchaka\n"
|
|
" • Semana 3: Warawas + F.L.O.R\n"
|
|
" • Semana 4: Autodefensa\n\n"
|
|
"🏛️ *Villa Paloma*\n"
|
|
" • Semana 1: OVT\n"
|
|
" • Semana 2: F.F.F\n"
|
|
" • Semana 3: Circo\n"
|
|
" • Semana 4: Hacklab\n\n"
|
|
"⬆️ *Planta 2 (Escalera)*\n"
|
|
" • Semana 1: Enrefugio\n"
|
|
" • Semana 2: Yoga\n"
|
|
" • Semana 3: Asamblea\n"
|
|
" • Semana 4: Fermentos + hongos\n"
|
|
)
|
|
|
|
def get_main_menu():
|
|
"""Devuelve el teclado principal con las 4 opciones."""
|
|
keyboard = [
|
|
[InlineKeyboardButton("NUEVOS COLECTIVOS 📢", callback_data='nuevos_colectivos')],
|
|
[InlineKeyboardButton("EVENTOS EXTERNOS 🎉", callback_data='eventos_externos')],
|
|
[InlineKeyboardButton("KAFETAS ENRE ☕", callback_data='kafetas_enre')],
|
|
[InlineKeyboardButton("CUADRANTE LIMPIEZA 🧹", callback_data='cuadrante_limpieza')]
|
|
]
|
|
return InlineKeyboardMarkup(keyboard)
|
|
|
|
def get_back_menu():
|
|
"""Devuelve un teclado con el botón para volver al menú principal."""
|
|
keyboard = [
|
|
[InlineKeyboardButton("🔙 Volver al menú", callback_data='volver')]
|
|
]
|
|
return InlineKeyboardMarkup(keyboard)
|
|
|
|
async def info(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
|
# Comando /info que muestra la bienvenida y el menú principal
|
|
if update.message:
|
|
await update.message.reply_text(
|
|
WELCOME_MESSAGE,
|
|
parse_mode='Markdown',
|
|
reply_markup=get_main_menu()
|
|
)
|
|
|
|
async def button(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
|
query = update.callback_query
|
|
await query.answer()
|
|
|
|
# Si el usuario pulsa "volver", se muestra el menú principal nuevamente
|
|
if query.data == 'volver':
|
|
await query.edit_message_text(
|
|
text=WELCOME_MESSAGE,
|
|
parse_mode='Markdown',
|
|
reply_markup=get_main_menu()
|
|
)
|
|
return
|
|
|
|
# Selecciona el contenido según la opción elegida
|
|
if query.data == 'nuevos_colectivos':
|
|
texto = NUEVOS_COLECTIVOS
|
|
elif query.data == 'eventos_externos':
|
|
texto = EVENTOS_EXTERNOS
|
|
elif query.data == 'kafetas_enre':
|
|
texto = KAFETAS_ENRE
|
|
elif query.data == 'cuadrante_limpieza':
|
|
texto = CUADRANTE_LIMPIEZA
|
|
else:
|
|
texto = "❓ Opción no reconocida."
|
|
|
|
# Muestra el contenido seleccionado junto con el botón para volver
|
|
await query.edit_message_text(
|
|
text=texto,
|
|
parse_mode='Markdown',
|
|
reply_markup=get_back_menu()
|
|
)
|
|
|
|
# ----- AVISO AUTOMÁTICO DE LIMPIEZA -----
|
|
|
|
async def aviso_cuadrante(bot):
|
|
# Calcula la semana del mes (0-3)
|
|
today = datetime.now(pytz.timezone('Europe/Madrid'))
|
|
week_num = ((today.day - 1) // 7) % 4
|
|
cuadrante = CUADRANTE[week_num]
|
|
msg = (
|
|
f"🧹 *Aviso semanal de limpieza*\n\n"
|
|
f"🏠 *Planta Baja*: {cuadrante['Planta Baja']}\n"
|
|
f"🏛️ *Villa Paloma*: {cuadrante['Villa Paloma']}\n"
|
|
f"⬆️ *Planta 2 (Escalera)*: {cuadrante['Planta 2 (Escalera)']}\n\n"
|
|
f"¡Recordad pasaros a limpiar esta semana! 😉"
|
|
)
|
|
await bot.send_message(chat_id=GROUP_CHAT_ID, text=msg, parse_mode="Markdown")
|
|
|
|
# ----- FIN AVISO AUTOMÁTICO -----
|
|
|
|
# ----- PRINT CHAT_ID SOLO EN LOG -----
|
|
async def print_chat_id(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
|
chat = update.effective_chat
|
|
logger.info(f"El chat_id de este chat es: {chat.id}")
|
|
await update.message.reply_text("¡ID registrado en el log del servidor! 👍")
|
|
|
|
# --------------------------------------
|
|
|
|
async def main() -> None:
|
|
# Cargar el token desde config.json
|
|
with open('config.json', 'r') as config_file:
|
|
config = json.load(config_file)
|
|
token = config.get("TOKEN")
|
|
if not token:
|
|
logger.error("El token no se ha encontrado en el archivo config.json")
|
|
return
|
|
|
|
application = Application.builder().token(token).build()
|
|
|
|
# Se registra el comando /info en lugar de /start
|
|
application.add_handler(CommandHandler('info', info))
|
|
application.add_handler(CommandHandler('id', print_chat_id))
|
|
application.add_handler(CallbackQueryHandler(button))
|
|
|
|
# ------ SCHEDULER ------
|
|
scheduler = AsyncIOScheduler(timezone='Europe/Madrid')
|
|
# Lunes a las 13:12
|
|
scheduler.add_job(
|
|
aviso_cuadrante,
|
|
trigger=CronTrigger(day_of_week='mon', hour=13, minute=12),
|
|
args=[application.bot]
|
|
)
|
|
scheduler.start()
|
|
# -----------------------
|
|
|
|
await application.run_polling()
|
|
|
|
if __name__ == '__main__':
|
|
asyncio.run(main())
|
|
|