网页控制台新增插件管理

This commit is contained in:
Wuyi无疑 2023-05-06 01:04:53 +08:00
parent 54bf5df9c1
commit b26fe93a19
11 changed files with 173 additions and 31 deletions

8
.gitignore vendored
View File

@ -665,10 +665,8 @@ FodyWeavers.xsd
config.json
res_data
GsData.db
GenshinUID
StarRailUID
data
plugins/*
!plugins/core_command
!plugins/gs_test.py
gsuid_core/plugins/*
!gsuid_core/plugins/core_command
!gsuid_core/plugins/gs_test.py
logs

View File

@ -23,6 +23,14 @@ from gsuid_core.utils.plugins_config.models import ( # noqa: E402
from gsuid_core.utils.plugins_config.gs_config import ( # noqa: E402
all_config_list,
)
from gsuid_core.utils.plugins_update._plugins import ( # noqa: E402
check_status,
check_plugins,
install_plugin,
update_plugins,
check_can_update,
get_plugins_list,
)
app = FastAPI()
HOST = core_config.get_config('HOST')
@ -95,6 +103,47 @@ def main():
value = data[name]
all_config_list[config_name].set_config(name, value)
@app.get('/genshinuid/api/getPlugins')
@site.auth.requires('admin')
async def _get_plugins(request: Request):
tasks = []
plugins_list = await get_plugins_list()
for name in plugins_list:
plugin = plugins_list[name]
link = plugin['link']
plugin_name = link.split('/')[-1]
# git_path = f'{proxy_url}{link}.git'
sample = {
'label': plugin_name,
'key': name,
'status': check_status(plugin_name),
'remark': plugin['info'],
}
tasks.append(sample)
return tasks
@app.post('/genshinuid/api/updatePlugins')
@site.auth.requires('admin')
async def _update_plugins(request: Request, data: Dict):
repo = check_plugins(data['label'])
if repo:
if check_can_update(repo):
try:
update_plugins(data['label'])
retcode = 0
except: # noqa:E722
retcode = -1
else:
retcode = 0
else:
try:
retcode = await install_plugin(data['key'])
retcode = 0
except: # noqa:E722
retcode = -1
return {'status': retcode, 'msg': '', 'data': {}}
site.mount_app(app)
uvicorn.run(
@ -102,23 +151,23 @@ def main():
host=HOST,
port=PORT,
log_config={
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"default": {
"class": "gsuid_core.logger.LoguruHandler",
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'default': {
'class': 'gsuid_core.logger.LoguruHandler',
},
},
"loggers": {
"uvicorn.error": {"handlers": ["default"], "level": "INFO"},
"uvicorn.access": {
"handlers": ["default"],
"level": "INFO",
'loggers': {
'uvicorn.error': {'handlers': ['default'], 'level': 'INFO'},
'uvicorn.access': {
'handlers': ['default'],
'level': 'INFO',
},
},
},
)
if __name__ == "__main__":
if __name__ == '__main__':
main()

View File

@ -1,8 +1,7 @@
from gsuid_core.sv import SV
from gsuid_core.bot import Bot
from gsuid_core.models import Event
from ._plugins import (
from gsuid_core.utils.plugins_update._plugins import (
refresh_list,
update_plugins,
get_plugins_url,

View File

@ -231,6 +231,10 @@ async def _deal_ck(bot_id: str, mes: str, user_id: str) -> str:
if is_add_stoken:
im_list.append(f'添加Stoken成功,stuid={account_id},stoken={stoken}')
if uid is None:
uid = '0'
await sqla.insert_user_data(
user_id, uid, sr_uid, account_cookie, app_cookie
)

View File

@ -2,7 +2,7 @@ from typing import Dict, List, Union, Optional
import aiohttp
from git.repo import Repo
from git.exc import GitCommandError
from git.exc import GitCommandError, InvalidGitRepositoryError
from gsuid_core.logger import logger
@ -27,6 +27,12 @@ async def refresh_list() -> List[str]:
return refresh_list
async def get_plugins_list() -> Dict[str, Dict[str, str]]:
if not plugins_list:
await refresh_list()
return plugins_list
async def get_plugins_url(name: str) -> Optional[Dict[str, str]]:
if not plugins_list:
await refresh_list()
@ -50,9 +56,54 @@ def install_plugins(plugins: Dict[str, str]) -> str:
if path.exists():
return '该插件已经安装过了!'
Repo.clone_from(git_path, path, single_branch=True, depth=1)
logger.info(f'插件{plugin_name}安装成功!')
return f'插件{plugin_name}安装成功!发送[gs重启]以应用!'
async def install_plugin(plugin_name: str) -> int:
url = await get_plugins_url(plugin_name)
if url is None:
return -1
install_plugins(url)
return 0
def check_plugins(plugin_name: str) -> Optional[Repo]:
path = PLUGINS_PATH / plugin_name
if path.exists():
try:
repo = Repo(path)
except InvalidGitRepositoryError:
return None
return repo
else:
return None
def check_can_update(repo: Repo) -> bool:
try:
remote = repo.remote() # 获取远程仓库
remote.fetch() # 从远程获取最新版本
except GitCommandError as e:
logger.error(f'发生Git命令错误{e}!')
return False
local_commit = repo.commit() # 获取本地最新提交
remote_commit = remote.fetch()[0].commit # 获取远程最新提交
if local_commit.hexsha == remote_commit.hexsha: # 比较本地和远程的提交哈希值
return False
return True
def check_status(plugin_name: str) -> int:
repo = check_plugins(plugin_name)
if repo is None:
return 3
if check_can_update(repo):
return 1
else:
return 4
def update_plugins(
plugin_name: str,
level: int = 0,
@ -66,10 +117,9 @@ def update_plugins(
plugin_name = _name
break
path = PLUGINS_PATH / plugin_name
if not path.exists():
repo = check_plugins(plugin_name)
if not repo:
return '更新失败, 不存在该插件!'
repo = Repo(path) # type: ignore
o = repo.remotes.origin
if level >= 2:

View File

@ -7,4 +7,4 @@ plugins_lib = 'https://docs.gsuid.gbots.work/plugin_list.json'
proxy_url = 'https://ghproxy.com/'
PLUGINS_PATH = Path(__file__).parents[2]
PLUGINS_PATH = Path(__file__).parents[2] / 'plugins'

View File

@ -0,0 +1,20 @@
def get_tasks_panel():
return {
'type': 'tasks',
'name': 'tasks',
'items': [{'label': '加载中, 请稍等...', 'key': 'wait', 'status': 2}],
'id': 'u:571849ba0356',
'initialStatusCode': 0,
'readyStatusCode': 1,
'loadingStatusCode': 2,
'errorStatusCode': 3,
'finishStatusCode': 4,
'canRetryStatusCode': 5,
'statusTextMap': ['未开始', '可更新', '安装中', '未安装', '已最新', '出错'],
'taskNameLabel': '插件列表',
'operationLabel': '操作',
'remarkLabel': '备注说明',
'btnText': '安装/更新',
'submitApi': 'post:/genshinuid/api/updatePlugins',
'checkApi': 'get:/genshinuid/api/getPlugins',
}

View File

@ -1,3 +1,5 @@
from typing import TypedDict
from fastapi_user_auth.auth.models import User
from fastapi_amis_admin.models.fields import Field
@ -8,3 +10,10 @@ class WebUser(User, table=True):
parent_id: int = Field(
None, title='Superior', foreign_key='auth_user.id'
) # type:ignore
class Task(TypedDict):
label: str
key: str
status: int
remark: str

View File

@ -43,6 +43,7 @@ from gsuid_core.utils.cookie_manager.add_ck import _deal_ck
from gsuid_core.webconsole.html import gsuid_webconsole_help
from gsuid_core.webconsole.create_sv_panel import get_sv_page
from gsuid_core.version import __version__ as GenshinUID_version
from gsuid_core.webconsole.create_task_panel import get_tasks_panel
from gsuid_core.webconsole.create_config_panel import get_config_page
from gsuid_core.utils.database.models import GsBind, GsPush, GsUser, GsCache
from gsuid_core.webconsole.login_page import ( # noqa # 不要删
@ -395,7 +396,7 @@ class SVManagePage(GsAdminPage):
class ConfigManagePage(GsAdminPage):
page_schema = PageSchema(
label=('修改设定'),
icon='fa fa-sliders',
icon='fa fa-cogs',
url='/ConfigManage',
isDefaultPage=True,
sort=100,
@ -403,5 +404,17 @@ class ConfigManagePage(GsAdminPage):
page = Page.parse_obj(get_config_page())
@site.register_admin
class PluginsManagePage(GsAdminPage):
page_schema = PageSchema(
label=('插件管理'),
icon='fa fa-puzzle-piece',
url='/ConfigManage',
isDefaultPage=True,
sort=100,
)
page = Page.parse_obj(get_tasks_panel())
# 取消注册默认管理类
site.unregister_admin(admin.HomeAdmin, APIDocsApp)

12
poetry.lock generated
View File

@ -667,14 +667,14 @@ reference = "mirrors"
[[package]]
name = "fastapi-amis-admin"
version = "0.5.5"
version = "0.5.6"
description = "FastAPI-Amis-Admin is a high-performance, efficient and easily extensible FastAPI admin framework. Inspired by Django-admin, and has as many powerful functions as Django-admin."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "fastapi_amis_admin-0.5.5-py3-none-any.whl", hash = "sha256:8faeece0962a7db0f807e68c09fa45ed75e79ba55c9990e734de486ee6bbf4c1"},
{file = "fastapi_amis_admin-0.5.5.tar.gz", hash = "sha256:b3c57f42fad800906cb39e0d1ea67d597747c09875ae74f20fda1d516e8b2580"},
{file = "fastapi_amis_admin-0.5.6-py3-none-any.whl", hash = "sha256:df9160d4b28f2a2165c17ec678eddc2bfe7323c77c9dfdd8217a7e8b6895e99d"},
{file = "fastapi_amis_admin-0.5.6.tar.gz", hash = "sha256:8bcb74d11d4e1b605b2d3eccecf308a6c5ffce65d4d8bef300de6764f0b64107"},
]
[package.dependencies]
@ -1054,14 +1054,14 @@ reference = "mirrors"
[[package]]
name = "identify"
version = "2.5.23"
version = "2.5.24"
description = "File identification library for Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "identify-2.5.23-py2.py3-none-any.whl", hash = "sha256:17d9351c028a781456965e781ed2a435755cac655df1ebd930f7186b54399312"},
{file = "identify-2.5.23.tar.gz", hash = "sha256:50b01b9d5f73c6b53e5fa2caf9f543d3e657a9d0bbdeb203ebb8d45960ba7433"},
{file = "identify-2.5.24-py2.py3-none-any.whl", hash = "sha256:986dbfb38b1140e763e413e6feb44cd731faf72d1909543178aa79b0e258265d"},
{file = "identify-2.5.24.tar.gz", hash = "sha256:0aac67d5b4812498056d28a9a512a483f5085cc28640b02b258a59dac34301d4"},
]
[package.extras]

View File

@ -17,7 +17,7 @@ click==8.1.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
colorama==0.4.6 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0" and platform_system == "Windows" or python_full_version >= "3.8.1" and python_full_version < "4.0.0" and sys_platform == "win32"
dnspython==2.3.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
email-validator==2.0.0.post2 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi-amis-admin==0.5.5 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi-amis-admin==0.5.6 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi-user-auth==0.5.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi==0.95.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
frozenlist==1.3.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"