天天看点

autojs-robot-基于通知栏监听的机器人

牙叔教程 简单易懂

autojs-robot的优势

  • 不依赖任何框架, 因为根本不是用的协议
  • 支持任何版本的qq
  • 不会出现滑块之类的问题, 只要你的Q号没问题

autojs-robot适用场景

管理自己的Q群, 需要简单的问答机器人, 机器人发言频率不高

autojs-robot不适用场景

机器人频繁发消息, 发言频率特别快的场景, 因为通知栏监听不过来, 会漏掉消息

为啥写autojs-robot

我原来用的机器人是npm的oicq, 前几天频繁出滑块, 填写了ticket, 还是提示请用手机号登录之类的,

用手机号登录吧, 又提示

The value of "value" is out of range. It must 
be >= 0 and <= 4294967295. Received 18_888_888_888           

以下代码可以复现这个问题

uin = 18888888888;
const buf = Buffer.alloc(8);
buf.writeUInt32BE(uin);           

寻思着换个机器人

  • nenobot
  • zerobot
  • go-cqhttp
  • ovqq
  • mirai

不管那个, 对我来说, 上手成本都不低, 因此我决定用autojs写个机器人

注意

使用我这个机器人有个前提条件, 必须有两台废旧手机, 两个Q号, 如果没有, 就别往下看了

原理

  • 一台手机做客户端, 监听通知栏, 监听到消息后, 提交消息给另外一台手机
  • 一台手机做服务端, 接收另一台手机发送的消息, 接收到消息之后, 在qq群发消息

autojspro的优势

  • autojspro支持nodejs, nodejs可以做服务端
  • autojspro的两个引擎, rhino和nodejs可以通信
  • 无障碍

autojspro的劣势

  • 屏蔽了QQ

我的autojspro怎么能操作QQ

我的autojspro也不能操作qq呀, 我是打包以后, 用mt管理器修改了文件, 才可以操作qq的

如果不会去限制怎么办

我们的目的是机器人发消息, 那么有两种办法

  • 图色
  • 用二开的autojs, 比如
  • Auto.js author: TonyJiangWJ
  • AutoX author: kkevsekk1
  • AutoJs6 author: SuperMonster003

二开的autojs要和autojspro通信的话, 可以用广播通信, 比如autox和autojspro通信,

那么就可以跳过autojspro的限制, 用autox操作所有app, 而autojspro的nodejs功能我们仍然可以使用

广播通信

发送广播

var action = "android.intent.action.牙叔教程";
app.sendBroadcast({
    action: action,
    extras: {
        name: "牙叔教程",
        dream: "One Piece",
    },
});           

监听广播

importPackage(android.content);
var filter = new IntentFilter();
filter.addAction("android.intent.action.牙叔教程");
var receiver = new JavaAdapter(android.content.BroadcastReceiver, {
    onReceive: function (context, intent) {
        var extras = intent.getExtras();
        if (extras != null) {
            log("name: " + extras.getString("name"));
            log("dream: " + extras.getString("dream"));
        }
    },
});
context.registerReceiver(receiver, filter);
setInterval(() => {}, 1000);
events.on("exit", function () {
    context.unregisterReceiver(receiver);
});           

下面开始讲机器人的代码

监听通知栏

首先要开启通知监听

auto();
events.observeNotification();
events.onNotification(function(notification){
    log(notification.getText());
});           

监听到通知栏有新消息后, 我们先看看消息的具体内容

let obj = {
    title: notification.getTitle(),
    text: notification.text,
    when: notification.when,
    tickerText: notification.tickerText,
    packageName: notification.getPackageName(),
};
//   { title: '牙叔教程二群 (7条新消息)',
//   text: '☾ 分寸 ☽: 输入法弹出还行,1秒:左右,输入:文字后缩进要8秒',
//   when: 1666862029027,
//   tickerText: '☾ 分寸 ☽(牙叔教程二群):输入法弹出还行,1秒左右,输入文字后缩进要8秒',
//   packageName: 'com.tencent.mobileqq' }           

这个通知栏的消息里面, 有qq群聊的文字内容, 有qq群名字

我们要分析这个消息是否是我们关心的消息,

我只关心我的群里的消息, 其他群不关心, 因此我先定义一个我关心的消息过滤规则

let groupMap = {
    私人订制3: "xxxxxxx",
    牙叔教程二群: "582976637",
    牙叔教程: "zzzzzzzz",
};
let groupName = obj.title.split(" ")[0];
let groupId = groupMap[groupName];
if (groupId && groupName && message) {
    // 是我关心的消息
  	...
}           

过滤消息以后, 我们把消息发送给服务端

function postData(data) {
    log("客户端发送的数据: " + JSON.stringify(data));
    http.postJson(baseUrl, data, {}, function (res, err) {
        if (err) {
            console.error(err);
            return;
        }
        log("code = " + res.statusCode);
        log("html = " + res.body.string());
    });
}           

服务端

服务端这边是用autojspro实现的,

nodejs的koa监听3333端口

"nodejs";
const Koa = require("koa");
const router = require("koa-router")();
var bodyParser = require("koa-bodyparser");
/* -------------------------------------------------------------------------- */
var app = new Koa();
app.use(bodyParser());
/* -------------------------------------------------------------------------- */
router.post("/group-msg", async (ctx) => {
    ctx.body = "hello world";
});
/* -------------------------------------------------------------------------- */
// 调用router.routes()来组装匹配好的路由,返回一个合并好的中间件
// 调用router.allowedMethods()获得一个中间件,当发送了不符合的请求时,会返回 `405 Method Not Allowed` 或 `501 Not Implemented`
app.use(router.routes());
app.use(router.allowedMethods({}));
app.listen(3333, () => {
    console.log("koa is listening in 3333");
});           

监听到消息以后, 把消息提取出来, 然后处理消息

router.post("/group-msg", async (ctx) => {
    let postParam = ctx.request.body;
    if (!postParam.groupId || !postParam.groupName || !postParam.message) {
        ctx.response.status = 400;
        ctx.body = "必须包含三个字段: groupId, groupName, message";
        return;
    }
    let data = await handleMessage(postParam);
    if (!data) {
        console.log("拒绝处理空消息");
        return false;
    }
    serverEngine.emit("reply", data);
    return (ctx.body = {
        code: 200,
        message: "成功",
        data: data,
    });
});           

处理消息 handleMessage 这里就是看机器人应该回复群成员什么消息,

这里就看你自己了, 你在这里的目标就是设置关键词对应的内容,

群成员触发了关键词, 你就发送对应的内容给群成员;

我在这里主要是搜索我的语雀教程, 群成员发送了关键词,

我就去语雀文档搜索对应的教程, 然后发给群成员教程链接

发送消息

最基础的无障碍操作

这是发消息的逻辑代码

function sendGroupMsg(data) {
    if (!data.groupId || !data.groupName || !data.message) {
        log("参数异常" + JSON.stringify(data));
        return;
    }
    openQqGroup(data.groupId);
    click发消息按钮();
    enterMsg(data.message);
    clickSendButton();
}           

这是点击按钮的代码, 基础的无障碍操作代码我就不贴了

function clickSendButton() {
    let view = text("发送")
        .visibleToUser(true)
        .boundsInside(0, device.height * 0.7, device.width, device.height)
        .findOne(3000);
    if (!view) {
        throw new Error("没有找到发送按钮");
    }
    view.click();
}           

其中最关键的代码是跳转qq群页面

function openQqGroup(groupId) {
    let data = "mqqapi://card/show_pslcard?src_type=internal&version=1&card_type=group&uin=" + groupId;
    app.startActivity({
        action: "android.intent.action.VIEW",
        data: data,
        packageName: "com.tencent.mobileqq",
    });
}           

队列

队列的出现, 是为了存用户发送的消息, 我们处理完一个消息, 再从队列里面取下一条消息处理

监听到消息, 先把消息存起来

$events.on("reply", (data) => {
    console.log("rhino 收到回复: " + JSON.stringify(data));
    queue.push(data);
});           

一个无限循环处理队列, 依次排序回复用户消息

threads.start(function () {
    while (true) {
        if (queue.length > 0) {
            let data = queue.shift();
            serverService.sendGroupMsg(data);
        }
        sleep(1000);
    }
});           

多个用户触发多个关键词

我不用考虑高并发, 因为我的群里没几个人发言, 就算有, 那也没问题;

我把消息存到了队列里面, 机器人会依次回复消息的;

除非同一时间多个用户发消息, 通知栏监听漏掉消息, 一般没这种情况发生

总结

大家主要理解这个机器人思路, 代码都很简单,

学习成本低, 可比那些用协议的机器人简单多了, 用那种协议框架, 啃文档成本就很大, 最烦的就是登录不进去;

现在这个autojs-robot, 只要你的q号可以在手机正常登录, 那么就不会遇到任何登录问题, 也不会发生密码泄露;

自己的机器人, 自己掌握, 不依赖任何人, 任何框架, 一个autojspro就搞定

环境

设备: 两台废旧手机, 安卓7以上(含安卓7)

autojspro: 9.2.13

名人名言

思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最后才是群里问问 --- 牙叔教程

声明

部分内容来自网络 本教程仅用于学习, 禁止用于其他用途

继续阅读