|
|
|
|
@ -13,29 +13,46 @@ from servermanager.api.blogapi import BlogApi
|
|
|
|
|
from servermanager.api.commonapi import ChatGPT, CommandHandler
|
|
|
|
|
from .MemcacheStorage import MemcacheStorage
|
|
|
|
|
|
|
|
|
|
# 初始化微信机器人实例,配置token和启用session功能
|
|
|
|
|
robot = WeRoBot(token=os.environ.get('DJANGO_WEROBOT_TOKEN')
|
|
|
|
|
or 'lylinux', enable_session=True)
|
|
|
|
|
# 创建Memcache存储实例用于session存储
|
|
|
|
|
memstorage = MemcacheStorage()
|
|
|
|
|
# 根据存储可用性配置机器人的session存储方式
|
|
|
|
|
if memstorage.is_available:
|
|
|
|
|
robot.config['SESSION_STORAGE'] = memstorage
|
|
|
|
|
else:
|
|
|
|
|
# 如果文件存储存在则删除旧文件,使用文件存储作为session存储
|
|
|
|
|
if os.path.exists(os.path.join(settings.BASE_DIR, 'werobot_session')):
|
|
|
|
|
os.remove(os.path.join(settings.BASE_DIR, 'werobot_session'))
|
|
|
|
|
robot.config['SESSION_STORAGE'] = FileStorage(filename='werobot_session')
|
|
|
|
|
|
|
|
|
|
# 初始化博客API和命令处理器实例
|
|
|
|
|
blogapi = BlogApi()
|
|
|
|
|
cmd_handler = CommandHandler()
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def convert_to_article_reply(articles, message):
|
|
|
|
|
"""
|
|
|
|
|
将文章列表转换为微信文章回复格式
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
articles: 文章对象列表
|
|
|
|
|
message: 微信消息对象
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ArticlesReply: 微信文章回复对象
|
|
|
|
|
"""
|
|
|
|
|
reply = ArticlesReply(message=message)
|
|
|
|
|
from blog.templatetags.blog_tags import truncatechars_content
|
|
|
|
|
for post in articles:
|
|
|
|
|
# 提取文章中的图片URL
|
|
|
|
|
imgs = re.findall(r'(?:http\:|https\:)?\/\/.*\.(?:png|jpg)', post.body)
|
|
|
|
|
imgurl = ''
|
|
|
|
|
if imgs:
|
|
|
|
|
imgurl = imgs[0]
|
|
|
|
|
# 创建单篇文章对象
|
|
|
|
|
article = Article(
|
|
|
|
|
title=post.title,
|
|
|
|
|
description=truncatechars_content(post.body),
|
|
|
|
|
@ -48,6 +65,16 @@ def convert_to_article_reply(articles, message):
|
|
|
|
|
|
|
|
|
|
@robot.filter(re.compile(r"^\?.*"))
|
|
|
|
|
def search(message, session):
|
|
|
|
|
"""
|
|
|
|
|
处理文章搜索请求,根据关键词搜索文章并返回结果
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
message: 微信消息对象,包含搜索关键词
|
|
|
|
|
session: 用户会话对象
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ArticlesReply或str: 搜索结果或提示信息
|
|
|
|
|
"""
|
|
|
|
|
s = message.content
|
|
|
|
|
searchstr = str(s).replace('?', '')
|
|
|
|
|
result = blogapi.search_articles(searchstr)
|
|
|
|
|
@ -61,6 +88,16 @@ def search(message, session):
|
|
|
|
|
|
|
|
|
|
@robot.filter(re.compile(r'^category\s*$', re.I))
|
|
|
|
|
def category(message, session):
|
|
|
|
|
"""
|
|
|
|
|
获取所有文章分类目录信息
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
message: 微信消息对象
|
|
|
|
|
session: 用户会话对象
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
str: 包含所有分类名称的字符串
|
|
|
|
|
"""
|
|
|
|
|
categorys = blogapi.get_category_lists()
|
|
|
|
|
content = ','.join(map(lambda x: x.name, categorys))
|
|
|
|
|
return '所有文章分类目录:' + content
|
|
|
|
|
@ -68,6 +105,16 @@ def category(message, session):
|
|
|
|
|
|
|
|
|
|
@robot.filter(re.compile(r'^recent\s*$', re.I))
|
|
|
|
|
def recents(message, session):
|
|
|
|
|
"""
|
|
|
|
|
获取最新发布的文章列表
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
message: 微信消息对象
|
|
|
|
|
session: 用户会话对象
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ArticlesReply或str: 最新文章列表或提示信息
|
|
|
|
|
"""
|
|
|
|
|
articles = blogapi.get_recent_articles()
|
|
|
|
|
if articles:
|
|
|
|
|
reply = convert_to_article_reply(articles, message)
|
|
|
|
|
@ -78,6 +125,16 @@ def recents(message, session):
|
|
|
|
|
|
|
|
|
|
@robot.filter(re.compile('^help$', re.I))
|
|
|
|
|
def help(message, session):
|
|
|
|
|
"""
|
|
|
|
|
返回系统帮助信息,包含所有可用命令说明
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
message: 微信消息对象
|
|
|
|
|
session: 用户会话对象
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
str: 帮助信息文本
|
|
|
|
|
"""
|
|
|
|
|
return '''欢迎关注!
|
|
|
|
|
默认会与图灵机器人聊天~~
|
|
|
|
|
你可以通过下面这些命令来获得信息
|
|
|
|
|
@ -100,22 +157,61 @@ def help(message, session):
|
|
|
|
|
|
|
|
|
|
@robot.filter(re.compile(r'^weather\:.*$', re.I))
|
|
|
|
|
def weather(message, session):
|
|
|
|
|
"""
|
|
|
|
|
处理天气查询请求(待实现)
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
message: 微信消息对象
|
|
|
|
|
session: 用户会话对象
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
str: 建设中提示信息
|
|
|
|
|
"""
|
|
|
|
|
return "建设中..."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@robot.filter(re.compile(r'^idcard\:.*$', re.I))
|
|
|
|
|
def idcard(message, session):
|
|
|
|
|
"""
|
|
|
|
|
处理身份证信息查询请求(待实现)
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
message: 微信消息对象
|
|
|
|
|
session: 用户会话对象
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
str: 建设中提示信息
|
|
|
|
|
"""
|
|
|
|
|
return "建设中..."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@robot.handler
|
|
|
|
|
def echo(message, session):
|
|
|
|
|
"""
|
|
|
|
|
主消息处理函数,创建消息处理器并处理用户消息
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
message: 微信消息对象
|
|
|
|
|
session: 用户会话对象
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
str或其他类型: 处理结果
|
|
|
|
|
"""
|
|
|
|
|
handler = MessageHandler(message, session)
|
|
|
|
|
return handler.handler()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MessageHandler:
|
|
|
|
|
"""微信消息处理器类,负责处理各种用户消息和命令"""
|
|
|
|
|
|
|
|
|
|
def __init__(self, message, session):
|
|
|
|
|
"""
|
|
|
|
|
初始化消息处理器
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
message: 微信消息对象
|
|
|
|
|
session: 用户会话对象
|
|
|
|
|
"""
|
|
|
|
|
userid = message.source
|
|
|
|
|
self.message = message
|
|
|
|
|
self.session = session
|
|
|
|
|
@ -129,27 +225,51 @@ class MessageHandler:
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def is_admin(self):
|
|
|
|
|
"""
|
|
|
|
|
判断当前用户是否为管理员
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
bool: 是否为管理员
|
|
|
|
|
"""
|
|
|
|
|
return self.userinfo.isAdmin
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def is_password_set(self):
|
|
|
|
|
"""
|
|
|
|
|
判断管理员密码是否已设置
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
bool: 密码是否已设置
|
|
|
|
|
"""
|
|
|
|
|
return self.userinfo.isPasswordSet
|
|
|
|
|
|
|
|
|
|
def save_session(self):
|
|
|
|
|
"""
|
|
|
|
|
保存用户会话信息到session中
|
|
|
|
|
"""
|
|
|
|
|
info = jsonpickle.encode(self.userinfo)
|
|
|
|
|
self.session[self.userid] = info
|
|
|
|
|
|
|
|
|
|
def handler(self):
|
|
|
|
|
"""
|
|
|
|
|
主要的消息处理逻辑,根据用户状态和输入内容进行相应处理
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
str: 处理结果响应文本
|
|
|
|
|
"""
|
|
|
|
|
info = self.message.content
|
|
|
|
|
|
|
|
|
|
# 处理管理员退出命令
|
|
|
|
|
if self.userinfo.isAdmin and info.upper() == 'EXIT':
|
|
|
|
|
self.userinfo = WxUserInfo()
|
|
|
|
|
self.save_session()
|
|
|
|
|
return "退出成功"
|
|
|
|
|
# 处理管理员登录命令
|
|
|
|
|
if info.upper() == 'ADMIN':
|
|
|
|
|
self.userinfo.isAdmin = True
|
|
|
|
|
self.save_session()
|
|
|
|
|
return "输入管理员密码"
|
|
|
|
|
# 处理管理员密码验证
|
|
|
|
|
if self.userinfo.isAdmin and not self.userinfo.isPasswordSet:
|
|
|
|
|
passwd = settings.WXADMIN
|
|
|
|
|
if settings.TESTING:
|
|
|
|
|
@ -159,6 +279,7 @@ class MessageHandler:
|
|
|
|
|
self.save_session()
|
|
|
|
|
return "验证通过,请输入命令或者要执行的命令代码:输入helpme获得帮助"
|
|
|
|
|
else:
|
|
|
|
|
# 处理密码错误次数限制
|
|
|
|
|
if self.userinfo.Count >= 3:
|
|
|
|
|
self.userinfo = WxUserInfo()
|
|
|
|
|
self.save_session()
|
|
|
|
|
@ -166,6 +287,7 @@ class MessageHandler:
|
|
|
|
|
self.userinfo.Count += 1
|
|
|
|
|
self.save_session()
|
|
|
|
|
return "验证失败,请重新输入管理员密码:"
|
|
|
|
|
# 处理管理员命令执行
|
|
|
|
|
if self.userinfo.isAdmin and self.userinfo.isPasswordSet:
|
|
|
|
|
if self.userinfo.Command != '' and info.upper() == 'Y':
|
|
|
|
|
return cmd_handler.run(self.userinfo.Command)
|
|
|
|
|
@ -176,12 +298,19 @@ class MessageHandler:
|
|
|
|
|
self.save_session()
|
|
|
|
|
return "确认执行: " + info + " 命令?"
|
|
|
|
|
|
|
|
|
|
# 默认使用ChatGPT处理普通消息
|
|
|
|
|
return ChatGPT.chat(info)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WxUserInfo():
|
|
|
|
|
"""微信用户信息类,存储用户的状态信息"""
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
"""
|
|
|
|
|
初始化用户信息,默认为非管理员状态
|
|
|
|
|
"""
|
|
|
|
|
self.isAdmin = False
|
|
|
|
|
self.isPasswordSet = False
|
|
|
|
|
self.Count = 0
|
|
|
|
|
self.Command = ''
|
|
|
|
|
|
|
|
|
|
|