bot/models/bot.py
2026-09-09 17:42:31 +00:00

232 lines
8.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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=15&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=15&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)