Skip to content

API 文档

windy664 edited this page Jul 20, 2026 · 2 revisions

API 文档

XingtuBot 对外暴露 XingtuBotService 接口,供第三方 Velocity/Bukkit 插件扩展功能。

获取 API 实例

Velocity:

XingtuBotService service = proxy.getPluginManager()
        .getPlugin("xingtubotvelocity")
        .flatMap(PluginContainer::getInstance)
        .map(p -> ((XingtuBotVelocity) p).getService())
        .orElse(null);

Bukkit:

XingtuBotHost host = getServer().getServicesManager()
        .load(XingtuBotHost.class);
// host 提供 registry / registerService / getService / permission 等能力

XingtuBotService 接口

继承自 CommandRegistrarMessageSenderCommandHookBusBotRuntimeInfo

public interface XingtuBotService
        extends CommandRegistrar, MessageSender, CommandHookBus, BotRuntimeInfo {

    int API_VERSION = 4;

    // API 版本
    int apiVersion();

    // 注册消息处理器
    void registerMessageHandler(BotMessageHandler handler);

    // 注册命令
    void registerCommand(BotCommand command);

    // 发送 Markdown 消息到群(可附带键盘模板)
    void sendToGroupMarkdown(String groupOpenId, String markdownContent,
                             String keyboardTemplateId);

    // 命令执行前钩子(返回 false 可拦截)
    void beforeCommand(BiPredicate<String, ? super BotMessageEvent> hook);

    // 命令执行后钩子
    void afterCommand(BiConsumer<String, ? super BotMessageEvent> hook);

    // 获取机器人 AppID
    String getBotAppId();
}

消息发送

被动回复(对话窗口内)

通过 BotMessageContext.reply() 系列方法回复当前消息:

event.reply("纯文本回复");
event.replyImage("https://...", "图片描述");
event.replyMarkdown("**加粗**内容", "keyboard_template_id");
event.replyKeyboard("Markdown 内容", keyboardJson);
event.replyVoice("https://...");
event.replyArk(arkJson);
event.replyEmbed(embedJson);

主动推送(不依赖回复窗口)

通过 ProactiveSender 服务主动向群发消息:

ProactiveSender sender = ctx.getService(ProactiveSender.class);
if (sender != null && sender.isReady()) {
    sender.sendGroupMessage(groupOpenId, "主动消息");
    sender.sendGroupMarkdown(groupOpenId, "**Markdown** 主动消息");
    sender.sendGroupMarkdownKeyboard(groupOpenId, "内容", keyboardJson);
}

未就绪或失败时应回退到 PendingMessageQueue

PendingMessageQueue.getInstance().offer(groupOpenId, message);

Markdown 卡片

使用 Md 工具类构建 Markdown 卡片:

String md = Md.card("📦", "标题")
        .subtitle("**副标题**")
        .quote("引用内容")
        .field("🔑", "字段名", "字段值")
        .link("点击查看", "https://...")
        .build();

消息接收

BotMessageEvent

方法 说明
getConversationId() 会话 ID(群 openid 或用户 openid)
getSenderId() 发送者 openid
getUsername() 发送者 QQ 昵称
getMessage() 消息文本
getImageUrls() 附带图片 URL 列表
getEventType() 原始 QQ 事件类型
getMessageType() 标准化消息类型枚举
isGroupMessage() 是否群消息
isGroupAtMessage() 是否 @ 机器人的消息

BotMessageType 枚举

说明
GROUP_AT 群 @ 消息
GROUP 群消息(非 @)
DIRECT 私聊消息
UNKNOWN 未知类型

命令系统

注册命令

// 方式一:通过 XingtuBotService
service.registerCommand(new MyCommand());

// 方式二:通过 ModuleContext(扩展插件推荐)
ctx.registry().register(new MyCommand());

BotCommand 接口

public interface BotCommand {
    boolean matches(String message);
    void handle(String message, BotMessageContext event);
    String name();
    boolean adminOnly();          // 默认 false
    boolean adminFor(String msg); // 默认同 adminOnly()
    List<String> triggers();      // 触发词
    String usage();               // 出现在 /help
    String description();         // 出现在 /help
    String category();            // 菜单分组
}

BotMessageHandler 接口

public interface BotMessageHandler {
    boolean matches(String message, BotMessageContext event);
    void handle(String message, BotMessageContext event);
    String name();
    int priority();               // 默认 100,越小越先
    boolean adminOnly();          // 默认 false
    boolean acceptsWithoutMention(); // 默认 false
    List<String> triggers();
    List<MenuEntry> menuEntries();
    String usage();
    String description();
    String category();
    void init(HandlerContext ctx);
    void shutdown();
}

分发规则

  1. priority() 升序排列
  2. 依次调用 matches()第一个命中的处理消息
  3. listen-mode=mention 时,非 @ 消息只触发 acceptsWithoutMention()=true 的 handler
  4. adminFor(msg)=true 时,非管理员被拦截

事件钩子

// 命令执行前拦截
service.beforeCommand((cmdName, event) -> {
    // 返回 false 拦截命令
    return true;
});

// 命令执行后回调
service.afterCommand((cmdName, event) -> {
    // 记录日志、统计等
});

权限系统

PermissionChecker permission = ctx.permission();
if (permission != null && permission.isAdmin(senderOpenid)) {
    // 是管理员
}

PermissionChecker 由 xt-auth 模块提供,未安装 xt-auth 时返回 null。

运行时信息

// 获取机器人 AppID
String appId = service.getBotAppId();

// 机器人昵称
String name = BotRuntimeState.getBotName();

// 是否大脑(主控端)
boolean isBrain = host.isBrain();

服务总线

核心与扩展、扩展与扩展之间通过服务总线共享能力:

// 注册
ctx.registerService(MyService.class, new MyServiceImpl());

// 也可以用字符串 key(跨 classloader)
ctx.registerService("my.service", new MyServiceImpl());

// 消费
MyService svc = ctx.getService(MyService.class);
Object svc = ctx.getServiceObject("my.service");

// 跨 classloader 反射获取
Class<?> cls = Class.forName("com.example.MyService");
Object svc = ctx.getServiceObject(cls);

已注册的服务列表

服务类型 提供方 获取方式
ProactiveSender 核心 ctx.getService(ProactiveSender.class)
PermissionChecker xt-auth ctx.permission()
Translator xt-modquery ctx.getService(Translator.class)
AiService xt-ai ctx.getService(AiService.class)
GroupChatLink xt-chatlink ctx.getServiceObject(Class.forName(...))

消息队列

当主动推送失败时,回退到被动队列(下次有人 @ 机器人时一并发出):

PendingMessageQueue.getInstance().offer(groupOpenId, markdownContent);

敏感词过滤

SensitiveFilter filter = SensitiveFilter.fromConfig(config, logger);
String filtered = filter.filter(rawText);

典型扩展模块结构

xt-myext/
├── build.gradle
└── src/main/
    ├── java/org/windy/xingtubot/
    │   ├── ext/xtmyext/
    │   │   ├── MyExtBukkitPlugin.java     # Bukkit 入口
    │   │   ├── MyExtBungeeCordPlugin.java # BungeeCord 入口
    │   │   └── MyExtVelocityPlugin.java   # Velocity 入口
    │   └── module/
    │       ├── MyExtModule.java           # BotModule 实现
    │       └── myext/
    │           ├── MyCommand.java         # 命令
    │           └── MyService.java         # 业务逻辑
    └── resources/
        ├── plugin.yml                     # Bukkit
        ├── bungee.yml                     # BungeeCord
        └── config.yml                     # 扩展配置

每个入口类只需十几行样板代码(定位宿主 → 调 ExtensionBootstrap.enable),业务逻辑全在 BotModule 实现中。

Clone this wiki locally