modified: README.md

new file:   app.py
new file:   config/config.toml
new file:   requirements.txt
new file:   run.bat
new file:   run.sh
new file:   src/__init__.py
new file:   src/file_store_api.py
new file:   src/mainprocess.py
new file:   src/modules/__init__.py
new file:   src/modules/plugin_modules.py
new file:   src/modules/user_modules.py
new file:   src/plugin_manager.py
This commit is contained in:
JianFeeeee
2025-08-13 19:41:56 +08:00
parent 0ddb6c3fd3
commit 7d1ccfba46
13 changed files with 1227 additions and 2 deletions

0
src/modules/__init__.py Normal file
View File

View File

@ -0,0 +1,113 @@
from abc import ABC, abstractmethod
from typing import Optional
from dataclasses import dataclass
import shutil
import zipfile
from pathlib import Path
from src.modules import user_modules as usermod
import src.file_store_api as file_M
class MessageContext:
"""封装消息处理的上下文数据"""
def __init__(self, uid: str, gid: Optional[str], raw_message: str,id:str):
self.raw_message = raw_message
self._processed = False
self.response: Optional[str] = None
# 核心服务实例化
self.chat_manager = file_M.ChatManager()
self.user = usermod.User(user_id=uid)
self.rebot_id = id
# 动态加载数据
if gid:
self.group = usermod.Group(group_id=gid)
self.group.current_user = self.user
else:
self.group = None
@dataclass
class PluginPermission:
access_private: bool = False # 允许处理私聊消息
access_group: bool = True # 允许处理群消息
read_history: bool = False # 允许读取历史记录
from pathlib import Path
import toml
import os
class BasePlugin(ABC):
def __init__(self, ctx: MessageContext):
self.ctx = ctx
self._config_dir = self._get_plugin_config_path()
self._config_manager = file_M.ConfigManager(self._config_dir)
def _get_plugin_resource(self, resource_path: str) -> bytes:
plugin_name = self.__class__.__name__.lower()
zip_path = Path("plugins") / f"{plugin_name}.zip"
if not zip_path.exists():
raise FileNotFoundError(f"插件ZIP包不存在: {zip_path}")
# 遍历可能的ZIP内路径
possible_paths = (
resource_path, # 直接路径config.toml
f"{plugin_name}/{resource_path}" # 插件子目录路径myplugin/config.toml
)
with zipfile.ZipFile(zip_path, 'r') as zf:
for path in possible_paths:
if path in zf.namelist():
return zf.read(path)
raise FileNotFoundError(f"文件 '{resource_path}' 不在ZIP包中")
def _ensure_config_exists(self):
"""确保配置文件存在不存在时从ZIP复制默认配置"""
config_file = Path(self._config_dir) / "config.toml"
# 外部配置已存在则直接返回
if config_file.exists():
return
# 尝试从ZIP复制默认配置
try:
for ext in ['.toml', '.json', '.yaml']:
try:
config_data = self._get_plugin_resource(f"config{ext}")
# 确保配置目录存在
config_file.parent.mkdir(parents=True, exist_ok=True)
# 统一保存为.toml格式或保持原格式
config_file.write_bytes(config_data)
print(f"✅ 已将默认配置复制到: {config_file}")
break
except FileNotFoundError:
continue
else:
print(f"⚠️ 插件包内未找到默认配置文件")
except Exception as e:
print(f"❌ 初始化配置失败: {str(e)}")
@property
def config(self) -> dict:
"""始终读取外部配置文件确保已通过_ensure_config_exists初始化"""
try:
config_data = self._config_manager.load_config("config")
except:
self._ensure_config_exists()
config_data = self._config_manager.load_config("config")
return config_data or {}
def _get_plugin_config_path(self) -> str:
"""获取插件配置目录路径(保持原有逻辑)"""
plugin_name = self.__class__.__name__.lower()
return str(Path("config") / plugin_name)
def save_config(self, config_dict: dict) -> bool:
"""保存配置到外部目录(与之前逻辑一致)"""
self._config_manager.update_config({"config": config_dict})
return self._config_manager.save_config()

119
src/modules/user_modules.py Normal file
View File

@ -0,0 +1,119 @@
import json
import requests
import time
import src.file_store_api as filer
config_m = filer.ConfigManager()
url = config_m.load_config("config")
mainurl = url.get("app").get("send_url")
class User:
def __init__(self, user_id,url = mainurl):
self.user_id = user_id
self.url = url
self.nickname = None
self.get_name()
self.messages = []
self.signal = True
self.db = filer.ChatManager()
def get_name(self):
"""
获取用户的名称
"""
try:
response = requests.post('{0}/ArkSharePeer'.format(self.url),json={'user_id':self.user_id})
except:
return 0
if response.status_code == 200:
# 解析返回的JSON数据
response_data = response.json()
# 检查是否有错误信息
if response_data.get("status") == "ok":
# 获取用户卡片信息
ark_json = response_data.get("data", {})
ark_msg_str = ark_json.get("arkMsg", "{}")
try:
ark_json = json.loads(ark_msg_str) # 字符串转字典
except json.JSONDecodeError:
ark_json = {}
user_nick = ark_json.get("meta", {}).get("contact", {}).get("nickname")
self.nickname = user_nick
else:
print(f"请求失败,错误信息: {response_data.get('errMsg')}")
else:
print(f"请求失败,状态码: {response.status_code}")
def set_input_status(self, status):
payload = json.dumps({
"user_id": self.user_id,
"event_type": status
})
headers = {
'Content-Type': 'application/json'
}
while self.signal:
print(f"刷新 {self.nickname} 的输入状态为: {status}")
requests.request("POST","{0}/set_input_status".format(self.url), headers=headers, data=payload)
time.sleep(0.5)
def send_message(self, message):
requests.post(url='{0}/send_private_msg'.format(self.url), json={'user_id':self.user_id, 'message':message})
self.db.save_private_message(self,role = 'assistant',content=message)#保存发送的消息
class Group:
def __init__(self, group_id,url = mainurl,user=None,users=None):
self.url = url
self.group_id = group_id
self.current_user = user
self.nickname = None
self.get_group_name()
self.users = users
self.get_group_users()
self.messages =[]
self.db = filer.ChatManager()
def get_group_name(self):
"""
获取群组的名称
"""
try:
response = requests.post('{0}/ArkSharePeer'.format(self.url), json={'group_id': self.group_id})
except:
return 0
if response.status_code == 200:
response_data = response.json()
if response_data.get("status") == "ok":
ark_json = response_data.get("data", {})
ark_msg_str = ark_json.get("arkJson", "{}")
try:
ark_json = json.loads(ark_msg_str)
except json.JSONDecodeError:
ark_json = {}
group_name = ark_json.get("meta", {}).get("contact", {}).get("nickname")
self.nickname = group_name
else:
print(f"请求失败,错误信息: {response_data.get('errMsg')}")
else:
print(f"请求失败,状态码: {response.status_code}")
def get_group_users(self):
try:
response = requests.post('{0}/get_group_member_list'.format(self.url), json={'group_id':self.group_id,'no_cache': False})
except:
return 0
if response.status_code == 200:
response_data = response.json()
if response_data.get("status") == "ok":
group_users = response_data.get("data", {})
self.users = group_users
else:
print(f"请求失败,错误信息: {response_data.get('errMsg')}")
else:
print(f"请求失败,状态码: {response.status_code}")
def send_message(self,message):
requests.post(url='{0}/send_group_msg'.format(self.url), json={'group_id': self.group_id, 'message': message})
self.db.save_group_message(self,'assistant',message, sender_id=0)#保存发送的消息