1
This commit is contained in:
@@ -24,11 +24,13 @@ UPLOAD_RATE_LIMIT = 5
|
||||
# 注意:/videos/feed、/videos/categories、/videos/search、/videos/upload/* 须先于 /videos/{video_id} 注册
|
||||
@router.get("/feed")
|
||||
async def get_feed(cursor: str | None = Query(None), limit: int = Query(10, ge=1, le=20),
|
||||
category_id: int | None = Query(None),
|
||||
category_id: int | None = Query(None), source_id: int | None = Query(None),
|
||||
type: str = Query("recommend", pattern="^(recommend|latest|hot|liked|viewed)$"),
|
||||
group: str | None = Query(None, pattern="^(series)$"),
|
||||
db: AsyncSession = Depends(get_db), redis: aioredis.Redis = Depends(get_redis),
|
||||
identity: Identity = Depends(get_identity)):
|
||||
return ok(await video_service.get_feed(db, redis, identity, type, cursor, limit, category_id))
|
||||
return ok(await video_service.get_feed(
|
||||
db, redis, identity, type, cursor, limit, category_id, source_id, group))
|
||||
|
||||
|
||||
@router.get("/categories")
|
||||
@@ -36,6 +38,12 @@ async def get_categories(db: AsyncSession = Depends(get_db)):
|
||||
return ok(await video_service.list_categories(db))
|
||||
|
||||
|
||||
@router.get("/sources")
|
||||
async def get_sources(db: AsyncSession = Depends(get_db)):
|
||||
"""内容来源列表(麻豆/91...),供 App 分类页筛选"""
|
||||
return ok(await video_service.list_sources(db))
|
||||
|
||||
|
||||
@router.get("/search")
|
||||
async def search_videos(request: Request, keyword: str = Query(min_length=1, max_length=30),
|
||||
sort: str = Query("hot", pattern="^(hot|latest)$"),
|
||||
@@ -103,6 +111,38 @@ async def delete_video(video_id: int, db: AsyncSession = Depends(get_db),
|
||||
return ok()
|
||||
|
||||
|
||||
# 站点管理员(按注册邮箱判定):可在 App 长按弹窗里下架任意视频
|
||||
SITE_ADMIN_EMAIL = "256kb@gmail.com"
|
||||
|
||||
|
||||
@router.post("/{video_id}/offline")
|
||||
async def offline_video_app(
|
||||
video_id: int,
|
||||
reason: str = Form(default="管理员长按下架"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
redis: aioredis.Redis = Depends(get_redis),
|
||||
identity: Identity = Depends(require_user),
|
||||
):
|
||||
"""App 端长按下架(仅限指定管理员邮箱);与后台 /admin/videos/{id}/offline 复用同一业务"""
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.core import errors
|
||||
from app.core.response import BizException
|
||||
from app.deps import AdminIdentity
|
||||
from app.models.user import User
|
||||
from app.services import admin_service
|
||||
|
||||
user = (await db.execute(
|
||||
select(User).where(User.id == identity.user_id)
|
||||
)).scalars().first()
|
||||
if user is None or (user.email or "").lower() != SITE_ADMIN_EMAIL:
|
||||
raise BizException(errors.FORBIDDEN, "无权限")
|
||||
|
||||
admin = AdminIdentity(admin_id=user.id, role="super")
|
||||
await admin_service.offline_video(db, redis, admin, video_id, reason, ip="app")
|
||||
return ok()
|
||||
|
||||
|
||||
@router.post("/{video_id}/watch")
|
||||
async def report_watch(video_id: int, req: WatchReq, db: AsyncSession = Depends(get_db),
|
||||
redis: aioredis.Redis = Depends(get_redis),
|
||||
@@ -141,6 +181,7 @@ async def get_series(series_id: int, db: AsyncSession = Depends(get_db)):
|
||||
"title": series.title,
|
||||
"cover_url": series.cover_url,
|
||||
"description": series.description,
|
||||
"source_id": series.source_id or 0,
|
||||
"total_episodes": len(eps),
|
||||
},
|
||||
"episodes": [
|
||||
@@ -181,6 +222,15 @@ async def get_video_series(video_id: int, db: AsyncSession = Depends(get_db)):
|
||||
prev_ep = all_eps[current_idx - 1] if current_idx > 0 else None
|
||||
next_ep = all_eps[current_idx + 1] if 0 <= current_idx < len(all_eps) - 1 else None
|
||||
|
||||
# 系列所属来源名称
|
||||
from app.models.video import Source
|
||||
|
||||
source_name = ""
|
||||
if series.source_id:
|
||||
source_name = (await db.execute(
|
||||
select(Source.name).where(Source.id == series.source_id)
|
||||
)).scalar_one_or_none() or ""
|
||||
|
||||
return ok({
|
||||
"has_series": True,
|
||||
"current_episode_no": video.episode_no,
|
||||
@@ -188,6 +238,8 @@ async def get_video_series(video_id: int, db: AsyncSession = Depends(get_db)):
|
||||
"id": series.id,
|
||||
"title": series.title,
|
||||
"cover_url": series.cover_url,
|
||||
"source_id": series.source_id or 0,
|
||||
"source_name": source_name,
|
||||
"total_episodes": len(all_eps),
|
||||
},
|
||||
"episodes": [
|
||||
|
||||
Reference in New Issue
Block a user