feat: dashboard partially

This commit is contained in:
Soulter
2023-12-12 20:23:39 +08:00
parent 63aa6ee9a5
commit 99ff8bc1f5
7 changed files with 145 additions and 48 deletions
+31
View File
@@ -0,0 +1,31 @@
from addons.dashboard.server import AstrBotDashBoard, DashBoardData
from pydantic import BaseModel
from typing import Union, Optional,
class DashBoardConfig(BaseModel):
type: str["group", "item"]
name: str
description: str
body: Union[dict, list]
value: Optional[Union[list, dict, str, int, bool]]
val_type: Optional[str["list", "dict", "str", "int", "bool"]]
body: Optional['DashBoardConfig']
class DashBoardHelper():
def __init__(self, dashboard_data: DashBoardData):
self.dashboard_data = dashboard_data
self.dashboard = AstrBotDashBoard(self.dashboard_data)
@self.dashboard.register("post_configs")
def on_post_configs(configs: dict):
self.dashboard_data.configs = configs
return True
# 将 config.yaml、 中的配置解析到 dashboard_data.configs 中
def parse_config(self, config: dict):
pass
def run(self):
self.dashboard.run()
+68
View File
@@ -0,0 +1,68 @@
from flask import Flask
import datetime
from pydantic import BaseModel
from util import general_utils as gu
class DashBoardData(BaseModel):
stats: dict
configs: dict
logs: dict
class Response(BaseModel):
status: str
message: str
data: dict
class AstrBotDashBoard():
def __init__(self, dashboard_data: DashBoardData):
self.dashboard_data = dashboard_data
self.dashboard_be = Flask(__name__)
self.funcs = {}
@self.dashboard_be.get("/stats")
def get_stats():
return Response(
status="success",
message="",
data=self.dashboard_data.stats
).dict()
@self.dashboard_be.get("/configs")
def get_configs():
return Response(
status="success",
message="",
data=self.dashboard_data.configs
).__dict__
@self.dashboard_be.post("/configs")
def post_configs():
if self.funcs["post_configs"](self.dashboard_data.configs):
return Response(
status="success",
message="",
data=self.dashboard_data.configs
).__dict__
return Response(
status="error",
message="",
data=self.dashboard_data.configs
).__dict__
@self.dashboard_be.get("/logs")
def get_logs():
return Response(
status="success",
message="",
data=self.dashboard_data.logs
).__dict__
def register(self, name: str):
def decorator(func):
self.funcs[name] = func
return func
return decorator
def run(self):
gu.log(f"\n\n==================\n您可以访问:\n\thttp://localhost:6185/\n来登录可视化面板。\n==================\n\n", tag="可视化面板")
self.dashboard_be.run(host="0.0.0.0", port=6185)
+15 -33
View File
@@ -39,7 +39,7 @@ import io
import traceback
from . global_object import GlobalObject
from typing import Union, Callable
from addons.dashboard.helper import DashBoardHelper
# 缓存的会话
session_dict = {}
@@ -48,9 +48,6 @@ count = {}
# 统计信息
stat_file = ''
# 日志记录
# logf = open('log.log', 'a+', encoding='utf-8')
# 用户发言频率
user_frequency = {}
# 时间默认值
@@ -64,11 +61,8 @@ announcement = ""
# 机器人私聊模式
direct_message_mode = True
# 适配pyinstaller
abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
# 版本
version = '3.0.4'
version = '3.1.0'
# 语言模型
REV_CHATGPT = 'rev_chatgpt'
@@ -160,27 +154,6 @@ def _runner(func: Callable, args: tuple):
loop.run_until_complete(func(*args))
loop.close()
# [Deprecated] 写入统计信息
def toggle_count(at: bool, message):
global stat_file
try:
if str(message.guild_id) not in count:
count[str(message.guild_id)] = {
'count': 1,
'direct_count': 1,
}
else:
count[str(message.guild_id)]['count'] += 1
if not at:
count[str(message.guild_id)]['direct_count'] += 1
stat_file = open(abs_path+"configs/stat", 'w', encoding='utf-8')
stat_file.write(json.dumps(count))
stat_file.flush()
stat_file.close()
except BaseException:
pass
# 上传统计信息并检查更新
def upload():
global version, gocq_bot, qqchannel_bot
@@ -228,6 +201,9 @@ def initBot(cfg, prov):
global baidu_judge, chosen_provider
global frequency_count, frequency_time, announcement, direct_message_mode, version
global keywords, _global_object
# 迁移旧配置
gu.try_migrate_config()
_event_loop = asyncio.new_event_loop()
asyncio.set_event_loop(_event_loop)
@@ -410,7 +386,7 @@ def initBot(cfg, prov):
# thread.join()
if thread_inst == None:
raise Exception("[System-Error] 没有启用/成功启用任何机器人,程序退出")
gu.log("没有启用/成功启用任何机器人平台", gu.LEVEL_CRITICAL)
default_personality_str = cc.get("default_personality_str", "")
if default_personality_str == "":
@@ -420,12 +396,18 @@ def initBot(cfg, prov):
"name": "default",
"prompt": default_personality_str,
}
# 初始化dashboard
dashboard_helper = DashBoardHelper(_global_object.dashboard_data)
dashboard_helper.parse_config(cfg)
dashboard_thread = threading.Thread(target=dashboard_helper.run, daemon=True)
dashboard_thread.start()
gu.log("🎉 项目启动完成。")
# asyncio.get_event_loop().run_until_complete(cli())
asyncio.get_event_loop().run_until_complete(cli())
thread_inst.join()
dashboard_thread.join()
async def cli():
time.sleep(1)
+3
View File
@@ -1,6 +1,7 @@
from model.platform.qqchan import QQChan, NakuruGuildMember, NakuruGuildMessage
from model.platform.qq import QQ
from model.provider.provider import Provider
from addons.dashboard.server import DashBoardData
from nakuru import (
CQHTTP,
GroupMessage,
@@ -27,6 +28,7 @@ class GlobalObject:
platform_qq: QQ
platform_qqchan: QQChan
default_personality: dict
dashboard_data: DashBoardData
def __init__(self):
self.nick = None # gocq 的昵称
@@ -41,6 +43,7 @@ class GlobalObject:
self.platform_qq = None
self.platform_qqchan = None
self.default_personality = None
self.dashboard_data = None
class AstrMessageEvent():
message_str: str # 纯消息字符串
+7 -3
View File
@@ -3,12 +3,17 @@ from pip._internal import main as pipmain
import warnings
import traceback
import threading
import logging
warnings.filterwarnings("ignore")
abs_path = os.path.dirname(os.path.realpath(sys.argv[0])) + '/'
def main():
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%H:%M:%S',
)
# config.yaml 配置文件加载和环境确认
try:
import cores.qqbot.core as qqBot
@@ -112,7 +117,6 @@ def get_platform():
print("other")
if __name__ == "__main__":
args = sys.argv
if '-cn' in args:
@@ -123,7 +127,7 @@ if __name__ == "__main__":
if '-replit' in args:
print("[System] 启动Replit Web保活服务...")
try:
from webapp_replit import keep_alive
from util.webapp_replit import keep_alive
keep_alive()
except BaseException as e:
print(e)
+21 -12
View File
@@ -5,6 +5,7 @@ from PIL import Image, ImageDraw, ImageFont
import os
import re
import requests
from util.cmd_config import CmdConfig
PLATFORM_GOCQ = 'gocq'
PLATFORM_QQCHAN = 'qqchan'
@@ -79,7 +80,14 @@ def log(
if len(msg) > max_len:
msg = msg[:max_len] + "..."
now = datetime.datetime.now().strftime("%m-%d %H:%M:%S")
pre = f"[{now}] [{level}] [{tag}]: {msg}"
pres = []
for line in msg.split("\n"):
if line == "\n":
pres.append("")
else:
pres.append(f"[{now}] [{level}] [{tag}]: {line}")
if level == "INFO":
if fg is None:
fg = FG_COLORS["green"]
@@ -100,8 +108,11 @@ def log(
fg = FG_COLORS["purple"]
if bg is None:
bg = BG_COLORS["default"]
print(f"\033[{fg};{bg}m{pre}\033[0m")
ret = ""
for line in pres:
ret += f"\033[{fg};{bg}m{line}\033[0m\n"
print(ret)
def port_checker(port: int, host: str = "localhost"):
@@ -501,14 +512,12 @@ def create_markdown_image(text: str):
return p
except Exception as e:
raise e
def test_markdown():
# 示例使用
markdown_text = """# Help Center
! [] (https://soulter.top/helpme.jpg)
"""
image = render_markdown(markdown_text)
image.show()
# test_markdown()
# 迁移配置文件到 cmd_config.json
def try_migrate_config(old_config: dict):
cc = CmdConfig()
if cc.get("qqbot", None) is None:
# 未迁移过
for k in old_config:
cc.put(k, old_config[k])