SHARE
TWEET

Untitled

a guest Jan 22nd, 2020 56 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import json
  2. import time
  3. import telebot
  4. import datetime
  5. import requests
  6. from bs4 import BeautifulSoup
  7.  
  8. with open('config.json') as conf:
  9.     config = json.load(conf)
  10.  
  11. bot = telebot.TeleBot(config['access_token'])
  12. WEEKDAYS = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']
  13. WEEKDAYS_RUSSIAN = {'monday':    'понедельник',
  14.                     'tuesday':   'вторник',
  15.                     'wednesday': 'среду',
  16.                     'thursday':  'четверг',
  17.                     'friday':    'пятницу',
  18.                     'saturday':  'субботу',
  19.                     'sunday':    'воскресенье'}
  20. WEEK_PARITY = {0: 'четная неделя', 1: 'нечетная неделя', 3: ''}
  21. EMOJI_NUMBERS = [u'\u0031\u20E3', u'\u0032\u20E3', u'\u0033\u20E3', u'\u0034\u20E3', u'\u0035\u20E3',
  22.                  u'\u0036\u20E3', u'\u0037\u20E3', u'\u0038\u20E3', u'\u0039\u20E3']
  23. CACHED_SCHEDULE = {}
  24.  
  25.  
  26. def get_week_number():
  27.     return datetime.date.today().isocalendar()[1] - 35
  28.  
  29.  
  30. def get_day_number():
  31.     return datetime.date.today().weekday() + 1
  32.  
  33.  
  34. def parse_command(message):
  35.     try:
  36.         day, group = message.text.split()
  37.         day = day[1:]
  38.     except ValueError:
  39.         bot.send_message(message.chat.id, 'You should specify your group number like "/monday K3140"')
  40.         return
  41.     return day, group
  42.  
  43.  
  44. def get_schedule_page(group, week: str = None):
  45.     if week is None or week == '0':
  46.         week = ''
  47.     else:
  48.         week = week + '/'
  49.  
  50.     url = f'{config["domain"]}/{group}/{week}raspisanie_zanyatiy_{group}.htm'
  51.     response = requests.get(url)
  52.     web_page = response.text
  53.     return web_page
  54.  
  55.  
  56. def parse_schedule_for_day(web_page, day_number: str):
  57.     soup = BeautifulSoup(web_page, "html5lib")
  58.  
  59.     # Получаем таблицу с расписанием на понедельник
  60.     schedule_table = soup.find("table", attrs={"id": f"{day_number}day"})
  61.  
  62.     if schedule_table is None:
  63.         return None
  64.  
  65.     times_list = schedule_table.find_all("td", attrs={"class": "time"})
  66.     times_list = [time.span.text for time in times_list]
  67.  
  68.     # Место проведения занятий
  69.     locations_list = schedule_table.find_all("td", attrs={"class": "room"})
  70.     locations_list = [room.span.text for room in locations_list]
  71.  
  72.     # Название дисциплин и имена преподавателей
  73.     lessons_list = schedule_table.find_all("td", attrs={"class": "lesson"})
  74.     lessons_list = [lesson.text.split('\n\n') for lesson in lessons_list]
  75.     lessons_list = [', '.join([
  76.         info.replace('\r\n', '(', 1).replace('\r\n', ') ', 1).replace('\t', '').replace('\n', '') for info in lesson_info if info
  77.     ]) for lesson_info in lessons_list]
  78.  
  79.     return times_list, locations_list, lessons_list
  80.  
  81.  
  82. def get_schedule_info(group: str, day: str, week: str = None):
  83.     global CACHED_SCHEDULE
  84.     if week is None:
  85.         week_key = 0
  86.     elif week == '0':
  87.         week_key = 0
  88.     elif week == '1':
  89.         week_key = 1
  90.     elif week == '2':
  91.         week_key = 2
  92.     elif int(week) % 2 == 0:
  93.         week_key = 1
  94.     else:
  95.         week_key = 2
  96.  
  97.     if CACHED_SCHEDULE.get(group) is None:
  98.         CACHED_SCHEDULE[group] = {}
  99.  
  100.     if CACHED_SCHEDULE[group].get(week_key) is None:
  101.         CACHED_SCHEDULE[group][week_key] = {}
  102.  
  103.     if CACHED_SCHEDULE[group][week_key].get(day) is None:
  104.         # print('Loading web-page with schedule...')
  105.         web_page = get_schedule_page(group, week)
  106.         schedule = parse_schedule_for_day(web_page, day)
  107.  
  108.         if schedule is None:
  109.             CACHED_SCHEDULE[group][week_key][day] = [[], [], []]
  110.             return None
  111.         else:
  112.             CACHED_SCHEDULE[group][week_key][day] = schedule
  113.             return schedule
  114.     else:
  115.         # print('Loading schedule from cache...')
  116.         schedule = CACHED_SCHEDULE[group][week_key][day]
  117.         if len(schedule[0]) == 0:
  118.             return None
  119.         return schedule
  120.  
  121.  
  122. @bot.message_handler(commands=WEEKDAYS)
  123. def get_schedule(message, week_number: str = None, return_reply=False, consider_week_parity=True):
  124.     """ Получить расписание на указанный день """
  125.     try:
  126.         day, week_number, group = message.text.split()
  127.         day = day[1:]
  128.     except ValueError:
  129.         _cmd = parse_command(message)
  130.         if _cmd is None:
  131.             return
  132.         else:
  133.             day, group = _cmd
  134.  
  135.     weekday_number = str(WEEKDAYS.index(day) + 1)
  136.     if consider_week_parity:
  137.         schedule = get_schedule_info(group, weekday_number, week_number)
  138.     else:
  139.         schedule = get_schedule_info(group, weekday_number)
  140.  
  141.     if schedule is None:
  142.         resp = 'На указанный день пар нет. Можно отдыхать :)'
  143.         if return_reply:
  144.             return resp
  145.         else:
  146.             bot.send_message(message.chat.id, resp)
  147.             return
  148.  
  149.     times_list, locations_list, lessons_list = schedule
  150.  
  151.     resp = f'Расписание на {WEEKDAYS_RUSSIAN[day]}:\n'
  152.     for i in range(len(times_list)):
  153.         resp += f'{EMOJI_NUMBERS[i]} {times_list[i]} | {lessons_list[i]} | {locations_list[i]}\n'
  154.  
  155.     if return_reply:
  156.         return resp
  157.     bot.send_message(message.chat.id, resp)
  158.  
  159.  
  160. @bot.message_handler(commands=['near'])
  161. def get_near_lesson(message):
  162.     """ Получить ближайшее занятие """
  163.     _cmd = parse_command(message)
  164.     if _cmd is None:
  165.         return
  166.     else:
  167.         day, group = _cmd
  168.  
  169.     weekday_number = get_day_number()
  170.     week_number = get_week_number()
  171.  
  172.     found = False
  173.     this_day = True
  174.     while not found:
  175.         schedule = get_schedule_info(group, str(weekday_number), str(weekday_number))
  176.         if schedule is not None:
  177.             times_list, locations_list, lessons_list = schedule
  178.             if this_day:
  179.                 time_now = time.strptime(time.strftime('%H:%M'), '%H:%M')
  180.                 for i in range(len(times_list)):
  181.                     lesson_start_time = time.strptime(times_list[0].split('-')[i], '%H:%M')
  182.                     if time_now < lesson_start_time:
  183.                         bot.send_message(message.chat.id, f'Ближайшая пара сегодня, в {times_list[i]}\n'
  184.                                                           f'{lessons_list[i]}\n'
  185.                                                           f'Корпус: {locations_list[i]}\n')
  186.                         found = True
  187.                         break
  188.             else:
  189.                 if len(times_list) != 0:
  190.                     if weekday_number <= get_day_number():
  191.                         weekday_number += 7
  192.                     bot.send_message(message.chat.id, f'Ближайшая пара через {weekday_number - get_day_number()} дня в '
  193.                                                       f'{WEEKDAYS_RUSSIAN[WEEKDAYS[weekday_number % 7 - 1]]}, {times_list[0]}\n'
  194.                                                       f'{lessons_list[0]}\n'
  195.                                                       f'Корпус: {locations_list[0]}\n')
  196.                     found = True
  197.         else:
  198.             this_day = False
  199.             weekday_number += 1
  200.             if weekday_number == 8:
  201.                 weekday_number = 1
  202.                 week_number += 1
  203.  
  204.  
  205. @bot.message_handler(commands=['tomorrow'])
  206. def get_tommorow(message):
  207.     """ Получить расписание на следующий день """
  208.     _cmd = parse_command(message)
  209.     if _cmd is None:
  210.         return
  211.     else:
  212.         _, group = _cmd
  213.  
  214.     day = get_day_number() + 1
  215.     week = get_week_number()
  216.     if day == 7:
  217.         day = 1
  218.         week += 1
  219.  
  220.     message.text = f'/{WEEKDAYS[day - 1]} {group}'
  221.     get_schedule(message, str(week))
  222.  
  223.  
  224. @bot.message_handler(commands=['all'])
  225. def get_all_schedule(message):
  226.     """ Получить расписание на всю неделю для указанной группы """
  227.     _cmd = parse_command(message)
  228.     if _cmd is None:
  229.         return
  230.     else:
  231.         _, group = _cmd
  232.  
  233.     all_response = []
  234.     for day in range(1, 8):
  235.         resp = ''
  236.         message.text = f'/{WEEKDAYS[day - 1]} {group}'
  237.         schedule_for_day = get_schedule(message, return_reply=True, consider_week_parity=False)
  238.         if 'пар нет' in schedule_for_day:
  239.             resp += f'Расписание на {WEEKDAYS_RUSSIAN[WEEKDAYS[day - 1]]}:\n' \
  240.                     f'Нет пар'
  241.         else:
  242.             resp += schedule_for_day
  243.         all_response.append(resp.strip())
  244.  
  245.     bot.send_message(message.chat.id, f'\n{"=" * 30}\n'.join(all_response))
  246.  
  247.  
  248. if __name__ == '__main__':
  249.     bot.polling(none_stop=True)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top