import json import random import telebot import datetime from zoneinfo import ZoneInfo from telebot.types import ReplyKeyboardMarkup, InlineQueryResultArticle, InputTextMessageContent, Message, ReplyKeyboardRemove, WebAppInfo, KeyboardButton import config from telebot import apihelper apihelper.proxy = { 'http': config.TELEGRAM_PROXY, 'https': config.TELEGRAM_PROXY } bot = telebot.TeleBot(config.TOKEN, parse_mode='html') from . import logger, user def send(target: Message | int | str, text: str, reply_markup = None, disable_web_page_preview: bool = True, **kwargs) -> Message: # type: ignore try: _ = target.from_user.id # type: ignore try: return bot.reply_to(target, text, reply_markup = reply_markup, disable_web_page_preview = True, **kwargs) # type: ignore except Exception as e: logger.error('Bot', f'{e}') except: try: return bot.send_message(target, text, reply_markup = reply_markup, disable_web_page_preview = True, **kwargs) # type: ignore except Exception as e: logger.error('Bot', f'{e}') class Inlines: def __init__(self, id: str, cache: int = 60) -> None: self.list = [] self.cache = cache self.id = id def add(self, title: str, description: str, output: str) -> None: self.list.append( InlineQueryResultArticle( id = str(random.randint(999,99999)), title = title, input_message_content = InputTextMessageContent( message_text = output, parse_mode = 'html', disable_web_page_preview = True ), description = description ) ) def send(self) -> bool: return bot.answer_inline_query( self.id, self.list, self.cache, is_personal = True ) class Strings: back_to_home = 'На главную 🏠' back_to_search = 'К поиску 🔎' # home map = 'Карта 🗺️' schedule = 'Расписание 📅' schedule_emoji = '📅' schedule_another_days = 'Другие дни 📁' search = 'Поиск 🔎' settings = '⚙️' support = 'Поддержка 💞' notifications = 'Уведомления ⏰' current_schedule_name_F = '{} 🔄' groups = 'Группы' rooms = 'Аудитории' teachers = 'Преподаватели' add_schedule = 'Добавить расписание 🔆' delete_active_schedule_F = 'Удалить "{}" 🗑' delete_other_schedules_F = 'Удалить все кроме "{}" 🗑' # register register_not_found_T = 'Моего {} нету ⚠' # schedule today = 'Сегодня 🔥' tomorrow = 'Завтра 🍀' weekdays: list[str] = ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ'] even = 'Четная 📅' odd = 'Нечетная 📅' delete = 'Удалить 🗑' save = 'Сохранить 🔆' @staticmethod def format(string: str, *args, **kwargs) -> str: return string.format(*args, **kwargs) class Markup_v2: @staticmethod def remove() -> ReplyKeyboardRemove: return ReplyKeyboardRemove() @staticmethod def default(user: user.User) -> ReplyKeyboardMarkup: markup = ReplyKeyboardMarkup(resize_keyboard=True) markup.add( KeyboardButton( text=Strings.map, web_app=WebAppInfo(f'{config.WEB_BASE_URL.rstrip("/")}/map/?v=14&mode=search') ), Strings.schedule, row_width=2 ) markup.add(Strings.search, Strings.current_schedule_name_F.format(user.group), row_width=2) markup.add(Strings.settings, Strings.support, row_width=2) return markup @staticmethod def schedule(is_added: bool, from_search: bool = False) -> ReplyKeyboardMarkup: odd_even = datetime.datetime.now(ZoneInfo('Europe/Moscow')).isocalendar().week % 2 == 0 markup = ReplyKeyboardMarkup(resize_keyboard=True) markup.add(Strings.back_to_home, row_width=1) if not from_search else markup.add(Strings.back_to_search,Strings.back_to_home, row_width=2) markup.add(Strings.today, Strings.tomorrow, row_width=2) markup.add(*Strings.weekdays, row_width=5) markup.add( f'{"" if odd_even else "→ "}{Strings.odd}', f'{"→ " if odd_even else ""}{Strings.even}', row_width=2, ) markup.add(Strings.delete if is_added else Strings.save, row_width=1) return markup class Markup_v1: @staticmethod def remove() -> ReplyKeyboardRemove: return ReplyKeyboardRemove() @staticmethod def default(user: user.User) -> ReplyKeyboardMarkup: markup = ReplyKeyboardMarkup(resize_keyboard=True) markup.add( KeyboardButton( text=Strings.map, web_app=WebAppInfo(f'{config.WEB_BASE_URL.rstrip("/")}/map/?v=14&mode=search') ), Strings.search, row_width=2 ) markup.add(Strings.today, Strings.tomorrow, row_width=2) markup.add(Strings.schedule_another_days, Strings.current_schedule_name_F.format(user.group), row_width=2) markup.add(Strings.notifications, Strings.support, row_width=2) return markup @staticmethod def search_types() -> ReplyKeyboardMarkup: markup = ReplyKeyboardMarkup(resize_keyboard=True) markup.add(Strings.back_to_home, row_width=1) markup.add(Strings.groups, row_width=1) markup.add(Strings.rooms, row_width=1) markup.add(Strings.teachers, row_width=1) return markup @staticmethod def search_results(results: list[str]) -> ReplyKeyboardMarkup: markup = ReplyKeyboardMarkup(resize_keyboard=True) markup.add(Strings.back_to_home, row_width=1) for result in results[:10]: markup.add(result, row_width=1) return markup @staticmethod def schedule( is_saved: bool, from_search: bool = False, include_today: bool = False ) -> ReplyKeyboardMarkup: even_week = datetime.datetime.now(ZoneInfo('Europe/Moscow')).isocalendar().week % 2 == 0 markup = ReplyKeyboardMarkup(resize_keyboard=True) markup.add(Strings.back_to_search if from_search else Strings.back_to_home, row_width=1) if from_search: markup.add(Strings.delete if is_saved else Strings.save, row_width=1) if from_search or include_today: markup.add(Strings.today, Strings.tomorrow, row_width=2) markup.add(*Strings.weekdays, row_width=5) markup.add( f'{"" if even_week else "→ "}{Strings.odd}', f'{"→ " if even_week else ""}{Strings.even}', row_width=2, ) if not from_search: markup.add(Strings.delete if is_saved else Strings.save, row_width=1) return markup @staticmethod def notifications() -> ReplyKeyboardMarkup: markup = ReplyKeyboardMarkup(resize_keyboard=True) markup.add(Strings.back_to_home, row_width=1) markup.add('Перед парой ⌛', row_width=1) markup.add('Вечером 🌆', row_width=1) markup.add('Файлом на неделю 📅', row_width=1) return markup @staticmethod def saved_schedules(u: user.User) -> ReplyKeyboardMarkup: markup = ReplyKeyboardMarkup(resize_keyboard=True) markup.add(Strings.back_to_home, row_width=1) markup.add(*(target['name'] for target in u.saved_schedules), row_width=4) markup.add(Strings.add_schedule, row_width=1) if u.active_target: markup.add(Strings.delete_active_schedule_F.format(u.group), row_width=1) markup.add(Strings.delete_other_schedules_F.format(u.group), row_width=1) return markup saved_groups = saved_schedules @staticmethod def selectGroup(groups: list[str]) -> ReplyKeyboardMarkup: markup = ReplyKeyboardMarkup(resize_keyboard=True) for group in groups: markup.add(group, row_width=1) markup.add('Моей группы нету ⚠', row_width=1) return markup Markup = Markup_v1 def Receive(state: str, text: str | None = None, strict: bool = True): return bot.message_handler( content_types = ['text'], func = lambda m: user.validate(m).state == state and ( (m.text in text if not strict else m.text == text) if text != None else True ) ) def Default(text: str, strict: bool = True): return Receive('default', text, strict)