1
0
mirror of https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git synced 2025-08-14 00:25:46 +02:00

отправка уведомлений в телеграм2

This commit is contained in:
MoonTestUse1
2025-01-03 01:25:24 +06:00
parent cda77a47c4
commit 8564803683
3 changed files with 98 additions and 87 deletions

View File

@@ -8,7 +8,7 @@ from ..schemas.request import RequestCreate, RequestResponse, RequestUpdate, Req
from ..utils.auth import get_current_admin, get_current_employee from ..utils.auth import get_current_admin, get_current_employee
from sqlalchemy import func from sqlalchemy import func
from ..models.employee import Employee from ..models.employee import Employee
from ..utils.telegram import notify_new_request from ..utils.telegram import notify_new_request, notify_status_change
router = APIRouter() router = APIRouter()
@@ -57,8 +57,19 @@ def create_request(
db.commit() db.commit()
db.refresh(db_request) db.refresh(db_request)
# Подготавливаем данные для уведомления
request_data = {
"id": db_request.id,
"title": db_request.title,
"description": db_request.description,
"priority": db_request.priority,
"status": db_request.status,
"employee_name": f"{current_employee.last_name} {current_employee.first_name}",
"created_at": db_request.created_at
}
# Отправляем уведомление в Telegram # Отправляем уведомление в Telegram
notify_new_request(db_request.id) notify_new_request(request_data)
return request_to_dict(db_request) return request_to_dict(db_request)
except Exception as e: except Exception as e:
@@ -94,10 +105,19 @@ def update_request_status(
if not db_request: if not db_request:
raise HTTPException(status_code=404, detail="Заявка не найдена") raise HTTPException(status_code=404, detail="Заявка не найдена")
old_status = db_request.status
db_request.status = status_update.status db_request.status = status_update.status
db.commit() db.commit()
db.refresh(db_request) db.refresh(db_request)
# Отправляем уведомление об изменении статуса, если у сотрудника есть telegram_id
if db_request.employee and db_request.employee.telegram_id:
notify_status_change(
request_id=db_request.id,
new_status=status_update.status,
employee_telegram_id=db_request.employee.telegram_id
)
return request_to_dict(db_request) return request_to_dict(db_request)
except HTTPException: except HTTPException:
raise raise

View File

@@ -1,42 +1,21 @@
"""Telegram bot utils""" """Telegram bot utils"""
from aiogram import Bot, Dispatcher
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
import asyncio
from datetime import datetime
import os import os
from fastapi import APIRouter, Request from logging import getLogger
from telebot import TeleBot
from telebot.types import Update
from ..models.request import RequestStatus, RequestPriority from ..models.request import RequestStatus, RequestPriority
from ..database import SessionLocal
from ..models.request import Request as DBRequest
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") # Initialize logger
TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID") logger = getLogger(__name__)
WEBHOOK_URL = "https://itformhelp.ru/telegram/webhook/"
WEBHOOK_PATH = "/telegram/webhook/"
bot = TeleBot(TELEGRAM_BOT_TOKEN) # Initialize bot with token
router = APIRouter() TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN", "7677506032:AAHduD5EePz3bE23DKlo35KoOp2_9lZuS34")
TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID", "5057752127")
@router.post(WEBHOOK_PATH) bot = Bot(token=TELEGRAM_BOT_TOKEN)
async def handle_webhook(request: Request): dp = Dispatcher()
"""Handle webhook from Telegram"""
json_string = await request.json()
update = Update.de_json(json_string)
bot.process_new_updates([update])
return {"ok": True}
def setup_webhook():
"""Setup webhook"""
bot.remove_webhook()
bot.set_webhook(url=WEBHOOK_URL)
@bot.message_handler(commands=['start'])
def start(message):
"""Handle /start command"""
bot.reply_to(message, "Привет! Я бот технической поддержки. Я буду уведомлять вас о статусе ваших заявок.")
@bot.message_handler(func=lambda message: True)
def handle_message(message):
"""Handle all messages"""
bot.reply_to(message, "Я получил ваше сообщение и обязательно обработаю его!")
def format_priority(priority: str) -> str: def format_priority(priority: str) -> str:
"""Format priority with emoji""" """Format priority with emoji"""
@@ -47,43 +26,63 @@ def format_priority(priority: str) -> str:
} }
return f"{priority_emoji.get(priority, '')} {priority.capitalize()}" return f"{priority_emoji.get(priority, '')} {priority.capitalize()}"
def notify_new_request(request_id: int): def format_status(status: str) -> str:
"""Send notification about new request""" """Format status with emoji"""
try: status_emoji = {
db = SessionLocal() RequestStatus.NEW: "🆕",
request = db.query(DBRequest).filter(DBRequest.id == request_id).first() RequestStatus.IN_PROGRESS: "",
if request: RequestStatus.COMPLETED: "",
message = ( RequestStatus.REJECTED: ""
f"📋 <b>Новая заявка #{request.id}</b>\n\n" }
f"📝 <b>Заголовок:</b> {request.title}\n" return f"{status_emoji.get(status, '')} {status.capitalize()}"
f"👤 <b>Сотрудник:</b> {request.employee.last_name} {request.employee.first_name}\n"
f"❗ <b>Приоритет:</b> {format_priority(request.priority)}\n\n"
f"📄 <b>Описание:</b>\n{request.description}"
)
bot.send_message(TELEGRAM_CHAT_ID, message, parse_mode="HTML")
except Exception as e:
print(f"Error sending telegram notification: {e}")
finally:
db.close()
def notify_status_change(request_id: int, new_status: RequestStatus): async def send_request_notification(request_data: dict):
"""Notify user about request status change""" """Send notification about new request to Telegram"""
try: try:
db = SessionLocal() message = (
request = db.query(DBRequest).filter(DBRequest.id == request_id).first() f"📋 <b>Новая заявка #{request_data['id']}</b>\n\n"
if request and request.employee and request.employee.telegram_id: f"📝 <b>Заголовок:</b> {request_data['title']}\n"
status_messages = { f"👤 <b>Сотрудник:</b> {request_data.get('employee_name', 'Не указан')}\n"
RequestStatus.NEW: "создана", f"❗ <b>Приоритет:</b> {format_priority(request_data['priority'])}\n"
RequestStatus.IN_PROGRESS: "взята в работу", f"📊 <b>Статус:</b> {format_status(request_data['status'])}\n\n"
RequestStatus.COMPLETED: "выполнена", f"📄 <b>Описание:</b>\n{request_data['description']}\n\n"
RequestStatus.REJECTED: "отклонена" f"🕒 <b>Создана:</b> {request_data['created_at'].strftime('%d.%m.%Y %H:%M')}"
} )
message = f"Статус вашей заявки №{request.id} изменен на: {status_messages.get(new_status, new_status)}"
bot.send_message(request.employee.telegram_id, message) await bot.send_message(
chat_id=TELEGRAM_CHAT_ID,
text=message,
parse_mode="HTML"
)
except Exception as e: except Exception as e:
print(f"Error sending telegram notification: {e}") logger.error(f"Error sending Telegram notification: {e}", exc_info=True)
finally:
db.close()
# Инициализация вебхука при запуске def notify_new_request(request_data: dict):
setup_webhook() """Wrapper to run async notification in sync context"""
try:
asyncio.run(send_request_notification(request_data))
except Exception as e:
logger.error(f"Failed to send notification: {e}", exc_info=True)
async def send_status_notification(request_id: int, new_status: str, employee_telegram_id: str):
"""Send notification about status change"""
try:
message = (
f"🔄 <b>Обновление статуса заявки #{request_id}</b>\n\n"
f"📊 <b>Новый статус:</b> {format_status(new_status)}"
)
await bot.send_message(
chat_id=employee_telegram_id,
text=message,
parse_mode="HTML"
)
except Exception as e:
logger.error(f"Error sending status notification: {e}", exc_info=True)
def notify_status_change(request_id: int, new_status: str, employee_telegram_id: str):
"""Wrapper to run async status notification in sync context"""
try:
asyncio.run(send_status_notification(request_id, new_status, employee_telegram_id))
except Exception as e:
logger.error(f"Failed to send status notification: {e}", exc_info=True)

View File

@@ -1,17 +1,9 @@
fastapi==0.110.0 fastapi==0.104.1
uvicorn==0.27.1 uvicorn==0.24.0
sqlalchemy==2.0.27 sqlalchemy==2.0.23
pydantic==2.6.3
pydantic-settings==2.2.1
python-multipart==0.0.9
python-jose[cryptography]==3.3.0
passlib[bcrypt]>=1.7.4
bcrypt>=4.0.1
aiogram>=3.4.1
python-dotenv==1.0.1
psycopg2-binary==2.9.9 psycopg2-binary==2.9.9
alembic==1.13.1 python-jose[cryptography]==3.3.0
pytest==8.0.0 passlib[bcrypt]==1.7.4
httpx==0.26.0 python-multipart==0.0.6
pytest-asyncio==0.23.5 aiogram==3.1.1
pytest-cov==4.1.0 python-dotenv==1.0.0