{"id":20251616,"url":"https://github.com/misakatat/shiro","last_synced_at":"2026-01-12T11:32:09.252Z","repository":{"id":37937602,"uuid":"400080035","full_name":"MisakaTAT/Shiro","owner":"MisakaTAT","description":"基于OneBot协议的QQ机器人快速开发框架","archived":false,"fork":false,"pushed_at":"2025-04-02T01:45:02.000Z","size":923,"stargazers_count":278,"open_issues_count":0,"forks_count":36,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-08T13:07:57.356Z","etag":null,"topics":["chatbot","cqhttp","go-cqhttp","java","kotlin","mirai-bot","mirai-http-api","onebot","onebot-sdk","qq","qq-guild","qqbot","qqrobot","springboot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MisakaTAT.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-08-26T07:28:08.000Z","updated_at":"2025-04-05T19:43:24.000Z","dependencies_parsed_at":"2023-09-27T08:13:26.192Z","dependency_job_id":"a9d10380-b6bd-4f8f-8d31-6bb0dc77a0e5","html_url":"https://github.com/MisakaTAT/Shiro","commit_stats":{"total_commits":554,"total_committers":15,"mean_commits":36.93333333333333,"dds":"0.36281588447653434","last_synced_commit":"717fb071b8b6bbee8c4b2414e24376addd002b23"},"previous_names":[],"tags_count":69,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MisakaTAT%2FShiro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MisakaTAT%2FShiro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MisakaTAT%2FShiro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MisakaTAT%2FShiro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MisakaTAT","download_url":"https://codeload.github.com/MisakaTAT/Shiro/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247847611,"owners_count":21006100,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chatbot","cqhttp","go-cqhttp","java","kotlin","mirai-bot","mirai-http-api","onebot","onebot-sdk","qq","qq-guild","qqbot","qqrobot","springboot"],"created_at":"2024-11-14T10:11:28.330Z","updated_at":"2026-01-08T10:11:35.801Z","avatar_url":"https://github.com/MisakaTAT.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\".github/assets/logo.png\" width=\"200\" height=\"200\" alt=\"Shiro\"\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n# Shiro\n\n_✨ 基于 [OneBot](https://github.com/howmanybots/onebot/blob/master/README.md) 协议的 QQ机器人 快速开发框架 ✨_\n\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://search.maven.org/search?q=com.mikuac.shiro\"\u003e\u003cimg src=\"https://img.shields.io/maven-central/v/com.mikuac/shiro.svg?label=Maven%20Central\u0026style=flat-square\" alt=\"maven\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/MisakaTAT/Shiro/issues\"\u003e\u003cimg src=\"https://img.shields.io/github/issues/MisakaTAT/Shiro?style=flat-square\" alt=\"issues\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/MisakaTAT/Shiro/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/MisakaTAT/Shiro?style=flat-square\" alt=\"license\"\u003e\u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/badge/JDK-17+-brightgreen.svg?style=flat-square\" alt=\"jdk-version\"\u003e\n    \u003ca href=\"\"\u003e\u003cimg src=\"https://img.shields.io/badge/QQ群-787828189-brightgreen.svg?style=flat-square\" alt=\"qq-group\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/howmanybots/onebot\"\u003e\u003cimg src=\"https://img.shields.io/badge/OneBot-v11-blue?style=flat-square\u0026logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABABAMAAABYR2ztAAAAIVBMVEUAAAAAAAADAwMHBwceHh4UFBQNDQ0ZGRkoKCgvLy8iIiLWSdWYAAAAAXRSTlMAQObYZgAAAQVJREFUSMftlM0RgjAQhV+0ATYK6i1Xb+iMd0qgBEqgBEuwBOxU2QDKsjvojQPvkJ/ZL5sXkgWrFirK4MibYUdE3OR2nEpuKz1/q8CdNxNQgthZCXYVLjyoDQftaKuniHHWRnPh2GCUetR2/9HsMAXyUT4/3UHwtQT2AggSCGKeSAsFnxBIOuAggdh3AKTL7pDuCyABcMb0aQP7aM4AnAbc/wHwA5D2wDHTTe56gIIOUA/4YYV2e1sg713PXdZJAuncdZMAGkAukU9OAn40O849+0ornPwT93rphWF0mgAbauUrEOthlX8Zu7P5A6kZyKCJy75hhw1Mgr9RAUvX7A3csGqZegEdniCx30c3agAAAABJRU5ErkJggg==\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://misakatat.github.io/shiro-docs\"\u003e文档\u003c/a\u003e\n  ·\n  \u003ca href=\"https://github.com/MisakaTAT/Shiro/releases\"\u003e下载\u003c/a\u003e\n  ·\n  \u003ca href=\"https://misakatat.github.io/shiro-docs\"\u003e快速开始\u003c/a\u003e\n  ·\n  \u003ca href=\"\"\u003e参与贡献\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![Repobeats analytics image](https://repobeats.axiom.co/api/embed/c0b4ba71b13fe79015de15fb9396651f97f3acf9.svg \"Repobeats analytics image\")](https://github.com/MisakaTAT/Shiro/pulse)\n\n\u003c/div\u003e\n\n# Migration Guide\n\n\u003e 从 `v2` 版本开始仅支持 `JDK 17+` 与 `SpringBoot 3.0.0+`\n\u003e\n\u003e详见项目文档 [v2迁移指南](https://misakatat.github.io/shiro-docs/migration.html)\n\n# QuickStart\n\n## 依赖引入\n\n\u003e 引入依赖时请替换版本 `latest` 为 `Maven Central` 实际的最新版本\n\n### Maven\n\n```xml\n\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.mikuac\u003c/groupId\u003e\n    \u003cartifactId\u003eshiro\u003c/artifactId\u003e\n    \u003cversion\u003elatest\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Gradle Kotlin DSL\n\n```kotlin\nimplementation(\"com.mikuac:shiro:latest\")\n```\n\n### Gradle Groovy DSL\n\n```groovy\nimplementation 'com.mikuac:shiro:latest'\n```\n\n## 示例插件\n\n### 注解调用\n\n\u003e 编写 `application.yaml` 配置文件\n\u003e 或参考 [进阶配置文件](https://misakatat.github.io/shiro-docs/advanced.html#进阶配置文件)\n\n```yaml\nserver:\n  port: 5000\n```\n\n```java\n\n@Shiro\n@Component\npublic class ExamplePlugin {\n    // 更多用法详见 @MessageHandlerFilter 注解源码\n\n    // 当机器人收到的私聊消息消息符合 cmd 值 \"hi\" 时，这个方法会被调用。\n    @PrivateMessageHandler\n    @MessageHandlerFilter(cmd = \"hi\")\n    public void fun1(Bot bot, PrivateMessageEvent event, Matcher matcher) {\n        // 构建消息\n        String sendMsg = MsgUtils.builder().face(66).text(\"Hello, this is shiro demo.\").build();\n        // 发送私聊消息\n        bot.sendPrivateMsg(event.getUserId(), sendMsg, false);\n    }\n\n    // 如果 at 参数设定为 AtEnum.NEED 则只有 at 了机器人的消息会被响应\n    @GroupMessageHandler\n    @MessageHandlerFilter(at = AtEnum.NEED)\n    public void fun2(GroupMessageEvent event) {\n        // 以注解方式调用可以根据自己的需要来为方法设定参数\n        // 例如群组消息可以传递 GroupMessageEvent, Bot, Matcher 多余的参数会被设定为 null\n        System.out.println(event.getMessage());\n    }\n\n    // 同时监听群组及私聊消息 并根据消息类型（私聊，群聊）回复\n    @AnyMessageHandler\n    @MessageHandlerFilter(cmd = \"say hello\")\n    public void fun3(Bot bot, AnyMessageEvent event) {\n        bot.sendMsg(event, \"hello\", false);\n    }\n}\n```\n\n### 重写父类方法\n\n- 注解方式编写的插件无需在插件列表 `plugin-list`定义\n- 服务端配置文件 `resources/application.yaml` 追加如下内容\n- 插件列表为顺序执行，如果前一个插件返回了 `MESSAGE_BLOCK` 将不会执行后续插件\n\n\u003e 编写 `application.yaml` 配置文件\n\u003e 或参考 [进阶配置文件](https://misakatat.github.io/shiro-docs/advanced.html#进阶配置文件)\n\n```yaml\nserver:\n  port: 5000\nshiro:\n  plugin-list:\n    - com.example.bot.plugins.ExamplePlugin\n```\n\n```java\n@Component\npublic class ExamplePlugin extends BotPlugin {\n\n    @Override\n    public int onPrivateMessage(Bot bot, PrivateMessageEvent event) {\n        if (\"hi\".equals(event.getMessage())) {\n            // 构建消息\n            String sendMsg = MsgUtils.builder()\n                    .face(66)\n                    .text(\"hello, this is shiro example plugin.\")\n                    .build();\n            // 发送私聊消息\n            bot.sendPrivateMsg(event.getUserId(), sendMsg, false);\n        }\n        // 返回 MESSAGE_IGNORE 执行 plugin-list 下一个插件，返回 MESSAGE_BLOCK 则不执行下一个插件\n        return MESSAGE_IGNORE;\n    }\n\n    @Override\n    public int onGroupMessage(Bot bot, GroupMessageEvent event) {\n        if (\"hi\".equals(event.getMessage())) {\n            // 构建消息\n            String sendMsg = MsgUtils.builder()\n                    .at(event.getUserId())\n                    .face(66)\n                    .text(\"hello, this is shiro example plugin.\")\n                    .build();\n            // 发送群消息\n            bot.sendGroupMsg(event.getGroupId(), sendMsg, false);\n        }\n        // 返回 MESSAGE_IGNORE 执行 plugin-list 下一个插件，返回 MESSAGE_BLOCK 则不执行下一个插件\n        return MESSAGE_IGNORE;\n    }\n\n}\n```\n\n### 加载外部插件\n\n#### 工作流程\n\n\u003cdetails\u003e\n  \u003csummary\u003e点击展开/折叠 Shiro 插件加载流程图\u003c/summary\u003e\n\n```mermaid\ngraph TD\n    A[Shiro 启动] --\u003e B[扫描 plugins/ 目录]\n    B --\u003e C{是否存在 JAR 文件?}\n    C -- 否 --\u003e D[跳过插件加载]\n    C -- 是 --\u003e E1[解析 JAR 的 manifest]\n    \n    subgraph 依赖处理\n        E1 --\u003e E2[提取 Dependencies 属性]\n        E2 --\u003e E3{是否有依赖需要解析?}\n        E3 -- 是 --\u003e E4[通过 DependencyResolver 解析依赖]\n        E4 --\u003e E5[下载缺失的依赖到 dependencies 目录]\n        E3 -- 否 --\u003e E6[跳过依赖解析]\n        E5 --\u003e E6\n    end\n    \n    E6 --\u003e E7[创建包含插件和依赖的 URLClassLoader]\n    E7 --\u003e E[加载并注册插件]\n    \n    subgraph 加载并注册插件\n        E --\u003e F[使用 URLClassLoader 加载 JAR]\n        F --\u003e G[使用 ServiceLoader 加载 BotPlugin]\n        G --\u003e H{插件是否实现 BotPlugin?}\n        H -- 否 --\u003e I[跳过插件]\n        H -- 是 --\u003e H1{是否有 @Component 注解?}\n        H1 -- 否 --\u003e I\n        H1 -- 是 --\u003e H2[注册到 Spring 容器]\n        H2 --\u003e J[检查主项目 BotPlugin]\n        J --\u003e K{主项目是否实现相同事件?}\n        K -- 否 --\u003e L[注册插件到事件列表]\n        K -- 是 --\u003e M[插件 onGroupMessage 低优先级执行]\n        M --\u003e N{主项目 MESSAGE_BLOCK 是否触发?}\n        N -- 是 --\u003e O[阻断插件逻辑]\n        N -- 否 --\u003e P[执行插件 onGroupMessage]\n    end\n\n    P --\u003e Q[插件加载完成]\n```\n\n\u003c/details\u003e\n\n#### 目录结构\n`Shiro` 支持自动加载 `.jar` 格式的插件，并通过 `ServiceLoader` 进行管理。默认情况下，`Shiro` 会扫描当前运行路径下的 `plugins` 目录，并尝试加载所有符合 `BotPlugin` 接口的插件。\n\n以下只是一个示例结构（可根据实际情况调整，比如替换 Gradle 为 Maven）\n```\nForeignPluginExample/\n├── src/                                                                  # 源代码目录\n│   ├── main/java/com/mikuac/demo/DemoPlugin.java                         # 插件实现\n│   ├── main/resources/META-INF/services/com.mikuac.shiro.core.BotPlugin  # SPI 注册文件\n├── build.gradle.kts            # Gradle 构建脚本\n├── settings.gradle.kts         # Gradle 设置文件\n├── gradlew                     # Gradle 可执行文件（Linux/macOS）\n├── gradlew.bat                 # Gradle 可执行文件（Windows）\n└── gradle/wrapper/             # Gradle Wrapper 相关文件\n```\n\n#### 开发指南\n\n##### 插件类定义\n\n插件必须实现 `BotPlugin` 接口，并使用 `@Component` 注解，以便 `Shiro` 能够正确识别。\n\n```java\npackage com.mikuac.demo;\n\nimport com.mikuac.shiro.core.Bot;\nimport com.mikuac.shiro.core.BotPlugin;\nimport com.mikuac.shiro.dto.event.message.GroupMessageEvent;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class DemoPlugin extends BotPlugin {\n    @Override\n    public int onGroupMessage(Bot bot, GroupMessageEvent event) {\n        String msg = event.getMessage();\n        if (msg.equals(\"ping\")) {\n            bot.sendGroupMsg(event.getGroupId(), \"pong\", false);\n            return MESSAGE_BLOCK;\n        }\n        return MESSAGE_IGNORE;\n    }\n}\n```\n##### 配置 META-INF/services\n\n为了让 `ServiceLoader` 能够发现插件，需要在 `src/main/resources/META-INF/services/` 目录下创建 `com.mikuac.shiro.core.BotPlugin` 文件，并填写插件的完整类名。\n\n```\ncom.mikuac.demo.DemoPlugin\n```\n\n##### 配置构建脚本\n\n在 `build.gradle.kts` 中添加以下配置，用于正确处理插件打包和依赖管理：\n\n```kotlin\ntasks.withType\u003cJar\u003e {\n    // 处理JAR中的重复文件，INCLUDE策略表示保留所有重复项\n    duplicatesStrategy = DuplicatesStrategy.INCLUDE\n\n    // 将主源集的所有编译输出加入JAR包\n    from(sourceSets.main.get().output)\n\n    manifest {\n        // 添加基本信息到 MANIFEST.MF\n        attributes(\n            mapOf(\n                \"Implementation-Title\" to project.name,       // 使用项目名称\n                \"Implementation-Version\" to project.version,  // 添加版本信息\n                \"Built-By\" to System.getProperty(\"user.name\"),\n                \"Created-By\" to \"Gradle ${gradle.gradleVersion}\"\n            )\n        )\n        \n        // 生成并添加依赖清单\n        val dependenciesString = configurations\n            .getByName(\"runtimeClasspath\")  // 获取运行时实际解析的依赖\n            .resolvedConfiguration\n            .resolvedArtifacts\n            .map {\n                // 将依赖格式化为 \"groupId:artifactId:version\" 格式\n                \"${it.moduleVersion.id.group}:${it.moduleVersion.id.name}:${it.moduleVersion.id.version}\"\n            }\n            .distinct()  // 移除重复项\n            .filterNot { coordinates -\u003e\n                // 过滤掉不应由插件加载的依赖\n                // 这些依赖应当由 Shiro 主程序提供，避免类加载冲突\n                coordinates.startsWith(\"org.springframework\") ||  // Spring框架\n                coordinates.startsWith(\"com.mikuac:shiro\") ||     // Shiro\n                coordinates.startsWith(\"org.slf4j\") ||            // 日志门面\n                coordinates.startsWith(\"ch.qos.logback\")          // 日志实现\n            }\n            .joinToString(\", \")  // 使用逗号分隔依赖列表\n\n        // 添加依赖列表到 manifest 中，Shiro 将解析此属性来下载所需依赖\n        attributes(mapOf(\"Dependencies\" to dependenciesString))\n    }\n}\n\n// 可选：配置依赖项\ndependencies {\n    // Shiro 本身仅在编译时需要，运行时由主程序提供\n    compileOnly(\"com.mikuac:shiro:latest\")\n    \n    // 添加其他依赖，这些将被包含在Dependencies清单中\n    implementation(\"com.example:some-library:1.0.0\")\n}\n```\n##### 编译插件\n\n```\n./gradlew build\n```\n\n生成的插件 `JAR` 文件位于 `build/libs/DemoPlugin-1.0-SNAPSHOT.jar`，需要将其移动到 `Shiro` 的 `plugins` 目录中。\n\n##### 重新启动 Shiro 以加载插件\n\n`Shiro` 在启动时会自动扫描 `plugins` 目录，并加载符合条件的插件。\n\n##### 相关配置\n`Shiro` 的 `application.yml` 中可以自定义插件目录:\n\n```yml\nshiro:\n  pluginScanPath: \"/home/user/mybot\"\n```\n这样，`Shiro` 将从 `/home/user/mybot` 目录加载插件，而不是默认的 `plugins`。\n\n# Community\n\n[社区项目/插件](https://misakatat.github.io/shiro-docs/community.html)\n\n## 如何添加项目？\n\n如果您想要添加自己的项目到社区页面，请按照以下格式提交 Pull Request 或者 Issue：\n\n您可以通过以下两种方式添加项目：\n\n1. 直接编辑文件：[点击这里编辑](https://github.com/MisakaTAT/shiro-docs/edit/main/community.md)\n2. 提交 Issue：在 [Issues](https://github.com/MisakaTAT/shiro-docs/issues) 页面提交新的 Issue\n\n请按照以下格式添加您的项目：\n\n```markdown\n### 项目名称\n\n- 仓库：项目仓库地址\n- 作者：作者名称\n- 描述：简短的项目描述（不超过 100 字）\n```\n\n\u003e注意事项\n\u003e1. 请确保您的项目是开源的\n\u003e2. 描述应该简洁明了，突出项目的主要功能\n\u003e3. 项目应该与 Shiro 框架相关\n\u003e4. 请将您的项目添加到合适的分类下（插件/项目）\n\n# Client\n\nShiro 兼容所有支持正反向 WebSocket 连接的 [OneBot-v11](https://github.com/howmanybots/onebot/tree/master/v11/specs) 客户端\n\n# Contributors\nSee [Contributing](https://github.com/MisakaTAT/Shiro/graphs/contributors) for details. Thanks to all the people who already contributed!\n\n[![contributors](https://stg.contrib.rocks/image?repo=MisakaTAT/Shiro)](https://github.com/MisakaTAT/Shiro/graphs/contributors)\n\n# Credits\n\n* [OneBot](https://github.com/botuniverse/onebot)\n* [pbbot-spring-boot-starter](https://github.com/ProtobufBot/pbbot-spring-boot-starter)\n\n# License\n\nThis product is licensed under the GNU General Public License version 3. The license is as published by the Free\nSoftware Foundation published at https://www.gnu.org/licenses/gpl-3.0.html.\n\nAlternatively, this product is licensed under the GNU Lesser General Public License version 3 for non-commercial use.\nThe license is as published by the Free Software Foundation published at https://www.gnu.org/licenses/lgpl-3.0.html.\n\nFeel free to contact us if you have any questions about licensing or want to use the library in a commercial closed\nsource product.\n\n# Stargazers over time\n\n[![Stargazers over time](https://starchart.cc/MisakaTAT/Shiro.svg)](https://starchart.cc/MisakaTAT/Shiro)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmisakatat%2Fshiro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmisakatat%2Fshiro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmisakatat%2Fshiro/lists"}