136 lines
4.7 KiB
Python
136 lines
4.7 KiB
Python
import math
|
||
from fastapi import APIRouter, Body, Form, Query, Request, Depends, Cookie, HTTPException
|
||
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
|
||
from sqlalchemy import func
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
from datetime import datetime
|
||
from db import crud
|
||
from db.db import async_session
|
||
from function import decrypt_token, get_authenticated_user, send_newsletter, get_user_with_access
|
||
from config import templates
|
||
from db.models import User
|
||
from sqlalchemy.future import select
|
||
import asyncio
|
||
import logging
|
||
from models import NewsletterRequest
|
||
|
||
|
||
from bot.db.models import UserTg, Otdels, Questions
|
||
|
||
|
||
user_router = APIRouter()
|
||
|
||
@user_router.get("/", response_class=HTMLResponse)
|
||
async def read_root(request: Request, user: User = Depends(get_authenticated_user)):
|
||
return templates.TemplateResponse("index.html", {"request": request, "user": user})
|
||
|
||
@user_router.get("/profile", response_class=HTMLResponse)
|
||
async def profile(request: Request, user: User = Depends(get_authenticated_user)):
|
||
|
||
|
||
return templates.TemplateResponse("profile.html", {"request": request, "user": user})
|
||
|
||
|
||
|
||
|
||
@user_router.get("/users", response_class=HTMLResponse)
|
||
async def users(
|
||
request: Request,
|
||
user: User = Depends(get_user_with_access),
|
||
page: int = Query(1, alias='page', ge=1)
|
||
):
|
||
ITEMS_PER_PAGE = 12
|
||
PAGINATION_BUTTONS = 10
|
||
|
||
async with async_session() as db_session:
|
||
# Подсчитываем общее количество пользователей
|
||
total_users = await db_session.execute(select(func.count(UserTg.id)))
|
||
total_users = total_users.scalar_one()
|
||
total_pages = (total_users + ITEMS_PER_PAGE - 1) // ITEMS_PER_PAGE
|
||
|
||
# Вычисляем смещение и лимит
|
||
offset = (page - 1) * ITEMS_PER_PAGE
|
||
|
||
# Создаем запрос с сортировкой по id
|
||
stmt = select(UserTg).order_by(UserTg.id).offset(offset).limit(ITEMS_PER_PAGE)
|
||
result = await db_session.execute(stmt)
|
||
users = result.scalars().all()
|
||
|
||
# Определяем страницы для отображения пагинации
|
||
start_page = max(1, page - PAGINATION_BUTTONS // 2)
|
||
end_page = min(total_pages, start_page + PAGINATION_BUTTONS - 1)
|
||
start_page = max(1, end_page - PAGINATION_BUTTONS + 1)
|
||
|
||
return templates.TemplateResponse(
|
||
"users.html",
|
||
{
|
||
"request": request,
|
||
"user": user,
|
||
"users": users,
|
||
"current_page": page,
|
||
"total_pages": total_pages,
|
||
"start_page": start_page,
|
||
"end_page": end_page
|
||
}
|
||
)
|
||
|
||
|
||
|
||
@user_router.post("/update_status/{user_id}", response_class=HTMLResponse)
|
||
async def update_status(
|
||
request: Request,
|
||
user_id: int,
|
||
user: User = Depends(get_user_with_access)
|
||
):
|
||
logging.info(f"Received request to update status for user_id: {user_id}")
|
||
async with async_session() as db_session:
|
||
result = await db_session.execute(select(UserTg).filter(UserTg.id == user_id))
|
||
user_record = result.scalars().first()
|
||
|
||
if not user_record:
|
||
raise HTTPException(status_code=404, detail="User not found")
|
||
|
||
user_record.has_access = not user_record.has_access
|
||
|
||
db_session.add(user_record)
|
||
await db_session.commit()
|
||
|
||
logging.info(f"Successfully updated status for user_id: {user_id}")
|
||
return JSONResponse(content={"status": "success"})
|
||
|
||
|
||
|
||
|
||
@user_router.post("/send-newsletter", response_class=JSONResponse)
|
||
async def newsletter(
|
||
request: NewsletterRequest, # Используем Pydantic модель
|
||
user: User = Depends(get_user_with_access)
|
||
):
|
||
async with async_session() as db_session:
|
||
try:
|
||
asyncio.create_task(send_newsletter(str(request.message), db_session))
|
||
except Exception as ex:
|
||
logging.error(ex)
|
||
return JSONResponse(content={"status": f"error", "message": f"error - {ex}"}, status_code=501)
|
||
|
||
return JSONResponse(content={"status": "success"}, status_code=200)
|
||
|
||
|
||
|
||
|
||
@user_router.get("/logout", response_class=HTMLResponse)
|
||
async def logout(request: Request, session_token: str = Cookie(None)):
|
||
if not session_token:
|
||
raise HTTPException(status_code=401, detail="Not authenticated")
|
||
|
||
try:
|
||
decrypted_token = decrypt_token(session_token)
|
||
except Exception:
|
||
raise HTTPException(status_code=401, detail="Invalid session token")
|
||
|
||
async with async_session() as db_session:
|
||
await crud.delete_session(db_session, decrypted_token)
|
||
|
||
response = RedirectResponse(url="/", status_code=303)
|
||
response.delete_cookie("session_token")
|
||
return response |