常见任务示例
本指南提供常见功能的实现示例,帮助你快速实现常用功能。
内容列表
- 数据持久化
- 定时任务
- 消息过滤
- 多平台适配
- 消息发送进阶(重试/超时/批量)
- 权限控制
- 消息统计
- 搜索功能
- 图片处理
数据持久化
简单计数器
from ErisPulse import sdk
from ErisPulse.Core.Event import command
@command("count", help="查看命令调用次数")
async def count_handler(event):
# 获取计数
count = sdk.storage.get("command_count", 0)
# 增加计数
count += 1
sdk.storage.set("command_count", count)
await event.reply(f"这是第 {count} 次调用此命令")
用户数据存储
@command("profile", help="查看个人资料")
async def profile_handler(event):
user_id = event.get_user_id()
# 获取用户数据
user_data = sdk.storage.get(f"user:{user_id}", {
"nickname": "",
"join_date": None,
"message_count": 0
})
profile_text = f"""
昵称: {user_data['nickname']}
加入时间: {user_data['join_date']}
消息数: {user_data['message_count']}
"""
await event.reply(profile_text.strip())
@command("setnick", help="设置昵称")
async def setnick_handler(event):
user_id = event.get_user_id()
args = event.get_command_args()
if not args:
await event.reply("请输入昵称")
return
# 更新用户数据
user_data = sdk.storage.get(f"user:{user_id}", {})
user_data["nickname"] = " ".join(args)
sdk.storage.set(f"user:{user_id}", user_data)
await event.reply(f"昵称已设置为: {' '.join(args)}")
定时任务
简单定时器
from ErisPulse import sdk
from ErisPulse.Core.Event import command
import asyncio
class TimerModule:
def __init__(self):
self.sdk = sdk
self._tasks = []
async def on_load(self, event):
"""模块加载时启动定时任务"""
self._start_timers()
@command("timer", help="定时器管理")
async def timer_handler(event):
await event.reply("定时器正在运行中...")
def _start_timers(self):
"""启动定时任务"""
# 每 60 秒执行一次
task = asyncio.create_task(self._every_minute())
self._tasks.append(task)
# 每天凌晨执行
task = asyncio.create_task(self._daily_task())
self._tasks.append(task)
async def _every_minute(self):
"""每分钟执行的任务"""
self.sdk.logger.info("每分钟任务执行")
# 你的逻辑...
async def _daily_task(self):
"""每天凌晨执行的任务(注:基于 UTC 时间计算,如需本地时间请自行调整)"""
import time
while True:
# 计算到凌晨的时间
now = time.time()
midnight = now + (86400 - now % 86400)
await asyncio.sleep(midnight - now)
# 执行任务
self.sdk.logger.info("每日任务执行")
# 你的逻辑...
使用生命周期事件
@sdk.lifecycle.on("core.init.complete")
async def init_complete_handler(event_data):
"""SDK 初始化完成后启动定时任务"""
import asyncio
async def daily_reminder():
"""每日提醒"""
await asyncio.sleep(86400) # 24小时
sdk.logger.info("执行每日任务")
# 启动后台任务
asyncio.create_task(daily_reminder())
消息过滤
关键词过滤
from ErisPulse.Core.Event import message
blocked_words = ["垃圾", "广告", "钓鱼"]
@message.on_message()
async def filter_handler(event):
text = event.get_text()
# 检查是否包含敏感词
for word in blocked_words:
if word in text:
sdk.logger.warning(f"拦截敏感消息: {word}")
return # 不处理此消息
# 正常处理消息
await event.reply(f"收到: {text}")
黑名单过滤
# 从配置或存储加载黑名单
blacklist = sdk.storage.get("user_blacklist", [])
@message.on_message()
async def blacklist_handler(event):
user_id = event.get_user_id()
if user_id in blacklist:
sdk.logger.info(f"黑名单用户: {user_id}")
return # 不处理
# 正常处理
await event.reply(f"你好,{user_id}")
多平台适配
平台特定响应
@command("help", help="显示帮助")
async def help_handler(event):
platform = event.get_platform()
if platform == "yunhu":
await event.reply("云湖平台帮助...")
elif platform == "telegram":
await event.reply("Telegram platform help...")
elif platform == "onebot11":
await event.reply("OneBot11 help...")
else:
await event.reply("通用帮助信息")
平台特性检测
@command("rich", help="发送富文本消息")
async def rich_handler(event):
platform = event.get_platform()
if platform == "yunhu":
# 云湖支持 HTML
yunhu = sdk.adapter.get("yunhu")
await yunhu.Send.To("user", event.get_user_id()).Html(
"<b>加粗文本</b><i>斜体文本</i>"
)
elif platform == "telegram":
# Telegram 支持 Markdown
telegram = sdk.adapter.get("telegram")
await telegram.Send.To("user", event.get_user_id()).Markdown(
"**加粗文本** *斜体文本*"
)
else:
# 其他平台使用纯文本
await event.reply("加粗文本 斜体文本")
消息发送进阶(重试/超时/批量)
除了简单的 event.reply(),你还可以通过适配器的 Send DSL 实现更复杂的发送场景:失败自动重试、超时取消、成功后执行逻辑、批量发送多条消息。
下面的示例用
event.get_detail_type()和event.get_target_id()从事件中获取目标类型和 ID(群聊自动取 group_id,私聊自动取 user_id),避免硬编码。
发送成功后执行逻辑
@command("pay", help="模拟支付")
async def pay_handler(event):
yunhu = sdk.adapter.get(event.get_platform())
user_id = event.get_user_id()
# 发送成功后才扣积分
await (yunhu.Send.To(event.get_detail_type(), event.get_target_id())
.Hook(lambda r: sdk.storage.set(f"points:{user_id}", -10))
.Text("支付成功,已扣除 10 积分"))
失败重试 + 超时取消
@command("notice", help="发送重要通知")
async def notice_handler(event):
adapter_inst = sdk.adapter.get(event.get_platform())
# 最多重试 3 次,每次超时 10 秒
task = (adapter_inst.Send.To(event.get_detail_type(), event.get_target_id())
.Retry(3)
.Timeout(10)
.OnError(lambda ctx: sdk.logger.error(f"通知发送失败: {ctx.error}"))
.Text("这是一条重要通知"))
# 不等待,后台发送
批量发送多条消息
一条链路发多条消息,统一执行:
@command("announce", help="发送公告")
async def announce_handler(event):
adapter_inst = sdk.adapter.get(event.get_platform())
# 构建多条消息,统一发送(默认并行)
results = await (adapter_inst.Send.To(event.get_detail_type(), event.get_target_id())
.Build()
.Text("📋 今日公告")
.Image("https://example.com/banner.jpg")
.Text("详细内容见上方图片")
.Retry(2) # 失败的条目各自重试
.send_all())
sdk.logger.info(f"批量发送完成,共 {len(results)} 条")
更完整的规则与批量说明请参考 平台特性指南。
权限控制
管理员检查
# 配置主人列表
MASTERS = ["user123", "user456"]
def is_master(user_id):
"""检查是否为框架主人"""
return user_id in MASTERS
@command("master", help="框架主人命令")
async def master_handler(event):
user_id = event.get_user_id()
if not is_master(user_id):
await event.reply("权限不足,此命令仅框架主人可用")
return
await event.reply("框架主人命令执行成功")
@command("addmaster", help="添加框架主人")
async def addmaster_handler(event):
if not is_master(event.get_user_id()):
return
args = event.get("text", "").split()
if len(args) < 2:
await event.reply("用法: /addmaster <用户ID>")
return
new_master = args[0]
MASTERS.append(new_master)
await event.reply(f"已添加框架主人: {new_master}")
群组权限
@command("groupinfo", help="查看群组信息")
async def groupinfo_handler(event):
if not event.is_group_message():
await event.reply("此命令仅限群聊使用")
return
group_id = event.get_group_id()
user_id = event.get_user_id()
await event.reply(f"群组 ID: {group_id}, 你的 ID: {user_id}")
消息统计
消息计数
注意:以下示例使用
sdk.storage.get/set进行简单计数。在高并发场景下,建议使用sdk.storage.transaction()保证原子性。
@message.on_message()
async def count_handler(event):
# 获取统计
stats = sdk.storage.get("message_stats", {
"total": 0,
"by_user": {},
"by_day": {}
})
# 更新统计
stats["total"] += 1
user_id = event.get_user_id()
stats["by_user"][user_id] = stats["by_user"].get(user_id, 0) + 1
# 保存
sdk.storage.set("message_stats", stats)
@command("stats", help="查看消息统计")
async def stats_handler(event):
stats = sdk.storage.get("message_stats", {
"total": 0,
"by_user": {},
"by_day": {}
})
top_users = sorted(
stats["by_user"].items(),
key=lambda x: x[1],
reverse=True
)[:5]
top_text = "\n".join(
f"{uid}: {count} 条消息" for uid, count in top_users
)
await event.reply(f"总消息数: {stats['total']}\n\n活跃用户:\n{top_text}")
搜索功能
简单搜索
注意:以下示例使用内存列表存储消息历史,程序重启后数据会丢失。生产环境建议使用
sdk.storage或 SQLite 表进行持久化存储。
from ErisPulse.Core.Event import command, message
# 存储消息历史
message_history = []
@message.on_message()
async def store_handler(event):
"""存储消息用于搜索"""
user_id = event.get_user_id()
text = event.get_text()
message_history.append({
"user_id": user_id,
"text": text,
"time": event.get_time()
})
# 限制历史记录数量
if len(message_history) > 1000:
message_history.pop(0)
@command("search", help="搜索消息")
async def search_handler(event):
args = event.get_command_args()
if not args:
await event.reply("请输入搜索关键词")
return
keyword = " ".join(args)
results = []
# 搜索历史记录
for msg in message_history:
if keyword in msg["text"]:
results.append(msg)
if not results:
await event.reply("未找到匹配的消息")
return
# 显示结果
result_text = f"找到 {len(results)} 条匹配消息:\n\n"
for i, msg in enumerate(results[:10], 1): # 最多显示 10 条
result_text += f"{i}. {msg['text']}\n"
await event.reply(result_text)
图片处理
图片下载和存储
from ErisPulse.Core import client
@message.on_message()
async def image_handler(event):
"""处理图片消息"""
message_segments = event.get_message()
for segment in message_segments:
if segment.get("type") == "image":
file_url = segment.get("data", {}).get("file")
if file_url:
# 推荐使用 SDK 内置客户端下载图片
resp = await client.get(file_url)
if resp.status == 200:
image_data = await resp.read()
# 存储到文件
filename = f"images/{event.get_time()}.jpg"
with open(filename, "wb") as f:
f.write(image_data)
sdk.logger.info(f"图片已保存: {filename}")
await event.reply("图片已保存")
图片识别示例
注意:以下示例使用占位 API 地址,实际使用时请替换为你自己的图片识别服务。
from ErisPulse.Core import client
@command("identify", help="识别图片")
async def identify_handler(event):
"""识别消息中的图片"""
message_segments = event.get_message()
for segment in message_segments:
if segment.get("type") == "image":
file_url = segment.get("data", {}).get("file")
# 调用图片识别 API
result = await _identify_image(file_url)
await event.reply(f"识别结果: {result}")
return
await event.reply("未找到图片")
async def _identify_image(url):
"""调用图片识别 API(示例)- 使用 SDK 内置客户端"""
resp = await client.post(
"https://api.example.com/identify",
json={"url": url}
)
data = await resp.json()
return data.get("description", "识别失败")