去除一些无用功能,以前的UI这些。
This commit is contained in:
76
db/tasks.py
76
db/tasks.py
@@ -1,76 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from db.base import BaseDBOperator
|
||||
from db.connection import DBConnectionManager
|
||||
|
||||
|
||||
class TasksDB(BaseDBOperator):
|
||||
"""任务管理相关数据库操作"""
|
||||
|
||||
def __init__(self, db_manager: DBConnectionManager):
|
||||
super().__init__(db_manager)
|
||||
|
||||
def initialize_table(self) -> bool:
|
||||
"""初始化任务表"""
|
||||
sql = """
|
||||
CREATE TABLE IF NOT EXISTS tasks (
|
||||
task_id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
task_description VARCHAR(255) NOT NULL,
|
||||
reminder_time TIME NOT NULL,
|
||||
task_type ENUM('single', 'recurring') DEFAULT 'single',
|
||||
status ENUM('pending', 'completed') DEFAULT 'pending',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
"""
|
||||
return self.execute_update(sql)
|
||||
|
||||
def add_task(self, description: str, reminder_time: str, task_type: str = 'single') -> Optional[int]:
|
||||
"""添加任务"""
|
||||
sql = """
|
||||
INSERT INTO tasks (task_description, reminder_time, task_type)
|
||||
VALUES (%s, %s, %s)
|
||||
"""
|
||||
conn = self.db_manager.get_mysql_connection()
|
||||
try:
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute(sql, (description, reminder_time, task_type))
|
||||
task_id = cursor.lastrowid
|
||||
conn.commit()
|
||||
return task_id
|
||||
except Exception as e:
|
||||
self.LOG.error(f"添加任务出错: {e}")
|
||||
conn.rollback()
|
||||
return None
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def get_pending_tasks(self) -> List[Dict]:
|
||||
"""获取待办任务"""
|
||||
sql = """
|
||||
SELECT task_id, task_description, reminder_time, task_type, status, created_at
|
||||
FROM tasks
|
||||
WHERE status = 'pending'
|
||||
ORDER BY reminder_time
|
||||
"""
|
||||
return self.execute_query(sql) or []
|
||||
|
||||
def complete_task(self, task_id: int) -> bool:
|
||||
"""完成任务"""
|
||||
sql = """
|
||||
UPDATE tasks
|
||||
SET status = 'completed'
|
||||
WHERE task_id = %s
|
||||
"""
|
||||
return self.execute_update(sql, (task_id,))
|
||||
|
||||
def get_tasks_by_time(self, current_time: str) -> List[Dict]:
|
||||
"""获取指定时间的任务"""
|
||||
sql = """
|
||||
SELECT task_id, task_description, reminder_time, task_type
|
||||
FROM tasks
|
||||
WHERE TIME_FORMAT(reminder_time, '%H:%i') = %s
|
||||
AND (status = 'pending' OR (status = 'completed' AND task_type = 'recurring'))
|
||||
"""
|
||||
return self.execute_query(sql, (current_time,)) or []
|
||||
@@ -123,7 +123,7 @@ class DouyinParser:
|
||||
|
||||
def _parse_douyin(self, url: str) -> Dict[str, Any]:
|
||||
try:
|
||||
api_url = "https://zj.v.api.aa1.cn/api/douyinjx/"
|
||||
api_url = "http://zj.v.api.aa1.cn/api/douyinjx/"
|
||||
clean_url = self._clean_url(url)
|
||||
params = {'text': clean_url, 'type': 'json'}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from datetime import datetime
|
||||
|
||||
import redis
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
@@ -85,13 +87,14 @@ class GroupMemberChange:
|
||||
added_members = members_current_set - members_previous_set
|
||||
removed_members = members_previous_set - members_current_set
|
||||
|
||||
now_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
# 添加变化成员的文案
|
||||
for wxid in added_members:
|
||||
nickname = members_current[wxid]
|
||||
result.append(f"检测到\n {nickname}({wxid})\n加入群聊")
|
||||
result.append(f"🎉 欢迎 【{nickname}】 加入群聊👋 \n 🕒 {now_time} 🕒 !")
|
||||
for wxid in removed_members:
|
||||
nickname = members_previous[wxid]
|
||||
result.append(f"检测到\n {nickname}({wxid})\n退出群聊")
|
||||
result.append(f"检测到\n {nickname}({wxid})\n退出群聊\n 🕒 {now_time} 🕒 !")
|
||||
|
||||
# 更新本地缓存
|
||||
print(f"Updating local cache with current membercount and members")
|
||||
|
||||
1
main.py
1
main.py
@@ -6,7 +6,6 @@ from argparse import ArgumentParser
|
||||
|
||||
from configuration import Config
|
||||
from constants import ChatType
|
||||
from game_task.game_task_encyclopedia import setup_schedule
|
||||
from robot import Robot, __version__
|
||||
from wcferry import Wcf
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
USE message_archive;
|
||||
-- auto-generated definition
|
||||
create table speech_counts
|
||||
(
|
||||
id int auto_increment
|
||||
primary key,
|
||||
group_id text null,
|
||||
wx_id text null,
|
||||
date text null,
|
||||
count int null,
|
||||
constraint speech_counts_group_id_wx_id_date_uindex
|
||||
unique (group_id, wx_id, date) using hash
|
||||
);
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import redis
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
from wcferry import WxMsg
|
||||
|
||||
# 连接到Redis
|
||||
r = redis.Redis(host='192.168.2.32', port=6379, db=0)
|
||||
|
||||
|
||||
def process_message(message: WxMsg):
|
||||
# 示例message字符串
|
||||
current_date = datetime.now().strftime('%Y-%m-%d')
|
||||
# 生成Redis key
|
||||
key = f"{message.roomid}:{message.sender}:{current_date}:count"
|
||||
|
||||
# 使用Redis哈希(或字符串)增加发言次数
|
||||
r.hincrby(key, 'count', 1) # 这里使用哈希,但也可以考虑用字符串的INCR操作
|
||||
# 设置时效为48小时
|
||||
r.expire(key, 86400 * 2)
|
||||
# 或者使用字符串:r.incr(key) # 如果只存储一个整数值,字符串类型可能更简单
|
||||
@@ -1,74 +0,0 @@
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from db.connection import DBConnectionManager
|
||||
from db.message_storage import MessageStorageDB
|
||||
|
||||
# 配置日志
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
# 获取数据库连接管理器的单例
|
||||
db_manager = DBConnectionManager()
|
||||
message_db = MessageStorageDB(db_manager)
|
||||
|
||||
|
||||
def write_to_db():
|
||||
"""从Redis读取发言统计数据并写入数据库"""
|
||||
# 获取Redis连接
|
||||
redis_conn = db_manager.get_redis_connection()
|
||||
|
||||
# 获取当前日期的前一天
|
||||
yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
|
||||
|
||||
# 遍历Redis中所有与昨天日期相关的key,并写入数据库
|
||||
for key_bytes in redis_conn.keys(f"*:*:{yesterday}:count"):
|
||||
key = key_bytes.decode('utf-8')
|
||||
parts = key.split(':')
|
||||
group_id, wx_id, _date = parts[0], parts[1], parts[2] # _date应该是yesterday
|
||||
|
||||
# 获取计数值
|
||||
count_bytes = redis_conn.hget(key, 'count')
|
||||
count = int(count_bytes) if isinstance(count_bytes, bytes) else 0
|
||||
|
||||
# 使用MessageStorageDB插入数据
|
||||
try:
|
||||
result = message_db.insert_speech_count(group_id, wx_id, yesterday, count)
|
||||
if result:
|
||||
logging.info(f"成功写入发言统计: {group_id}, {wx_id}, {yesterday}, {count}")
|
||||
else:
|
||||
logging.error(f"写入发言统计失败: {group_id}, {wx_id}, {yesterday}, {count}")
|
||||
except Exception as e:
|
||||
logging.error(f"写入发言统计出错: {e}")
|
||||
|
||||
|
||||
def generate_and_send_ranking(groupId, allContacts: dict):
|
||||
"""生成并发送群聊发言排名"""
|
||||
try:
|
||||
yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
|
||||
|
||||
# 使用数据库操作类获取排名数据
|
||||
results = message_db.get_speech_ranking(yesterday, groupId, limit=20)
|
||||
|
||||
if not results:
|
||||
logging.info(f"没有找到 {yesterday} 的群聊 {groupId} 发言记录")
|
||||
return f"{yesterday} 没有发言记录"
|
||||
|
||||
# 格式化输出字符串
|
||||
ranking_str = yesterday + "发言数量前20的用户排名:\n"
|
||||
for rank, result in enumerate(results, start=1):
|
||||
username = result['wx_id']
|
||||
speech_count = result['speech_count']
|
||||
ranking_str += f"{rank}. {allContacts.get(username, username)}: {speech_count} 次发言\n"
|
||||
|
||||
logging.info(f"成功生成 {yesterday} 的群聊 {groupId} 发言排名")
|
||||
return ranking_str
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"生成发言排名出错: {e}")
|
||||
return f"生成发言排名出错: {e}"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
write_to_db()
|
||||
@@ -1,63 +1,118 @@
|
||||
import pymysql
|
||||
from datetime import datetime, timedelta
|
||||
import redis
|
||||
import xml.etree.ElementTree as ET
|
||||
import logging
|
||||
|
||||
from wcferry import WxMsg
|
||||
|
||||
from message_summary.message_summary_4o import message_summary
|
||||
from db.connection import DBConnectionManager
|
||||
from db.message_storage import MessageStorageDB
|
||||
|
||||
import mysql.connector.pooling
|
||||
# 配置日志
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger("MessageStorage")
|
||||
|
||||
|
||||
class MessageStorage:
|
||||
|
||||
def __init__(self, db_pool: mysql.connector.pooling.MySQLConnectionPool, redis_pool: redis.ConnectionPool):
|
||||
self.redis_pool = redis_pool
|
||||
self.db_pool = db_pool
|
||||
def __init__(self):
|
||||
# 获取数据库连接管理器的单例
|
||||
self.db_manager = DBConnectionManager()
|
||||
self.message_db = MessageStorageDB(self.db_manager)
|
||||
# 初始化本地缓存字典,使用 group_id 作为键
|
||||
self.local_membercounts = {}
|
||||
self.local_members = {}
|
||||
|
||||
def _get_redis_connection(self):
|
||||
"""从连接池获取 Redis 连接"""
|
||||
return redis.Redis(connection_pool=self.redis_pool, decode_responses=True)
|
||||
def process_message(self, message: WxMsg):
|
||||
# 示例message字符串
|
||||
current_date = datetime.now().strftime('%Y-%m-%d')
|
||||
# 生成Redis key
|
||||
key = f"{message.roomid}:{message.sender}:{current_date}:count"
|
||||
# 获取 Redis 连接
|
||||
redis_conn = self.db_manager.get_redis_connection()
|
||||
# 使用Redis哈希(或字符串)增加发言次数
|
||||
redis_conn.hincrby(key, 'count', 1) # 这里使用哈希,但也可以考虑用字符串的INCR操作
|
||||
# 设置时效为48小时
|
||||
redis_conn.expire(key, 86400 * 2)
|
||||
# 或者使用字符串:r.incr(key) # 如果只存储一个整数值,字符串类型可能更简单
|
||||
|
||||
def archive_message(self, msg: WxMsg):
|
||||
# 连接到数据库
|
||||
connection = self.db_pool.get_connection()
|
||||
|
||||
try:
|
||||
now_time = str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
|
||||
with connection.cursor() as cursor:
|
||||
# 插入消息信息
|
||||
sql = """
|
||||
INSERT INTO messages (group_id,timestamp, sender, content, message_type, attachment_url,message_id,message_xml,message_thumb)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
"""
|
||||
cursor.execute(sql, (
|
||||
msg.roomid, now_time, msg.sender, msg.content, msg.type, msg.extra, msg.id, msg.xml, msg.thumb))
|
||||
# 使用 MessageStorageDB 类存档消息
|
||||
result = self.message_db.archive_message(msg)
|
||||
if result:
|
||||
logger.info(f"消息存档成功: {msg.roomid}:{msg.sender}: {msg.content}")
|
||||
else:
|
||||
logger.error(f"消息存档失败: {msg.roomid}:{msg.sender}")
|
||||
except Exception as e:
|
||||
logger.error(f"存档消息出错: {e}")
|
||||
|
||||
# 提交事务
|
||||
connection.commit()
|
||||
print(f"Archived:{now_time}:{msg.roomid}:{msg.sender}: {msg.content}")
|
||||
def write_to_db(self):
|
||||
"""从Redis读取发言统计数据并写入数据库"""
|
||||
# 获取Redis连接
|
||||
redis_conn = self.db_manager.get_redis_connection()
|
||||
|
||||
# 获取当前日期的前一天
|
||||
yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
|
||||
|
||||
# 遍历Redis中所有与昨天日期相关的key,并写入数据库
|
||||
for key_bytes in redis_conn.keys(f"*:*:{yesterday}:count"):
|
||||
key = key_bytes.decode('utf-8')
|
||||
parts = key.split(':')
|
||||
group_id, wx_id, _date = parts[0], parts[1], parts[2] # _date应该是yesterday
|
||||
|
||||
# 获取计数值
|
||||
count_bytes = redis_conn.hget(key, 'count')
|
||||
count = int(count_bytes) if isinstance(count_bytes, bytes) else 0
|
||||
|
||||
# 使用MessageStorageDB插入数据
|
||||
try:
|
||||
result = self.message_db.insert_speech_count(group_id, wx_id, yesterday, count)
|
||||
if result:
|
||||
logging.info(f"成功写入发言统计: {group_id}, {wx_id}, {yesterday}, {count}")
|
||||
else:
|
||||
logging.error(f"写入发言统计失败: {group_id}, {wx_id}, {yesterday}, {count}")
|
||||
except Exception as e:
|
||||
logging.error(f"写入发言统计出错: {e}")
|
||||
|
||||
def generate_and_send_ranking(self, groupId, allContacts: dict):
|
||||
"""生成并发送群聊发言排名"""
|
||||
try:
|
||||
yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
|
||||
|
||||
# 使用数据库操作类获取排名数据
|
||||
results = self.message_db.get_speech_ranking(yesterday, groupId, limit=20)
|
||||
|
||||
if not results:
|
||||
logging.info(f"没有找到 {yesterday} 的群聊 {groupId} 发言记录")
|
||||
return f"{yesterday} 没有发言记录"
|
||||
|
||||
# 格式化输出字符串
|
||||
ranking_str = yesterday + "发言数量前20的用户排名:\n"
|
||||
for rank, result in enumerate(results, start=1):
|
||||
username = result['wx_id']
|
||||
speech_count = result['speech_count']
|
||||
ranking_str += f"{rank}. {allContacts.get(username, username)}: {speech_count} 次发言\n"
|
||||
|
||||
logging.info(f"成功生成 {yesterday} 的群聊 {groupId} 发言排名")
|
||||
return ranking_str
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error archiving message: {e}")
|
||||
connection.rollback()
|
||||
|
||||
finally:
|
||||
# 关闭连接
|
||||
connection.close()
|
||||
logging.error(f"生成发言排名出错: {e}")
|
||||
return f"生成发言排名出错: {e}"
|
||||
|
||||
def get_messages(self, group_id, all_contacts: dict):
|
||||
# 连接到数据库
|
||||
with self.db_pool.get_connection() as connection:
|
||||
try:
|
||||
# 获取 Redis 连接
|
||||
redis_conn = self.db_manager.get_redis_connection()
|
||||
|
||||
# 获取 redis 中的上次总结时间,本次从上次开始算,若没有,则从 8 小时之前开始计算
|
||||
key = f"{group_id}:summary_time"
|
||||
last_summary_time = self._get_redis_connection().get(key)
|
||||
print(f"last_summary_time:{last_summary_time}")
|
||||
# 如果 Redis 返回值为字节类型,转换为字符串
|
||||
last_summary_time = redis_conn.get(key)
|
||||
logger.info(f"上次总结时间: {last_summary_time}")
|
||||
|
||||
current_time = datetime.now()
|
||||
current_date = current_time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
@@ -67,6 +122,10 @@ class MessageStorage:
|
||||
eight_hours_ago = current_time - timedelta(hours=8)
|
||||
last_summary_time = eight_hours_ago.strftime('%Y-%m-%d %H:%M:%S')
|
||||
else:
|
||||
# 如果 Redis 返回值为字节类型,转换为字符串
|
||||
if isinstance(last_summary_time, bytes):
|
||||
last_summary_time = last_summary_time.decode('utf-8')
|
||||
|
||||
# 检查 redis 中的时间与当前时间差是否小于 3 小时
|
||||
last_summary_time_obj = datetime.strptime(last_summary_time, '%Y-%m-%d %H:%M:%S')
|
||||
time_diff = current_time - last_summary_time_obj
|
||||
@@ -79,37 +138,33 @@ class MessageStorage:
|
||||
last_summary_time = (current_time - timedelta(hours=10)).strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 更新 Redis 存储的当前时间
|
||||
self._get_redis_connection().set(key, current_date)
|
||||
redis_conn.set(key, current_date)
|
||||
|
||||
with connection.cursor() as cursor:
|
||||
# 执行查询,获取最近 8 小时的消息
|
||||
query = """
|
||||
SELECT timestamp, sender, content,message_type
|
||||
FROM messages
|
||||
WHERE timestamp >= %s AND message_type in(1,49) AND group_id = %s
|
||||
AND length(content)>6
|
||||
AND content NOT LIKE '/%'
|
||||
"""
|
||||
cursor.execute(query, (last_summary_time, group_id))
|
||||
# 使用 MessageStorageDB 类获取最近消息
|
||||
hours_ago = int(
|
||||
(current_time - datetime.strptime(last_summary_time, '%Y-%m-%d %H:%M:%S')).total_seconds() / 3600) + 1
|
||||
messages = self.message_db.get_recent_messages(group_id, hours_ago=hours_ago)
|
||||
|
||||
# 构建最终的结果字符串
|
||||
# message_type 需要加入49类型,因为49是引用之后的发言。但是49是xml ,需要将content进行xml解析
|
||||
# 构建最终的结果字符串
|
||||
result = []
|
||||
for msg in messages:
|
||||
timestamp, sender, content, message_type = msg['timestamp'], msg['sender'], msg['content'], msg[
|
||||
'message_type']
|
||||
try:
|
||||
if message_type == 49: # 注意这里是整数类型
|
||||
# 解析 XML 字符串
|
||||
root = ET.fromstring(content)
|
||||
# 提取 title 内容
|
||||
content = root.find('.//title').text
|
||||
except Exception as e:
|
||||
logger.error(f"解析消息类型49出错: {e}")
|
||||
|
||||
result = []
|
||||
for row in cursor.fetchall():
|
||||
timestamp, sender, content, message_type = row
|
||||
try:
|
||||
if message_type == "49":
|
||||
# 解析 XML 字符串
|
||||
root = ET.fromstring(content)
|
||||
# 提取 title 内容
|
||||
content = root.find('.//title').text
|
||||
sender_name = all_contacts.get(sender, sender) # 获取发送者的名字,若找不到则使用原 ID
|
||||
result.append(f"{timestamp},{sender_name},{content}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"message_type 49 error: {e}")
|
||||
sender_name = all_contacts.get(sender, sender) # 获取发送者的名字,若找不到则使用原 ID
|
||||
result.append(f"{timestamp},{sender_name},{content}")
|
||||
result_str = "\n".join(result) # 将结果拼接为最终字符串
|
||||
return result_str
|
||||
|
||||
result_str = "\n".join(result) # 将结果拼接为最终字符串
|
||||
# print(result_str)
|
||||
return result_str
|
||||
except Exception as e:
|
||||
logger.error(f"获取消息出错: {e}")
|
||||
return ""
|
||||
|
||||
13
robot.py
13
robot.py
@@ -73,13 +73,13 @@ class Robot(Job):
|
||||
self.wxid = self.wcf.get_self_wxid()
|
||||
self.allContacts = self.get_all_contacts()
|
||||
self.LOG.info(f"DB+REDIS 连接池开始初始化")
|
||||
# 初始化数据库连接管理器
|
||||
# 初始化数据库连接管理器
|
||||
self.db_manager = DBConnectionManager(
|
||||
mysql_config=self.config.mariadb,
|
||||
redis_config=self.config.redis
|
||||
)
|
||||
self.LOG.info(f"数据库连接管理器初始化完成")
|
||||
|
||||
|
||||
# 为了兼容现有代码,保留原有的连接池
|
||||
self.db_pool = self.db_manager.mysql_pool
|
||||
self.redis_pool = self.db_manager.redis_pool
|
||||
@@ -89,7 +89,7 @@ class Robot(Job):
|
||||
self.groups = {} # 存储按group_id分组的消息列表,每个group_id最多保留10条消息
|
||||
GroupBotManager.load_local_cache()
|
||||
# 消息存档模块初始化,自动完成入库动作
|
||||
self.message_storage = MessageStorage(self.db_pool, self.redis_pool)
|
||||
self.message_storage = MessageStorage()
|
||||
# 权限模块加载
|
||||
self.gbm = GroupBotManager()
|
||||
# 群成员变更模块加载
|
||||
@@ -293,7 +293,7 @@ class Robot(Job):
|
||||
if msg.from_group():
|
||||
# 调用统计逻辑进行聊天数据统计:
|
||||
try:
|
||||
process_message(msg)
|
||||
self.message_storage.process_message(msg)
|
||||
except Exception as e:
|
||||
self.LOG.error(f"process_message error: {e}")
|
||||
|
||||
@@ -616,7 +616,7 @@ class Robot(Job):
|
||||
|
||||
def message_count_to_db(self):
|
||||
try:
|
||||
write_to_db()
|
||||
self.message_storage.write_to_db()
|
||||
except Exception as e:
|
||||
self.LOG.error(f"write_to_db error:{e}")
|
||||
|
||||
@@ -635,7 +635,8 @@ class Robot(Job):
|
||||
return
|
||||
for r in receivers:
|
||||
if self.gbm.get_group_permission(r, Feature.DAILY_SUMMARY) == PermissionStatus.ENABLED:
|
||||
self.send_text_msg(generate_and_send_ranking(r, self.allContacts), r)
|
||||
output = self.message_storage.generate_and_send_ranking(r, self.allContacts)
|
||||
self.send_text_msg(output, r)
|
||||
except Exception as e:
|
||||
self.LOG.error(f"SendRanking error:{e}")
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
|
||||
# 解析JSON
|
||||
def extract_content(data_string):
|
||||
try:
|
||||
data = json.loads(data_string)
|
||||
# 提取content字段
|
||||
content = data["choices"][0]["message"].get("content", "")
|
||||
return content
|
||||
except json.JSONDecodeError:
|
||||
print("Invalid JSON")
|
||||
return None
|
||||
|
||||
|
||||
def message_task_json(content):
|
||||
# 设置Authorization和URL
|
||||
authorization = "46a5674a-e978-491b-a810-5d54605f2c36" # 请替换为真实的Authorization token
|
||||
url = 'http://127.0.0.1:8080/v1/chat/completions'
|
||||
|
||||
prompt = "你是一个益智百科问答大师,可以随时提出百科类的问题,问题需要有一定的难度,回答完毕之后用户能有所收获,并且对问题进行打分,同时根据问题难度告知答对之后给多少分(1-10)请只返回JSON格式的内容:格式要求如下:{\"question\": \"哪个国家最早将玫瑰与爱情联系起来?\", \"score\":\"1\", \"answer\": \"波斯\",\"description\":\"描述问题答案的原因\"}"
|
||||
# 设置请求的payload
|
||||
# prompt ="你是一个益智百科问答大师,可以根据用户回答的答案进行判断,并且对问题答案进行打分,打分时请参考最高分要求,告知用户能获得多少分,请只返回JSON格式的内容:格式要求如下:{\"question\": \"哪个国家最早将玫瑰与爱情联系起来?\", \"score\":\"1\", \"answer\": \"波斯\",\"description\":\"描述问题答案的原因\"}"
|
||||
|
||||
data = {
|
||||
# "stream": True,
|
||||
"model": "windsurf/gpt4o",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": f"{prompt}"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": f"{content}"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
|
||||
# 设置请求头
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
"Authorization": authorization
|
||||
}
|
||||
|
||||
# 发送POST请求
|
||||
response = requests.post(url, headers=headers, data=json.dumps(data), )
|
||||
response.encoding = 'utf-8'
|
||||
|
||||
# 输出响应内容
|
||||
print(response.status_code)
|
||||
print(response.text)
|
||||
return extract_content(response.text)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# print(message_task_json('question:哪个国家的节日与裸体狂欢有关?,answer:古罗马,top_score:3'))
|
||||
print(message_task_json('请出题!'))
|
||||
@@ -1,156 +0,0 @@
|
||||
import pymysql
|
||||
import schedule
|
||||
import json
|
||||
from task.message_task_json import message_task_json
|
||||
|
||||
# 配置数据库连接
|
||||
db_config = {
|
||||
'host': '192.168.2.32', # 替换为你的MariaDB服务器地址
|
||||
'user': 'root', # 替换为你的MariaDB用户名
|
||||
'password': 'lw123456', # 替换为你的MariaDB密码
|
||||
'database': 'message_archive'
|
||||
}
|
||||
|
||||
|
||||
# 数据库连接
|
||||
def get_db_connection():
|
||||
connection = pymysql.connect(**db_config)
|
||||
return connection
|
||||
|
||||
|
||||
# 插入任务到数据库
|
||||
def insert_task_to_db(description, reminder_time, task_type):
|
||||
connection = get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
|
||||
# 插入任务信息
|
||||
query = "INSERT INTO tasks (task_description, reminder_time, task_type) VALUES (%s, %s, %s)"
|
||||
cursor.execute(query, (description, reminder_time, task_type))
|
||||
connection.commit()
|
||||
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
|
||||
# 提醒任务(根据任务描述输出具体内容)
|
||||
def reminder_task(task_id):
|
||||
connection = get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
|
||||
# 获取任务描述
|
||||
query = "SELECT task_description FROM tasks WHERE task_id = %s"
|
||||
cursor.execute(query, (task_id,))
|
||||
task = cursor.fetchone()
|
||||
|
||||
if task:
|
||||
task_description = task[0]
|
||||
print(f"Reminder: {task_description}") # 输出具体的任务内容
|
||||
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
|
||||
# 调度单次任务
|
||||
def schedule_single_task(reminder_time, task_id):
|
||||
schedule.every().day.at(reminder_time).do(reminder_task, task_id=task_id)
|
||||
print(f"Single task scheduled at {reminder_time}.")
|
||||
|
||||
|
||||
# 调度周期性任务(例如:每天执行)
|
||||
def schedule_recurring_task(reminder_time, task_id):
|
||||
schedule.every().day.at(reminder_time).do(reminder_task, task_id=task_id)
|
||||
print(f"Recurring task scheduled every day at {reminder_time}.")
|
||||
|
||||
|
||||
# 处理用户输入
|
||||
def handle_user_input(user_input, task_type):
|
||||
task_json = message_task_json(user_input)
|
||||
print(task_json)
|
||||
if task_json:
|
||||
|
||||
# 将JSON字符串解析为字典
|
||||
data = json.loads(task_json)
|
||||
|
||||
# 提取内容
|
||||
task = data["task"]
|
||||
reminder_time = data["reminder_time"]
|
||||
reason = data["reason"]
|
||||
|
||||
# 将任务存入数据库
|
||||
insert_task_to_db(user_input, reminder_time, task_type)
|
||||
|
||||
# 获取插入的任务ID
|
||||
connection = get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("SELECT LAST_INSERT_ID()")
|
||||
task_id = cursor.fetchone()[0]
|
||||
cursor.close()
|
||||
connection.commit()
|
||||
connection.close()
|
||||
# 根据任务类型调度任务
|
||||
if task_type == 'single':
|
||||
schedule_single_task(reminder_time, task_id)
|
||||
elif task_type == 'recurring':
|
||||
schedule_recurring_task(reminder_time, task_id)
|
||||
|
||||
|
||||
# 查询指定类型的任务
|
||||
def get_tasks_by_type(task_type):
|
||||
connection = get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
|
||||
# 查询指定类型的任务
|
||||
query = "SELECT task_id, task_description, reminder_time, status, task_type FROM tasks WHERE task_type = %s"
|
||||
cursor.execute(query, (task_type,))
|
||||
|
||||
tasks = cursor.fetchall()
|
||||
for task in tasks:
|
||||
print(
|
||||
f"Task ID: {task[0]}, Description: {task[1]}, Reminder Time: {task[2]}, Status: {task[3]}, Type: {task[4]}")
|
||||
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
|
||||
# 更新任务状态
|
||||
def update_task_status(task_id, status):
|
||||
connection = get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
|
||||
# 更新任务状态
|
||||
query = "UPDATE tasks SET status = %s WHERE task_id = %s"
|
||||
cursor.execute(query, (status, task_id))
|
||||
connection.commit()
|
||||
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
|
||||
# 获取所有周期性任务
|
||||
def get_all_recurring_tasks():
|
||||
get_tasks_by_type('recurring')
|
||||
|
||||
|
||||
# 获取所有单次任务
|
||||
def get_all_single_tasks():
|
||||
get_tasks_by_type('single')
|
||||
|
||||
|
||||
# 主函数(示例输入)
|
||||
def main():
|
||||
# 示例:单次任务
|
||||
user_input_single = "提醒我明天上午9点开会"
|
||||
handle_user_input(user_input_single, 'single')
|
||||
|
||||
# 示例:周期性任务
|
||||
user_input_recurring = "每天上午9点提醒我开会"
|
||||
handle_user_input(user_input_recurring, 'recurring')
|
||||
|
||||
# # 启动定时任务调度
|
||||
# while True:
|
||||
# schedule.run_pending()
|
||||
# time.sleep(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,8 +0,0 @@
|
||||
CREATE TABLE IF NOT EXISTS tasks (
|
||||
task_id INT AUTO_INCREMENT PRIMARY KEY, -- 任务ID,自增
|
||||
task_description VARCHAR(255) NOT NULL, -- 任务描述
|
||||
reminder_time TIME NOT NULL, -- 提醒时间
|
||||
task_type ENUM('single', 'recurring') DEFAULT 'single', -- 任务类型:单次或周期性
|
||||
status ENUM('pending', 'completed') DEFAULT 'pending', -- 任务状态:待办或已完成
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 创建时间,默认为当前时间
|
||||
);
|
||||
@@ -1,85 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>群组管理</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: white;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
input[type="text"], input[type="submit"], select {
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
input[type="submit"] {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
input[type="submit"]:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
.result {
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
background-color: #e7f4e7;
|
||||
border: 1px solid #d3f8d3;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>群组管理</h1>
|
||||
|
||||
<div class="container">
|
||||
<form method="POST">
|
||||
<div class="form-group">
|
||||
<label for="key">Key:</label>
|
||||
<input type="text" id="key" name="key" >
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="group_id">Group ID:</label>
|
||||
<input type="text" id="group_id" name="group_id" >
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="action">Action:</label>
|
||||
<select id="action" name="action">
|
||||
<option value="add">添加群组ID</option>
|
||||
<option value="del">删除群组ID</option>
|
||||
<option value="get">获取所有群组ID</option>
|
||||
<option value="get_first">获取第一个群组ID</option>
|
||||
<option value="get_instructions">获取群组指令</option>
|
||||
</select>
|
||||
</div>
|
||||
<input type="submit" value="提交">
|
||||
</form>
|
||||
|
||||
{% if result %}
|
||||
<div class="result">{{ result }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,50 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>系统菜单</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: white;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
button {
|
||||
padding: 10px 20px;
|
||||
margin: 10px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>欢迎进入系统</h1>
|
||||
|
||||
<div class="container">
|
||||
<button onclick="window.location.href='/redis_operations'">群组管理</button>
|
||||
<button onclick="window.location.href='/messages'">查看消息列表</button>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,110 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>消息列表</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: white;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
table th, table td {
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
table th {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
.table-container {
|
||||
max-height: 400px; /* 设置表格的最大高度 */
|
||||
overflow-y: auto; /* 启用垂直滚动条 */
|
||||
}
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.pagination a {
|
||||
padding: 8px 16px;
|
||||
margin: 0 5px;
|
||||
text-decoration: none;
|
||||
color: #007bff;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.pagination a:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
.pagination span {
|
||||
padding: 8px 16px;
|
||||
margin: 0 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>消息列表</h1>
|
||||
|
||||
<div class="container">
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>群ID</th>
|
||||
<th>时间戳</th>
|
||||
<th>发送者</th>
|
||||
<th>内容</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for message in messages %}
|
||||
<tr>
|
||||
<td>{{ message[0] }}</td>
|
||||
<td>{{ message[1] }}</td>
|
||||
<td>{{ message[2] }}</td>
|
||||
<td>{{ message[3] }}</td>
|
||||
<td>{{ message[4] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
{% if page > 1 %}
|
||||
<a href="/messages?page=1">首页</a>
|
||||
<a href="/messages?page={{ page - 1 }}">上一页</a>
|
||||
{% endif %}
|
||||
|
||||
<span>第 {{ page }} 页 / {{ total_pages }} 页</span>
|
||||
|
||||
{% if page < total_pages %}
|
||||
<a href="/messages?page={{ page + 1 }}">下一页</a>
|
||||
<a href="/messages?page={{ total_pages }}">末页</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
# 制作UI进行群管理,群功能管理,不使用指令完成。
|
||||
@@ -1,60 +0,0 @@
|
||||
from flask import Flask, render_template, request, jsonify
|
||||
|
||||
import os
|
||||
|
||||
from group_auto.group_auto_invite import add_mapping, del_mapping, get_first_group_id, get_group_ids
|
||||
from ui.messages_list import get_total_messages, get_messages
|
||||
|
||||
# 设置 Flask 实例化时指定模板文件夹路径
|
||||
app = Flask(__name__, template_folder=os.path.join(os.path.dirname(__file__), '..', 'templates'))
|
||||
|
||||
|
||||
# 主菜单页面
|
||||
@app.route('/')
|
||||
def index():
|
||||
return render_template('index.html')
|
||||
|
||||
|
||||
# Redis 操作页面
|
||||
@app.route('/redis_operations', methods=['GET', 'POST'])
|
||||
def redis_operations():
|
||||
if request.method == 'POST':
|
||||
key = request.form.get('key')
|
||||
group_id = request.form.get('group_id')
|
||||
action = request.form.get('action')
|
||||
|
||||
result = ''
|
||||
if action == 'add':
|
||||
result = add_mapping(key, group_id)
|
||||
elif action == 'del':
|
||||
result = del_mapping(key, group_id)
|
||||
elif action == 'get':
|
||||
result = get_group_ids(key)
|
||||
elif action == 'get_first':
|
||||
result = get_first_group_id(key)
|
||||
|
||||
return render_template('group_auto_invite_ui.html', result=result)
|
||||
|
||||
return render_template('group_auto_invite_ui.html', result='')
|
||||
|
||||
|
||||
# 显示消息列表(分页)
|
||||
@app.route('/messages', methods=['GET'])
|
||||
def messages():
|
||||
page = int(request.args.get('page', 1)) # 获取当前页,默认为第一页
|
||||
per_page = 10 # 每页显示10条数据
|
||||
messages = get_messages(page, per_page) # 获取指定页的数据
|
||||
total = get_total_messages() # 获取总的消息数量
|
||||
total_pages = (total // per_page) + (1 if total % per_page > 0 else 0) # 总页数
|
||||
|
||||
# 分页控制,确保当前页数在有效范围内
|
||||
if page > total_pages:
|
||||
page = total_pages
|
||||
if page < 1:
|
||||
page = 1
|
||||
|
||||
return render_template('message_list.html', messages=messages, page=page, total_pages=total_pages)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True)
|
||||
@@ -1,42 +0,0 @@
|
||||
import pymysql
|
||||
|
||||
# MySQL 配置
|
||||
db_config = {
|
||||
'host': '192.168.2.32',
|
||||
'user': 'root',
|
||||
'password': 'lw123456',
|
||||
'database': 'message_archive'
|
||||
}
|
||||
|
||||
|
||||
# 获取消息列表,按时间倒序
|
||||
def get_messages(page=1, per_page=10):
|
||||
try:
|
||||
connection = pymysql.connect(**db_config)
|
||||
with connection.cursor() as cursor:
|
||||
offset = (page - 1) * per_page
|
||||
cursor.execute(
|
||||
"SELECT id, group_id, timestamp, sender, content FROM messages ORDER BY timestamp DESC LIMIT %s OFFSET %s",
|
||||
(per_page, offset))
|
||||
messages = cursor.fetchall()
|
||||
return messages
|
||||
except pymysql.MySQLError as e:
|
||||
print(f"数据库查询失败: {e}")
|
||||
return []
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
|
||||
# 获取消息总数
|
||||
def get_total_messages():
|
||||
try:
|
||||
connection = pymysql.connect(**db_config)
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("SELECT COUNT(*) FROM messages")
|
||||
total = cursor.fetchone()[0]
|
||||
return total
|
||||
except pymysql.MySQLError as e:
|
||||
print(f"数据库查询失败: {e}")
|
||||
return 0
|
||||
finally:
|
||||
connection.close()
|
||||
Reference in New Issue
Block a user