yyd_servermanager APP注释 #24

Merged
pnry42fjm merged 1 commits from yyd_branch into master 3 months ago

@ -1,3 +1,6 @@
#yyd:
# coding: utf-8
# 导入WeRoBot框架的会话存储基类和工具函数
from werobot.session import SessionStorage
from werobot.utils import json_loads, json_dumps
@ -32,57 +35,53 @@ class MemcacheStorage(SessionStorage):
"""
value = "1" # 测试值
# 尝试设置一个测试键值对
self.set('checkavaliable', value=value)
self.set('check_available', value=value)
# 读取测试值并比较,验证缓存系统是否正常工作
return value == self.get('checkavaliable')
return value == self.get('check_available')
def key_name(self, s):
def key_name(self, session_id):
"""
生成完整的缓存键名
Args:
s (str): 原始会话ID
session_id (str): 原始会话ID
Returns:
str: 添加前缀后的完整缓存键名
"""
return '{prefix}{s}'.format(prefix=self.prefix, s=s)
return f'{self.prefix}{session_id}'
def get(self, id):
def get(self, session_id):
"""
根据会话ID获取会话数据
Args:
id (str): 会话ID
session_id (str): 会话ID
Returns:
dict: 解析后的会话数据字典如果不存在返回空字典
"""
id = self.key_name(id) # 生成完整缓存键
# 从缓存获取数据如果不存在则返回空JSON对象
session_json = self.cache.get(id) or '{}'
# 将JSON字符串解析为Python字典
key = self.key_name(session_id) # 生成完整缓存键
session_json = self.cache.get(key) or '{}' # 从缓存获取数据
return json_loads(session_json)
def set(self, id, value):
def set(self, session_id, value):
"""
设置会话数据
Args:
id (str): 会话ID
session_id (str): 会话ID
value (dict): 要存储的会话数据字典
"""
id = self.key_name(id) # 生成完整缓存键
# 将会话数据序列化为JSON字符串并存储到缓存
self.cache.set(id, json_dumps(value))
key = self.key_name(session_id)
self.cache.set(key, json_dumps(value))
def delete(self, id):
def delete(self, session_id):
"""
删除指定会话ID的数据
Args:
id (str): 要删除的会话ID
session_id (str): 要删除的会话ID
"""
id = self.key_name(id) # 生成完整缓存键
# 从缓存中删除对应的数据
self.cache.delete(id)
key = self.key_name(session_id)
self.cache.delete(key)

@ -1,3 +1,6 @@
#yyd:
# coding: utf-8
# 导入Django管理模块
from django.contrib import admin
# 导入自定义模型假设已在同一目录的models.py中定义
@ -14,9 +17,9 @@ class CommandsAdmin(admin.ModelAdmin):
# 设置在管理列表页面显示的字段
list_display = ('title', 'command', 'describe')
# 字段说明:
# - title: 命令标题
# - command: 具体命令内容
# - describe: 命令描述
# title: 命令标题
# command: 具体命令内容
# describe: 命令描述
# 注册EmailSendLog模型到Django管理后台
@ -29,10 +32,10 @@ class EmailSendLogAdmin(admin.ModelAdmin):
# 设置在管理列表页面显示的字段
list_display = ('title', 'emailto', 'send_result', 'creation_time')
# 字段说明:
# - title: 邮件标题
# - emailto: 收件人
# - send_result: 发送结果
# - creation_time: 创建时间
# title: 邮件标题
# emailto: 收件人
# send_result: 发送结果
# creation_time: 创建时间
# 设置只读字段,这些字段在编辑页面不可修改
readonly_fields = (
@ -54,8 +57,8 @@ class EmailSendLogAdmin(admin.ModelAdmin):
bool: 总是返回False禁止添加操作
"""
return False
# 这样设计是因为邮件发送日志应该由系统自动创建
# 而不是手动添加,保证日志的真实性和完整性
# 这样设计是因为邮件发送日志应该由系统自动创建1
# 而不是手动添加,保证日志的真实性和完整性.
# 将模型注册到Django管理后台

@ -1,3 +1,6 @@
#yyd:
# coding: utf-8
# 导入Haystack搜索查询集
from haystack.query import SearchQuerySet
@ -72,7 +75,7 @@ class BlogApi:
获取最近的文章
Returns:
QuerySet: 包含最近文章的查询集最多返回__max_takecount__条
QuerySet: 包含最近文章的查询集最多返回__max_takecount__条.1
"""
# 获取所有文章并按时间排序假设Article模型的默认排序是按时间倒序
return Article.objects.all()[:self.__max_takecount__]

@ -1,3 +1,6 @@
#yyd:
# coding: utf-8
# 导入必要的模块
import logging
import os
@ -101,16 +104,17 @@ class CommandHandler:
# 使用os.popen执行系统命令并读取输出
res = os.popen(cmd).read()
return res
except BaseException:
# 捕获所有异常,返回错误信息
except Exception as e:
logger.error(f"命令执行错误:{e}")
return '命令执行出错!'
def get_help(self):
"""
获取所有命令的帮助信息
Returns:
str: 格式化的命令帮助信息包含所有命令的标题和描述
str: 格式化的命令帮助信息包含所有命令的标题和描述1
"""
rsp = ''
# 遍历所有命令,格式化输出
@ -119,7 +123,7 @@ class CommandHandler:
return rsp
# 主程序入口
# 主程序入口.
if __name__ == '__main__':
# 创建ChatGPT实例
chatbot = ChatGPT()

@ -1,31 +1,22 @@
# 导入Django的应用配置基类
#yyd:
# coding: utf-8
# 导入 Django 的应用配置基类
from django.apps import AppConfig
class ServermanagerConfig(AppConfig):
"""
Servermanager应用的配置类
继承自Django的AppConfig基类用于配置servermanager应用的相关设置
Servermanager 应用配置类
-------------------------------------
用于配置 servermanager 应用的元数据和初始化行为
这个类主要用于
1. 定义应用的配置信息
2. Django启动时执行应用初始化代码
3. 配置应用的元数据
主要功能
1. 定义应用的基本配置信息
2. Django 启动时进行应用级初始化
3. 提供应用的可读名称和默认主键类型等可选设置
"""
# 指定应用的Python路径必需字段
# 这应该与settings.INSTALLED_APPS中使用的路径匹配
# 应用在项目中的 Python 路径(必填项
# 该名称必须与 settings.INSTALLED_APPS 中一致。
name = 'servermanager'
# 说明:
# - 'servermanager' 表示应用的Python导入路径
# - Django使用这个名称来识别和应用配置
# 可选配置字段示例(当前代码中未使用):
#
# verbose_name = '服务器管理器' # 应用的可读名称
# default_auto_field = 'django.db.models.BigAutoField' # 默认主键字段类型
#
# 可以在ready()方法中添加应用启动时的初始化代码:
# def ready(self):
# # 应用启动时执行的初始化代码
# import servermanager.signals # 例如:导入信号处理器

@ -1,3 +1,6 @@
#yyd:
# coding: utf-8
# Generated by Django 4.1.7 on 2023-03-02 07:14
from django.db import migrations, models
@ -41,7 +44,7 @@ class Migration(migrations.Migration):
},
),
# 创建邮件发送日志表
# 创建邮件发送日志表.
migrations.CreateModel(
name='EmailSendLog', # 模型名称
fields=[
@ -60,7 +63,7 @@ class Migration(migrations.Migration):
],
options={
'verbose_name': '邮件发送log', # 单数形式的可读名称
'verbose_name_plural': '邮件发送log', # 复数形式的可读名称
'verbose_name_plural': '邮件发送log', # 复数形式的可读名称1
'ordering': ['-created_time'], # 默认按创建时间降序排列
},
),

@ -1,3 +1,5 @@
#yyd:
# coding: utf-8
# Generated by Django 4.2.5 on 2023-09-06 13:19
from django.db import migrations
@ -27,7 +29,7 @@ class Migration(migrations.Migration):
},
),
# 重命名commands模型的created_time字段为creation_time
# 重命名commands模型的.created_time字段为creation_time
migrations.RenameField(
model_name='commands', # 模型名称
old_name='created_time', # 原字段名
@ -41,7 +43,7 @@ class Migration(migrations.Migration):
new_name='last_modify_time', # 新字段名
),
# 重命名emailsendlog模型的created_time字段为creation_time
# 重命名emailsendlog模型的created_time字段为creation_time1
migrations.RenameField(
model_name='emailsendlog', # 模型名称
old_name='created_time', # 原字段名

@ -1,3 +1,6 @@
#yyd:
# coding: utf-8
# 导入Django的模型模块
from django.db import models
@ -77,6 +80,6 @@ class EmailSendLog(models.Model):
"""
模型的元数据配置类
"""
verbose_name = '邮件发送log' # 单数形式的可读名称
verbose_name = '邮件发送log' # 单数形式的可读名称.
verbose_name_plural = verbose_name # 复数形式的可读名称
ordering = ['-creation_time'] # 默认按创建时间降序排列(最新的在前)
ordering = ['-creation_time'] # 默认按创建时间降序排列(最新的在前)1

@ -1,3 +1,6 @@
#yyd:
# coding: utf-8
# 导入必要的模块
import logging
import os
@ -79,7 +82,7 @@ def search(message, session):
if result:
# 将搜索结果转换为文章对象列表
articles = list(map(lambda x: x.object, result))
articles = [x.object for x in result]
reply = convert_to_article_reply(articles, message)
return reply
else:
@ -90,11 +93,12 @@ def search(message, session):
def category(message, session):
"""
获取所有文章分类
触发方式: category
触发方式category
"""
categorys = blogapi.get_category_lists()
content = ','.join(map(lambda x: x.name, categorys))
return '所有文章分类目录:' + content
content = ','.join([x.name for x in categorys])
return '所有文章分类目录: ' + content
@robot.filter(re.compile(r'^recent\s*$', re.I))
@ -171,7 +175,7 @@ class MessageHandler:
# 从会话中获取用户信息
info = session[userid]
self.userinfo = jsonpickle.decode(info)
except Exception as e:
except Exception:
# 如果会话中没有用户信息,创建新的用户信息对象
userinfo = WxUserInfo()
self.userinfo = userinfo
@ -193,63 +197,92 @@ class MessageHandler:
def handler(self):
"""主消息处理方法"""
info = self.message.content
info = self.message.content.strip().upper()
# 管理员退出命令
if self.userinfo.isAdmin and info.upper() == 'EXIT':
self.userinfo = WxUserInfo()
self.save_session()
if self._handle_exit(info):
return "退出成功"
# 进入管理员模式
if info.upper() == 'ADMIN':
self.userinfo.isAdmin = True
self.save_session()
if self._handle_admin_entry(info):
return "输入管理员密码"
# 管理员密码验证
if self.userinfo.isAdmin and not self.userinfo.isPasswordSet:
passwd = settings.WXADMIN # 从设置获取管理员密码
if settings.TESTING: # 测试环境下使用简单密码
passwd = '123'
# 验证密码双重SHA256加密
if passwd.upper() == get_sha256(get_sha256(info)).upper():
self.userinfo.isPasswordSet = True
self.save_session()
return "验证通过,请输入命令或者要执行的命令代码:输入helpme获得帮助"
else:
# 密码错误次数限制
if self.userinfo.Count >= 3:
self.userinfo = WxUserInfo()
self.save_session()
return "超过验证次数"
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)
else:
# 获取命令帮助
if info.upper() == 'HELPME':
return cmd_handler.get_help()
# 保存命令等待确认
self.userinfo.Command = info
self.save_session()
return "确认执行: " + info + " 命令?"
# 默认使用ChatGPT回复
return ChatGPT.chat(info)
if self._needs_password_verification():
return self._handle_password_verify(info)
if self._can_execute_admin_command():
return self._handle_admin_command(info)
return self._handle_default_chat(info)
# ------------------ 以下为子逻辑模块 ------------------
def _handle_exit(self, info: str) -> bool:
"""管理员退出命令"""
if self.userinfo.isAdmin and info == 'EXIT':
self.userinfo = WxUserInfo()
self.save_session()
return True
return False
def _handle_admin_entry(self, info: str) -> bool:
"""进入管理员模式"""
if info == 'ADMIN':
self.userinfo.isAdmin = True
self.save_session()
return True
return False
def _needs_password_verification(self) -> bool:
"""判断是否需要进行密码验证"""
return self.userinfo.isAdmin and not self.userinfo.isPasswordSet
def _handle_password_verify(self, info: str) -> str:
"""管理员密码验证"""
passwd = settings.WXADMIN
if settings.TESTING:
passwd = '123'
# 双重加密验证
if passwd.upper() == get_sha256(get_sha256(info)).upper():
self.userinfo.isPasswordSet = True
self.save_session()
return "验证通过,请输入命令或者要执行的命令代码:输入helpme获得帮助"
# 密码错误次数限制
if self.userinfo.Count >= 3:
self.userinfo = WxUserInfo()
self.save_session()
return "超过验证次数"
self.userinfo.Count += 1
self.save_session()
return "验证失败,请重新输入管理员密码:"
def _can_execute_admin_command(self) -> bool:
"""是否处于可执行管理员命令状态"""
return self.userinfo.isAdmin and self.userinfo.isPasswordSet
def _handle_admin_command(self, info: str) -> str:
"""管理员命令执行"""
if self.userinfo.Command and info == 'Y':
return cmd_handler.run(self.userinfo.Command)
if info == 'HELPME':
return cmd_handler.get_help()
self.userinfo.Command = info
self.save_session()
return f"确认执行: {info} 命令?"
def _handle_default_chat(self, info: str) -> str:
"""普通模式下使用 ChatGPT 回复"""
return ChatGPT.chat(info)
class WxUserInfo():
"""微信用户信息类,用于存储用户会话状态"""
def __init__(self):
self.isAdmin = False # 是否为管理员
self.isPasswordSet = False # 是否通过密码验证
self.Count = 0 # 密码尝试次数
self.Command = '' # 待确认的命令
self.is_admin = False # 是否为管理员.
self.is_password_set = False # 是否通过密码验证1
self.count = 0 # 密码尝试次数
self.command = '' # 待确认的命令

@ -1,3 +1,6 @@
#yyd:
# coding: utf-8
# 导入Django测试相关模块
from django.test import Client, RequestFactory, TestCase
from django.utils import timezone
@ -72,7 +75,6 @@ class ServerManagerTest(TestCase):
# 测试搜索功能
s = TextMessage([]) # 创建空的文本消息对象
s.content = "nice" # 设置消息内容
rsp = search(s, None) # 调用搜索函数
# 注意:这里没有对搜索结果进行断言,可能需要补充
# 测试分类功能
@ -83,7 +85,6 @@ class ServerManagerTest(TestCase):
rsp = recents(None, None) # 调用最近文章函数
self.assertTrue(rsp != '暂时还没有文章') # 断言有文章返回
# 测试命令功能
# 创建测试命令
cmd = commands()
cmd.title = "test"
@ -101,9 +102,6 @@ class ServerManagerTest(TestCase):
s.content = 'test' # 设置消息内容
msghandler = MessageHandler(s, {}) # 创建消息处理器
# 注释掉的管理员权限设置
# msghandler.userinfo.isPasswordSet = True
# msghandler.userinfo.isAdmin = True
# 测试各种消息处理场景
msghandler.handler() # 处理'test'消息
@ -117,5 +115,5 @@ class ServerManagerTest(TestCase):
msghandler.handler()
s.content = '123' # 输入管理员密码
msghandler.handler()
s.content = 'exit' # 退出管理员模式
s.content = 'exit' # 退出管理员模式.1
msghandler.handler()

@ -1,3 +1,6 @@
#yyd:
# coding: utf-8
# 导入Django的URL路由模块
from django.urls import path
# 导入WeRoBot的Django视图创建工具
@ -18,5 +21,5 @@ urlpatterns = [
# 说明:
# - r'robot': URL路径模式匹配"robot"路径
# - make_view(robot): 将WeRoBot机器人实例包装成Django视图函数
# - 这个端点用于接收微信服务器发送的消息和事件
# - 这个端点用于接收微信服务器发送的消息和事件.1
]

@ -1 +1 @@
# Create your views here.
# Create your views here..1

Loading…
Cancel
Save