Skip to content

Commit 8d92857

Browse files
committed
Agrego logica para la feature de anuncios de proyectos.
1 parent aea37c8 commit 8d92857

File tree

1 file changed

+239
-28
lines changed

1 file changed

+239
-28
lines changed
Lines changed: 239 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,257 @@
1-
from telegram.ext import CommandHandler
1+
from telegram import Update, Bot
2+
from telegram.ext import ConversationHandler, CommandHandler, MessageHandler, filters, CallbackContext
23
from pycamp_bot.models import Project, Pycampista, Vote
34
from pycamp_bot.commands.auth import get_admins_username
5+
from pycamp_bot.logger import logger
6+
from pycamp_bot.commands.manage_pycamp import active_needed
47

8+
PROYECTO, LUGAR, MENSAJE = ["proyecto", "lugar", "mensaje"]
59

6-
async def announce(update, context):
7-
username = update.message.from_user.username
8-
admins = get_admins_username()
9-
project_name = update.message.text.split()[1:]
10+
ERROR_MESSAGES = {
11+
"format_error": "Error de formato, recuerde que el formato debe ser el siguiente:\n/anunciar tu_proyecto\nPor favor comienza de nuevo.",
12+
"not_admin": "No tenes proyectos para anunciar y no eres admin.",
13+
"not_found": "No se encontro el proyecto *{project_name}*. Intenta de nuevo por favor.",
14+
"no_admin": "No puedes anunciar proyectos si no eres el owner.\nPor favor contacta un admin"
15+
}
1016

11-
project_name = " ".join(project_name)
12-
project = Project.select().where(Project.name == project_name)
1317

14-
if len(project) <= 0:
15-
await context.bot.send_message(
16-
chat_id=update.message.chat_id,
17-
text=f"El proyecto '{project_name}' no existe o esta mal escroto.\n"
18-
"El formato de este comando es:\n"
19-
"/anunciar NOMBRE_DEL_PROYECTO"
20-
)
21-
return
18+
class AnnouncementState:
19+
def __init__(self):
20+
self.username = None
21+
self.p_name = ''
22+
self.current_project = False
23+
self.projects = []
24+
self.owner = ''
25+
self.lugar = ''
26+
self.mensaje = ''
2227

23-
if not (project.get().owner.username == username or username in admins):
24-
await context.bot.send_message(
25-
chat_id=update.message.chat_id,
26-
text="No sos ni admin ni el owner de este proyecto, Careta."
27-
)
28-
return
28+
state = AnnouncementState()
29+
30+
async def user_is_admin(pycampist: str) -> bool:
31+
return pycampist in get_admins_username()
32+
33+
async def should_be_able_to_announce(pycampista: str, proyect: Project) -> bool:
34+
return pycampista == proyect.owner.username or await user_is_admin(pycampista)
35+
36+
37+
@active_needed
38+
async def announce(update: Update, context: CallbackContext) -> str:
39+
logger.info("Announcement project process started")
40+
parameters: list[str] = update.message.text.split()
41+
42+
if len(parameters) > 2:
43+
await handle_error(context, update.message.chat_id, "format_error")
44+
logger.warning("Error de formato en la solicitud. Too many parameters")
45+
return ConversationHandler.END
46+
state.username = update.message.from_user.username
47+
state.projects = Project.select().join(Pycampista).where(Pycampista.username == state.username)
48+
49+
if len(state.projects) == 0:
50+
if not await user_is_admin(state.username):
51+
await context.bot.send_message(
52+
chat_id=update.message.chat_id,
53+
text=ERROR_MESSAGES["no_admin"],
54+
)
55+
logger.warn(f"Pycampista {state.username} no contiene proyectos creados.")
56+
return ConversationHandler.END
57+
else:
58+
state.projects = Project.select()
59+
return await get_project(update, context)
60+
61+
if len(parameters) == 1:
62+
project_list: str = ""
63+
if len(state.projects) == 0:
64+
await context.bot.send_message(
65+
chat_id=update.message.chat_id,
66+
text="Ingresá el Nombre del Proyecto a anunciar."
67+
)
68+
else:
69+
project_list = "\n".join(p.name.capitalize() for p in state.projects)
70+
await context.bot.send_message(
71+
chat_id=update.message.chat_id,
72+
text=f"""Ingresá el Nombre del Proyecto a anunciar.\n\nTienes los siguientes proyectos:\n{project_list}""",
73+
)
74+
75+
if len(parameters) == 2:
76+
print('-Handle correct commands-')
77+
state.p_name = update.message.text.split()[1].lower()
78+
_projects = Project.select().join(Pycampista).where(Project.name == state.p_name)
79+
80+
if len(_projects) == 0:
81+
await context.bot.send_message(
82+
chat_id=update.message.chat_id,
83+
text=f"No existe el proyecto: *{state.p_name}*.",
84+
parse_mode='Markdown'
85+
)
86+
return ConversationHandler.END
87+
elif not await should_be_able_to_announce(state.username, _projects[0]):
88+
await context.bot.send_message(
89+
chat_id=update.message.chat_id,
90+
text=ERROR_MESSAGES["no_admin"],
91+
)
92+
logger.warn(f"Solicitud de anuncio no autorizada.")
93+
return ConversationHandler.END
94+
else:
95+
await context.bot.send_message(
96+
chat_id=update.message.chat_id,
97+
text=f"Anunciando el proyecto: *{_projects[0].name.capitalize()}* !!!",
98+
parse_mode='Markdown'
99+
)
100+
state.owner = _projects[0].owner.username
101+
state.current_project = _projects[0]
102+
return await get_project(update, context)
103+
return PROYECTO
104+
105+
106+
async def get_project(update: Update, context: CallbackContext) -> str:
107+
'''Dialog to set project to announce'''
108+
logger.info("Getting project")
109+
parameters_list: list[str] = update.message.text.split()
110+
111+
if len(parameters_list) > 2:
112+
await handle_error(context, update.message.chat_id, "format_error")
113+
return ConversationHandler.END
114+
115+
if "/anunciar" in parameters_list:
116+
if len(parameters_list) == 2:
117+
state.current_project = Project.select().join(Pycampista).where(Project.name == parameters_list[1].lower())
118+
if not await should_be_able_to_announce(update.message.from_user.username, state.current_project[0]):
119+
await handle_error(context, update.message.chat_id, "format_error", state.current_project)
120+
logger.warning(f"Project {parameters_list[1]} not found!")
121+
return PROYECTO
122+
else:
123+
await context.bot.send_message(
124+
chat_id=update.message.chat_id,
125+
text="Ingrese lugar donde comienza el proyecto."
126+
)
127+
state.p_name = parameters_list[1].lower()
128+
state.current_project = state.current_project[0]
129+
if len(parameters_list) == 1:
130+
await context.bot.send_message(
131+
chat_id=update.message.chat_id,
132+
text="Ingrese el nombre del proyecto."
133+
)
134+
return PROYECTO
135+
136+
elif len(parameters_list) == 2:
137+
await handle_error(context, update.message.chat_id, "format_error")
138+
logger.warning("Error de formato en la solicitud. Too many parameters")
139+
return PROYECTO
29140

30-
pycampistas = Vote.select().join(Pycampista).where((Vote.project == project) & (Vote.interest))
141+
else:
142+
c_proyect = Project.select().where(Project.name == parameters_list[0].lower()).first()
143+
print('c_proyect: ', c_proyect)
144+
if c_proyect:
145+
if await should_be_able_to_announce(update.message.from_user.username, c_proyect):
146+
state.current_project = c_proyect
147+
state.p_name = c_proyect.name
148+
state.owner = c_proyect.owner.username
149+
await context.bot.send_message(
150+
chat_id=update.message.chat_id,
151+
text="Ingrese lugar donde comienza el proyecto."
152+
)
153+
else:
154+
logger.warning("Solicitud de anuncio no autorizada.")
155+
await handle_error(
156+
context,
157+
update.message.chat_id,
158+
"no_admin"
159+
)
160+
return ConversationHandler.END
161+
else:
162+
logger.warning("Solicitud de anuncio no autorizada.")
163+
await handle_error(
164+
context,
165+
update.message.chat_id,
166+
"not_found",
167+
project_name=parameters_list[0]
168+
)
169+
logger.warning("Error de formato en la solicitud. No se encontró el proyecto.")
170+
return PROYECTO
171+
return LUGAR
31172

32-
chat_id_list = [user.pycampista.chat_id for user in pycampistas]
33173

174+
async def meeting_place(update: Update, context: CallbackContext) -> str:
175+
'''Dialog to set the place of the meeting'''
176+
logger.info("Setting place")
177+
state.lugar = update.message.text.capitalize()
178+
await context.bot.send_message(
179+
chat_id=update.message.chat_id,
180+
text="Escribe un mensaje a los pycampistas suscriptos ..."
181+
)
182+
return MENSAJE
183+
184+
185+
async def message_project(update: Update, context: CallbackContext) -> str:
186+
'''Dialog to set project topic'''
187+
state.mensaje = update.message.text.capitalize()
188+
pycampistas: list[Vote] = Vote.select().join(
189+
Pycampista).where(
190+
(Vote.project == Project.select().where(
191+
Project.name == state.current_project.name)) & (Vote.interest))
192+
chat_id_list: list[int] = [user.pycampista.chat_id for user in pycampistas]
34193
for chat_id in chat_id_list:
35-
await context.bot.send_message(
36-
chat_id=chat_id,
37-
text=f"Esta por empezar {project_name} a cargo de @{project.get().owner.username}."
38-
)
194+
try:
195+
await context.bot.send_message(
196+
chat_id=chat_id,
197+
text=f'''Está por empezar el proyecto *"{(state.p_name).capitalize()}"* a cargo de *@{state.owner}*.\n*¿Dónde?* 👉🏼 {state.lugar}''',
198+
parse_mode='Markdown'
199+
)
200+
if update.message.from_user.username == state.owner:
201+
await context.bot.send_message(
202+
chat_id=chat_id,
203+
text=f'*Project Owner says:* **{state.mensaje}**',
204+
parse_mode='Markdown'
205+
)
206+
else:
207+
await context.bot.send_message(
208+
chat_id=chat_id,
209+
text=f'Admin *@{update.message.from_user.username}* says: **{state.mensaje}**',
210+
parse_mode='Markdown'
211+
)
212+
except Exception as e:
213+
logger.error(f"Error al enviar el mensaje: {e}")
39214
await context.bot.send_message(
40215
chat_id=update.message.chat_id,
41216
text="Anunciado!"
42217
)
218+
logger.info('Project announced!')
219+
return ConversationHandler.END
220+
221+
222+
async def cancel(update: Update, context: CallbackContext) -> str:
223+
'''Cancel the project announcement'''
224+
await context.bot.send_message(
225+
chat_id=update.message.chat_id,
226+
text="Has cancelado el anuncio del proyecto")
227+
logger.warning("Announcement canceled")
228+
return ConversationHandler.END
229+
230+
231+
async def handle_error(context: CallbackContext, chat_id: int, error_key: str, **kwargs: list) -> None:
232+
error_message = ERROR_MESSAGES[error_key].format(**kwargs)
233+
print('error_message: ', error_message)
234+
'''Handle error messages'''
235+
try:
236+
await context.bot.send_message(
237+
chat_id=chat_id,
238+
text=error_message,
239+
#parse_mode='Markdown'
240+
)
241+
except Exception as e:
242+
logger.error(f"Error al enviar el mensaje: {e}")
243+
43244

245+
start_project_handler = ConversationHandler(
246+
entry_points=[CommandHandler('anunciar', announce)],
247+
states={
248+
PROYECTO: [MessageHandler(filters.TEXT & ~filters.COMMAND, get_project)],
249+
LUGAR: [MessageHandler(filters.TEXT & ~filters.COMMAND, meeting_place)],
250+
MENSAJE: [MessageHandler(filters.TEXT & ~filters.COMMAND, message_project)]
251+
},
252+
fallbacks=[CommandHandler('cancel', cancel)]
253+
)
44254

45255
def set_handlers(application):
46-
application.add_handler(CommandHandler('anunciar', announce))
256+
'''Add handlers to the application'''
257+
application.add_handler(start_project_handler)

0 commit comments

Comments
 (0)