# Анатомия корпоративного Telegram-бота: разбор по модулям
Привет, разработчики! Сегодня хочу поделиться опытом создания корпоративного Telegram-бота, который из простого справочника контактов вырос в полноценного цифрового ассистента. Особое внимание уделю архитектуре и отдельным модулям, а также расскажу о самых интересных технических вызовах, с которыми пришлось столкнуться.
## Архитектура проекта
Сразу решил строить бота по модульному принципу. Каждый компонент функциональности - отдельный менеджер, который отвечает за свою область. Базовая структура выглядит так:
class TelegramBot:
def __init__(self):
self.config = Config(str(DATA_DIR / 'config.json'))
self.poll_manager = PollManager(self.config)
self.department_manager = DepartmentManager(self.config)
self.contact_manager = ContactManager(self.config)
self.moderator_manager = ModeratorManager(self.config)
self.notification_manager = NotificationManager(self.config)
self.weather_manager = WeatherManager(self.config)
## Система контактов и подразделений
Первым делом реализовал базовый функционал - справочник контактов. Здесь интересным решением стала двухуровневая структура: подразделения и контакты внутри них. Для каждого контакта можно указать не только стандартные поля вроде должности, ФИО и телефона, но и дополнительную информацию:
async def show_department_contacts_view(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
dept_id = update.callback_query.data.replace("view_dept_contacts_", "")
department = next(
(d for d in self.config.data.get('departments', []) if d['id'] == dept_id),
None
)
text = f"📍 <b>{department['name']}</b>\n"
for contact in department['contacts']:
text += "═══════════════════\n\n"
text += f"👔 {contact['position']}\n"
text += f"👤 {contact['name']}\n"
text += f"📞 {contact['phone']}\n"
if 'hours' in contact:
text += f"🕒 {contact['hours']}\n"
## Погодный модуль: интеграция с существующей системой
Особенно горжусь модулем погоды. До этого у меня уже был опыт создания сайта погоды (gdnmeteo.ru), который собирает данные с моей личной метеостанции на Харасавэе и из открытых API для других локаций. Было логично интегрировать эту систему и в бота.
def get_city_weather(self, city: str) -> Dict[str, Any]:
try:
prefix = self.cities[city]['prefix']
query = f'''
from(bucket: "data")
|> range(start: -15m)
|> filter(fn: (r) => r["_measurement"] == "measur")
|> filter(fn: (r) => r["_field"] =~ /^{prefix}.*/ )
|> last()
'''
tables = self.influx_client.query_api().query(query)
weather_data = {}
Интересной особенностью стала система контекстных шуток о погоде. В зависимости от погодных условий бот выдаёт разные комментарии, учитывая специфику работы на производственных объектах:
def get_weather_joke(temp: float, wind_speed: float, humidity: float, pressure: float, city: str) -> str:
if temp <= -45 and city in field_sites:
jokes.extend([
"🥶 На приборах сегодня температура '404 - тепло не найдено'!",
"❄️ Инструменты на морозе так сжались, что размеры уменьшились на номер!"
])
## Система верификации: сложный, но необходимый модуль
Одним из самых сложных для реализации стал модуль верификации пользователей. Задача была непростой: нужно было обеспечить доступ к определённым функциям бота только сотрудникам организации, при этом сохранив часть функционала доступной для всех.
2 минуты
25 ноября 2024