基于 GO-CQHTTP 协议开发的 QQ 功能型机器人
pip install -r requements.txt
- 基础插件
- 权限管理插件
- 插件管理器插件
- ChatGPT插件
- Warframe插件
- 二维码编码解码插件
- 权重查询插件
- ...
"""
修改文件 main.py
path: 插件路径 (string) 对应 plugins 文件夹下的文件夹路径 plugins/example/default.py
name: 插件名称 (string) 用于显示在控制台
data: 是否需要数据目录 (bool) 用于创建数据目录 resources/plugins/example/default/*
"""
plugins = [
# {'path': '路径(string)', 'remarks': '名称(string)'}, # 例子毋删
{'path': 'example.default', 'remarks': '示例插件'},
]
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : Lkeme
import os
from dataclasses import dataclass
from typing import Union
from app.adapter import Friend
from app.adapter.actions import MessageAction
from app.adapter.core import get_bot
from app.adapter.events import MessageEvent
from app.adapter.message import AdapterMessageSegment
from app.config import config_mg
from app.logger import logger
from app.permission import ROLE
from app.plugin import plugin_mg as PM
from app.request import request
from app.utils.convert.convert import img2b64
from app.utils.funcs import cron, scheduler
from app.utils.funcs import re_filter
section = 'base.default'
@dataclass
class Config:
enable: bool = False
def __post_init__(self):
self.enable = config_mg.get_bool(section, 'enable', appoint='plugin')
CONFIG: Union[Config, None] = None
def init_config():
"""
初始化配置
"""
config_mg.add(section, 'enable', 'true', appoint='plugin')
config_mg.save(appoint='plugin')
#
global CONFIG
CONFIG = Config()
init_config()
def current_path(additional_path: str, resources: str) -> str:
cp = os.path.abspath(os.path.dirname(__file__))
return f"{cp}{os.sep}{additional_path}{os.sep}{resources}"
@PM.reg_event('message')
@re_filter(pattern="^状态$", role=ROLE.SU, enable=CONFIG.enable)
async def status(event: MessageEvent) -> None:
from bootstrap import DASH_PANEL
response = await event.ma.adapter.utils.get_version_info()
stat_str = f"当前状态: \n\n\
● 应用版本:{response['app_version']} \n\
● 协议类型:{response['protocol_name']} \n\
● 协议版本:{response['protocol_version']} \n\
● 系统环境:{response['runtime_os']} \n\
● 系统版本:{response['runtime_version']} \n\
● 启动时间:{DASH_PANEL.bot_start_time()} \n\
● 运行时间:{DASH_PANEL.bot_running_time()}"
await event.reply(stat_str)
@PM.reg_event('message')
@re_filter("^ping$", role=ROLE.SU, enable=CONFIG.enable)
async def ping(event: MessageEvent):
await event.reply("pong")
@PM.reg_event('message.group')
@re_filter("^test group reply$", role=ROLE.USER, enable=CONFIG.enable)
async def reply_me(event: MessageEvent):
await event.reply("just replied", True)
@PM.reg_event('message.private')
@re_filter("^test private reply$", role=ROLE.USER, enable=CONFIG.enable)
async def reply_me(event: MessageEvent):
await event.reply("just replied", True)
# @PM.reg_event("Boot")
# async def hello():
# bot = get_bot()
# image = await img2b64(current_path('data', 'hello.gif'), True)
# content = AdapterMessageSegment.image(image)
# target_id = config_mg.get_int('permission', 'admin', appoint='plugin')
# await MessageAction(bot.adapter).send_msg(Friend(user_id=target_id), str(content))
async def __moyu():
url = 'https://api.vvhan.com/api/moyu'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36'
}
logger.debug(f'Fetch check_warframe_price {url}')
try:
rsp = await request.get(url, headers=headers, stream=True, timeout=20)
if 200 == rsp.status_code:
return await rsp.content
logger.error(f'Failed check_warframe_price {url}. HTTP {rsp.status_code}')
except Exception as e:
logger.error(f'Failed check_warframe_price {url}. {type(e)}')
logger.exception(e)
return None # error'
@PM.reg_event('scheduler')
@scheduler.scheduled_job(cron(hour=22, minute=2))
async def moyu():
bot = get_bot()
img = await __moyu()
pic = await img2b64(img)
content = AdapterMessageSegment.image(pic)
target_id = config_mg.get_int('permission', 'admin', appoint='plugin')
await MessageAction(bot.adapter).send_msg(Friend(user_id=target_id), str(content))
from app.plugin import plugin_mg as PM
from app.utils.funcs import cron, scheduler
@PM.reg_event('scheduler')
@scheduler.scheduled_job(cron(hour=22, minute=2))
async def example():
pass
from app.plugin import plugin_mg as PM
"""
不同装饰器参数对应不同的消息类型,遇到该事件类型会对应触发该对应函数
"""
@PM.reg_event('message')
@PM.reg_event('message.group')
@PM.reg_event('message.private')
async def test():
pass
from app.permission import ROLE
from app.utils.funcs import re_filter
"""
参数1: 触发正则表达式
参数2: 触发角色,可选值 ROLE.SU, ROLE.USER, ROLE.ADMIN..
参数3: 是否启用, 根据CONFIG.enable的值来决定是否启用
"""
@re_filter("^test private reply$", role=ROLE.USER, enable=True)
async def test():
pass
- message包括 private 私聊消息 和 group 群聊消息
- notice包括 群文件上传 群成员增加/减少
- request包括 新朋友 和 进群邀请
- meta
- unknown (考虑到未来的兼容性)
> 参考plugins/base/default.py的内容进行开发
-
PM.reg_event(fingerprint)
-
接受指纹作为参数 装饰插件函数,当遇到具有该指纹类型的事件的时候,函数会被触发
-
re_filter(pattern)
-
根据正则表达式进行过滤,只有通过过滤的消息才会触发函数
-
get_bot()
-
获取bot实例,用于编写涉及到bot层的插件。