9a2aea038a
- Add pyproject.toml with uv and ruff configuration - Pin Python version to 3.13 via .python-version - Add Makefile commands: lint, format, fix - Apply ruff formatting to entire codebase - Remove unused imports (base64 in yookassa/simple_subscription) - Update .gitignore for new config files
152 lines
4.2 KiB
Python
152 lines
4.2 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import func, select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.database.models import Webhook, WebhookDelivery
|
|
|
|
|
|
async def create_webhook(
|
|
db: AsyncSession,
|
|
name: str,
|
|
url: str,
|
|
event_type: str,
|
|
secret: str | None = None,
|
|
description: str | None = None,
|
|
) -> Webhook:
|
|
"""Создать новый webhook."""
|
|
webhook = Webhook(
|
|
name=name,
|
|
url=url,
|
|
event_type=event_type,
|
|
secret=secret,
|
|
description=description,
|
|
is_active=True,
|
|
)
|
|
db.add(webhook)
|
|
await db.commit()
|
|
await db.refresh(webhook)
|
|
return webhook
|
|
|
|
|
|
async def get_webhook_by_id(db: AsyncSession, webhook_id: int) -> Webhook | None:
|
|
"""Получить webhook по ID."""
|
|
result = await db.execute(select(Webhook).where(Webhook.id == webhook_id))
|
|
return result.scalar_one_or_none()
|
|
|
|
|
|
async def list_webhooks(
|
|
db: AsyncSession,
|
|
event_type: str | None = None,
|
|
is_active: bool | None = None,
|
|
limit: int = 100,
|
|
offset: int = 0,
|
|
) -> tuple[list[Webhook], int]:
|
|
"""Список webhooks с фильтрами."""
|
|
query = select(Webhook)
|
|
|
|
if event_type:
|
|
query = query.where(Webhook.event_type == event_type)
|
|
if is_active is not None:
|
|
query = query.where(Webhook.is_active == is_active)
|
|
|
|
# Подсчет общего количества
|
|
count_query = select(func.count()).select_from(query.subquery())
|
|
total = await db.scalar(count_query) or 0
|
|
|
|
# Получение данных
|
|
query = query.order_by(Webhook.created_at.desc()).offset(offset).limit(limit)
|
|
result = await db.execute(query)
|
|
webhooks = result.scalars().all()
|
|
|
|
return list(webhooks), int(total)
|
|
|
|
|
|
async def get_active_webhooks_for_event(
|
|
db: AsyncSession,
|
|
event_type: str,
|
|
) -> list[Webhook]:
|
|
"""Получить все активные webhooks для конкретного события."""
|
|
result = await db.execute(select(Webhook).where(Webhook.event_type == event_type).where(Webhook.is_active == True))
|
|
return list(result.scalars().all())
|
|
|
|
|
|
async def update_webhook(
|
|
db: AsyncSession,
|
|
webhook: Webhook,
|
|
name: str | None = None,
|
|
url: str | None = None,
|
|
secret: str | None = None,
|
|
description: str | None = None,
|
|
is_active: bool | None = None,
|
|
) -> Webhook:
|
|
"""Обновить webhook."""
|
|
if name is not None:
|
|
webhook.name = name
|
|
if url is not None:
|
|
webhook.url = url
|
|
if secret is not None:
|
|
webhook.secret = secret
|
|
if description is not None:
|
|
webhook.description = description
|
|
if is_active is not None:
|
|
webhook.is_active = is_active
|
|
|
|
webhook.updated_at = datetime.utcnow()
|
|
await db.commit()
|
|
await db.refresh(webhook)
|
|
return webhook
|
|
|
|
|
|
async def delete_webhook(db: AsyncSession, webhook: Webhook) -> None:
|
|
"""Удалить webhook."""
|
|
await db.delete(webhook)
|
|
await db.commit()
|
|
|
|
|
|
async def record_webhook_delivery(
|
|
db: AsyncSession,
|
|
webhook_id: int,
|
|
event_type: str,
|
|
payload: dict,
|
|
status: str,
|
|
response_status: int | None = None,
|
|
response_body: str | None = None,
|
|
error_message: str | None = None,
|
|
attempt_number: int = 1,
|
|
) -> WebhookDelivery:
|
|
"""Записать попытку доставки webhook."""
|
|
delivery = WebhookDelivery(
|
|
webhook_id=webhook_id,
|
|
event_type=event_type,
|
|
payload=payload,
|
|
status=status,
|
|
response_status=response_status,
|
|
response_body=response_body,
|
|
error_message=error_message,
|
|
attempt_number=attempt_number,
|
|
delivered_at=datetime.utcnow() if status == 'success' else None,
|
|
)
|
|
db.add(delivery)
|
|
await db.commit()
|
|
await db.refresh(delivery)
|
|
return delivery
|
|
|
|
|
|
async def update_webhook_stats(
|
|
db: AsyncSession,
|
|
webhook: Webhook,
|
|
success: bool,
|
|
) -> Webhook:
|
|
"""Обновить статистику webhook."""
|
|
if success:
|
|
webhook.success_count += 1
|
|
else:
|
|
webhook.failure_count += 1
|
|
webhook.last_triggered_at = datetime.utcnow()
|
|
await db.commit()
|
|
await db.refresh(webhook)
|
|
return webhook
|