Skip to content
This repository has been archived by the owner on Feb 11, 2023. It is now read-only.
/ PicqBotX Public archive

基于 CQHTTP 插件的 Java QQ 机器人类库

Notifications You must be signed in to change notification settings

HyDevelop/PicqBotX

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation



PicqBotX

一个基于 酷Q HTTP 插件 的 Java QQ 机器人类库




2020 Aug 02 注意:

CQ 已经停止运营啦 (cqp.cc), 所以这个项目作为 CQHTTP 的 SDK 也不会继续维护啦w

img

友情链接w

2021 想开发 bot 的话可以去看看下面几个库:

Mirai
YuQ

( 其实还想继续用 PicqBotX 的话可以去看看 go-cqhttp 啦,但是下面"配置环境"的教程帮不到你啦w



Maven 导入:

没有添加 JitPack 的 Repo 的话首先添加 Repo, 在 pom 里面把这些粘贴进去:

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

然后添加这个库:

<dependency>
    <groupId>com.github.hydevelop</groupId>
    <artifactId>PicqBotX</artifactId>
    <version>4.15.0.1072</version>
</dependency>

然后 Reimport 之后就导入好了!


Gradle 导入:

没有添加 JitPack 的 Repo 的话首先添加 Repo, 在 pom 里面把这些粘贴进去:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

然后添加这个库:

dependencies {
    implementation 'com.github.hydevelop:PicqBotX:4.15.0.1072'
}

配置环境:

注意: 下面的教程适用于 Windows 酷Q v5.15.10, Linux 教程以后可能会进行补充
还有, HTTP 插件支持的版本是v4.15.0, 2020/04/21刚检查过

1. 下载 酷Q... (如果有 酷Q Pro 的话效果更好哦!)

  • 下载地址: https://cqp.cc/b/news (好像是登录之后才能看到下载 Pro 的链接)
  • 下载完后解压到你想安装的目录下
  • 首次启动请运行 cqa.execqp.exe, 并登陆机器人的 QQ 号
  • 然后退出 酷Q (右键悬浮窗点退出)

2. 添加 酷Q HTTP 插件:

  • .cpk 文件下载下来, 放进 酷Q安装目录/app 文件夹里
  • 启动 酷Q
  • 右键悬浮窗, 然后点击 应用 -> 应用管理
  • 列表里现在应该有 [未启用] CQHTTP, 点击它, 点击启用
  • 启用的时候会提示需要一些敏感权限, 选择继续
  • 启用之后在 酷Q安装目录/app 文件夹里创建 io.github.richardchien.coolqhttpapi 文件夹
  • 退出 酷Q

3. 配置 酷Q HTTP 插件:

  • app/io.github.richardchien.coolqhttpapi 文件夹里创建一个文件名为 config.ini 的配置文件
  • 并在其中写入以下配置代码
[general]
host=0.0.0.0
port=酷Q端口
post_url=http://127.0.0.1:Picq端口
  • 酷Q端口Picq端口改成你的机器人程序里用的端口 (测试机器人的酷Q端口31091, Picq端口31092)
  • 如果 酷Q 要和你的机器人程序分开运行的话, 请把127.0.0.1改成你的机器人部署的服务器的地址
  • 保存配置文件

4. 配置完成! 启动 酷Q!


基础开发概括:

开发文档 (JavaDocs)

  • 不过Gitpage可能被墙了x
  • 墙了的话, 去git clone或者download zip
  • 然后打开Docs文件夹,
  • 打开Index.html就是一样的啦w

启动机器人: 基础开发概括 (Main类):

在 main 方法中, 先创建一个机器人配置对象:

// 创建机器人配置 ( 传入Picq端口 )
PicqConfig config = new PicqConfig(31092);

注意: 这里的Picq端口要和酷Qconfig.cfg配置里面设置的Picq端口一样!!
之后可以通过config.set...来配置机器人了.
详细请看配置说明

接下来创建一个机器人对象:

// 创建机器人对象 ( 传入机器人配置对象 )
PicqBotX bot = new PicqBotX(config);

接下来要添加机器人账户:
(一个酷Q端就是一个机器人账户嗯)

// 添加一个机器人账户 ( 传入名字, 酷Q URL, 酷Q端口 )
bot.addAccount("Bot01", "127.0.0.1", 31091);

注册监听器:
可以注册多个监听器,
监听器的构造器可以有参数,
如何创建监听器请看事件说明

// 注册事件监听器, 可以注册多个监听器
bot.getEventManager().registerListeners(new 监听器1(), new 监听器2(), ...);

启用指令管理器:
如果不想用自带的指令管理器, 不写这行就好了.
不过这个指令管理器真的很方便哦w!

// 启用指令管理器
// 这些字符串是指令前缀, 比如 !help 的前缀就是"!"
bot.enableCommandManager("bot -", "!", "/", "~");

注册指令:

// 注册指令, 可以注册多个指令
bot.getCommandManager().registerCommands(new 指令1(), new 指令2(), ...);

启动机器人:

// 启动机器人, 不会占用主线程
bot.startBot();

嗯, 然后就没了!
就这么简单方便w!
完整例子代码:

public class TestBot
{
    public static void main(String[] args)
    {
        // 创建机器人对象 ( 传入配置 )
        PicqBotX bot = new PicqBotX(new PicqConfig(31092).setDebug(true));

        // 添加一个机器人账户 ( 名字, 发送URL, 发送端口 )
        bot.addAccount("Bot01", "127.0.0.1", 31091);

        // 注册事件监听器, 可以注册多个监听器
        bot.getEventManager().registerListeners(
                new TestListener(), 
                new RequestListener(),
                new ExceptionListener()
        );

        // 启用指令管理器
        // 这些字符串是指令前缀, 比如指令"!help"的前缀就是"!"
        bot.enableCommandManager("bot -", "!", "/", "~");

        // 注册指令, 可以注册多个指令
        bot.getCommandManager().registerCommands(
                new CommandSay(),
                new CommandTest(),
                new CommandVersion()
        );

        // 启动机器人, 不会占用主线程
        bot.startBot();
    }
}
其他例子去看TestBot!

完整开发文档:

1. 配置:

// 创建机器人配置 ( 传入Picq端口 )
PicqConfig config = new PicqConfig(31092);

可以通过config.set...来配置机器人嗯w
下面这些是可以配置的配置项:

配置项 Set 方法和默认值 配置项介绍
setDebug(false) 是否输出Debug消息
setNoVerify(false) 是否跳过酷Q版本验证 (不推荐)
setCommandAlsoCallEvents(true) 指令是否触发消息事件
setUseAsyncCommands(true) 是否异步执行指令
setMaintenanceMode(false) 是否启用维护模式
setmaintenanceResponse("- 机器人正在维护 -") 维护模式回复 (设为空就不会回复了)
setAutoMultiAccountOptimizatinos(true) 是否自动判断是否开启多账号优化
setMultiAccountOptimizatinos(true) 不自动判断的时候是否手动开启多账号优化
setEventPaused(false) 是否暂停事件
setHttpPaused(false) 是否暂停HTTP接收
setSecret("") SHA1 验证秘钥 (设置为空就是不验证w)
setAccessToken("") Access Token 访问令牌 (设置为空就是不用令牌)
setApiRateLimited(false) 是否启用限速调用API (需要enable_rate_limited_actions=true)
setApiAsync(false) 是否异步调用API
setCommandArgsSplitRegex(" ") 解析指令的时候用来分割参数的正则

还有一些必须在new PicqBotX(config)之前设置的配置项:
这些项启动之后改掉也没用了啦w

配置项 Set 方法和默认值 配置项介绍
setColorSupportLevel(FORCED) Logger颜色支持级别 (设为DISABLED就没有颜色了)
setLogPath("logs") Logger日志路径 (设为空就不输出文件了)
setLogFileName("PicqBotX-Log") Logger日志文件名
setLogInit(true) 是否输出启动日志

2. 监听事件:

public class 类名随意 extends IcqListener // 必须继承 IcqListener 监听器类
{
    @EventHandler // 这个注解必须加, 用于反射时判断哪些方法是事件方法的, 不用 @Override
    public void 方法名随意(事件类名 event) // 想监听什么事件就写在事件类名这里, 一个方法只能有一个事件参数
    {
        // 处理
    }

    @EventHandler
    public void 方法名随意(事件类名 event) // 同一个类下可以无限添加监听器方法
    ...
}

嗯... 创建一个类, 写成上面那个样子就行了_(:з」∠)_

可用事件:

事件类名 事件介绍
Event 所有事件(不推荐监听)
EventMessage 所有消息事件
EventDiscussMessage 讨论组消息事件
EventGroupMessage 群聊消息事件
EventPrivateMessage 私聊消息事件
EventNotice 所有提醒事件
EventNoticeFriendAdd 加好友提醒
EventNoticeGroupAdminChange 所有群管理员数量更改事件
EventNoticeGroupAdminSet 群员被设为管理员事件
EventNoticeGroupAdminRemove 群员被取消管理员事件
EventNoticeGroupMemberChange 所有群员数量更改事件
EventNoticeGroupMemberDecrease 所有群员数量减少事件
EventNoticeGroupMemberKick 群员被踢事件
EventNoticeGroupMemberKickBot 自己被踢事件
EventNoticeGroupMemberLeave 群员主动退出事件
EventNoticeGroupMemberIncrease 所有群员数量增加事件
EventNoticeGroupMemberApprove 群员被同意进群事件
EventNoticeGroupMemberInvite 群员被邀请进群事件
EventNoticeGroupUpload 上传群文件事件
EventNoticeGroupRecall 群消息撤回事件
EventNoticeFriendRecall 好友消息撤回事件
EventNoticeGroupPoke 群戳一戳事件
EventNoticeFriendPoke 好友戳一戳事件 (go-cqhttp 拓展)
EventNoticeGroupCard 群成员名片更新事件 (go-cqhttp 拓展)
EventNoticeGroupHonor 群成员荣耀变更事件
EventNoticeGroupLuckyKing 群红包运气王事件
EventRequest 所有请求事件
EventFriendRequest 加好友请求事件
EventGroupAddRequest 加群请求事件
EventGroupInviteRequest 拉你入群请求事件
EventLocal 所有本地事件
EventLocalSendMessage 所有本地向外发送的事件
EventLocalSendDiscussMessage 发送讨论组消息事件
EventLocalSendGroupMessage 发送群聊消息事件
EventLocalSendPrivateMessage 发送私聊消息事件
EventLocalHttpRecieveEvent 接收HTTP请求事件
EventLocalHttpFailEvent 接收HTTP请求失败事件
EventMeta Meta事件
EventMetaLifecycle 生命周期事件
EventMetaHeartbeat 心跳事件

例子1:

public class TestListener extends IcqListener
{
    @EventHandler
    public void onPMEvent(EventPrivateMessage event)
    {
        System.out.println("接到消息");
    
        // 判断消息是不是这段文字, 如果是就回复那段文字, 很简单的测试_(:з」∠)_
        if (event.getMessage().equals("你以为这是 yangjinhe/maintain-robot?"))
            event.respond("其实是我 HyDevelop/PicqBotX 哒!");
    }
}

例子2. 用事件监听实现消息替换过滤:

public class TestFilter extends IcqListener
{
    @EventHandler
    public void onAllLocalMessageEvent(EventLocalSendMessage event) // 监听所有发送消息的事件
    {
        // 获取消息
        String message = event.getMessage();
        
        // 这里可以做任何处理
        // 我把所有"%prefix%"变量替换成了"!"
        message = message.replace("%prefix%", "!");
        
        // 设置消息, 因为这个事件是在发送之前执行的, 所以这样设置的消息能生效
    // 设置为 null 就能拦截了
        event.setMessage(message);
    }
}

3. 发送/获取信息:

获取IcqHttpApi对象:

需要一个IcqHttpApi对象, 请不要使用全局变量存IcqHttpApi对象
其实监听器里的话直接用 event.getHttpApi() 就行了w

如果不在事件里,
但是只有一个账号的话,
bot.getAccountManager().getNonAccountSpecifiedApi() 就好啦w
如果有多个账号, 要用所有账号的话,
可以用 bot.getAccountManager().getAccounts() 获取账号列表循环一下w

发送/获取信息:

如果已经封装过了的话, 这样发送:

icqHttpApi.封装方法名(参数); // 返回的就是响应数据啦w

封装方法列表:

IcqHttpApi 封装方法 作用
.sendPrivateMsg 发送私聊消息
.sendGroupMsg 发送群聊消息
.sendDiscussMsg 发送讨论组消息
.deleteMsg 撤回消息
.getMsg 获取消息
.sendLike 好友点赞
.sendGroupNotice 发送群公告
.setGroupKick 飞机票
.setGroupBan 群用户禁言
.setGroupAnonymousBan 群匿名用户禁言
.setGroupWholeBan 群全体禁言
(什么鬼方法名x
(怪 RC! (摔w
.setGroupAdmin 设置管理员
.setGroupAnonymous 设置是否允许匿名
.setGroupCard 设置群备注
.setGroupLeave 退出群
.setGroupSpecialTitle 设置专属头衔
.setDiscussLeave 退出讨论组
.setFriendAndRequest 处理加好友请求
.setGroupAndRequest 处理加群请求
.approveGroupRequest 同意加群请求
.rejectGroupRequest 拒绝加群请求
.setRestartPlugin 重启插件
.setRestartUnsafe 重启酷Q (不安全)
.cleanDataDir 清空数据文件夹
.clearPluginLog 清空插件日志
.getLoginInfo 获取登录号信息
.getStrangerInfo 获取陌生人信息
.getVIPInfo 获取会员信息
.getGroupList 获取群列表
.getGroupMemberInfo 获取群成员信息
.getGroupInfo 获取群信息
.getGroupMemberList 获取群成员列表
.getFriendList 获取好友列表
.getRecord 获取语音文件
.getImage 获取图片路径 (String)
.getImageFile 获取图片路径 (File)
.getGroupNotices 获取群公告列表
.canSendImage 能不能发图
.canSendRecord 能不能发语音
.getVersionInfo 获取版本信息
.getCookies 抢走曲奇w
.getCsrfToken 获取 CSRF TOKEN
.getCredentials 上面两个加起来
.getStatus 获取运行状态

例子1. 发送:

icqHttpApi.sendPrivateMsg(565656, "hi"); // 给小桂发送"hi"

例子2. 获取:

RStatus status = icqHttpApi.getStatus().getData(); // 获取当前运行状态

如果没有封装过的话, 或者想手动添加参数对的话, 这样发送:

icqHttpApi.send(请求目标, 参数);

例子:

// 因为是隐藏接口, 就没有封装, 所以要用的话这样发送w
// 检查更新:
icqHttpApi.send(".check_update", 
    "automatic", false); 

// 对事件执行快速操作:
icqHttpApi.send(".handle_quick_operation", 
    "context", ...,
    "operation", ...); 

返回数据:

大部分返回数据为 ReturnData<Pojo 数据类> 形式, 获取数据的话用 response.getData() 就行了w
列表的话会返回 ReturnListData<Pojo 数据类> 形式.

复杂的消息建造 (比如图片什么的) 用 MessageBuilder 类:

注意: .add(Object) 方法对于所有类型的对象都有效, 只要能 toString() 就行

new MessageBuilder()
    .add("添加一条字符串消息")
    .add(123)
    .add(16.5f)
    .newLine() // 换行
    .add(new ComponentImage("此处填图片文件路径或者 URL")) // 图片组件
    .add(new ComponentImageBase64("此处填图片 Base64 码")) // Base64 图片组件
    .add(new ComponentRecord("此处填语音文件路径或者 URL")) // 语音组件
    .toString();

可用组件 (需要 酷Q Pro 才能用, 详细介绍请看CQ码):

组件类名 组件介绍
ComponentAt @组件
ComponentReply 消息回复组件
ComponentBFace 原创表情组件
ComponentEmoji Emoji 表情组件
ComponentFace QQ 表情组件
ComponentImage 图片组件
ComponentImageBase64 Base64 编码图片组件
ComponentSFace 小表情组件
ComponentShare 分享链接组件
ComponentPoke 群聊戳一戳组件 (适配 go-cqhttp, 与 OneBot 标准有差异)
ComponentDice 掷骰子组件 (只能单独发送)
ComponentMusic 音乐组件 (只能单独发送)
ComponentRecord 语音组件 (只能单独发送)
ComponentRockPaperSissors 猜拳组件 (只能单独发送)
ComponentShake 抖一抖组件 (只能单独发送)

4. 指令

每一个指令需要单独创建一个类, 实现一个指令接口
如果这个指令在所有消息环境内都能执行的话, 实现 EverywhereCommand
如果这个指令只需要在 群 或者 讨论组 或者 私聊 执行的话,
实现 GroupCommand 或者 DiscussCommand 或者 PrivateCommand 就可以了w

例子:

public class CommandVersion implements EverywhereCommand // 实现EverywhereCommand就是无论私聊群聊还是讨论组都能收到的指令
{
    // 指令属性
    @Override
    public CommandProperties properties()
    {
        // 这个括号里填指令名和其他名称, 指令名必须至少有一个
        // 这个的话, 用"!v", "!version", 和"!版本"都能触发指令 (感叹号为你设置的前缀, 不一定必须要感叹号)
        return new CommandProperties("version", "v", "版本");
    }
    
    // 机器人接到指令后会执行这个方法 ( 实现不同的接口的话方法名不一定一样 )
    @Override
    public String run(EventMessage event, User sender, String command, ArrayList<String> args)
    {
        // 处理, 返回值会自动回复回去
        // 这里因为这个指令是用来查版本的, 所以直接返回字符串了
        return "TestBot - PicqBotX v4.15.0.1072";
    }
}

注册指令:

// 注册指令, 可以注册多个指令
bot.getCommandManager().registerCommands(new 指令1(), new 指令2(), ...);

常见问题:

Q: 为什么刚加的群不能回复消息?

因为用户信息在账号管理器里缓存了啦...
不会自动刷新的...
监听加群的事件然后
event.getBot().getAccountManager().refreshCache(); 就行啦w


Q: java.lang.NullPointerException at cc.moecraft.icq.accounts.AccountManager.getOptimal(...)?

和上一条一样
因为 groupAccountIndex 里面如果没有这个群的话,
groupAccountIndex.get(groupId) 就是 null 了w
所以用 null 调用 .entrySet() 就会丢报错w
所以 event.getBot().getAccountManager().refreshCache(); 就行啦w
( 前提是加了这个群!


Q: 如何在事件外获取IcqHttpApi对象用来发消息?

因为有多账号管理,
每个账号都有单独的IcqHttpApi对象...
如果要用一个不指定账号的API对象的话,
bot.getAccountManager().getNonAccountSpecifiedApi()
有多个账号的话不推荐用这个.

如果要用所有账号的话,
bot.getAccountManager().getAccounts() 获取个列表,
然后循环过去就好啦w

如果要用一个指定账号的话,
还是像上面那样循环过去,
然后每个账号判断getId()好啦w


Q: 如何加密?

随便生成一个Secret, 和一个AccessToken嗯
(可以用 https://passwordsgenerator.net/ 生成)

然后在酷Q HTTP插件的配置config.cfg里面写:

secret=这里填Secret
access_token=这里填AccessToken

然后在Picq的配置里面写:

config.setSecret("这里填Secret")
    .setAccessToken("这里填AccessToken");

然后重启就有加密啦w



如果发现 Bug 的话, 请开一个 issue 说明问题

或者加开发群 498386389 问吧w