first init
This commit is contained in:
220
core/routers/card/routes.py
Normal file
220
core/routers/card/routes.py
Normal file
@@ -0,0 +1,220 @@
|
||||
# -*- coding = utf-8 -*-
|
||||
# @Time : 2025/2/13 下午4:51
|
||||
# @File : routes.py
|
||||
# @Software : PyCharm
|
||||
# @Author : xingc
|
||||
# @Desc :
|
||||
import logging
|
||||
from typing import Literal, List
|
||||
|
||||
import ujson
|
||||
from fastapi import APIRouter, Depends, Query, HTTPException, status
|
||||
import redis.asyncio as aioredis
|
||||
from sqlalchemy import select, func
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from . import schema
|
||||
from .scraper import card_scraper
|
||||
from config import settings
|
||||
from core.base import schema as base_schema
|
||||
from core.db.crud import CRUD
|
||||
from core.db.engine import get_async_session, get_cache
|
||||
from core.db.models import Card, SearchCardCache, UserCollection
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
card_router = APIRouter(prefix='/card', tags=['卡册模块'])
|
||||
|
||||
|
||||
@card_router.get('/search', response_model=base_schema.BaseResponse[schema.CardOut])
|
||||
async def get_card_search(
|
||||
cert_number: str = Query(pattern='[a-zA-Z0-9]+'),
|
||||
platform: base_schema.SupportPlatformType = Query(...),
|
||||
db_session: AsyncSession = Depends(get_async_session),
|
||||
redis_conn: aioredis.Redis = Depends(get_cache)
|
||||
):
|
||||
logger.info(f'Get card search request: {cert_number}')
|
||||
logger.info(platform)
|
||||
result = None
|
||||
# 缓存
|
||||
cache_keyname = f'card_book:card_search:{platform.value}:{cert_number}'
|
||||
result_str = await redis_conn.get(cache_keyname)
|
||||
if result_str is not None:
|
||||
result = ujson.decode(result_str)
|
||||
return {'data': result}
|
||||
|
||||
db_crud = CRUD(db_session, SearchCardCache)
|
||||
# 缓存库
|
||||
if result is None:
|
||||
card = await db_crud.get(filters={'cert_number': cert_number, 'source': platform.value})
|
||||
if card is not None:
|
||||
result = card.data
|
||||
|
||||
# 采集
|
||||
if result is None:
|
||||
scraper_result = await card_scraper.choice(platform.value, cert_number)
|
||||
if scraper_result is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail='相关卡片信息未找到'
|
||||
)
|
||||
result = scraper_result['data']
|
||||
await db_crud.create(
|
||||
data={
|
||||
**scraper_result,
|
||||
'source': result.get('source') or platform.value,
|
||||
},
|
||||
filters={'cert_number': cert_number, 'source': platform.value}
|
||||
)
|
||||
await redis_conn.set(cache_keyname, ujson.encode(result), ex=settings.REDIS_CACHE_EXPIRATION_SECONDS)
|
||||
|
||||
return {'data': result}
|
||||
|
||||
|
||||
@card_router.get(
|
||||
'/me/all',
|
||||
response_model=base_schema.BaseResponse[
|
||||
base_schema.Paginated[
|
||||
List[schema.CardOut]
|
||||
]
|
||||
],
|
||||
)
|
||||
async def get_me_all_card(
|
||||
page: int = Query(default=1, gt=0),
|
||||
page_size: int = Query(default=15, gt=0, le=200),
|
||||
category: Literal['all', 'anime', 'sports', 'other', 'displayed'] = Query(default='all'),
|
||||
db_session: AsyncSession = Depends(get_async_session)
|
||||
):
|
||||
user_id = None
|
||||
conditions = [
|
||||
UserCollection.user_id == user_id,
|
||||
]
|
||||
if category in ['anime', 'sports', 'other']:
|
||||
conditions.append(Card.category == category)
|
||||
|
||||
if category == 'displayed':
|
||||
conditions.append(UserCollection.displayed is True)
|
||||
|
||||
total_stmt = (
|
||||
select(func.count()).select_from(UserCollection).filter(
|
||||
*conditions
|
||||
)
|
||||
)
|
||||
total = await db_session.execute(total_stmt)
|
||||
stmt = (
|
||||
select(UserCollection, Card)
|
||||
.join(Card, UserCollection.card_id == Card.id)
|
||||
.where(*conditions)
|
||||
.order_by(UserCollection.created_at.desc()).limit(page_size).offset((page - 1) * page_size)
|
||||
)
|
||||
records = await db_session.execute(stmt)
|
||||
|
||||
return {
|
||||
'data': {
|
||||
'list': [record.dict() for record in records.scalars().all()],
|
||||
'total': total.scalar(),
|
||||
'page': page,
|
||||
'page_size': page_size,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@card_router.get(
|
||||
'/visit/{user_id}/all',
|
||||
response_model=base_schema.BaseResponse[
|
||||
base_schema.Paginated[
|
||||
List[schema.CardOut]
|
||||
]
|
||||
],
|
||||
)
|
||||
async def get_visit_user_all_card(
|
||||
user_id: str,
|
||||
page: int = Query(default=1, gt=0),
|
||||
page_size: int = Query(default=15, gt=0, le=200),
|
||||
# category: Literal['displayed'] = Query(default='displayed'),
|
||||
db_session: AsyncSession = Depends(get_async_session)
|
||||
):
|
||||
conditions = [
|
||||
UserCollection.user_id == user_id, UserCollection.displayed is True
|
||||
]
|
||||
total_stmt = (
|
||||
select(func.count()).select_from(UserCollection).filter(*conditions)
|
||||
)
|
||||
total = await db_session.execute(total_stmt)
|
||||
stmt = (
|
||||
select(UserCollection, Card)
|
||||
.join(Card, UserCollection.card_id == Card.id)
|
||||
.where(*conditions)
|
||||
.order_by(UserCollection.created_at.desc()).limit(page_size).offset((page - 1) * page_size)
|
||||
)
|
||||
records = await db_session.execute(stmt)
|
||||
|
||||
return {
|
||||
'data': {
|
||||
'list': [record.dict() for record in records.scalars().all()],
|
||||
'total': total.scalar(),
|
||||
'page': page,
|
||||
'page_size': page_size,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@card_router.post('/create', response_model=base_schema.BaseResponse[schema.CardOut])
|
||||
async def created_card(
|
||||
payload: schema.Card,
|
||||
db_session: AsyncSession = Depends(get_async_session)
|
||||
):
|
||||
db_crud = CRUD(db_session, Card)
|
||||
card: Card = await db_crud.create(
|
||||
data={
|
||||
**payload.dict(exclude_none=True),
|
||||
'create_user_id': None,
|
||||
'source': payload.source.value,
|
||||
},
|
||||
filters={'cert_number': payload.cert_number, 'source': payload.source.value}
|
||||
)
|
||||
return {'data': card}
|
||||
|
||||
|
||||
@card_router.post('/{card_id}/update/')
|
||||
async def update_card_price_info(
|
||||
card_id: int,
|
||||
payload: schema.UpdateCard,
|
||||
db_session: AsyncSession = Depends(get_async_session),
|
||||
):
|
||||
db_crud = CRUD(db_session, UserCollection)
|
||||
result = await db_crud.update(
|
||||
data=payload.dict(exclude_none=True),
|
||||
filters={'card_id': card_id, 'user_id': None}
|
||||
)
|
||||
return {'message': 'success' if result is not None else 'fail'}
|
||||
|
||||
|
||||
@card_router.post('/{card_id}/display/')
|
||||
async def display_card_status(
|
||||
card_id: int,
|
||||
status: bool,
|
||||
db_session: AsyncSession = Depends(get_async_session)
|
||||
):
|
||||
db_crud = CRUD(db_session, UserCollection)
|
||||
result = await db_crud.update(
|
||||
data={
|
||||
'displayed': status
|
||||
},
|
||||
filters={'card_id': card_id, 'user_id': None}
|
||||
)
|
||||
return {'message': 'success' if result is not None else 'fail'}
|
||||
|
||||
|
||||
@card_router.delete('/delete/', response_model=base_schema.BaseResponse)
|
||||
async def delete_card(
|
||||
payload: schema.DeleteCardIn,
|
||||
db_session: AsyncSession = Depends(get_async_session)
|
||||
):
|
||||
db_crud = CRUD(db_session, Card)
|
||||
state = await db_crud.delete(filters={'card_id_in': payload.card_ids})
|
||||
|
||||
if state is False:
|
||||
db_crud = CRUD(db_session, UserCollection)
|
||||
state = await db_crud.delete(filters={'card_id_in': payload.card_ids, 'user_id': None})
|
||||
|
||||
return {'message': 'success' if state else 'fail'}
|
||||
Reference in New Issue
Block a user