1.添加手动添加群组的能力
2.添加异步入库的能力
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
import logging
|
import logging
|
||||||
|
import concurrent.futures # 添加线程池支持
|
||||||
|
|
||||||
from wcferry import WxMsg
|
from wcferry import WxMsg
|
||||||
|
|
||||||
@@ -24,6 +25,10 @@ class MessageStorage:
|
|||||||
# 初始化本地缓存字典,使用 group_id 作为键
|
# 初始化本地缓存字典,使用 group_id 作为键
|
||||||
self.local_membercounts = {}
|
self.local_membercounts = {}
|
||||||
self.local_members = {}
|
self.local_members = {}
|
||||||
|
# 创建线程池,用于异步存储消息
|
||||||
|
self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=5)
|
||||||
|
# 用于跟踪异步任务的列表
|
||||||
|
self.pending_tasks = []
|
||||||
|
|
||||||
def process_message(self, message: WxMsg):
|
def process_message(self, message: WxMsg):
|
||||||
# 示例message字符串
|
# 示例message字符串
|
||||||
@@ -39,15 +44,58 @@ class MessageStorage:
|
|||||||
# 或者使用字符串:r.incr(key) # 如果只存储一个整数值,字符串类型可能更简单
|
# 或者使用字符串:r.incr(key) # 如果只存储一个整数值,字符串类型可能更简单
|
||||||
|
|
||||||
def archive_message(self, msg: WxMsg):
|
def archive_message(self, msg: WxMsg):
|
||||||
|
"""异步存档消息,防止堵塞主线程"""
|
||||||
|
# 提交任务到线程池
|
||||||
|
future = self.executor.submit(self._archive_message_task, msg)
|
||||||
|
# 可选:添加回调函数处理完成后的操作
|
||||||
|
future.add_done_callback(self._archive_callback)
|
||||||
|
# 将任务添加到待处理列表
|
||||||
|
self.pending_tasks.append(future)
|
||||||
|
# 清理已完成的任务
|
||||||
|
self._cleanup_completed_tasks()
|
||||||
|
|
||||||
|
def _archive_message_task(self, msg: WxMsg):
|
||||||
|
"""实际执行消息存档的任务函数"""
|
||||||
try:
|
try:
|
||||||
# 使用 MessageStorageDB 类存档消息
|
# 使用 MessageStorageDB 类存档消息
|
||||||
result = self.message_db.archive_message(msg)
|
result = self.message_db.archive_message(msg)
|
||||||
if result:
|
return {
|
||||||
logger.info(f"消息存档成功: {msg.roomid}:{msg.sender}: {msg.content}")
|
'success': result,
|
||||||
else:
|
'roomid': msg.roomid,
|
||||||
logger.error(f"消息存档失败: {msg.roomid}:{msg.sender}")
|
'sender': msg.sender
|
||||||
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"存档消息出错: {e}")
|
logger.error(f"存档消息出错: {e}")
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'roomid': msg.roomid,
|
||||||
|
'sender': msg.sender,
|
||||||
|
'error': str(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
def _archive_callback(self, future):
|
||||||
|
"""处理异步存档任务完成后的回调"""
|
||||||
|
try:
|
||||||
|
result = future.result()
|
||||||
|
if result['success']:
|
||||||
|
logger.info(f"消息存档成功: {result['roomid']}:{result['sender']}")
|
||||||
|
else:
|
||||||
|
error_msg = result.get('error', '未知错误')
|
||||||
|
logger.error(f"消息存档失败: {result['roomid']}:{result['sender']} - {error_msg}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"处理存档回调时出错: {e}")
|
||||||
|
|
||||||
|
def _cleanup_completed_tasks(self):
|
||||||
|
"""清理已完成的任务,防止内存泄漏"""
|
||||||
|
# 过滤出已完成的任务
|
||||||
|
completed_tasks = [task for task in self.pending_tasks if task.done()]
|
||||||
|
# 从待处理列表中移除已完成的任务
|
||||||
|
for task in completed_tasks:
|
||||||
|
self.pending_tasks.remove(task)
|
||||||
|
|
||||||
|
# 如果待处理任务过多,记录警告日志
|
||||||
|
if len(self.pending_tasks) > 100:
|
||||||
|
logger.warning(f"待处理的存档任务数量过多: {len(self.pending_tasks)}")
|
||||||
|
|
||||||
def write_to_db(self):
|
def write_to_db(self):
|
||||||
"""从Redis读取发言统计数据并写入数据库"""
|
"""从Redis读取发言统计数据并写入数据库"""
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ class DouyinParserPlugin(MessagePluginInterface):
|
|||||||
try:
|
try:
|
||||||
api_url = "http://192.168.2.240:9081/api/hybrid/video_data"
|
api_url = "http://192.168.2.240:9081/api/hybrid/video_data"
|
||||||
clean_url = self._clean_url(url)
|
clean_url = self._clean_url(url)
|
||||||
params = {'url': clean_url, 'type': 'json'}
|
params = {'url': clean_url, 'minimal': True}
|
||||||
|
|
||||||
self.LOG.info(f"[抖音] 请求API: {api_url}, 参数: {repr(params)}")
|
self.LOG.info(f"[抖音] 请求API: {api_url}, 参数: {repr(params)}")
|
||||||
proxy = {"http": self.http_proxy, "https": self.http_proxy} if self.http_proxy else None
|
proxy = {"http": self.http_proxy, "https": self.http_proxy} if self.http_proxy else None
|
||||||
|
|||||||
@@ -159,6 +159,46 @@ class DashboardServer:
|
|||||||
self.logger.error(f"批量操作失败: {e}")
|
self.logger.error(f"批量操作失败: {e}")
|
||||||
return jsonify({"success": False, "error": str(e)}), 400
|
return jsonify({"success": False, "error": str(e)}), 400
|
||||||
|
|
||||||
|
# 添加:手动添加群组的API接口
|
||||||
|
@app.route('/api/robot/add_group', methods=['POST'])
|
||||||
|
def api_add_group():
|
||||||
|
try:
|
||||||
|
data = request.json
|
||||||
|
group_id = data.get('group_id')
|
||||||
|
|
||||||
|
if not group_id or not group_id.strip():
|
||||||
|
return jsonify({"success": False, "error": "群组ID不能为空"}), 400
|
||||||
|
|
||||||
|
group_id = group_id.strip()
|
||||||
|
|
||||||
|
# 检查群组是否已存在
|
||||||
|
if group_id in GroupBotManager.local_cache["group_list"]:
|
||||||
|
return jsonify({"success": False, "error": "该群组已存在"}), 400
|
||||||
|
|
||||||
|
# 添加群组到列表并启用机器人功能
|
||||||
|
GroupBotManager.local_cache["group_list"].add(group_id)
|
||||||
|
r = self.db_manager.get_redis_connection()
|
||||||
|
r.sadd("group:list", group_id)
|
||||||
|
|
||||||
|
# 设置ROBOT功能为启用状态
|
||||||
|
GroupBotManager.set_group_permission(group_id, Feature.ROBOT, PermissionStatus.ENABLED)
|
||||||
|
|
||||||
|
# 获取群组名称(如果可能)
|
||||||
|
group_name = self.contact_manager.get_nickname(group_id)
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"success": True,
|
||||||
|
"message": f"群组 {group_id} 已成功添加",
|
||||||
|
"group": {
|
||||||
|
"group_id": group_id,
|
||||||
|
"group_name": group_name,
|
||||||
|
"robot_status": "enabled"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"添加群组失败: {e}")
|
||||||
|
return jsonify({"success": False, "error": str(e)}), 500
|
||||||
|
|
||||||
@app.route('/api/plugin_stats')
|
@app.route('/api/plugin_stats')
|
||||||
def api_plugin_stats():
|
def api_plugin_stats():
|
||||||
days = request.args.get('days', 7, type=int)
|
days = request.args.get('days', 7, type=int)
|
||||||
|
|||||||
@@ -10,6 +10,13 @@
|
|||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<div slot="header" class="clearfix">
|
<div slot="header" class="clearfix">
|
||||||
<span>群机器人管理</span>
|
<span>群机器人管理</span>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
style="float: right; margin-left: 10px;"
|
||||||
|
@click="showAddGroupDialog">
|
||||||
|
添加群组
|
||||||
|
</el-button>
|
||||||
<el-input
|
<el-input
|
||||||
placeholder="搜索群组..."
|
placeholder="搜索群组..."
|
||||||
v-model="searchQuery"
|
v-model="searchQuery"
|
||||||
@@ -107,6 +114,22 @@
|
|||||||
<el-button @click="permissionDialogVisible = false">关闭</el-button>
|
<el-button @click="permissionDialogVisible = false">关闭</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 添加群组对话框 -->
|
||||||
|
<el-dialog
|
||||||
|
title="添加群组"
|
||||||
|
:visible.sync="addGroupDialogVisible"
|
||||||
|
width="30%">
|
||||||
|
<el-form :model="addGroupForm" :rules="addGroupRules" ref="addGroupForm">
|
||||||
|
<el-form-item label="群组ID" prop="groupId">
|
||||||
|
<el-input v-model="addGroupForm.groupId" placeholder="请输入群组ID"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="addGroupDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submitAddGroup">确定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@@ -123,7 +146,18 @@
|
|||||||
currentGroupName: '',
|
currentGroupName: '',
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
selectedGroups: [],
|
selectedGroups: [],
|
||||||
permissionDialogVisible: false
|
permissionDialogVisible: false,
|
||||||
|
// 添加群组相关数据
|
||||||
|
addGroupDialogVisible: false,
|
||||||
|
addGroupForm: {
|
||||||
|
groupId: ''
|
||||||
|
},
|
||||||
|
addGroupRules: {
|
||||||
|
groupId: [
|
||||||
|
{ required: true, message: '请输入群组ID', trigger: 'blur' },
|
||||||
|
{ pattern: /^\S+$/, message: '群组ID不能包含空格', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -237,6 +271,38 @@
|
|||||||
this.$message.error('更新权限失败: ' + error.message);
|
this.$message.error('更新权限失败: ' + error.message);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// 显示添加群组对话框
|
||||||
|
showAddGroupDialog() {
|
||||||
|
this.addGroupForm.groupId = '';
|
||||||
|
this.addGroupDialogVisible = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 提交添加群组
|
||||||
|
submitAddGroup() {
|
||||||
|
this.$refs.addGroupForm.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
axios.post('/api/robot/add_group', {
|
||||||
|
group_id: this.addGroupForm.groupId
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.data.success) {
|
||||||
|
this.$message.success(response.data.message);
|
||||||
|
// 添加新群组到列表
|
||||||
|
if (response.data.group) {
|
||||||
|
this.groups.push(response.data.group);
|
||||||
|
}
|
||||||
|
this.addGroupDialogVisible = false;
|
||||||
|
} else {
|
||||||
|
this.$message.error(response.data.error || '添加失败');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('添加群组失败:', error);
|
||||||
|
this.$message.error('添加群组失败: ' + (error.response?.data?.error || error.message));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
enableAllPermissions() {
|
enableAllPermissions() {
|
||||||
this.$confirm('确定要启用所有功能吗?', '提示', {
|
this.$confirm('确定要启用所有功能吗?', '提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
|
|||||||
Reference in New Issue
Block a user