diff --git a/main.py b/main.py index 6b260b3..20fbdd1 100644 --- a/main.py +++ b/main.py @@ -7,12 +7,15 @@ CallbackQueryHandler, ConversationHandler, ContextTypes, ) +from telegram_bot.actions.confirmation import process_confirmation +from telegram_bot.actions.start_date import process_meeting_start_date +from telegram_bot.actions.start_time import process_meeting_start_time from telegram_bot.constants import ENTER_START_TIME, ENTER_MEETING_TYPE, ENTER_START_DATE, MEETING_NAME, \ - MEETING_DESCRIPTION, ENTER_NUM_PLAYERS + MEETING_DESCRIPTION, ENTER_NUM_PLAYERS, ENTER_CONFIRMATION from utils.logger import logger from telegram_bot.quedada_entry import quedada from telegram_bot.message_handler import first_answer, second_answer, process_num_players -from telegram_bot.actions.action_handler import action_handler +from telegram_bot.actions.meeting_type import process_meeting_type from telegram_bot.actions.attendance import attendance_button_handler import tracemalloc from dotenv import load_dotenv @@ -20,10 +23,6 @@ tracemalloc.start() - - - - def main(): logger.info("Starting the bot application") @@ -42,9 +41,10 @@ def main(): MEETING_NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, first_answer)], MEETING_DESCRIPTION: [MessageHandler(filters.TEXT & ~filters.COMMAND, second_answer)], ENTER_NUM_PLAYERS: [CallbackQueryHandler(process_num_players)], - ENTER_START_TIME: [CallbackQueryHandler(action_handler)], - ENTER_START_DATE: [CallbackQueryHandler(action_handler)], - ENTER_MEETING_TYPE: [CallbackQueryHandler(action_handler)], + ENTER_START_DATE: [CallbackQueryHandler(process_meeting_start_date)], + ENTER_START_TIME: [CallbackQueryHandler(process_meeting_start_time)], + ENTER_MEETING_TYPE: [CallbackQueryHandler(process_meeting_type)], + ENTER_CONFIRMATION: [CallbackQueryHandler(process_confirmation)], }, fallbacks=[CommandHandler("cancel", cancel)], ) diff --git a/requirements.txt b/requirements.txt index e5998cf..b275606 100644 Binary files a/requirements.txt and b/requirements.txt differ diff --git a/telegram_bot/actions/action_handler.py b/telegram_bot/actions/action_handler.py deleted file mode 100644 index ed9e776..0000000 --- a/telegram_bot/actions/action_handler.py +++ /dev/null @@ -1,48 +0,0 @@ -from telegram import Update -from telegram.ext import ContextTypes, ConversationHandler -from ..constants import ENTER_START_DATE, ENTER_START_TIME, ENTER_MEETING_TYPE -from ..keyboards.calendar_keyboard import create_calendar_keyboard -from .start_date import process_meeting_start_date -from .start_time import process_meeting_start_time -from .meeting_type import process_meeting_type - - - -async def action_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> ConversationHandler: - query = update.callback_query - action = query.data - if str(query.from_user.id) != str(context.chat_data["current"]["creator_id"]): - return - - if any(x in action for x in ("PREV-MONTH", "NEXT-MONTH")): - arguments = action.split(';') - year = arguments[2] - month = arguments[3] - date_type = "start_date" - message="Indique la fecha de inicio" - reply_markup = create_calendar_keyboard(date_type, year, month) - result = ENTER_START_DATE - else: - if "start_date" in action: - message, reply_markup = process_meeting_start_date(action, context) - result = ENTER_START_TIME - elif "start_time" in action: - message, reply_markup = process_meeting_start_time(action, context) - result = ENTER_MEETING_TYPE - elif "Abierta" in action or "Cerrada" in action: - message, reply_markup = process_meeting_type(action,context) - event_message_id = context.chat_data["current_event_id"] - context.chat_data[event_message_id] = context.chat_data["current"] - del context.chat_data["current_event_id"] - del context.chat_data["current"] - result = ConversationHandler.END - - await query.edit_message_text(message, reply_markup=reply_markup, parse_mode='Markdown') - return result - - - - - - - diff --git a/telegram_bot/actions/attendance.py b/telegram_bot/actions/attendance.py index b155d9e..2fa3adb 100644 --- a/telegram_bot/actions/attendance.py +++ b/telegram_bot/actions/attendance.py @@ -15,53 +15,43 @@ async def attendance_button_handler(update: Update, context: ContextTypes.DEFAUL alert, response_msg = handle_meeting_action(event_id, action, username,context) await query.answer(response_msg, show_alert=alert) logger.info(response_msg) + message = build_final_message(context.chat_data[event_id]) + message = "¿Desea confirmar creación de la partida?\n" + message reply_markup = build_attendance_keyboard(event_id) - with suppress(telegram.error.BadRequest): await query.edit_message_text(message, reply_markup=reply_markup, parse_mode='Markdown') def handle_meeting_action(event_id, action, username, context): alert = False response_msg = '' + # We handle the event of user joining, leaving, adding or removing a guest - found = any(username in user for user in context.chat_data[event_id]["players"]) - #We check if the user is already present on the list - if found: - #We get the index of the person already present on the list - if action == "join": + if is_fullgame(context, event_id) and action in ('join', '+1'): + response_msg = "Partida sin sitios disponibles" + elif action == "join": + if username in context.chat_data[event_id]["players"]: response_msg = "Usuario ya agregado en la lista" - elif action == "+1": - if is_fullgame(context, event_id): - response_msg = "Partida sin sitios disponibles" - else: - #We add +1 to the guest field - context.chat_data[event_id]["players"][username] += 1 - response_msg = f"{username} +1!" - elif action == "leave": - #We remove the user from the list + else: + context.chat_data[event_id]["players"][username] = 0 + response_msg = f"{username} joined!" + elif action == "leave": + if username in context.chat_data[event_id]["players"]: del context.chat_data[event_id]["players"][username] response_msg = "Usuario quitado de la quedada" - elif action == "-1": - #We verify if the user has guests - if context.chat_data[event_id]["players"][username] > 0: - context.chat_data[event_id]["players"][username] -= 1 - else: - response_msg = "Sin invitados que quitar" - alert = True - else: - if action == 'join': - if is_fullgame(context, event_id): - response_msg = "Partida sin sitios disponibles" - else: - context.chat_data[event_id]["players"][username] = 0 - response_msg = f"{username} joined!" - elif action == "+1": - if is_fullgame(context, event_id): - response_msg = "Partida sin sitios disponibles" - else: - context.chat_data[event_id]["players"][username] += 0 - response_msg = f"{username} +1!" - elif action == '-1': + elif action == "+1": + if username in context.chat_data[event_id]["players"]: + # We add +1 to the guest field + context.chat_data[event_id]["players"][username] += 1 + else: + context.chat_data[event_id]["players"][username] = 0 + response_msg = f"{username} +1!" + elif action == '-1': + if username not in context.chat_data[event_id]["players"]: response_msg = "El usuario no está en la lista" + elif context.chat_data[event_id]["players"][username] > 0: + context.chat_data[event_id]["players"][username] -= 1 + else: + response_msg = "Sin invitados que quitar" + alert = True return alert, response_msg \ No newline at end of file diff --git a/telegram_bot/actions/confirmation.py b/telegram_bot/actions/confirmation.py new file mode 100644 index 0000000..7be9d7b --- /dev/null +++ b/telegram_bot/actions/confirmation.py @@ -0,0 +1,36 @@ +from telegram import Update +from telegram.ext import ConversationHandler, CallbackContext + +from telegram_bot.final_message_builder import build_final_message +from telegram_bot.keyboards.keyboard_builder import build_attendance_keyboard +from utils.logger import logger +from telegram_bot.apis.gcalendar import create_event + + +async def process_confirmation(update: Update, context: CallbackContext) -> None: + query = update.callback_query + action = query.data + if str(query.from_user.id) != str(context.chat_data["current"]["creator_id"]): + return + + if action == "submit": + event_message_id = context.chat_data["current_event_id"] + + # Persists the collected game info and creates the GCalendar event + context.chat_data[event_message_id] = context.chat_data["current"] + + logger.info("Summary keyboard about to show") + message = build_final_message(context.chat_data["current"]) + reply_markup = build_attendance_keyboard(context.chat_data["current_event_id"]) + await query.edit_message_text(message, reply_markup=reply_markup, parse_mode='Markdown') + + create_event(context.chat_data[event_message_id]) + else: + await query.edit_message_text(f"Creación de partida '{context.chat_data['current']['meeting_name']}' cancelada", parse_mode='Markdown') + + # Cleans the draft game info so that another game could be created + del context.chat_data["current_event_id"] + del context.chat_data["current"] + + result = ConversationHandler.END + return result diff --git a/telegram_bot/actions/meeting_type.py b/telegram_bot/actions/meeting_type.py index b20bc5b..189cbe7 100644 --- a/telegram_bot/actions/meeting_type.py +++ b/telegram_bot/actions/meeting_type.py @@ -1,20 +1,21 @@ -from utils.logger import logger -from ..keyboards.keyboard_builder import build_attendance_keyboard +from ..constants import ENTER_CONFIRMATION +from ..keyboards.confirm_keyboard import build_confirm_keyboard from ..final_message_builder import build_final_message -import re -from datetime import datetime -from telegram.ext import ContextTypes -from telegram import InlineKeyboardMarkup +from telegram.ext import ContextTypes, ConversationHandler +from telegram import Update + + +async def process_meeting_type(update: Update, context: ContextTypes.DEFAULT_TYPE): + query = update.callback_query + action = query.data + if str(query.from_user.id) != str(context.chat_data["current"]["creator_id"]): + return -def process_meeting_type(action: str,context: ContextTypes.DEFAULT_TYPE) -> (str, InlineKeyboardMarkup): - """ - We mark the event as open or closed in the shared dictionary - :param action: - :param context: - :return: - """ context.chat_data["current"]["meeting_type"] = str(action) message = build_final_message(context.chat_data["current"]) - reply_markup = build_attendance_keyboard(context.chat_data["current_event_id"]) - logger.info("Summary keyboard about to show") - return message, reply_markup \ No newline at end of file + reply_markup = build_confirm_keyboard() + + result = ENTER_CONFIRMATION + + await query.edit_message_text(message, reply_markup=reply_markup, parse_mode='Markdown') + return result diff --git a/telegram_bot/actions/start_date.py b/telegram_bot/actions/start_date.py index 648bdfb..a0e3ae8 100644 --- a/telegram_bot/actions/start_date.py +++ b/telegram_bot/actions/start_date.py @@ -1,17 +1,39 @@ from utils.logger import logger +from ..constants import ENTER_START_TIME, ENTER_START_DATE +from ..keyboards.calendar_keyboard import create_calendar_keyboard from ..keyboards.time_keyboard_builder import build_time_keyboard import re from datetime import datetime -from telegram.ext import ContextTypes -from telegram import InlineKeyboardMarkup +from telegram.ext import ContextTypes, ConversationHandler +from telegram import InlineKeyboardMarkup, Update -def process_meeting_start_date(action: str,context: ContextTypes.DEFAULT_TYPE) -> (str, InlineKeyboardMarkup): - # We trim the 'CALENDAR;start_date;' string to insert the date into the context_data dictionary - start_date = re.sub('CALENDAR;start_date;', '', str(action)) - start_date = datetime.strptime(start_date, '%Y;%m;%d').date() - context.chat_data["current"]["start_date"] = start_date - message = "Indique la hora de inicio" - reply_markup = build_time_keyboard('start_time') - log_message = "Start time keyboard about to show" - logger.info(log_message) - return message, reply_markup \ No newline at end of file +async def process_meeting_start_date(update: Update, context: ContextTypes.DEFAULT_TYPE) -> ConversationHandler: + query = update.callback_query + action = query.data + if str(query.from_user.id) != str(context.chat_data["current"]["creator_id"]): + return + + if any(x in action for x in ("PREV-MONTH", "NEXT-MONTH")): + arguments = action.split(';') + year = arguments[2] + month = arguments[3] + date_type = "start_date" + + reply_markup = create_calendar_keyboard(date_type, year, month) + message="Indique la fecha de inicio" + result = ENTER_START_DATE + else: + # We trim the 'CALENDAR;start_date;' string to insert the date into the context_data dictionary + start_date = re.sub('CALENDAR;start_date;', '', str(action)) + start_date = datetime.strptime(start_date, '%Y;%m;%d').date() + context.chat_data["current"]["start_date"] = start_date + + log_message = "Start time keyboard about to show" + logger.info(log_message) + + reply_markup = build_time_keyboard('start_time') + message = "Indique la hora de inicio" + result = ENTER_START_TIME + + await query.edit_message_text(message, reply_markup=reply_markup, parse_mode='Markdown') + return result \ No newline at end of file diff --git a/telegram_bot/actions/start_time.py b/telegram_bot/actions/start_time.py index b8e1a35..1209bb0 100644 --- a/telegram_bot/actions/start_time.py +++ b/telegram_bot/actions/start_time.py @@ -1,16 +1,26 @@ from utils.logger import logger +from ..constants import ENTER_MEETING_TYPE from ..keyboards.status_keyboard import build_meeting_type_keyboard import re from datetime import datetime -from telegram.ext import ContextTypes -from telegram import InlineKeyboardMarkup +from telegram.ext import ContextTypes, ConversationHandler +from telegram import InlineKeyboardMarkup, Update -def process_meeting_start_time(action: str,context: ContextTypes.DEFAULT_TYPE) -> (str, InlineKeyboardMarkup): - message = "Indique si la quedada es abierta o cerrada" +async def process_meeting_start_time(update: Update, context: ContextTypes.DEFAULT_TYPE) -> ConversationHandler: + query = update.callback_query + if str(query.from_user.id) != str(context.chat_data["current"]["creator_id"]): + return + + + action = query.data # We trim the 'Start-' string to insert the hour into the context_data dictionary context.chat_data["current"]["start_time"] = re.sub('start_time-', '', str(action)) # We build the keyboard asking for meeting status - reply_markup = build_meeting_type_keyboard() logger.info("Meeting type keyboad about to show") - return message, reply_markup \ No newline at end of file + + reply_markup = build_meeting_type_keyboard() + message = "Indique si la quedada es abierta o cerrada" + await query.edit_message_text(message, reply_markup=reply_markup, parse_mode='Markdown') + result = ENTER_MEETING_TYPE + return result \ No newline at end of file diff --git a/telegram_bot/apis/__init__.py b/telegram_bot/apis/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/telegram_bot/apis/gcalendar.py b/telegram_bot/apis/gcalendar.py new file mode 100644 index 0000000..830ead9 --- /dev/null +++ b/telegram_bot/apis/gcalendar.py @@ -0,0 +1,44 @@ +from googleapiclient.discovery import build +import pickle +import datetime as dt + +from utils.logger import logger + +service = None + +try: + with open("desktop_token.pkl", "rb") as token: + creds = pickle.load(token) + service = build("calendar", "v3", credentials=creds) +except FileNotFoundError: + logger.info("Could not create GCalendar API service: No token.pkl found") + +def create_event(game_info): + global service + + if service is None: + logger.info('Could not create calendar event due to the lack of a token') + return + + start_time = dt.time.fromisoformat(game_info['start_time']) + start_dt = dt.datetime.combine(game_info['start_date'], start_time) + + end_dt = start_dt + dt.timedelta(minutes=120) + + event = { + 'summary': game_info['meeting_name'], + 'location': 'Asociación Draco Rúa Merced, 59, 15009 A Coruña', + 'description': game_info['meeting_description'], + 'start': { + 'dateTime': start_dt.isoformat(), + 'timeZone': 'Europe/Madrid', + }, + 'end': { + 'dateTime': end_dt.isoformat(), + 'timeZone': 'Europe/Madrid', + }, + } + + calendar_id = "primary" # or your shared calendar's ID + created_event = service.events().insert(calendarId=calendar_id, body=event).execute() + return created_event['htmlLink'] \ No newline at end of file diff --git a/telegram_bot/button_handler.py b/telegram_bot/button_handler.py deleted file mode 100644 index 824236f..0000000 --- a/telegram_bot/button_handler.py +++ /dev/null @@ -1,166 +0,0 @@ -import re -from contextlib import suppress - -import telegram -from telegram import Update -from telegram.ext import ContextTypes, ConversationHandler -from utils.logger import logger -from datetime import datetime - -from .constants import ENTER_START_DATE, ENTER_START_TIME, ENTER_MEETING_TYPE -from .final_message_builder import build_final_message -from .keyboards.keyboard_builder import build_attendance_keyboard -from .keyboards.calendar_keyboard import create_calendar_keyboard -from .keyboards.time_keyboard_builder import build_time_keyboard -from .keyboards.status_keyboard import build_meeting_type_keyboard -from .utils import get_username - - -async def button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE): - if context.chat_data.get("edit_id", None) is None: - event_message_id = "current" - else: - event_message_id = context.chat_data["edit_id"] - query = update.callback_query - action = query.data - if str(query.from_user.id) != str(context.chat_data[event_message_id]["creator_id"]): - return - - if any(x in action for x in ("PREV-MONTH", "NEXT-MONTH")): - arguments = action.split(';') - year = arguments[2] - month = arguments[3] - date_type = "start_date" - message="Indique la fecha de inicio" - reply_markup = create_calendar_keyboard(date_type, year, month) - result = ENTER_START_DATE - else: - if "start_date" in action: - message, reply_markup = process_meeting_start_date(action, context) - result = ENTER_START_TIME - elif "start_time" in action: - message, reply_markup = process_meeting_start_time(action, context) - result = ENTER_MEETING_TYPE - elif "Open" in action or "Closed" in action: - message, reply_markup = process_meeting_type(action,context) - event_message_id = context.chat_data["current_event_id"] - context.chat_data[event_message_id] = context.chat_data["current"] - del context.chat_data["current_event_id"] - del context.chat_data["current"] - result = ConversationHandler.END - - await query.edit_message_text(message, reply_markup=reply_markup, parse_mode='Markdown') - return result - - -def process_meeting_start_date(action,context): - if context.chat_data.get("edit_id", None) is None: - event_message_id = "current" - else: - event_message_id = context.chat_data["edit_id"] - # We trim the 'CALENDAR;start_date;' string to insert the date into the context_data dictionary - start_date = re.sub('CALENDAR;start_date;', '', str(action)) - start_date = datetime.strptime(start_date, '%Y;%m;%d').date() - context.chat_data[event_message_id]["start_date"] = start_date - message = "Indique la hora de inicio" - reply_markup = build_time_keyboard('start_time') - log_message = "Start time keyboard about to show" - logger.info(log_message) - return message, reply_markup - -def process_meeting_start_time(action,context): - if context.chat_data.get("edit_id", None) is None: - event_message_id = "current" - else: - event_message_id = context.chat_data["edit_id"] - message = "Indique si la quedada es abierta o cerrada" - # We trim the 'Start-' string to insert the hour into the context_data dictionary - context.chat_data[event_message_id]["start_time"] = re.sub('start_time-', '', str(action)) - # We build the keyboard asking for meeting status - reply_markup = build_meeting_type_keyboard() - logger.info("Meeting type keyboad about to show") - return message, reply_markup - -def process_meeting_type(action, context): - """ - We mark the event as open or closed in the shared dictionary - :param action: - :param context: - :return: - """ - if context.chat_data.get("edit_id", None) is None: - event_message_id = "current" - else: - event_message_id = context.chat_data["edit_id"] - context.chat_data[event_message_id]["meeting_type"] = str(action) - message = build_final_message(context.chat_data[event_message_id]) - reply_markup = build_attendance_keyboard(context.chat_data["current_event_id"]) - logger.info("Summary keyboard about to show") - return message, reply_markup - -async def attendance_button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE): - query = update.callback_query - username = await get_username(update) - event_id, action = query.data.split(',') - alert, response_msg = handle_meeting_action(event_id, action, username,context) - await query.answer(response_msg, show_alert=alert) - logger.info(response_msg) - message = build_final_message(context.chat_data[event_id]) - reply_markup = build_attendance_keyboard(event_id) - - with suppress(telegram.error.BadRequest): - await query.edit_message_text(message, reply_markup=reply_markup, parse_mode='Markdown') - -def handle_meeting_action(event_id, action, username, context): - alert = False - response_msg = '' - # We handle the event of user joining, leaving, adding or removing a guest - found = any(username in user for user in context.chat_data[event_id]["players"]) - #We check if the user is already present on the list - if found: - #We get the index of the person already present on the list - if action == "join": - response_msg = "Usuario ya agregado en la lista" - elif action == "+1": - if is_fullgame(context, event_id): - response_msg = "Partida sin sitios disponibles" - else: - #We add +1 to the guest field - context.chat_data[event_id]["players"][username] += 1 - response_msg = f"{username} +1!" - elif action == "leave": - #We remove the user from the list - del context.chat_data[event_id]["players"][username] - response_msg = "Usuario quitado de la quedada" - elif action == "-1": - #We verify if the user has guests - if context.chat_data[event_id]["players"][username] > 0: - context.chat_data[event_id]["players"][username] -= 1 - else: - response_msg = "Sin invitados que quitar" - alert = True - else: - if action == 'join': - if is_fullgame(context, event_id): - response_msg = "Partida sin sitios disponibles" - else: - context.chat_data[event_id]["players"][username] = 0 - response_msg = f"{username} joined!" - elif action == "+1": - if is_fullgame(context, event_id): - response_msg = "Partida sin sitios disponibles" - else: - context.chat_data[event_id]["players"][username] += 0 - response_msg = f"{username} +1!" - elif action == '-1': - response_msg = "El usuario no está en la lista" - return alert, response_msg - - -def is_fullgame(context, event_id): - current_players = len(context.chat_data[event_id]["players"].keys()) - current_guests = sum(context.chat_data[event_id]["players"].values()) - total_players = current_players + current_guests - is_full_game = total_players >= int(context.chat_data[event_id]["max_players"]) - return is_full_game - diff --git a/telegram_bot/constants.py b/telegram_bot/constants.py index 7d02335..582e683 100644 --- a/telegram_bot/constants.py +++ b/telegram_bot/constants.py @@ -1,6 +1,7 @@ -MEETING_NAME = "MEETING_NAME" -MEETING_DESCRIPTION = "MEETING_DESCRIPTION" -ENTER_NUM_PLAYERS=0 -ENTER_START_TIME=1 -ENTER_START_DATE=2 -ENTER_MEETING_TYPE=3 \ No newline at end of file +MEETING_NAME = 0 +MEETING_DESCRIPTION = 1 +ENTER_NUM_PLAYERS=2 +ENTER_START_DATE=3 +ENTER_START_TIME=4 +ENTER_MEETING_TYPE=5 +ENTER_CONFIRMATION=6 \ No newline at end of file diff --git a/telegram_bot/keyboards/calendar_keyboard.py b/telegram_bot/keyboards/calendar_keyboard.py index 6d17794..3a2a416 100644 --- a/telegram_bot/keyboards/calendar_keyboard.py +++ b/telegram_bot/keyboards/calendar_keyboard.py @@ -57,15 +57,6 @@ def create_calendar_keyboard(time_event_description:str, year=None, month=None): return InlineKeyboardMarkup(keyboard) -def create_callback_data(action,year,month,day=None): - """ Create the callback data associated to each button""" - tokens = [str(action), str(year), str(month)] - if day is not None: - tokens.append(str(day)) - - return CALENDAR_CALLBACK + ";" + ";".join(tokens) - - def create_previous_month_info(action,year,month): if month == 1: year -= 1 @@ -82,3 +73,16 @@ def create_next_month_info(action,year,month): else: month += 1 return create_callback_data(action, year, month) + + +def create_callback_data(action,year,month,day=None): + """ + Create the callback data associated to each button with structure: + eg. CALENDAR;PREV-MONTH;2025;6 + eg. CALENDAR;NEXT-MONTH;2025;5;25 + """ + tokens = [str(action), str(year), str(month)] + if day is not None: + tokens.append(str(day)) + + return CALENDAR_CALLBACK + ";" + ";".join(tokens) \ No newline at end of file diff --git a/telegram_bot/keyboards/confirm_keyboard.py b/telegram_bot/keyboards/confirm_keyboard.py new file mode 100644 index 0000000..dbae340 --- /dev/null +++ b/telegram_bot/keyboards/confirm_keyboard.py @@ -0,0 +1,11 @@ +from telegram import InlineKeyboardButton, InlineKeyboardMarkup + + +def build_confirm_keyboard(): + keyboard = [ + [ + InlineKeyboardButton("Cancelar", callback_data=f"cancel"), + InlineKeyboardButton("Confirmar", callback_data=f"submit"), + ] + ] + return InlineKeyboardMarkup(keyboard) \ No newline at end of file diff --git a/telegram_bot/message_handler.py b/telegram_bot/message_handler.py index 9b41a2b..ce4e69e 100644 --- a/telegram_bot/message_handler.py +++ b/telegram_bot/message_handler.py @@ -1,7 +1,7 @@ from telegram import Update from telegram.ext import ContextTypes -from .constants import MEETING_DESCRIPTION, ENTER_START_TIME, ENTER_NUM_PLAYERS +from .constants import MEETING_DESCRIPTION, ENTER_NUM_PLAYERS, ENTER_START_DATE from utils.logger import logger from .keyboards.calendar_keyboard import create_calendar_keyboard from .keyboards.players_keyboard import create_num_keyboard @@ -28,7 +28,7 @@ async def second_answer(update: Update, context: ContextTypes.DEFAULT_TYPE) -> i return ENTER_NUM_PLAYERS -async def process_num_players(update: Update, context: ContextTypes.DEFAULT_TYPE) ->int: +async def process_num_players(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: if context.chat_data.get("edit_id", None) is None: event_message_id = "current" else: @@ -36,4 +36,4 @@ async def process_num_players(update: Update, context: ContextTypes.DEFAULT_TYPE context.chat_data[event_message_id]["max_players"] = update.callback_query.data await update.callback_query.edit_message_text("Indique la fecha de inicio", reply_markup=create_calendar_keyboard("start_date")) logger.info("Start time keyboard shown") - return ENTER_START_TIME \ No newline at end of file + return ENTER_START_DATE \ No newline at end of file diff --git a/telegram_bot/quedada_entry.py b/telegram_bot/quedada_entry.py index e557735..ca2c2e1 100644 --- a/telegram_bot/quedada_entry.py +++ b/telegram_bot/quedada_entry.py @@ -1,3 +1,5 @@ +from collections import defaultdict + from telegram import Update from telegram.ext import ContextTypes from utils.logger import logger @@ -5,7 +7,7 @@ from .utils import get_username -async def quedada(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str: +async def quedada(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: #Add the user that created the event to the dict event_id = update.message.message_id context.chat_data["current_event_id"] = str(event_id) @@ -18,9 +20,9 @@ async def quedada(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str: "start_date": None, "start_time": None, "meeting_type": "Open", - "players": { + "players": defaultdict(int, { f"{await get_username(update)}":0 - } + }) } logger.info(f"Building quedada message: message id {event_id}") #Starts the routin that will ask for start time, end time and status diff --git a/token_generator.py b/token_generator.py new file mode 100644 index 0000000..97c07dd --- /dev/null +++ b/token_generator.py @@ -0,0 +1,26 @@ +""" +Used for generating the first token, which is not to be changed. + +Preconditions: + - An app in Google Cloud console must be created + - The credentials must be created as "Desktop app" + - The Google Calendar API must be enabled + - The user owning the calendar (e.g. sysarmygalicia@gmail.com) must authorize the app and share the calendar with it + - The user (e.g. sysarmygalicia@gmail.com) must be added as "Test user" under "Audience" when in Testing mode + +Once you execute this and complete the manual authentication flow only once, +a *.pkl file is remaining as a result. You should use that within the bot for using Calendar API. + +""" +from google_auth_oauthlib.flow import InstalledAppFlow +import pickle + +SCOPES = ['https://www.googleapis.com/auth/calendar'] +flow = InstalledAppFlow.from_client_secrets_file( + 'credentials_desktop.json', SCOPES) + +creds = flow.run_local_server(port=0) + +# Save token for future use +with open('desktop_token.pkl', 'wb') as token: + pickle.dump(creds, token) \ No newline at end of file