Skip to content
/ Numeron Public
forked from Erzbir/Numeron

基于 Mirai 框架的 QQ 机器人项目, 支持多 bot, 可作脚手架快速开发

License

Notifications You must be signed in to change notification settings

Mnbqq/Numeron

 
 

Repository files navigation

Numeron

介绍:

这是一个使用 mirai-core 开发的 qqBot, 也可用作简单脚手架

JDK 为 Oracle OpenJDK 17

构建系统为 Gradle (Kotlin DSL)

模块:

  • core: 脚手架(消息过滤和监听注册实现)
  • boot: 启动机器人功能, 目前程序的入口在此模块下
  • menu: 图片菜单生成
  • plugin: 目前用于实现功能, 此模块下的类会在程序运行最初被加载, 可用于扩展功能(引入 core 模块即可)
  • console: 控制台(待开发) 和插件模式
  • annotation: 注解
  • api: core 的 api 接口
  • utils: 一些通用工具
  • deps: 用于引入第三方依赖

plugin模块实现的功能:

  • 消息回复
  • @禁言, qq 号禁言
  • 全体禁言
  • 黑名单检测
  • 违禁词检测
  • 精准问答
  • 防撤回
  • 入群欢迎/退群反馈
  • 代码和命令执行, 支持JavaScript/Python/Shell
  • 群签到功能
  • 发送/help获取自动生成的命令表(在方法上加上@Command注解生成)
  • 对接openai
    • 聊天
    • 补全
    • 问答
    • 绘画
  • 游戏王查卡
  • rss订阅
  • 生成图片菜单目录

启动项目:

在 clone 代码并完成 gradle 构建后, 在 numeron-boot 模块下运行启动类的 main() 方法即可

第一次启动时会在命令行输入 bot 相关配置信息, 第一次启动默认为 ANDROID_WATCH 协议扫码且默认启用并登陆, 后续在 erzbirnumeron/config/botconfig.json 文件中可进行配置配置

说明:

配置文件:

botconfig.json:

[
  {
    "account": 12412414,
    "password": "niqd123131",
    "enable": true,
    "master": 138312819,
    "heartbeatStrategy": "STAT_HB",
    "miraiProtocol": "ANDROID_WATCH",
    "loginType": "QR"
  },
  {
    "account": 329130123,
    "password": "oqdi1397121",
    "enable": false,
    "master": 138312819,
    "heartbeatStrategy": "STAT_HB",
    "miraiProtocol": "ANDROID_WATCH",
    "loginType": "PASSWORD"
  }
]
  • account: bot 帐号
  • password: bot 密码
  • master: 主人帐号
  • heartbeatStrategy: 心跳策略
  • miraiProtocol: 登陆协议
  • loginType: 登陆方式
    • 目前 mirai 只提供了密码和扫码 (只有 ANDROID_WATCH 支持) 两种, 如果为 QR (扫码) 则登陆协议必须为 ANDROID_WATCH
  • enable: 是否启用
    • 如果 enable 为 false, 则只会创建此 bot 实例而不会登陆

API:

api模块下

  • BotService 有关 Bot 的各种操作
  • AdminService 群管理的相关操作
  • BlackService 黑名单操作
  • GroupService 授权群操作
  • WhiteService 白名单操作
  • ListenerRegister 监听注册器接口
  • Processor 处理器接口
    • 实现此接口的类会在程序启动时或者所有 bot 关机并有一个 bot 重启时执行一次 onApplicationEvent()
    • 在所有 bot 关机时执行 destroy() 方法
  • Numeron 程序接口
    • 获取此程序的各种配置信息
    • 可以通过此类向注册监听方法的前后和监听回调函数执行前后插入方法
    • 增加 Processor 处理器

插件模式:

console 模块下

实现 Plugin 接口, 目前插件打包时需包含所有依赖打包

将打包的插件 jar 放到运行目录的 numeron_plugins 目录下

@Message 使用:

@Message

可以标记在所有消息事件类型的处理方法上, 监听到满足此注解定义的规则的事件就会反射调用被标记的方法, 类上必须有@Listener标记

这个注解适合用于命令类型的监听(给机器人发送一个消息, 进行相关代码运行),

如果不是消息事件则使用下文介绍的@Event

@Listener
public class Test {
    // 消息匹配规则设置了默认值, 默认是equals()完全匹配

    @Message(messageRule = MessageRule.REGEX, text = "\\d+", permission = PermissionType.ALL, filterRule = FilterRule.BLACKLIST)
    // 处理群消息事件, 正则匹配模式, 匹配数字, 权限是所有人, 过滤规则是过滤掉黑名单
    private void regex(GroupMessageEvent event) {
        event.getSubject().sendMessage("这是一个数字");
    }

    @Message(text = "hi", permission = PermissionType.WHITE, filterRule = FilterRule.NONE)
    // 处理消息用户消息事件 匹配"hi", 权限是白名单, 不过滤
    private void sayHello(UserMessageEvent event) {
        event.getSubject().sendMessage("hi");
    }

    @Message(text = "晚安", permission = PermissionType.MASTER, filterRule = FilterRule.NORMAL)
    // 匹配消息事件 匹配"晚安", 权限是主人, 过滤掉groupList以外的群 
    private void sayGoodNight(MessageEvent event) {
        event.getSubject().sendMessage("晚安");
    }

    // 权限是所有人, 不过滤
    @Message(text = "你好", permission = PermissionType.ALL, filterRule = FilterRule.NONE)
    private void sayH(MessageEvent e) {
        e.getSubject().sendMessage("你好");
    }

    // 这是一个较为复杂的例子, 禁言一个人, 支持@和qq号
    @Message(text = "/mute\\s+?@?(\\d+?) (\\d+)", filterRule = FilterRule.NONE, messageRule = MessageRule.REGEX, permission = PermissionType.MASTER)
    private void muteSingle(MessageEvent event) {
        String[] s = event.getMessage().contentToString().split("\\s+");
        long id;
        int time;
        s[1] = s[1].replaceAll("@", "");
        id = Long.parseLong(s[1]);
        time = Integer.parseInt(s[2]);
        if (event instanceof GroupMessageEvent event1) {
            Objects.requireNonNull(event1.getGroup().get(id)).mute(time);
        } else {
            AtomicReference<NormalMember> member = new AtomicReference<>();
            GlobalConfig.groupList.forEach(v -> member.set(Objects.requireNonNull(event.getBot().getGroup(v)).get(id)));
            if (member.get().getPermission().getLevel() < 1) {
                member.get().mute(time);
            }
        }
    }
}

可以用消息处理注解做到什么?

  • 三种过滤规则: 不过滤 / 过滤黑名单 / 正常过滤
  • 四种权限规则: 主人 / 白名单 / 所有人 / 群管理员
  • 六种消息匹配规则: 以?开头 / 以?结尾 / 包含? / 相等 / 正则 / 在数组中?

@Event使用:

@Event 和mirai提供的@EventHandler用法基本一样, 只是使用这个注解不用让类继承, 不过类上必须有@Listener标记

@Listener
public class Test {

    @Event
    private void test(MessageRecallEvent.GroupRecall event) {
        System.out.println("有人撤回了消息");
    }
}

@Menu

用于生成图片菜单(有@Command会为这个menu生成帮助)

@Command

用于生成指令表

用@Command生成指令表:

@Listener
class Test {
    @Command(
            name = "自动回复",
            dec = "添加关键词回复",
            help = "/learn ques answer",
            permission = PermissionType.ALL
    )
    @Message(
            messageRule = MessageRule.REGEX,
            text = "^/learn\\s+?.*?\\s+?.*",
            filterRule = FilterRule.BLACK,
            permission = PermissionType.ALL
    )
    private void learn(MessageEvent e) {
        String[] split = e.getMessage().contentToString().split("\\s+");
        AutoReplyData.INSTANCE.add(split[1], split[2], e.getSender().getId());
        e.getSubject().sendMessage("学会了");
    }

    @Command(
            name = "自动回复",
            dec = "删除关键词回复",
            help = "/forget ques",
            permission = PermissionType.ALL
    )
    @Message(
            messageRule = MessageRule.REGEX,
            text = "^/forget\\s+?.*",
            filterRule = FilterRule.BLACK,
            permission = PermissionType.ALL
    )
    private void forget(MessageEvent e) {
        String[] split = e.getMessage().contentToString().split("\\s+");
        try {
            AutoReplyData.INSTANCE.remove(split[1], split[2]);
        } catch (SQLException ex) {
            throw new RuntimeException(ex);
        }
        e.getSubject().sendMessage("忘掉了");
    }
}

效果: 2023031916.30.57

用@Menu生成图片菜单:

有@Command会为这个menu生成帮助

@Listener
@Menu(name = "学习对话")
class Test {
    @Command(
            name = "自动回复",
            dec = "添加关键词回复",
            help = "/learn ques answer",
            permission = PermissionType.ALL
    )
    @Message(
            messageRule = MessageRule.REGEX,
            text = "^/learn\\s+?.*?\\s+?.*",
            filterRule = FilterRule.BLACK,
            permission = PermissionType.ALL
    )
    private void learn(MessageEvent e) {
        String[] split = e.getMessage().contentToString().split("\\s+");
        AutoReplyData.INSTANCE.add(split[1], split[2], e.getSender().getId());
        e.getSubject().sendMessage("学会了");
    }

    @Command(
            name = "自动回复",
            dec = "删除关键词回复",
            help = "/forget ques",
            permission = PermissionType.ALL
    )
    @Message(
            messageRule = MessageRule.REGEX,
            text = "^/forget\\s+?.*",
            filterRule = FilterRule.BLACK,
            permission = PermissionType.ALL
    )
    private void forget(MessageEvent e) {
        String[] split = e.getMessage().contentToString().split("\\s+");
        try {
            AutoReplyData.INSTANCE.remove(split[1], split[2]);
        } catch (SQLException ex) {
            throw new RuntimeException(ex);
        }
        e.getSubject().sendMessage("忘掉了");
    }
}

效果: f44d0e472c5d15199ab8917cba107ace

9f7c0b37e82f492e8c282e54ddd7e755

开发计划:

  • 群管理功能
  • api 和实现分离
  • console 控制台
  • 功能热加载
  • 注解处理器
  • 插件模式
  • 只监听某个 id(好友/群) 的事件监听注册(用注解实现)
  • 兼容 mirai-console 的插件

联系方式:

email:

About

基于 Mirai 框架的 QQ 机器人项目, 支持多 bot, 可作脚手架快速开发

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 98.0%
  • Kotlin 2.0%