make_events.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import asyncio
  2. from aiogram import types, Dispatcher
  3. from bot import database, sql
  4. from bot.keyboards import register_kb, make_calendar, events_kb, cancel_booking, main_kb
  5. from bot.functions import make_date, time_validator, normalize_time, to_quotes, check_overlap, beauty_booked_time
  6. from handlers.user.states import BookingState
  7. from aiogram.dispatcher.storage import FSMContext
  8. from bot import messages
  9. from handlers.admin.notifications import new_event
  10. from datetime import date, datetime
  11. import calendar
  12. async def make_event(message: types.message):
  13. today = date.today()
  14. month = today.month
  15. days_in_month = calendar.monthrange(today.year, month)[1]
  16. db = database.Database()
  17. if not db.sql_fetchone(f"select tg_id from user_table where tg_id ={message.from_user.id}") or \
  18. not db.sql_fetchone(f"select approved from user_table where tg_id={message.from_user.id}"):
  19. await message.delete()
  20. await message.answer(messages.non_register, reply_markup=register_kb)
  21. else:
  22. if message.text == "🎯 Запланировать мероприятие":
  23. await message.delete()
  24. await message.answer(messages.events_welcome(make_date()), reply_markup=make_calendar(month,
  25. days_in_month,
  26. f"month_prev:{month}",
  27. f"month_next:{month}"))
  28. async def select_date(call: types.CallbackQuery, state: FSMContext):
  29. db = database.Database()
  30. date = call.data.split("_")[1]
  31. booked = db.sql_fetchall(sql.sql_booked_time(date))
  32. today = datetime.strftime(datetime.today(), '%Y-%m-%d')
  33. t_day = today.split("-")[2]
  34. t_month = today.split("-")[1]
  35. if int(date.split("-")[1]) == int(t_month):
  36. if int(date.split("-")[2]) >= int(t_day):
  37. if len(booked) == 0:
  38. await BookingState.start.set()
  39. await state.update_data(date=to_quotes(date))
  40. await state.update_data(owner=call.from_user.id)
  41. await call.message.edit_text(f"Вы выбрали дату: {date}\n"
  42. f"На этот день мероприятий не запланированно", reply_markup=events_kb())
  43. else:
  44. await BookingState.start.set()
  45. await state.update_data(date=to_quotes(date))
  46. await state.update_data(owner=call.from_user.id)
  47. await call.message.edit_text(f"Вы выбрали дату: {date}\n\n"
  48. f"Занятое время\n\n"
  49. f"{beauty_booked_time(sorted(booked, key=lambda t: t['e_start'], reverse=False))}",
  50. reply_markup=events_kb())
  51. else:
  52. msg = await call.message.answer("Нельзя выбрать дату позже сегодняшней")
  53. await asyncio.sleep(5)
  54. await msg.delete()
  55. elif int(date.split("-")[1]) > int(t_month):
  56. if len(booked) == 0:
  57. await BookingState.start.set()
  58. await state.update_data(date=to_quotes(date))
  59. await state.update_data(owner=call.from_user.id)
  60. await call.message.edit_text(f"Вы выбрали дату: {date}\n"
  61. f"На этот день мероприятий не запланированно", reply_markup=events_kb())
  62. else:
  63. await BookingState.start.set()
  64. await state.update_data(date=to_quotes(date))
  65. await state.update_data(owner=call.from_user.id)
  66. await call.message.edit_text(f"Вы выбрали дату: {date}\n\n"
  67. f"Занятое время\n\n"
  68. f"{beauty_booked_time(sorted(booked, key=lambda t: t['e_start'], reverse=False))}",
  69. reply_markup=events_kb())
  70. else:
  71. msg = await call.message.answer("Нельзя выбрать дату позже сегодняшней")
  72. await asyncio.sleep(5)
  73. await msg.delete()
  74. async def edit_date(call: types.CallbackQuery, state: FSMContext):
  75. today = date.today()
  76. month = today.month
  77. days_in_month = calendar.monthrange(today.year, month)[1]
  78. await call.message.edit_text(f"выберите дату чтобы увидеть список мероприятий\n\n"
  79. f"Так же календарь мероприятий можно посмотреть в "
  80. f"<a href=moodle.tomtit-tomsk.ru>Moodle</a>\n\n"
  81. f"Сегодняшняя дата <b>{make_date()}</b>", reply_markup=make_calendar(month,
  82. days_in_month,
  83. f"month_prev:{month}",
  84. f"month_next:{month}"))
  85. await state.finish()
  86. async def booking_date(call: types.CallbackQuery):
  87. await call.message.answer("Введите диапазон времени\n"
  88. "Возможные форматы\n\n"
  89. "13.00 15.30\n"
  90. "8.00-9.00\n"
  91. "10:30 14:00\n"
  92. "11.50-12.30\n", reply_markup=cancel_booking())
  93. await BookingState.time.set()
  94. async def get_time(message: types.Message, state: FSMContext):
  95. # Парсим то что ввел пользователь
  96. time = normalize_time(message.text)
  97. await message.delete()
  98. date = await state.get_data()
  99. # Проверяем валидность времени
  100. if time_validator(message.text):
  101. # Проверяем что старт не позже конца
  102. if time[0] > time[1]:
  103. await message.answer("Начало не может быть раньше конца")
  104. elif not check_overlap(time[0], time[1], date['date']):
  105. await message.answer("Указанное время пеерсекается")
  106. else:
  107. await state.update_data(t_start=time[0])
  108. await state.update_data(t_end=time[1])
  109. await BookingState.description.set()
  110. await message.answer("Введите краткое описание мероприятия", reply_markup=cancel_booking())
  111. else:
  112. await message.answer("Неверный формат времени")
  113. async def send_event(message: types.Message, state: FSMContext):
  114. db = database.Database()
  115. if len(message.text) > 100:
  116. await message.answer("Описание слишком длинное")
  117. else:
  118. await state.update_data(description=message.text)
  119. await state.update_data(approved=0)
  120. data = await state.get_data()
  121. await message.delete()
  122. await message.answer("Заявка принята\n"
  123. "Уведомлять администраторов не требуется\n"
  124. "они получат оповощение автоматически", reply_markup=main_kb)
  125. await state.finish()
  126. db.sql_query_send(sql.sql_send_event(data))
  127. await new_event()
  128. async def next_month(call: types.CallbackQuery):
  129. m_id = int(call.data.split(":")[1])+1
  130. days = calendar.monthrange(2022, m_id)[1]
  131. await call.message.edit_reply_markup(reply_markup=make_calendar(m_id,
  132. days,
  133. f"month_prev:{m_id}",
  134. f"month_next:{m_id}"))
  135. async def prev_month(call: types.CallbackQuery):
  136. m_id = int(call.data.split(":")[1])-1
  137. days = calendar.monthrange(2022, m_id)[1]
  138. await call.message.edit_reply_markup(reply_markup=make_calendar(m_id,
  139. days,
  140. f"month_prev:{m_id}",
  141. f"month_next:{m_id}"))
  142. def events_register(dp: Dispatcher):
  143. dp.register_message_handler(make_event, text="🎯 Запланировать мероприятие")
  144. dp.register_callback_query_handler(select_date, text_startswith='date_')
  145. dp.register_callback_query_handler(edit_date, text=['change', 'cancel_booking'], state=[BookingState.start,
  146. BookingState.time,
  147. BookingState.description])
  148. dp.register_callback_query_handler(booking_date, text='booking', state=BookingState.start)
  149. dp.register_message_handler(get_time, state=BookingState.time)
  150. dp.register_message_handler(send_event, state=BookingState.description)
  151. dp.register_callback_query_handler(next_month, text_startswith='month_next')
  152. dp.register_callback_query_handler(prev_month, text_startswith='month_prev')