feat: 验证码自动识别

This commit is contained in:
shanmite 2023-06-29 09:19:01 +08:00
parent 909fb83f79
commit eec22ffd76
11 changed files with 158 additions and 23 deletions

View File

@ -8,11 +8,12 @@
- [以源码方式运行](#以源码方式运行) - [以源码方式运行](#以源码方式运行)
- [Docker](#docker) - [Docker](#docker)
- [青龙面板](#青龙面板) - [青龙面板](#青龙面板)
- [防重复转发(可选)](#防重复转发可选)
- [检测中奖](#检测中奖) - [检测中奖](#检测中奖)
- [检测未读信息, 已读未读信息](#检测未读信息-已读未读信息) - [检测未读信息, 已读未读信息](#检测未读信息-已读未读信息)
- [中奖推送(可选)](#中奖推送可选) - [中奖推送](#中奖推送)
- [设置说明](#设置说明) - [设置说明](#设置说明)
- [评论验证码识别](#评论验证码识别)
- [其他](#其他)
- [Awesome](#awesome) - [Awesome](#awesome)
[Github仓库链接](https://github.com/shanmiteko/LotteryAutoScript) [Github仓库链接](https://github.com/shanmiteko/LotteryAutoScript)
@ -145,14 +146,6 @@ Chrome浏览器:
---------------------------------------- ----------------------------------------
## 防重复转发(可选)
- 脚本将转发过的动态和被过滤的动态都写入`dyids/dyid*.txt`文件中
- 是否点赞
----------------------------------------
## 检测中奖 ## 检测中奖
### 检测未读信息, 已读未读信息 ### 检测未读信息, 已读未读信息
@ -165,7 +158,7 @@ Chrome浏览器:
关键词有限 可能会有**漏掉**的或**误报** 关键词有限 可能会有**漏掉**的或**误报**
### 中奖推送(可选) ### 中奖推送
> 填写在env.js内 > 填写在env.js内
@ -204,6 +197,12 @@ Chrome浏览器:
## 设置说明 ## 设置说明
### 评论验证码识别
[点击跳转](doc/chat_captcha_orc.md)
### 其他
详见[env.example.js](./env.example.js)文件内部注释 详见[env.example.js](./env.example.js)文件内部注释
详见[my_config.example.js](./my_config.example.js)文件内部注释 详见[my_config.example.js](./my_config.example.js)文件内部注释

13
doc/chat_captcha_orc.md Normal file
View File

@ -0,0 +1,13 @@
使用此功能前需启动OCR服务
## 拉取镜像
```
docker pull shanmite/ocr_api_server
```
## 启动容器
```
docker run -p 9898:9898 -d ocr_api_server
```
### 非docker启动方式
[ocr_api_server](https://github.com/shanmiteko/ocr_api_server)

View File

@ -5,11 +5,14 @@ module.exports = Object.freeze({
* - `NOTE` 帐号备注 * - `NOTE` 帐号备注
* - `NUMBER` 表示是第几个账号 * - `NUMBER` 表示是第几个账号
* - `CLEAR` 是否启用清理功能 * - `CLEAR` 是否启用清理功能
* ## 高级功能
* - `ENABLE_CHAT_CAPTCHA_OCR` 开启评论验证码识别
* - `ENABLE_MULTIPLE_ACCOUNT` 是否启用多账号 * - `ENABLE_MULTIPLE_ACCOUNT` 是否启用多账号
* - `MULTIPLE_ACCOUNT_PARM` 多账号参数(JSON格式) * - `MULTIPLE_ACCOUNT_PARM` 多账号参数(JSON格式) <不推荐使用
* ## 调试相关 * ## 调试相关
* - `LOTTERY_LOG_LEVEL` 输出日志等级 Error<Warn<Info<Debug 1<2<3<4 * - `LOTTERY_LOG_LEVEL` 输出日志等级 Error<Warn<Info<Debug 1<2<3<4
* - `NOT_GO_LOTTERY` 关闭抽奖行为 * - `NOT_GO_LOTTERY` 关闭抽奖行为
*
* ## 多账号 * ## 多账号
* 1. ENABLE_MULTIPLE_ACCOUNT 的值改为true * 1. ENABLE_MULTIPLE_ACCOUNT 的值改为true
* 2. 将账号信息依次填写于 multiple_account_parm , 参考例子类推 * 2. 将账号信息依次填写于 multiple_account_parm , 参考例子类推
@ -23,6 +26,7 @@ module.exports = Object.freeze({
NUMBER: 1, NUMBER: 1,
CLEAR: true, CLEAR: true,
ENABLE_CHAT_CAPTCHA_OCR: "",
ENABLE_MULTIPLE_ACCOUNT: false, ENABLE_MULTIPLE_ACCOUNT: false,
MULTIPLE_ACCOUNT_PARM: "", MULTIPLE_ACCOUNT_PARM: "",

View File

@ -612,7 +612,7 @@ class Monitor extends Searcher {
status = await retryfn( status = await retryfn(
6, 6,
[4], [4],
() => bili.sendChat( () => bili.sendChatWithOcr(
rid, rid,
is_repost_then_chat ? relay_chat.split('//')[0] : chat, is_repost_then_chat ? relay_chat.split('//')[0] : chat,
chat_type chat_type
@ -621,7 +621,7 @@ class Monitor extends Searcher {
if (status === 8 || if (status === 8 ||
status === 9) { status === 9) {
status = await bili.sendChat( status = await bili.sendChatWithOcr(
rid, rid,
"[doge][doge][doge][doge][doge]", "[doge][doge][doge][doge][doge]",
chat_type chat_type

View File

@ -1,5 +1,5 @@
const GlobalVar = require('../data/global_var'); const GlobalVar = require('../data/global_var');
const { strToJson, log } = require('../utils'); const { strToJson, log, ocr, hasEnv } = require('../utils');
const { send } = require('./http'); const { send } = require('./http');
const API = require('./api.bili'); const API = require('./api.bili');
@ -117,7 +117,7 @@ function post({ url, config, contents, query }) {
config, config,
headers: { headers: {
"accept": 'application/json, text/plain, */*', "accept": 'application/json, text/plain, */*',
"content-type": 'application/x-www-form-urlencoded; charset=utf-8', "content-type": 'application/x-www-form-urlencoded; charset=UTF-8',
"cookie": GlobalVar.get("cookie") "cookie": GlobalVar.get("cookie")
}, },
query, query,
@ -1050,15 +1050,16 @@ const bili_client = {
* cid_str * cid_str
* @param {string} msg * @param {string} msg
* @param {number} type * @param {number} type
* @param {string} code
* 1(视频) * 1(视频)
* 11(有图) * 11(有图)
* 17(无图) * 17(无图)
* @returns {Promise<number>} * @returns {Promise<number|string>}
* - 成功 0 * - 成功 0
* - 未知错误 1 * - 未知错误 1
* - 原动态已删除 2 * - 原动态已删除 2
* - 评论区已关闭 3 * - 评论区已关闭 3
* - 需要输入验证码 4 * - 需要输入验证码 4 -> url
* - 已被对方拉入黑名单 5 * - 已被对方拉入黑名单 5
* - 黑名单用户无法互动 6 * - 黑名单用户无法互动 6
* - UP主已关闭评论区 7 * - UP主已关闭评论区 7
@ -1066,8 +1067,9 @@ const bili_client = {
* - 重复评论 9 * - 重复评论 9
* - 帐号未登录 10 * - 帐号未登录 10
* - 关注UP主7天以上的人可发评论 11 * - 关注UP主7天以上的人可发评论 11
* - 验证码错误 12
*/ */
async sendChat(rid, msg, type) { async sendChat(rid, msg, type, code) {
const const
responseText = await post({ responseText = await post({
url: API.REPLY_ADD, url: API.REPLY_ADD,
@ -1075,6 +1077,7 @@ const bili_client = {
oid: rid, oid: rid,
type: type, type: type,
message: msg, message: msg,
code,
csrf: GlobalVar.get("csrf") csrf: GlobalVar.get("csrf")
} }
}), }),
@ -1091,7 +1094,7 @@ const bili_client = {
return 3; return 3;
case 12015: case 12015:
log.error('自动评论', '需要输入验证码'); log.error('自动评论', '需要输入验证码');
return 4; return res.data.url;
case 12035: case 12035:
log.error('自动评论', `已被对方拉入黑名单`); log.error('自动评论', `已被对方拉入黑名单`);
return 5; return 5;
@ -1113,11 +1116,77 @@ const bili_client = {
case 12078: case 12078:
log.error('自动评论', '关注UP主7天以上的人可发评论'); log.error('自动评论', '关注UP主7天以上的人可发评论');
return 11; return 11;
case 12073:
log.error('自动评论', '验证码错误');
return 12;
default: default:
log.error('自动评论', `未知错误\n${responseText}`); log.error('自动评论', `未知错误\n${responseText}`);
return 1; return 1;
} }
}, },
/**
* 发送评论 自动识别验证码
* @param {string} rid
* cid_str
* @param {string} msg
* @param {number} type
* 1(视频)
* 11(有图)
* 17(无图)
* @returns {Promise<number>}
* - 成功 0
* - 未知错误 1
* - 原动态已删除 2
* - 评论区已关闭 3
* - 需要输入验证码 4 -> url
* - 已被对方拉入黑名单 5
* - 黑名单用户无法互动 6
* - UP主已关闭评论区 7
* - 评论内容包含敏感信息 8
* - 重复评论 9
* - 帐号未登录 10
* - 关注UP主7天以上的人可发评论 11
* - 验证码错误 12
*/
async sendChatWithOcr(rid, msg, type) {
let need_captcha = false;
let url = "";
let status = 0;
do {
if (need_captcha) {
const code = await ocr(url);
if (code) {
log.info("验证码识别", `${url} -> ${code}`);
status = await bili_client.sendChat(
rid,
msg,
type,
code
);
if (status === 0) {
need_captcha = false
} else if (status === 12) {
need_captcha = true
} else {
need_captcha = false
}
}
} else {
url = await bili_client.sendChat(
rid,
msg,
type
)
if (typeof url === "string"
&& hasEnv("ENABLE_CHAT_CAPTCHA_OCR")) {
need_captcha = true
} else {
status = url
}
}
} while (need_captcha);
return status;
},
/** /**
* 查询评论 * 查询评论
* @param {*} rid * @param {*} rid

View File

@ -275,6 +275,29 @@ const utils = {
} }
} }
}, },
/**
* 验证码识别
* @param {string} url
* @returns {Promise<string>}
*/
ocr(url) {
return new Promise((resolve) => {
send({
method: 'POST',
url: 'http://127.0.0.1:9898/ocr/url/text',
headers: {
"content-type": 'application/x-www-form-urlencoded; charset=UTF-8',
},
contents: { url },
success: res => {
resolve(res.body)
},
failure: () => {
resolve()
}
})
})
},
/** /**
* 下载文件 * 下载文件
* @param {string} url * @param {string} url

View File

@ -82,6 +82,7 @@ if [[ -z "\$(docker ps -a | grep \$NAME)" ]]; then
docker run \\ docker run \\
-v $PWD/$ENV_FILE:/lottery/$ENV_FILE \\ -v $PWD/$ENV_FILE:/lottery/$ENV_FILE \\
-v $PWD/$CONFIG_FILE:/lottery/$CONFIG_FILE \\ -v $PWD/$CONFIG_FILE:/lottery/$CONFIG_FILE \\
--network host \\
--name \$NAME \\ --name \$NAME \\
$DOCKER_REPO \\ $DOCKER_REPO \\
start start
@ -103,6 +104,7 @@ if [[ -z "\$(docker ps -a | grep \$NAME)" ]]; then
docker run \\ docker run \\
-v $PWD/$ENV_FILE:/lottery/$ENV_FILE \\ -v $PWD/$ENV_FILE:/lottery/$ENV_FILE \\
-v $PWD/$CONFIG_FILE:/lottery/$CONFIG_FILE \\ -v $PWD/$CONFIG_FILE:/lottery/$CONFIG_FILE \\
--network host \\
--name \$NAME \\ --name \$NAME \\
$DOCKER_REPO \\ $DOCKER_REPO \\
check check
@ -124,6 +126,7 @@ if [[ -z "\$(docker ps -a | grep \$NAME)" ]]; then
docker run \\ docker run \\
-v $PWD/$ENV_FILE:/lottery/$ENV_FILE \\ -v $PWD/$ENV_FILE:/lottery/$ENV_FILE \\
-v $PWD/$CONFIG_FILE:/lottery/$CONFIG_FILE \\ -v $PWD/$CONFIG_FILE:/lottery/$CONFIG_FILE \\
--network host \\
--name \$NAME \\ --name \$NAME \\
$DOCKER_REPO \\ $DOCKER_REPO \\
clear clear
@ -144,6 +147,7 @@ NAME=shanmite-lottery-debug
echo "create temporary debug container" echo "create temporary debug container"
docker run \\ docker run \\
-it \\ -it \\
--network host \\
--name \$NAME \\ --name \$NAME \\
--entrypoint /bin/bash \\ --entrypoint /bin/bash \\
$DOCKER_REPO -c bash $DOCKER_REPO -c bash

View File

@ -6,7 +6,7 @@ const { parseDynamicCard } = require('../lib/core/searcher');
(async () => { (async () => {
assert(await bili_client.getMyinfo()); assert(await bili_client.getMyinfo());
await util.par_run([0, 1, 2, 3, 4, 6], [ await util.par_run([0, 3], [
// 0 // 0
async () => { async () => {
assert.equal((await bili_client.getTopRcmd()).length, 10) assert.equal((await bili_client.getTopRcmd()).length, 10)

View File

@ -3,7 +3,7 @@ const bili_client = require("../lib/net/bili");
const util = require('./util'); const util = require('./util');
(async () => { (async () => {
await util.par_run([0], [ await util.par_run([], [
// 0 // 0
async () => { async () => {
let info = await bili_client.getOneArticleByCv(22112353); let info = await bili_client.getOneArticleByCv(22112353);

View File

@ -3,7 +3,7 @@ const global_var = require("../lib/data/global_var");
const { log } = require('../lib/utils'); const { log } = require('../lib/utils');
const fs = require('fs'); const fs = require('fs');
log._level = 2 log._level = 4
env.init() env.init()
global_var.init(process.env["COOKIE"], 1) global_var.init(process.env["COOKIE"], 1)

23
test/ocr.test.js Normal file
View File

@ -0,0 +1,23 @@
const assert = require('assert');
const bili_client = require("../lib/net/bili");
const util = require('./util');
const { parseDynamicCard } = require('../lib/core/searcher');
(async () => {
await util.par_run([], [
// 0
async () => {
assert(await bili_client.getMyinfo());
const rid = parseDynamicCard(await bili_client.getOneDynamicByDyid("551416252543796684")).rid_str;
for (let index = 0; index < 100; index++) {
console.log(index);
await bili_client.sendChatWithOcr(
rid,
Date.now().toString(),
17,
)
}
},]);
})()