This commit is contained in:
jxxghp 2023-06-19 15:44:24 +08:00
parent 6417659f14
commit 5f48d9d4a2
16 changed files with 130 additions and 48 deletions

View File

@ -21,7 +21,7 @@ def start_douban_chain():
DoubanChain().sync()
@router.get("/sync", response_model=schemas.Response)
@router.get("/sync", summary="同步豆瓣想看", response_model=schemas.Response)
async def sync_douban(
background_tasks: BackgroundTasks,
_: User = Depends(get_current_active_superuser)) -> Any:
@ -32,7 +32,7 @@ async def sync_douban(
return schemas.Response(success=True, message="任务已启动")
@router.get("/id", response_model=schemas.Context)
@router.get("/id", summary="豆瓣ID识别", response_model=schemas.Context)
async def recognize_doubanid(doubanid: str,
_: User = Depends(get_current_active_user)) -> Any:
"""
@ -43,7 +43,7 @@ async def recognize_doubanid(doubanid: str,
return context.to_dict()
@router.get("/info", response_model=schemas.MediaInfo)
@router.get("/info", summary="查询豆瓣详情", response_model=schemas.MediaInfo)
async def douban_info(doubanid: str) -> Any:
"""
根据豆瓣ID查询豆瓣媒体信息
@ -55,7 +55,7 @@ async def douban_info(doubanid: str) -> Any:
return schemas.MediaInfo()
@router.get("/movies", response_model=List[schemas.MediaInfo])
@router.get("/movies", summary="豆瓣电影", response_model=List[schemas.MediaInfo])
async def douban_movies(sort: str = "R",
tags: str = "",
start: int = 0,
@ -71,7 +71,7 @@ async def douban_movies(sort: str = "R",
return [MediaInfo(douban_info=movie).to_dict() for movie in movies]
@router.get("/tvs", response_model=List[schemas.MediaInfo])
@router.get("/tvs", summary="豆瓣剧集", response_model=List[schemas.MediaInfo])
async def douban_tvs(sort: str = "R",
tags: str = "",
start: int = 0,
@ -87,7 +87,7 @@ async def douban_tvs(sort: str = "R",
return [MediaInfo(douban_info=tv).to_dict() for tv in tvs]
@router.get("/movie_top250", response_model=List[schemas.MediaInfo])
@router.get("/movie_top250", summary="豆瓣电影TOP250", response_model=List[schemas.MediaInfo])
async def movie_top250(page: int = 1,
count: int = 30,
_: User = Depends(get_current_active_user)) -> Any:
@ -98,7 +98,7 @@ async def movie_top250(page: int = 1,
return [MediaInfo(douban_info=movie).to_dict() for movie in movies]
@router.get("/tv_weekly_chinese", response_model=List[schemas.MediaInfo])
@router.get("/tv_weekly_chinese", summary="豆瓣国产剧集周榜", response_model=List[schemas.MediaInfo])
async def tv_weekly_chinese(page: int = 1,
count: int = 30,
_: User = Depends(get_current_active_user)) -> Any:
@ -109,7 +109,7 @@ async def tv_weekly_chinese(page: int = 1,
return [MediaInfo(douban_info=tv).to_dict() for tv in tvs]
@router.get("/tv_weekly_global", response_model=List[schemas.MediaInfo])
@router.get("/tv_weekly_global", summary="豆瓣全球剧集周榜", response_model=List[schemas.MediaInfo])
async def tv_weekly_global(page: int = 1,
count: int = 30,
_: User = Depends(get_current_active_user)) -> Any:

View File

@ -14,7 +14,7 @@ from app.db.models.user import User
router = APIRouter()
@router.post("/login/access-token", response_model=schemas.Token)
@router.post("/login/access-token", summary="获取token", response_model=schemas.Token)
async def login_access_token(
db: Session = Depends(get_db), form_data: OAuth2PasswordRequestForm = Depends()
) -> Any:

View File

@ -10,19 +10,19 @@ from app.db.userauth import get_current_active_user
router = APIRouter()
@router.get("/recognize", response_model=schemas.Context)
@router.get("/recognize", summary="识别媒体信息", response_model=schemas.Context)
async def recognize(title: str,
subtitle: str = None,
_: User = Depends(get_current_active_user)) -> Any:
"""
识别媒体信息
根据标题副标题识别媒体信息
"""
# 识别媒体信息
context = MediaChain().recognize_by_title(title=title, subtitle=subtitle)
return context.to_dict()
@router.get("/search", response_model=List[schemas.MediaInfo])
@router.get("/search", summary="搜索媒体信息", response_model=List[schemas.MediaInfo])
async def search_by_title(title: str,
_: User = Depends(get_current_active_user)) -> Any:
"""

View File

@ -20,7 +20,7 @@ def start_message_chain(body: Any, form: Any, args: Any):
MessageChain().process(body=body, form=form, args=args)
@router.post("/", response_model=schemas.Response)
@router.post("/", summary="接收用户消息", response_model=schemas.Response)
async def user_message(background_tasks: BackgroundTasks, request: Request):
"""
用户消息响应
@ -32,7 +32,7 @@ async def user_message(background_tasks: BackgroundTasks, request: Request):
return schemas.Response(success=True)
@router.get("/")
@router.get("/", summary="微信验证")
async def wechat_verify(echostr: str, msg_signature: str,
timestamp: Union[str, int], nonce: str) -> Any:
"""

View File

@ -10,7 +10,7 @@ from app.db.userauth import get_current_active_user
router = APIRouter()
@router.get("/", response_model=schemas.Response)
@router.get("/", summary="运行插件方法", response_model=schemas.Response)
@router.post("/")
async def run_plugin_method(plugin_id: str, method: str,
_: User = Depends(get_current_active_user),
@ -23,3 +23,7 @@ async def run_plugin_method(plugin_id: str, method: str,
method=method,
*args,
**kwargs)
# 注册插件API
for api in PluginManager().get_plugin_apis():
router.add_api_route(**api)

View File

@ -11,7 +11,7 @@ from app.schemas.types import MediaType
router = APIRouter()
@router.get("/tmdbid", response_model=List[schemas.Context])
@router.get("/tmdbid", summary="精确搜索资源", response_model=List[schemas.Context])
async def search_by_tmdbid(tmdbid: int,
mtype: str = None,
_: User = Depends(get_current_active_user)) -> Any:
@ -24,7 +24,7 @@ async def search_by_tmdbid(tmdbid: int,
return [torrent.to_dict() for torrent in torrents]
@router.get("/title", response_model=List[schemas.TorrentInfo])
@router.get("/title", summary="模糊搜索资源", response_model=List[schemas.TorrentInfo])
async def search_by_title(title: str,
_: User = Depends(get_current_active_user)) -> Any:
"""

View File

@ -14,7 +14,7 @@ from app.db.userauth import get_current_active_user, get_current_active_superuse
router = APIRouter()
@router.get("/", response_model=List[schemas.Site])
@router.get("/", summary="所有站点", response_model=List[schemas.Site])
async def read_sites(db: Session = Depends(get_db),
_: User = Depends(get_current_active_user)) -> List[dict]:
"""
@ -23,7 +23,7 @@ async def read_sites(db: Session = Depends(get_db),
return Site.list(db)
@router.put("/", response_model=schemas.Site)
@router.put("/", summary="更新站点", response_model=schemas.Site)
async def update_site(
*,
db: Session = Depends(get_db),
@ -43,7 +43,7 @@ async def update_site(
return site
@router.get("/{site_id}", response_model=schemas.Site)
@router.get("/{site_id}", summary="站点详情", response_model=schemas.Site)
async def read_site(
site_id: int,
db: Session = Depends(get_db),
@ -61,7 +61,7 @@ async def read_site(
return site
@router.get("/cookiecloud", response_model=schemas.Response)
@router.get("/cookiecloud", summary="CookieCloud同步", response_model=schemas.Response)
async def cookie_cloud_sync(_: User = Depends(get_current_active_user)) -> Any:
"""
运行CookieCloud同步站点信息
@ -72,7 +72,7 @@ async def cookie_cloud_sync(_: User = Depends(get_current_active_user)) -> Any:
return schemas.Response(success=True, message="同步成功!")
@router.get("/cookie", response_model=schemas.Response)
@router.get("/cookie", summary="更新站点Cookie&UA", response_model=schemas.Response)
async def update_cookie(
site_id: int,
username: str,

View File

@ -24,7 +24,7 @@ def start_subscribe_chain(title: str, year: str,
mtype=mtype, tmdbid=tmdbid, season=season, username=username)
@router.get("/", response_model=List[schemas.Subscribe])
@router.get("/", summary="所有订阅", response_model=List[schemas.Subscribe])
async def read_subscribes(
db: Session = Depends(get_db),
_: User = Depends(get_current_active_superuser)) -> Any:
@ -34,7 +34,7 @@ async def read_subscribes(
return Subscribe.list(db)
@router.post("/", response_model=schemas.Response)
@router.post("/", summary="新增订阅", response_model=schemas.Response)
async def create_subscribe(
*,
subscribe_in: schemas.Subscribe,
@ -47,7 +47,7 @@ async def create_subscribe(
return schemas.Response(success=result)
@router.put("/", response_model=schemas.Subscribe)
@router.put("/", summary="更新订阅", response_model=schemas.Subscribe)
async def update_subscribe(
*,
db: Session = Depends(get_db),
@ -67,7 +67,7 @@ async def update_subscribe(
return subscribe
@router.delete("/", response_model=schemas.Response)
@router.delete("/", summary="删除订阅", response_model=schemas.Response)
async def delete_subscribe(
*,
db: Session = Depends(get_db),
@ -81,7 +81,7 @@ async def delete_subscribe(
return schemas.Response(success=True)
@router.post("/seerr", response_model=schemas.Response)
@router.post("/seerr", summary="OverSeerr/JellySeerr通知订阅", response_model=schemas.Response)
async def seerr_subscribe(request: Request, background_tasks: BackgroundTasks,
authorization: str = Header(None)) -> Any:
"""
@ -134,7 +134,7 @@ async def seerr_subscribe(request: Request, background_tasks: BackgroundTasks,
return schemas.Response(success=True)
@router.get("/refresh", response_model=schemas.Response)
@router.get("/refresh", summary="刷新订阅", response_model=schemas.Response)
async def refresh_subscribes(
_: User = Depends(get_current_active_superuser)) -> Any:
"""
@ -144,7 +144,7 @@ async def refresh_subscribes(
return schemas.Response(success=True)
@router.get("/search", response_model=schemas.Response)
@router.get("/search", summary="搜索订阅", response_model=schemas.Response)
async def search_subscribes(
_: User = Depends(get_current_active_superuser)) -> Any:
"""

View File

@ -12,10 +12,10 @@ from app.schemas.types import MediaType
router = APIRouter()
@router.get("/info", response_model=schemas.MediaInfo)
@router.get("/info", summary="TMDB详情", response_model=schemas.MediaInfo)
async def tmdb_info(tmdbid: int, type_name: str) -> Any:
"""
根据TMDBID查询themoviedb媒体信息
根据TMDBID查询themoviedb媒体信息type_name: 电影/电视剧
"""
mtype = MediaType.MOVIE if type_name == MediaType.MOVIE.value else MediaType.TV
tmdbinfo = TmdbChain().tmdb_info(tmdbid=tmdbid, mtype=mtype)
@ -25,7 +25,7 @@ async def tmdb_info(tmdbid: int, type_name: str) -> Any:
return MediaInfo(tmdb_info=tmdbinfo).to_dict()
@router.get("/movies", response_model=List[schemas.MediaInfo])
@router.get("/movies", summary="TMDB电影", response_model=List[schemas.MediaInfo])
async def tmdb_movies(sort_by: str = "popularity.desc",
with_genres: str = "",
with_original_language: str = "",
@ -44,7 +44,7 @@ async def tmdb_movies(sort_by: str = "popularity.desc",
return [MediaInfo(tmdb_info=movie).to_dict() for movie in movies]
@router.get("/tvs", response_model=List[schemas.MediaInfo])
@router.get("/tvs", summary="TMDB剧集", response_model=List[schemas.MediaInfo])
async def tmdb_tvs(sort_by: str = "popularity.desc",
with_genres: str = "",
with_original_language: str = "",
@ -63,7 +63,7 @@ async def tmdb_tvs(sort_by: str = "popularity.desc",
return [MediaInfo(tmdb_info=tv).to_dict() for tv in tvs]
@router.get("/trending", response_model=List[schemas.MediaInfo])
@router.get("/trending", summary="TMDB流行趋势", response_model=List[schemas.MediaInfo])
async def tmdb_trending(page: int = 1,
_: User = Depends(get_current_active_user)) -> Any:
"""

View File

@ -12,7 +12,7 @@ from app.db.userauth import get_current_active_superuser, get_current_active_use
router = APIRouter()
@router.get("/", response_model=List[schemas.User])
@router.get("/", summary="所有用户", response_model=List[schemas.User])
async def read_users(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_active_superuser),
@ -24,7 +24,7 @@ async def read_users(
return users
@router.post("/", response_model=schemas.User)
@router.post("/", summary="新增用户", response_model=schemas.User)
async def create_user(
*,
db: Session = Depends(get_db),
@ -49,7 +49,7 @@ async def create_user(
return user
@router.put("/", response_model=schemas.User)
@router.put("/", summary="更新用户", response_model=schemas.User)
async def update_user(
*,
db: Session = Depends(get_db),
@ -73,7 +73,7 @@ async def update_user(
return user
@router.delete("/", response_model=schemas.Response)
@router.delete("/", summary="删除用户", response_model=schemas.Response)
async def delete_user(
*,
db: Session = Depends(get_db),
@ -93,7 +93,7 @@ async def delete_user(
return schemas.Response(success=True)
@router.get("/{user_id}", response_model=schemas.User)
@router.get("/{user_id}", summary="用户详情", response_model=schemas.User)
async def read_user_by_id(
user_id: int,
current_user: User = Depends(get_current_active_user),

View File

@ -16,7 +16,7 @@ def start_webhook_chain(body: Any, form: Any, args: Any):
WebhookChain().message(body=body, form=form, args=args)
@router.post("/", response_model=schemas.Response)
@router.post("/", summary="Webhook消息响应", response_model=schemas.Response)
async def webhook_message(background_tasks: BackgroundTasks,
token: str, request: Request) -> Any:
"""

View File

@ -102,6 +102,27 @@ class PluginManager(metaclass=Singleton):
ret_commands += plugin.get_command()
return ret_commands
def get_plugin_apis(self) -> List[Dict[str, Any]]:
"""
获取插件API
[{
"path": "/xx",
"endpoint": self.xxx,
"methods": ["GET", "POST"],
"summary": "API名称",
"description": "API说明"
}]
"""
ret_apis = []
for pid, plugin in self._running_plugins.items():
if hasattr(plugin, "get_api") \
and ObjectUtils.check_method(plugin.get_api):
apis = plugin.get_api()
for api in apis:
api["path"] = f"/{pid}{api['path']}"
ret_apis.extend(apis)
return ret_apis
def run_plugin_method(self, pid: str, method: str, *args, **kwargs) -> Any:
"""
运行插件方法

View File

@ -3,8 +3,6 @@ from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from uvicorn import Config
from app.api.apiv1 import api_router
from app.api.servarr import arr_router
from app.command import Command
from app.core.config import settings
from app.core.module import ModuleManager
@ -27,16 +25,22 @@ App.add_middleware(
allow_headers=["*"],
)
# API路由
App.include_router(api_router, prefix=settings.API_V1_STR)
# Radarr、Sonarr路由
App.include_router(arr_router, prefix="/api/v3")
# uvicorn服务
Server = uvicorn.Server(Config(App, host=settings.HOST, port=settings.PORT, reload=settings.RELOAD))
def init_routers():
"""
初始化路由
"""
from app.api.apiv1 import api_router
from app.api.servarr import arr_router
# API路由
App.include_router(api_router, prefix=settings.API_V1_STR)
# Radarr、Sonarr路由
App.include_router(arr_router, prefix="/api/v3")
@App.on_event("shutdown")
def shutdown_server():
"""
@ -71,6 +75,8 @@ def start_module():
Command()
# 站点管理
SitesHelper()
# 初始化路由
init_routers()
if __name__ == '__main__':

View File

@ -60,6 +60,20 @@ class _PluginBase(metaclass=ABCMeta):
"""
pass
@abstractmethod
def get_api(self) -> List[Dict[str, Any]]:
"""
获取插件API
[{
"path": "/xx",
"endpoint": self.xxx,
"methods": ["GET", "POST"],
"summary": "API名称",
"description": "API说明"
}]
"""
pass
@abstractmethod
def stop_service(self):
"""

View File

@ -25,6 +25,7 @@ from app.schemas.types import EventType
class AutoSignIn(_PluginBase):
# 插件名称
plugin_name = "站点自动签到"
# 插件描述
@ -78,6 +79,24 @@ class AutoSignIn(_PluginBase):
"data": {}
}]
def get_api(self) -> List[Dict[str, Any]]:
"""
获取插件API
[{
"path": "/xx",
"endpoint": self.xxx,
"methods": ["GET", "POST"],
"summary": "API说明"
}]
"""
return [{
"path": "/signin_by_domain",
"endpoint": self.signin_by_domain,
"methods": ["GET"],
"summary": "站点签到",
"description": "使用站点域名签到站点",
}]
@eventmanager.register(EventType.SiteSignin)
def sign_in(self, event: Event = None):
"""

View File

@ -77,6 +77,24 @@ class SiteStatistic(_PluginBase):
"data": {}
}]
def get_api(self) -> List[Dict[str, Any]]:
"""
获取插件API
[{
"path": "/xx",
"endpoint": self.xxx,
"methods": ["GET", "POST"],
"summary": "API说明"
}]
"""
return [{
"path": "/refresh_by_domain",
"endpoint": self.refresh_by_domain,
"methods": ["GET"],
"summary": "刷新站点数据",
"description": "刷新对应域名的站点数据",
}]
def stop_service(self):
pass