摘要
早就给Mirai点Star好久了,一直没动手用一下。这次就尝试自己定制一个机器人。
正文
周末本来想继续学Vue来着,这不又搞这个了,唉,这计划赶不上变化啊。
参考文档
mamoe/mirai: 高效率 QQ 机器人支持库 Gradle 下载的依赖jar包在哪? - 简书 基于MIRAI的QQ机器人 - 知乎 ja-netfilter/ja-netfilter - 码云 - 开源中国 JETBRA.IN CHECKER | IPFS0-在线获取激活码 IntelliJ IDEA 2021.3.3永久破解激活教程(可自定义有效期,亲测有效) - 码霸霸 ja-netfilter2.2.2下载 「Java」基于Mirai的qq机器人开发踩坑笔记(其一)_TioYae的博客-CSDN博客 no acceptable C compiler found in $PATH_JAVA-LPF的博客-CSDN博客 mirai的文档还是很详细的,直接查看用户手册
一、配置Mirai 以下所有的配置,都是使用命令行的,图形界面会造成过多的内存消耗。
不管windows或者linux,都是自己去Github下载mcl-installer 。
windows
展开
然后创建一个单独的文件夹,把下载器放进去。
展开
双击运行,根据你的需求进行相应的选择。像我本身就有Java环境,就不需要再进行安装了,我试了安装一个新版jdk,也是可以的。
展开
之后,本地会将mirai的jar包下载下来。直接执行代码运行
又会进行一波核心插件之类的下载,直到提示mirai-console started successfully。
展开
基本的命令,控制台也提示了,像autoLogin, help, login, logout, permission, status, stop。
执行命令进行登录
可能会弹出验证码,不弹更好,弹出来之后,直接浏览器打开抓包拿到ticket,然后输入到ticket框回车即可。
之后,或许还会弹出设备锁验证,这个直接浏览器打开,手机扫码授权后,关闭窗口即可进行最后一步登录了。
展开
展开
linux 虽然mirai的安装器上面提示可以使用java8,其实已经不支持了。如果想要使用java8趁早打消这个念头吧。
手动安装jdk,这个就直接创建一个脚本
添加内容后保存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/user/bin/env bash
set -e
yum -y install java-11-openjdk java-11-openjdk-devel
cat > /etc/profile.d/java11.sh <<EOF
export JAVA_HOME=\$(dirname \$(dirname \$(readlink \$(readlink \$(which javac)))))
export PATH=\$PATH:\$JAVA_HOME/bin
export CLASSPATH=.:\$JAVA_HOME/jre/lib:\$JAVA_HOME/lib:\$JAVA_HOME/lib/tools.jar
EOF
source /etc/profile.d/java11.sh
java -version
javac -version
echo $JAVA_HOME
授权执行 或者不授权执行,任选一种即可。
1
2
3
4
5
6
7
8
9
# 授权后直接执行脚本
chmod 744 openJdk11.sh
./openJdk11.sh
# 不授权执行
sh openJdk11.sh
# 查看安装后的java版本
java -version
下载mirai安装器,linux就不多说了,windows的玩过,linux也就这个流程。
1
2
3
4
5
6
7
8
9
10
11
wget https://github.com/iTXTech/mcl-installer/releases/download/v1.0.4/mcl-installer-1.0.4-linux-amd64
# 查看是否有execute权限
ll
# 进行授权
chown -R root mcl-installer-1.0.4-linux-amd64
chmod 744 mcl-installer-1.0.4-linux-amd64
# 执行安装
./mcl-installer-1.0.4-linux-amd64
结果此时报错了。
1
2
3
4
5
[ root@localhost ~] # ./mcl-installer-1.0.4-linux-amd64
./mcl-installer-1.0.4-linux-amd64: /lib64/libc.so.6: version ` GLIBC_2.29' not found (required by ./mcl-installer-1.0.4-linux-amd64)
./mcl-installer-1.0.4-linux-amd64: /lib64/libc.so.6: version `GLIBC_2.25' not found ( required by ./mcl-installer-1.0.4-linux-amd64)
./mcl-installer-1.0.4-linux-amd64: /lib64/libc.so.6: version ` GLIBC_2.28' not found (required by ./mcl-installer-1.0.4-linux-amd64)
./mcl-installer-1.0.4-linux-amd64: /lib64/libc.so.6: version `GLIBC_2.18' not found ( required by ./mcl-installer-1.0.4-linux-amd64)
这个官方有回答 ,需要自己进行编译。进行编译,首先要看自己有没有c环境
1
2
3
4
gcc -v
# 如果没有,就安装c环境
yum -y install gcc-c++
考虑到后面步骤比较麻烦,直接将windows已经下好的mirai打包丢上去,直接就能执行。这个的好处是,还能带着cookie,不用进行二次认证。
直接启动
1
nohup java - jar mcl . jar > bot . log 2 >& 1 &
关闭命令
1
2
3
4
[ root@iZp62wy25rtcetZ qqbot] # ps -ef|grep mcl.jar
root 2440 2255 2 18:59 pts/1 00:00:11 java -jar mcl.jar
root 2558 2255 0 19:06 pts/1 00:00:00 grep --color= auto mcl.jar
[ root@iZp62wy25rtcetZ qqbot] # kill -9 2440
在Linux上,后台启动会导致input服务无法使用,会报错,这个无所谓了。
展开
反正大致的流程就是这样了。
二、开发定制插件 开发插件 因为开发Mirai插件的配置和依赖我们也不知道,为了方便开发,他们也提供了MiraiConsole这个插件,便于开发的。但是只支持最新版Idea。破解过程,参考最上面的链接。
插件整好之后,就可以直接创建项目了
展开
展开
展开
展开
下面展示一个小样。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public final class Monitorbili extends JavaPlugin {
public static final Monitorbili INSTANCE = new Monitorbili ();
public static boolean flag = false ;
private Monitorbili () {
super ( new JvmPluginDescriptionBuilder ( "top.meethigher.monitorbili.monitorbili" , "1.0" )
. name ( "monitorbili" )
. author ( "meethigher" )
. build ());
}
@Override
public void onEnable () {
getLogger (). info ( "直播监控插件加载完毕!" );
createTask ();
GlobalEventChannel . INSTANCE . subscribeAlways ( GroupMessageEvent . class , event -> {
Member sender = event . getSender ();
MessageChain message = event . getMessage ();
SingleMessage singleMessage = message . get ( 1 );
if ( singleMessage . toString (). contains ( "看直播" )) {
event . getGroup (). sendMessage ( "Avavaava,今天也要轻松快乐看直播" );
}
});
}
}
像我这边用到了http,之前写的都是基于SpringBoot的Http,所以对这种项目来说,太臃肿了,这里就推荐使用Hutool 。
由于这是一个Kotlin项目所以引用依赖时,需要用Gradle(Kotlin格式),在build.gradle.kts,kts表示kotlin script。
1
2
3
4
dependencies {
// https://mvnrepository.com/artifact/cn.hutool/hutool-all
implementation ( "cn.hutool:hutool-all:5.8.0.M2" )
}
如果插件编写完毕,想要进行单元测试,可以直接运行RunTerminal.kt。
展开
展开
上面是被动的获取监听到消息的机器人,让机器人回复消息。
如果想要主动的发送消息,这么玩。具体的也可以仔细阅读文档
1
2
3
4
Bot bot = Bot . findInstance ( 111111 );
if ( bot == null ) return ;
Group group = bot . getGroup ( 111111 );
if ( group == null ) return ;
部署插件 idea右侧找到gradle,找到jar,然后双击就能打包了。
展开
最后输出的jar包就是在项目的根目录下的build/libs下面,最后将该jar包移动到mirai机器人根目录的plugins下面,重新运行查看到直播监控插件加载完毕 表示成功。
三、注意事项 顶号问题 像手机与pad或者电脑被顶号,会把机器人也顶下去,为了能保持所有设备同时在线,自动登录时,配置为手表,如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
accounts :
- # 账号, 现只支持 QQ 数字账号
account : 257636396
password :
# 密码种类, 可选 PLAIN 或 MD5
kind : PLAIN
# 密码内容, PLAIN 时为密码文本, MD5 时为 16 进制
value : fjldajdlfajlfja
# 账号配置. 可用配置列表 (注意大小写):
# "protocol": "ANDROID_PHONE" / "ANDROID_PAD" / "ANDROID_WATCH" /"MAC" / "IPAD"
# "device": "device.json"
# "enable": true
configuration :
protocol : ANDROID_WATCH
jar包问题 像我在上面引用了hutool工具类,但是,我部署到服务器后,启动后,定时任务一直没跑。直到我把定时任务线程池换成了Timer,才发现报错是因为hutool的包不存在。
1
2
3
4
5
6
7
8
private void createTask () {
//Timer timer = new Timer();
//timer.scheduleAtFixedRate(new MonitorLiveRunnable(), 1000L, 1000L);
/*有错不会丢出*/
ScheduledExecutorService scheduledExecutorService = new ExecutorConfig (). scheduledExecutorService ();
scheduledExecutorService . scheduleAtFixedRate ( new MonitorLiveRunnable (), 5L , 60L , TimeUnit . SECONDS );
}
解决办法也很简单,直接将所需要的jar包丢到,mirai的plugin下面即可。
当然了,gradle打包时,将依赖包打进去也可以,我懒得搞了。
最后,放上一张机器人运行图。
展开
线程异常导致任务丢失 下面模拟了一下,异常,发现任务就会丢失了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Test {
public static void main ( String [] args ) {
ScheduledExecutorService service = Executors . newScheduledThreadPool ( 5 );
service . scheduleAtFixedRate ( new Runnable () {
@Override
public void run () {
System . out . println ( "hhh" );
int i = 1 / 0 ;
}
}, 5L , 1L , TimeUnit . SECONDS );
service . scheduleAtFixedRate ( new Runnable () {
@Override
public void run () {
System . out . println ( "aaa" );
}
}, 5L , 1L , TimeUnit . SECONDS );
}
}
展开
我这边直接抓个异常解决。