diff --git a/base/func_deepseek.py b/base/func_deepseek.py
new file mode 100644
index 0000000..f9ae493
--- /dev/null
+++ b/base/func_deepseek.py
@@ -0,0 +1,132 @@
+import requests
+import json
+import logging
+
+from datetime import datetime
+
+
+class DeepSeek():
+ def __init__(self, conf: dict) -> None:
+ self.key = conf.get("key")
+ self.api = conf.get("api")
+ prompt = conf.get("prompt")
+ self.model = conf.get("model")
+ self.LOG = logging.getLogger("deepseek")
+ self.conversation_list = {}
+ self.system_content_msg = {"role": "system", "content": prompt}
+
+ def __repr__(self):
+ return 'DeepSeek'
+
+ def get_answer(self, question: str, wxid: str) -> str:
+ # 设置请求头
+ self.updateMessage(wxid, question, "user")
+ rsp = ""
+ try:
+ headers = {
+ "Content-Type": "application/json; charset=utf-8",
+ "Authorization": f"Bearer {self.key}"
+ }
+ # 设置请求的payload
+ data = {
+ "model": self.model,
+ "messages": [
+ self.system_content_msg,
+ {
+ "role": "user",
+ "content": f"{question}"
+ }
+
+ ]
+ }
+ # 发送POST请求
+ response = requests.post(self.api, headers=headers, data=json.dumps(data), )
+ response.encoding = 'utf-8'
+
+ # 输出响应内容
+ print(response.status_code)
+ # print(response.text)
+ rsp = extract_content(response.text)
+ self.updateMessage(wxid, rsp, "assistant")
+ except Exception as e0:
+ self.LOG.error(f"发生未知错误:{str(e0)}")
+ return rsp
+
+ def updateMessage(self, wxid: str, question: str, role: str) -> None:
+ now_time = str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
+
+ time_mk = "当需要回答时间时请直接参考回复:"
+ # 初始化聊天记录,组装系统信息
+ if wxid not in self.conversation_list.keys():
+ question_ = [
+ self.system_content_msg,
+ {"role": "system", "content": "" + time_mk + now_time}
+ ]
+ self.conversation_list[wxid] = question_
+
+ # 当前问题
+ content_question_ = {"role": role, "content": question}
+ self.conversation_list[wxid].append(content_question_)
+
+ for cont in self.conversation_list[wxid]:
+ if cont["role"] != "system":
+ continue
+ if cont["content"].startswith(time_mk):
+ cont["content"] = time_mk + now_time
+
+ # 只存储10条记录,超过滚动清除
+ i = len(self.conversation_list[wxid])
+ if i > 10:
+ print("滚动清除微信记录:" + wxid)
+ # 删除多余的记录,倒着删,且跳过第一个的系统消息
+ del self.conversation_list[wxid][1]
+
+ @staticmethod
+ def value_check(conf: dict) -> bool:
+ if conf:
+ if conf.get("key") and conf.get("api") and conf.get("prompt"):
+ return True
+ return False
+
+
+# 解析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
+
+
+if __name__ == '__main__':
+ from configuration import Config
+
+ config = Config().DEEPSEEK
+ if not config:
+ exit(0)
+
+ chat = DeepSeek(config)
+
+ while True:
+ q = input(">>> ")
+ try:
+ time_start = datetime.now() # 记录开始时间
+ print(chat.get_answer(q, "Jyunere"))
+ time_end = datetime.now() # 记录结束时间
+
+ print(f"{round((time_end - time_start).total_seconds(), 2)}s") # 计算的时间差为程序的执行时间,单位为秒/s
+ except Exception as e:
+ print(e)
+
+#
+# [
+# "windsurf/claude-3-5-sonnet",
+# "windsurf/gpt4o",
+# "windsurf/deepseek-chat",
+# "windsurf/deepseek-reasoner",
+# "windsurf/gpt4-o3-mini",
+# "windsurf/gemini-2.0-flash",
+# ]
diff --git a/config.yaml b/config.yaml
index 2b2fdea..a876ce3 100644
--- a/config.yaml
+++ b/config.yaml
@@ -92,6 +92,18 @@ claude:
key: 46a5674a-e978-491b-a810-5d54605f2c36
api: http://127.0.0.1:8080/v1/chat/completions # 如果你不知道这是干嘛的,就不要改
model: windsurf/gpt4o #
+ prompt: '你是一个信息归纳分析工程师,你根据提问会搜索相关资料。经过信息精炼之后返回内容。
+ 请回复时以以下格式进行返回:
+ - 问题描述:
+ - 问题评价:分析问题的提出角度,如(财经、彩票、房产、股票、家居、教育、科技、社会、时尚、时政、体育、星座、游戏、娱乐)等
+ - 总结:经过300个字以内的优化返回,返回内容请进行一定程度的结构化,方便快速阅读' # 根据需要对角色进行设定
+
+# DEEPSEEK
+#
+deepseek:
+ key: sk-14bf1893e78040989a43b6f05c07974a
+ api: https://api.deepseek.com/chat/completions # 如果你不知道这是干嘛的,就不要改
+ model: deepseek-chat #
prompt: '你是一个信息归纳分析工程师,你根据提问会搜索相关资料。经过信息精炼之后返回内容。
请回复时以以下格式进行返回:
- 问题描述:
diff --git a/configuration.py b/configuration.py
index 361f425..1178b84 100644
--- a/configuration.py
+++ b/configuration.py
@@ -38,3 +38,4 @@ class Config(object):
self.BardAssistant = yconfig.get("bard", {})
self.ZhiPu = yconfig.get("zhipu", {})
self.CLAUDE = yconfig.get("claude", {})
+ self.DEEPSEEK =yconfig.get("deepseek",{})
diff --git a/robot.py b/robot.py
index c7be625..c539594 100644
--- a/robot.py
+++ b/robot.py
@@ -40,8 +40,8 @@ from message_report.write_db import write_to_db, generate_and_send_ranking
from message_storage.message_to_db import archive_message, get_messages
from message_summary.message_summary_4o import message_summary
from sehuatang.shehuatang import pdf_file_path
+from xiuren.meitu_dl import meitu_dowload_pic
from xiuren.random_pic import get_xiuren_pic
-from xiuren.xiuren_dl import xiuren_dowload_pic
class Robot(Job):
@@ -538,7 +538,7 @@ class Robot(Job):
def xiu_ren_download_task(self):
try:
- path = xiuren_dowload_pic()
+ path = meitu_dowload_pic()
self.wcf.send_file(path, "45317011307@chatroom")
except Exception as e:
self.LOG.error(f"xiuren_dowload_pic error:{e}")
diff --git a/templates/group_auto_invite_ui.html b/templates/group_auto_invite_ui.html
new file mode 100644
index 0000000..0b12085
--- /dev/null
+++ b/templates/group_auto_invite_ui.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+ 群组管理
+
+
+
+
+ 群组管理
+
+
+
+
+ {% if result %}
+
{{ result }}
+ {% endif %}
+
+
+
+
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 0000000..c7adcc8
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+ 系统菜单
+
+
+
+
+ 欢迎进入系统
+
+
+
+
+
+
+
+
diff --git a/templates/message_list.html b/templates/message_list.html
new file mode 100644
index 0000000..dc76c8d
--- /dev/null
+++ b/templates/message_list.html
@@ -0,0 +1,110 @@
+
+
+
+
+
+ 消息列表
+
+
+
+
+ 消息列表
+
+
+
+
+
+
+ | ID |
+ 群ID |
+ 时间戳 |
+ 发送者 |
+ 内容 |
+
+
+
+ {% for message in messages %}
+
+ | {{ message[0] }} |
+ {{ message[1] }} |
+ {{ message[2] }} |
+ {{ message[3] }} |
+ {{ message[4] }} |
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+
diff --git a/ui/README.md b/ui/README.md
new file mode 100644
index 0000000..20ce36b
--- /dev/null
+++ b/ui/README.md
@@ -0,0 +1 @@
+# 制作UI进行群管理,群功能管理,不使用指令完成。
diff --git a/ui/message_ui.py b/ui/message_ui.py
new file mode 100644
index 0000000..71275b7
--- /dev/null
+++ b/ui/message_ui.py
@@ -0,0 +1,60 @@
+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)
diff --git a/ui/messages_list.py b/ui/messages_list.py
new file mode 100644
index 0000000..6320ebd
--- /dev/null
+++ b/ui/messages_list.py
@@ -0,0 +1,42 @@
+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()
diff --git a/xiuren/meitu_dl.py b/xiuren/meitu_dl.py
new file mode 100644
index 0000000..0a080a9
--- /dev/null
+++ b/xiuren/meitu_dl.py
@@ -0,0 +1,161 @@
+import requests
+from bs4 import BeautifulSoup
+import time
+import os
+import re
+from urllib.parse import urljoin
+from selenium import webdriver
+from selenium.webdriver.chrome.options import Options
+from selenium.webdriver.common.by import By
+from PIL import Image
+from io import BytesIO
+
+from xiuren.xiuren_pdf import generate_pdf_from_images
+
+headers = {
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/91.0.4472.124 Safari/537.36',
+ 'Referer': 'https://www.mntuce.com/'
+}
+
+seen_posts = set()
+download_root = "xiuren" # 全局定义下载根目录
+
+
+def fetch_posts(base_url, posts_per_batch=10):
+ posts = []
+ page = 1
+
+ while len(posts) < posts_per_batch:
+ url = f"{base_url}/page/{page}" if page > 1 else base_url
+ try:
+ response = requests.get(url, headers=headers, timeout=10)
+ response.raise_for_status()
+ soup = BeautifulSoup(response.text, 'html.parser')
+
+ post_elements = soup.select('posts.posts-item.card h2.item-heading a')
+ if not post_elements:
+ print(f"页面 {page} 未找到帖子,停止爬取")
+ break
+
+ for post in post_elements:
+ post_url = urljoin(base_url, post.get('href'))
+ post_title = post.get_text().strip()
+
+ # 检查帖子是否已下载
+ match = re.search(r'No\.(\d+)', post_title)
+ folder_name = match.group(1) if match else f"unknown_{len(posts) + 1}"
+ folder_path = os.path.join(download_root, folder_name)
+
+ if post_url not in seen_posts:
+ if os.path.exists(folder_path):
+ seen_posts.add(post_url) # 标记为已见过,避免重复检查
+ continue # 跳过已下载的帖子
+
+ seen_posts.add(post_url)
+ posts.append({'title': post_title, 'url': post_url})
+ if len(posts) == posts_per_batch:
+ break # 凑齐所需数量后退出内层循环
+
+ page += 1
+ time.sleep(1)
+ except requests.RequestException as e:
+ print(f"请求 {url} 失败: {e}")
+ break
+
+ return posts
+
+
+def get_total_pages(post_url):
+ try:
+ response = requests.get(post_url, headers=headers, timeout=10)
+ response.raise_for_status()
+ soup = BeautifulSoup(response.text, 'html.parser')
+
+ page_links = soup.select('p.post-nav-links a.post-page-numbers')
+ pages = [int(link.text) for link in page_links if link.text.isdigit()]
+ return max(pages) if pages else 1
+ except requests.RequestException as e:
+ print(f"请求 {post_url} 失败,默认1页: {e}")
+ return 1
+
+
+def fetch_images(post_url):
+ images = []
+ total_pages = get_total_pages(post_url)
+ print(f"帖子 {post_url} 共有 {total_pages} 页")
+
+ options = Options()
+ options.headless = True
+ driver = webdriver.Chrome(options=options)
+
+ for page in range(1, total_pages + 1):
+ url = f"{post_url}/{page}" if page > 1 else post_url
+ driver.get(url)
+ time.sleep(2)
+
+ img_elements = driver.find_elements(By.CSS_SELECTOR, 'figure.wp-block-gallery figure.wp-block-image img')
+ for img in img_elements:
+ img_url = img.get_attribute('src')
+ if img_url and img_url.startswith('http'):
+ images.append(img_url)
+
+ print(f"已爬取 {url},找到 {len(img_elements)} 张图片")
+
+ driver.quit()
+ return images
+
+
+def download_image(img_url, folder_path, img_index):
+ try:
+ response = requests.get(img_url, headers=headers, timeout=10)
+ response.raise_for_status()
+
+ img = Image.open(BytesIO(response.content)).convert('RGB')
+ img_name = f"{img_index:03d}.jpg"
+ img_path = os.path.join(folder_path, img_name)
+
+ img.save(img_path, 'JPEG', quality=95)
+ print(f"已下载并转换为JPG: {img_path}")
+ except Exception as e:
+ print(f"处理图片 {img_url} 失败: {e}")
+
+
+def meitu_dowload_pic():
+ base_url = "https://www.mntuce.com/"
+
+ if not os.path.exists(download_root):
+ os.makedirs(download_root)
+
+ print(f"开始爬取 {base_url} 的帖子...")
+ posts = fetch_posts(base_url, 10)
+
+ if not posts:
+ print("未获取到符合条件的帖子,请检查选择器或网络连接。")
+ return
+
+ print(f"成功选择 {len(posts)} 个未下载的帖子,开始下载图片...")
+ for i, post in enumerate(posts, 1):
+ print(f"\n{i}. 标题: {post['title']}")
+ print(f" 链接: {post['url']}")
+
+ match = re.search(r'No\.(\d+)', post['title'])
+ folder_name = match.group(1) if match else f"unknown_{i}"
+ folder_path = os.path.join(download_root, folder_name)
+
+ os.makedirs(folder_path, exist_ok=True) # 创建目录,exist_ok=True 避免重复创建报错
+ images = fetch_images(post['url'])
+ if images:
+ print(f"共找到 {len(images)} 张图片,开始下载...")
+ for idx, img_url in enumerate(images, 1):
+ download_image(img_url, folder_path, idx)
+ else:
+ print("未找到图片,可能需要调整策略。")
+
+ time.sleep(1)
+
+ # 将下载好的帖子生成PDF
+ return generate_pdf_from_images(download_root)
+
+
+if __name__ == "__main__":
+ meitu_dowload_pic()
\ No newline at end of file