mirror of
https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git
synced 2025-08-14 00:25:46 +02:00
отправка уведомлений в телеграм2
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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"
|
|
||||||
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):
|
|
||||||
"""Notify user about request status change"""
|
|
||||||
try:
|
|
||||||
db = SessionLocal()
|
|
||||||
request = db.query(DBRequest).filter(DBRequest.id == request_id).first()
|
|
||||||
if request and request.employee and request.employee.telegram_id:
|
|
||||||
status_messages = {
|
|
||||||
RequestStatus.NEW: "создана",
|
|
||||||
RequestStatus.IN_PROGRESS: "взята в работу",
|
|
||||||
RequestStatus.COMPLETED: "выполнена",
|
|
||||||
RequestStatus.REJECTED: "отклонена"
|
|
||||||
}
|
}
|
||||||
message = f"Статус вашей заявки №{request.id} изменен на: {status_messages.get(new_status, new_status)}"
|
return f"{status_emoji.get(status, '⚪')} {status.capitalize()}"
|
||||||
bot.send_message(request.employee.telegram_id, message)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error sending telegram notification: {e}")
|
|
||||||
finally:
|
|
||||||
db.close()
|
|
||||||
|
|
||||||
# Инициализация вебхука при запуске
|
async def send_request_notification(request_data: dict):
|
||||||
setup_webhook()
|
"""Send notification about new request to Telegram"""
|
||||||
|
try:
|
||||||
|
message = (
|
||||||
|
f"📋 <b>Новая заявка #{request_data['id']}</b>\n\n"
|
||||||
|
f"📝 <b>Заголовок:</b> {request_data['title']}\n"
|
||||||
|
f"👤 <b>Сотрудник:</b> {request_data.get('employee_name', 'Не указан')}\n"
|
||||||
|
f"❗ <b>Приоритет:</b> {format_priority(request_data['priority'])}\n"
|
||||||
|
f"📊 <b>Статус:</b> {format_status(request_data['status'])}\n\n"
|
||||||
|
f"📄 <b>Описание:</b>\n{request_data['description']}\n\n"
|
||||||
|
f"🕒 <b>Создана:</b> {request_data['created_at'].strftime('%d.%m.%Y %H:%M')}"
|
||||||
|
)
|
||||||
|
|
||||||
|
await bot.send_message(
|
||||||
|
chat_id=TELEGRAM_CHAT_ID,
|
||||||
|
text=message,
|
||||||
|
parse_mode="HTML"
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error sending Telegram notification: {e}", exc_info=True)
|
||||||
|
|
||||||
|
def notify_new_request(request_data: dict):
|
||||||
|
"""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)
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user