mirror of
https://github.com/Genshin-bots/gsuid_core.git
synced 2025-05-08 21:15:46 +08:00
✨ 网页控制台新增插件管理
This commit is contained in:
parent
54bf5df9c1
commit
b26fe93a19
8
.gitignore
vendored
8
.gitignore
vendored
@ -665,10 +665,8 @@ FodyWeavers.xsd
|
|||||||
config.json
|
config.json
|
||||||
res_data
|
res_data
|
||||||
GsData.db
|
GsData.db
|
||||||
GenshinUID
|
|
||||||
StarRailUID
|
|
||||||
data
|
data
|
||||||
plugins/*
|
gsuid_core/plugins/*
|
||||||
!plugins/core_command
|
!gsuid_core/plugins/core_command
|
||||||
!plugins/gs_test.py
|
!gsuid_core/plugins/gs_test.py
|
||||||
logs
|
logs
|
||||||
|
@ -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
|
from gsuid_core.utils.plugins_config.gs_config import ( # noqa: E402
|
||||||
all_config_list,
|
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()
|
app = FastAPI()
|
||||||
HOST = core_config.get_config('HOST')
|
HOST = core_config.get_config('HOST')
|
||||||
@ -95,6 +103,47 @@ def main():
|
|||||||
value = data[name]
|
value = data[name]
|
||||||
all_config_list[config_name].set_config(name, value)
|
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)
|
site.mount_app(app)
|
||||||
|
|
||||||
uvicorn.run(
|
uvicorn.run(
|
||||||
@ -102,23 +151,23 @@ def main():
|
|||||||
host=HOST,
|
host=HOST,
|
||||||
port=PORT,
|
port=PORT,
|
||||||
log_config={
|
log_config={
|
||||||
"version": 1,
|
'version': 1,
|
||||||
"disable_existing_loggers": False,
|
'disable_existing_loggers': False,
|
||||||
"handlers": {
|
'handlers': {
|
||||||
"default": {
|
'default': {
|
||||||
"class": "gsuid_core.logger.LoguruHandler",
|
'class': 'gsuid_core.logger.LoguruHandler',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"loggers": {
|
'loggers': {
|
||||||
"uvicorn.error": {"handlers": ["default"], "level": "INFO"},
|
'uvicorn.error': {'handlers': ['default'], 'level': 'INFO'},
|
||||||
"uvicorn.access": {
|
'uvicorn.access': {
|
||||||
"handlers": ["default"],
|
'handlers': ['default'],
|
||||||
"level": "INFO",
|
'level': 'INFO',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
from gsuid_core.sv import SV
|
from gsuid_core.sv import SV
|
||||||
from gsuid_core.bot import Bot
|
from gsuid_core.bot import Bot
|
||||||
from gsuid_core.models import Event
|
from gsuid_core.models import Event
|
||||||
|
from gsuid_core.utils.plugins_update._plugins import (
|
||||||
from ._plugins import (
|
|
||||||
refresh_list,
|
refresh_list,
|
||||||
update_plugins,
|
update_plugins,
|
||||||
get_plugins_url,
|
get_plugins_url,
|
||||||
|
@ -231,6 +231,10 @@ async def _deal_ck(bot_id: str, mes: str, user_id: str) -> str:
|
|||||||
|
|
||||||
if is_add_stoken:
|
if is_add_stoken:
|
||||||
im_list.append(f'添加Stoken成功,stuid={account_id},stoken={stoken}')
|
im_list.append(f'添加Stoken成功,stuid={account_id},stoken={stoken}')
|
||||||
|
|
||||||
|
if uid is None:
|
||||||
|
uid = '0'
|
||||||
|
|
||||||
await sqla.insert_user_data(
|
await sqla.insert_user_data(
|
||||||
user_id, uid, sr_uid, account_cookie, app_cookie
|
user_id, uid, sr_uid, account_cookie, app_cookie
|
||||||
)
|
)
|
||||||
|
@ -2,7 +2,7 @@ from typing import Dict, List, Union, Optional
|
|||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from git.repo import Repo
|
from git.repo import Repo
|
||||||
from git.exc import GitCommandError
|
from git.exc import GitCommandError, InvalidGitRepositoryError
|
||||||
|
|
||||||
from gsuid_core.logger import logger
|
from gsuid_core.logger import logger
|
||||||
|
|
||||||
@ -27,6 +27,12 @@ async def refresh_list() -> List[str]:
|
|||||||
return refresh_list
|
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]]:
|
async def get_plugins_url(name: str) -> Optional[Dict[str, str]]:
|
||||||
if not plugins_list:
|
if not plugins_list:
|
||||||
await refresh_list()
|
await refresh_list()
|
||||||
@ -50,9 +56,54 @@ def install_plugins(plugins: Dict[str, str]) -> str:
|
|||||||
if path.exists():
|
if path.exists():
|
||||||
return '该插件已经安装过了!'
|
return '该插件已经安装过了!'
|
||||||
Repo.clone_from(git_path, path, single_branch=True, depth=1)
|
Repo.clone_from(git_path, path, single_branch=True, depth=1)
|
||||||
|
logger.info(f'插件{plugin_name}安装成功!')
|
||||||
return f'插件{plugin_name}安装成功!发送[gs重启]以应用!'
|
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(
|
def update_plugins(
|
||||||
plugin_name: str,
|
plugin_name: str,
|
||||||
level: int = 0,
|
level: int = 0,
|
||||||
@ -66,10 +117,9 @@ def update_plugins(
|
|||||||
plugin_name = _name
|
plugin_name = _name
|
||||||
break
|
break
|
||||||
|
|
||||||
path = PLUGINS_PATH / plugin_name
|
repo = check_plugins(plugin_name)
|
||||||
if not path.exists():
|
if not repo:
|
||||||
return '更新失败, 不存在该插件!'
|
return '更新失败, 不存在该插件!'
|
||||||
repo = Repo(path) # type: ignore
|
|
||||||
o = repo.remotes.origin
|
o = repo.remotes.origin
|
||||||
|
|
||||||
if level >= 2:
|
if level >= 2:
|
@ -7,4 +7,4 @@ plugins_lib = 'https://docs.gsuid.gbots.work/plugin_list.json'
|
|||||||
|
|
||||||
proxy_url = 'https://ghproxy.com/'
|
proxy_url = 'https://ghproxy.com/'
|
||||||
|
|
||||||
PLUGINS_PATH = Path(__file__).parents[2]
|
PLUGINS_PATH = Path(__file__).parents[2] / 'plugins'
|
20
gsuid_core/webconsole/create_task_panel.py
Normal file
20
gsuid_core/webconsole/create_task_panel.py
Normal 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',
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import TypedDict
|
||||||
|
|
||||||
from fastapi_user_auth.auth.models import User
|
from fastapi_user_auth.auth.models import User
|
||||||
from fastapi_amis_admin.models.fields import Field
|
from fastapi_amis_admin.models.fields import Field
|
||||||
|
|
||||||
@ -8,3 +10,10 @@ class WebUser(User, table=True):
|
|||||||
parent_id: int = Field(
|
parent_id: int = Field(
|
||||||
None, title='Superior', foreign_key='auth_user.id'
|
None, title='Superior', foreign_key='auth_user.id'
|
||||||
) # type:ignore
|
) # type:ignore
|
||||||
|
|
||||||
|
|
||||||
|
class Task(TypedDict):
|
||||||
|
label: str
|
||||||
|
key: str
|
||||||
|
status: int
|
||||||
|
remark: str
|
||||||
|
@ -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.html import gsuid_webconsole_help
|
||||||
from gsuid_core.webconsole.create_sv_panel import get_sv_page
|
from gsuid_core.webconsole.create_sv_panel import get_sv_page
|
||||||
from gsuid_core.version import __version__ as GenshinUID_version
|
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.webconsole.create_config_panel import get_config_page
|
||||||
from gsuid_core.utils.database.models import GsBind, GsPush, GsUser, GsCache
|
from gsuid_core.utils.database.models import GsBind, GsPush, GsUser, GsCache
|
||||||
from gsuid_core.webconsole.login_page import ( # noqa # 不要删
|
from gsuid_core.webconsole.login_page import ( # noqa # 不要删
|
||||||
@ -395,7 +396,7 @@ class SVManagePage(GsAdminPage):
|
|||||||
class ConfigManagePage(GsAdminPage):
|
class ConfigManagePage(GsAdminPage):
|
||||||
page_schema = PageSchema(
|
page_schema = PageSchema(
|
||||||
label=('修改设定'),
|
label=('修改设定'),
|
||||||
icon='fa fa-sliders',
|
icon='fa fa-cogs',
|
||||||
url='/ConfigManage',
|
url='/ConfigManage',
|
||||||
isDefaultPage=True,
|
isDefaultPage=True,
|
||||||
sort=100,
|
sort=100,
|
||||||
@ -403,5 +404,17 @@ class ConfigManagePage(GsAdminPage):
|
|||||||
page = Page.parse_obj(get_config_page())
|
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)
|
site.unregister_admin(admin.HomeAdmin, APIDocsApp)
|
||||||
|
12
poetry.lock
generated
12
poetry.lock
generated
@ -667,14 +667,14 @@ reference = "mirrors"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastapi-amis-admin"
|
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."
|
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"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "fastapi_amis_admin-0.5.5-py3-none-any.whl", hash = "sha256:8faeece0962a7db0f807e68c09fa45ed75e79ba55c9990e734de486ee6bbf4c1"},
|
{file = "fastapi_amis_admin-0.5.6-py3-none-any.whl", hash = "sha256:df9160d4b28f2a2165c17ec678eddc2bfe7323c77c9dfdd8217a7e8b6895e99d"},
|
||||||
{file = "fastapi_amis_admin-0.5.5.tar.gz", hash = "sha256:b3c57f42fad800906cb39e0d1ea67d597747c09875ae74f20fda1d516e8b2580"},
|
{file = "fastapi_amis_admin-0.5.6.tar.gz", hash = "sha256:8bcb74d11d4e1b605b2d3eccecf308a6c5ffce65d4d8bef300de6764f0b64107"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -1054,14 +1054,14 @@ reference = "mirrors"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "identify"
|
name = "identify"
|
||||||
version = "2.5.23"
|
version = "2.5.24"
|
||||||
description = "File identification library for Python"
|
description = "File identification library for Python"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "identify-2.5.23-py2.py3-none-any.whl", hash = "sha256:17d9351c028a781456965e781ed2a435755cac655df1ebd930f7186b54399312"},
|
{file = "identify-2.5.24-py2.py3-none-any.whl", hash = "sha256:986dbfb38b1140e763e413e6feb44cd731faf72d1909543178aa79b0e258265d"},
|
||||||
{file = "identify-2.5.23.tar.gz", hash = "sha256:50b01b9d5f73c6b53e5fa2caf9f543d3e657a9d0bbdeb203ebb8d45960ba7433"},
|
{file = "identify-2.5.24.tar.gz", hash = "sha256:0aac67d5b4812498056d28a9a512a483f5085cc28640b02b258a59dac34301d4"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
|
@ -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"
|
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"
|
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"
|
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-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"
|
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"
|
frozenlist==1.3.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user