Skip to content

Commit 535d978

Browse files
committed
feat(admin): add /movergrupo command to recategorize groups
- Created /movergrupo <name> command for admins - Displays an inline keyboard to choose the new Listable category - Added 'MoverGrupo' callback logic to update the group's type directly in DB
1 parent f767441 commit 535d978

3 files changed

Lines changed: 77 additions & 2 deletions

File tree

bot_logic.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from utils.orga2Utils import noitip, asm
22
from handlers.basic import start, help_command, estasvivo, colaborar
33
from handlers.info import campusvivo, flan, flanviejo, aulas, cuandovence, listarlabos
4-
from handlers.admin import checodepers, checodeppers, sugerirNoticia, get_logs, joder
4+
from handlers.admin import checodepers, checodeppers, sugerirNoticia, get_logs, joder, movergrupo
55
from handlers.groups import listar, listaroptativa, listareci, listarotro, cubawiki, agregargrupo, agregaroptativa, agregarotros, agregareci, sugerirgrupo, sugeriroptativa, sugerireci, sugerirotro, actualizar_grupos, _update_groups
66
from handlers.callbacks import button
77
from handlers.crons import felizdia, actualizarRiver
@@ -11,6 +11,10 @@
1111
'handler': joder,
1212
'description': '(Admin) Enviar un mensaje al grupo general'
1313
},
14+
'movergrupo': {
15+
'handler': movergrupo,
16+
'description': '(Admin) Cambiar la categoría de un grupo'
17+
},
1418
'logs': {
1519
'handler': get_logs,
1620
'description': '(Admin) Revisa los últimos 10 errores en GCP.'

handlers/admin.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,55 @@ async def joder(update: Update, context: ContextTypes.DEFAULT_TYPE):
2929
logger.error(f"Failed to send joder message: {e}")
3030
await update.message.reply_text(f"Error al enviar el mensaje: {e}")
3131

32+
async def movergrupo(update: Update, context: ContextTypes.DEFAULT_TYPE):
33+
user_id = update.effective_user.id
34+
if user_id not in admin_ids and str(user_id) not in admin_ids:
35+
logger.warning(f"Unauthorized user {user_id} tried to access /movergrupo")
36+
return
37+
38+
if not context.args:
39+
await update.message.reply_text("Uso: /movergrupo <nombre exacto del grupo>")
40+
return
41+
42+
name = " ".join(context.args)
43+
with get_session() as session:
44+
from models import Listable
45+
groups = session.query(Listable).filter(Listable.name.ilike(f"%{name}%")).all()
46+
47+
if not groups:
48+
await update.message.reply_text("No se encontró ningún grupo con ese nombre.")
49+
return
50+
51+
if len(groups) > 1:
52+
names = "\n".join([f"- {g.name} ({g.type})" for g in groups])
53+
await update.message.reply_text(f"Se encontraron múltiples grupos:\n{names}\n\nPor favor, sé más específico.")
54+
return
55+
56+
group = groups[0]
57+
58+
keyboard = [
59+
[
60+
InlineKeyboardButton("Grupo (Oblig.)", callback_data=f"MoverGrupo|{group.id}|Grupo"),
61+
InlineKeyboardButton("GrupoOptativa", callback_data=f"MoverGrupo|{group.id}|GrupoOptativa"),
62+
InlineKeyboardButton("ECI", callback_data=f"MoverGrupo|{group.id}|ECI")
63+
],
64+
[
65+
InlineKeyboardButton("Otro", callback_data=f"MoverGrupo|{group.id}|Otro"),
66+
InlineKeyboardButton("GrupoOtros", callback_data=f"MoverGrupo|{group.id}|GrupoOtros"),
67+
InlineKeyboardButton("Obligatoria (viejo)", callback_data=f"MoverGrupo|{group.id}|Obligatoria"),
68+
],
69+
[
70+
InlineKeyboardButton("Optativa (viejo)", callback_data=f"MoverGrupo|{group.id}|Optativa"),
71+
InlineKeyboardButton("Cancelar", callback_data=f"MoverGrupo|{group.id}|Cancelar")
72+
]
73+
]
74+
reply_markup = InlineKeyboardMarkup(keyboard)
75+
await update.message.reply_text(
76+
f"Seleccioná la nueva categoría para el grupo:\n\n*Nombre:* {group.name}\n*Categoría Actual:* {group.type}",
77+
reply_markup=reply_markup,
78+
parse_mode=ParseMode.MARKDOWN
79+
)
80+
3281
async def checodepers(update: Update, context: ContextTypes.DEFAULT_TYPE):
3382
if not context.args:
3483
ejemplo = """ Ejemplo de uso:

handlers/callbacks.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ async def button(update: Update, context: ContextTypes.DEFAULT_TYPE):
99
query = update.callback_query
1010
await query.answer()
1111
message = query.message
12-
buttonType, id_val, action = query.data.split("|")
12+
13+
# Parse button data safely
14+
data_parts = query.data.split("|")
15+
buttonType = data_parts[0]
16+
id_val = data_parts[1] if len(data_parts) > 1 else None
17+
action = data_parts[2] if len(data_parts) > 2 else None
1318

1419
with get_session() as session:
1520
if buttonType == "Listable":
@@ -24,6 +29,23 @@ async def button(update: Update, context: ContextTypes.DEFAULT_TYPE):
2429
await query.edit_message_text(text=message.text + action_text)
2530
else:
2631
await query.edit_message_text(text=message.text + "\n[Botón huérfano: El grupo ya no existe en la base de datos]")
32+
33+
elif buttonType == "MoverGrupo":
34+
if action == "Cancelar":
35+
await query.edit_message_text(text=f"❌ Operación cancelada para el grupo ID {id_val}.")
36+
return
37+
38+
group = session.query(Listable).filter_by(id=int(id_val)).first()
39+
if group:
40+
old_type = group.type
41+
new_type = action
42+
# Update the polymorphic identity directly via the type column
43+
group.type = new_type
44+
# Depending on SQLAlchemy, modifying the polymorphic column directly might require
45+
# a raw SQL update or session.flush() to be safe. We'll rely on SQLAlchemy's update.
46+
await query.edit_message_text(text=f"✅ Grupo *{group.name}* movido exitosamente:\nDe `{old_type}` ➡️ a `{new_type}`", parse_mode=ParseMode.MARKDOWN)
47+
else:
48+
await query.edit_message_text(text=message.text + "\n[Botón huérfano: El grupo ya no existe]")
2749

2850
elif buttonType == "Noticia":
2951
noticia = session.query(Noticia).filter_by(id=int(id_val)).first()

0 commit comments

Comments
 (0)