Compare commits

..
3 Commits
Author SHA1 Message Date
shanmite 77245c0391 env.js 2023-06-30 08:44:57 +08:00
shanmite c0dbdee343 proxy all 2023-06-29 16:40:01 +08:00
shanmite a0a2502148 test case 2023-06-29 15:37:49 +08:00
20 changed files with 119 additions and 214 deletions
-17
View File
@@ -1,22 +1,5 @@
<!-- markdownlint-disable MD036 MD024-->
# CHANGELOG
## 主要变化(2.8.1)
* d44981b fix: 随机cookie参数buvid3
* 3bfc93f fix: 目前回复无法正常推送 (#302)
* ef8366b fix: tg推送代理设置出错 (#298)
* a7e31b4 docs: update
* f4f45c5 fix: cookie参数buvid3错误导致专栏获取滞后
_如果之前版本小于上一版本,请查看[CHANGELOG](https://github.com/shanmiteko/LotteryAutoScript/blob/main/CHANGELOG.md)变更说明_
## 主要变化(2.8.0)
* 2f935bb chore: update env.js
* eec22ff feat: 验证码自动识别
* 909fb83 chore: update qinglong script
* 41b0369 ci: fix pkg.yml
_如果之前版本小于上一版本,请查看[CHANGELOG](https://github.com/shanmiteko/LotteryAutoScript/blob/main/CHANGELOG.md)变更说明_
## 主要变化(2.7.11)
* 5a3c16d fix: 专栏获取内容不正确,需要排除推荐内容 (#293)
+13 -14
View File
@@ -8,12 +8,11 @@
- [以源码方式运行](#以源码方式运行)
- [Docker](#docker)
- [青龙面板](#青龙面板)
- [防重复转发(可选)](#防重复转发可选)
- [检测中奖](#检测中奖)
- [检测未读信息, 已读未读信息](#检测未读信息-已读未读信息)
- [中奖推送](#中奖推送)
- [中奖推送(可选)](#中奖推送可选)
- [设置说明](#设置说明)
- [评论验证码识别](#评论验证码识别)
- [其他](#其他)
- [Awesome](#awesome)
[Github仓库链接](https://github.com/shanmiteko/LotteryAutoScript)
@@ -74,7 +73,7 @@ Chrome浏览器:
.cookie
.split(/\s*;\s*/)
.map(it => it.split('='))
.filter(it => ['DedeUserID','bili_jct', 'SESSDATA', 'buvid3'].indexOf(it[0]) > -1)
.filter(it => ['DedeUserID','bili_jct', 'SESSDATA'].indexOf(it[0]) > -1)
.map(it => it.join('='))
.join('; ')
.split()
@@ -83,9 +82,7 @@ Chrome浏览器:
也可以采用**其他方式获取**所需的Cookie
只需含有 `DedeUserID=...;SESSDATA=...;bili_jct=...;buvid3=...` 即可
buvid3亦可不填 使用随机生成值
只需含有 `DedeUserID=...;SESSDATA=...;bili_jct=...` 三项即可
(分号分割, 不要换行, 顺序随意)
@@ -148,6 +145,14 @@ buvid3亦可不填 使用随机生成值
----------------------------------------
## 防重复转发(可选)
- 脚本将转发过的动态和被过滤的动态都写入`dyids/dyid*.txt`文件中
- 是否点赞
----------------------------------------
## 检测中奖
### 检测未读信息, 已读未读信息
@@ -160,7 +165,7 @@ buvid3亦可不填 使用随机生成值
关键词有限 可能会有**漏掉**的或**误报**
### 中奖推送
### 中奖推送(可选)
> 填写在env.js内
@@ -199,12 +204,6 @@ buvid3亦可不填 使用随机生成值
## 设置说明
### 评论验证码识别
[点击跳转](doc/chat_captcha_orc.md)
### 其他
详见[env.example.js](./env.example.js)文件内部注释
详见[my_config.example.js](./my_config.example.js)文件内部注释
-18
View File
@@ -1,18 +0,0 @@
使用此功能前需启动OCR服务
## 拉取镜像
```
docker pull shanmite/ocr_api_server
```
## 启动容器
```
docker run -p 9898:9898 -d ocr_api_server
```
### 非docker启动方式
![ocr server](pic/ocr1.png)
[ocr_api_server](https://github.com/shanmiteko/ocr_api_server)
![start](pic/ocr0.png)
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

+9 -5
View File
@@ -5,14 +5,15 @@ module.exports = Object.freeze({
* - `NOTE` 帐号备注
* - `NUMBER` 表示是第几个账号
* - `CLEAR` 是否启用清理功能
* ## 高级功能
* - `ENABLE_CHAT_CAPTCHA_OCR` 开启评论验证码识别 使用方法见README
* - `ENABLE_MULTIPLE_ACCOUNT` 是否启用多账号
* - `MULTIPLE_ACCOUNT_PARM` 多账号参数(JSON格式) <不推荐使用
* - `MULTIPLE_ACCOUNT_PARM` 多账号参数(JSON格式)
* ## 代理相关
* - `ENABLE_PROXY` 启用代理
* - `XMDL_ORDERNNO` 熊猫动态代理订单号
* - `XMDL_SECRET` 熊猫动态代理密钥
* ## 调试相关
* - `LOTTERY_LOG_LEVEL` 输出日志等级 Error<Warn<Info<Debug 1<2<3<4
* - `NOT_GO_LOTTERY` 关闭抽奖行为
*
* ## 多账号
* 1. 将 ENABLE_MULTIPLE_ACCOUNT 的值改为true
* 2. 将账号信息依次填写于 multiple_account_parm 中, 参考例子类推
@@ -26,9 +27,12 @@ module.exports = Object.freeze({
NUMBER: 1,
CLEAR: true,
ENABLE_CHAT_CAPTCHA_OCR: "",
ENABLE_MULTIPLE_ACCOUNT: false,
ENABLE_PROXY: "",
XMDL_ORDERNNO: "",
XMDL_SECRET: "",
MULTIPLE_ACCOUNT_PARM: "",
LOTTERY_LOG_LEVEL: 3,
NOT_GO_LOTTERY: ""
+2 -2
View File
@@ -612,7 +612,7 @@ class Monitor extends Searcher {
status = await retryfn(
6,
[4],
() => bili.sendChatWithOcr(
() => bili.sendChat(
rid,
is_repost_then_chat ? relay_chat.split('//')[0] : chat,
chat_type
@@ -621,7 +621,7 @@ class Monitor extends Searcher {
if (status === 8 ||
status === 9) {
status = await bili.sendChatWithOcr(
status = await bili.sendChat(
rid,
"[doge][doge][doge][doge][doge]",
chat_type
+3 -18
View File
@@ -1,4 +1,4 @@
const { getRemoteConfig, getRandomOne, createDir, createFile, dyids_dir } = require("../utils");
const { getRemoteConfig, createDir, createFile, dyids_dir } = require("../utils");
const config = require("../data/config");
let global_var = {
@@ -29,22 +29,7 @@ let global_var = {
config.updata(num);
if (!/buvid3/.test(cookie)) {
const charset = "0123456789ABCDEF".split("");
const buvid3 = "x".repeat(8).split("").map(() => getRandomOne(charset)).join("")
+ "-"
+ "x".repeat(4).split("").map(() => getRandomOne(charset)).join("")
+ "-"
+ "x".repeat(4).split("").map(() => getRandomOne(charset)).join("")
+ "-"
+ "x".repeat(4).split("").map(() => getRandomOne(charset)).join("")
+ "-"
+ "x".repeat(17).split("").map(() => getRandomOne(charset)).join("")
+ "infoc";
this.set('cookie', cookie + ";" + buvid3);
} else {
this.set('cookie', cookie);
}
this.set('cookie', cookie + ';buvid3=AAAAAAAA-BBBB-CCCC-DDDD-DDDDDDDDDDDDDDDDDinfoc');
cookie.split(/\s*;\s*/).forEach(item => {
const _item = item.split('=');
@@ -68,4 +53,4 @@ let global_var = {
};
module.exports = global_var;
module.exports = global_var;
+2 -2
View File
@@ -495,8 +495,8 @@ function tgBotNotify(text, desp) {
}
if (TG_PROXY_HOST && TG_PROXY_PORT) {
options.proxy = {
url: "http://" + TG_PROXY_HOST + ":" + TG_PROXY_PORT,
auth_headers: []
hostname: TG_PROXY_HOST,
port: TG_PROXY_PORT * 1
}
}
send(options)
+26
View File
@@ -0,0 +1,26 @@
const { log } = require('../utils');
const crypto = require('crypto');
/**
* [熊猫代理](http://www.xiongmaodaili.com)
* @returns {import("../net/http").ProxyConfig}
*/
function xiongmaodaili() {
log.info("熊猫代理", "开始")
let timestamp = parseInt(new Date().getTime() / 1000);
let orderno = process.env["XMDL_ORDERNNO"];
let secret = process.env["XMDL_SECRET"];
let txt = 'orderno=' + orderno + ',secret=' + secret + ',timestamp=' + timestamp;
let md5 = crypto.createHash('md5');
let sign = md5.update(txt).digest('hex').toUpperCase();
return {
url: "http://dtan.xiongmaodaili.com:8088",
auth_headers: [
["Proxy-Authorization", 'sign=' + sign + '&orderno=' + orderno + "&timestamp=" + timestamp]
]
}
}
module.exports = { xiongmaodaili }
+20 -82
View File
@@ -1,7 +1,8 @@
const GlobalVar = require('../data/global_var');
const { strToJson, log, ocr, hasEnv } = require('../utils');
const { strToJson, log, hasEnv } = require('../utils');
const { send } = require('./http');
const API = require('./api.bili');
const proxies = require("../helper/proxies");
class Line {
/**
@@ -88,7 +89,7 @@ class Line {
*/
function get({ url, config, contents, query }) {
return new Promise((resolve) => {
send({
let ro = {
url,
method: 'GET',
config,
@@ -100,7 +101,11 @@ function get({ url, config, contents, query }) {
contents,
success: res => resolve(res.body),
failure: err => resolve(err)
})
}
if (hasEnv("ENABLE_PROXY")) {
ro.proxy = proxies.xiongmaodaili();
}
send(ro)
})
}
@@ -111,20 +116,24 @@ function get({ url, config, contents, query }) {
*/
function post({ url, config, contents, query }) {
return new Promise((resolve) => {
send({
let ro = {
url,
method: 'POST',
config,
headers: {
"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")
},
query,
contents,
success: res => resolve(res.body),
failure: err => resolve(err)
})
};
if (hasEnv("ENABLE_PROXY")) {
ro.proxy = proxies.xiongmaodaili();
}
send(ro)
})
}
@@ -218,9 +227,7 @@ const bili_client = {
items = data.items || [];
log.info('获取一页回复', `成功(${items.length})`);
return items
.filter(it => it.item !== undefined
&& it.user !== undefined
&& it.reply_time !== undefined)
.filter(it => it.item.type === 'reply')
.map(it => {
return {
nickname: it.user.nickname,
@@ -1052,16 +1059,15 @@ const bili_client = {
* cid_str
* @param {string} msg
* @param {number} type
* @param {string} code
* 1(视频)
* 11(有图)
* 17(无图)
* @returns {Promise<number|string>}
* @returns {Promise<number>}
* - 成功 0
* - 未知错误 1
* - 原动态已删除 2
* - 评论区已关闭 3
* - 需要输入验证码 4 -> url
* - 需要输入验证码 4
* - 已被对方拉入黑名单 5
* - 黑名单用户无法互动 6
* - UP主已关闭评论区 7
@@ -1069,9 +1075,8 @@ const bili_client = {
* - 重复评论 9
* - 帐号未登录 10
* - 关注UP主7天以上的人可发评论 11
* - 验证码错误 12
*/
async sendChat(rid, msg, type, code) {
async sendChat(rid, msg, type) {
const
responseText = await post({
url: API.REPLY_ADD,
@@ -1079,7 +1084,6 @@ const bili_client = {
oid: rid,
type: type,
message: msg,
code,
csrf: GlobalVar.get("csrf")
}
}),
@@ -1096,7 +1100,7 @@ const bili_client = {
return 3;
case 12015:
log.error('自动评论', '需要输入验证码');
return res.data.url;
return 4;
case 12035:
log.error('自动评论', `已被对方拉入黑名单`);
return 5;
@@ -1118,77 +1122,11 @@ const bili_client = {
case 12078:
log.error('自动评论', '关注UP主7天以上的人可发评论');
return 11;
case 12073:
log.error('自动评论', '验证码错误');
return 12;
default:
log.error('自动评论', `未知错误\n${responseText}`);
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
-23
View File
@@ -275,29 +275,6 @@ 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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "lottery-auto-script",
"version": "2.8.1",
"version": "2.7.11",
"description": "自动参与B站动态抽奖",
"main": "main.js",
"scripts": {
-4
View File
@@ -82,7 +82,6 @@ if [[ -z "\$(docker ps -a | grep \$NAME)" ]]; then
docker run \\
-v $PWD/$ENV_FILE:/lottery/$ENV_FILE \\
-v $PWD/$CONFIG_FILE:/lottery/$CONFIG_FILE \\
--network host \\
--name \$NAME \\
$DOCKER_REPO \\
start
@@ -104,7 +103,6 @@ if [[ -z "\$(docker ps -a | grep \$NAME)" ]]; then
docker run \\
-v $PWD/$ENV_FILE:/lottery/$ENV_FILE \\
-v $PWD/$CONFIG_FILE:/lottery/$CONFIG_FILE \\
--network host \\
--name \$NAME \\
$DOCKER_REPO \\
check
@@ -126,7 +124,6 @@ if [[ -z "\$(docker ps -a | grep \$NAME)" ]]; then
docker run \\
-v $PWD/$ENV_FILE:/lottery/$ENV_FILE \\
-v $PWD/$CONFIG_FILE:/lottery/$CONFIG_FILE \\
--network host \\
--name \$NAME \\
$DOCKER_REPO \\
clear
@@ -147,7 +144,6 @@ NAME=shanmite-lottery-debug
echo "create temporary debug container"
docker run \\
-it \\
--network host \\
--name \$NAME \\
--entrypoint /bin/bash \\
$DOCKER_REPO -c bash
+1 -2
View File
@@ -2,7 +2,6 @@
set -e
NAME=LotteryAutoScript
BRABCH=main
# 视网络情况选择链接
GIT_REPO=https://github.com/shanmiteko/${NAME}.git
@@ -13,7 +12,7 @@ if [ -d "$NAME" ]; then
git pull
cd ..
else
git clone -b $BRABCH $GIT_REPO $NAME
git clone $GIT_REPO $NAME --depth=1
fi
if [ -f "$NAME/my_config.js" ]; then
+1 -1
View File
@@ -6,7 +6,7 @@ const { parseDynamicCard } = require('../lib/core/searcher');
(async () => {
assert(await bili_client.getMyinfo());
await util.par_run([0, 3], [
await util.par_run([0, 1, 2, 3, 4, 5], [
// 0
async () => {
assert.equal((await bili_client.getTopRcmd()).length, 10)
+1 -1
View File
@@ -3,7 +3,7 @@ const bili_client = require("../lib/net/bili");
const util = require('./util');
(async () => {
await util.par_run([], [
await util.par_run([0], [
// 0
async () => {
let info = await bili_client.getOneArticleByCv(22112353);
+2 -1
View File
@@ -3,10 +3,11 @@ const global_var = require("../lib/data/global_var");
const { log } = require('../lib/utils');
const fs = require('fs');
log._level = 4
log._level = 2
env.init()
global_var.init(process.env["COOKIE"], 1)
fs.readdirSync(module.path)
.filter(file => file.endsWith(".test.js"))
.forEach(file => require(`${module.path}/${file}`))
-23
View File
@@ -1,23 +0,0 @@
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,
)
}
},]);
})()
+38
View File
@@ -0,0 +1,38 @@
const util = require('./util');
const crypto = require('crypto');
const { send } = require('../lib/net/http');
(async () => {
await util.par_run([], [
// 0
async () => {
let timestamp = parseInt(new Date().getTime() / 1000);
let orderno = process.env["XMDL_ORDERNNO"];
let secret = process.env["XMDL_SECRET"];
if (orderno && secret) {
let txt = 'orderno=' + orderno + ',secret=' + secret + ',timestamp=' + timestamp;
let md5 = crypto.createHash('md5');
let sign = md5.update(txt).digest('hex').toUpperCase();
console.log(await new Promise((resolve) => {
send({
url: "https://api.bilibili.com/client_info",
proxy: {
url: "http://dtan.xiongmaodaili.com:8088",
auth_headers: [
["Proxy-Authorization", 'sign=' + sign + '&orderno=' + orderno + "&timestamp=" + timestamp]
]
},
config: {
retry: false
},
success: (res) => { resolve(JSON.parse(res.body)) },
failure: resolve
})
}));
console.log("proxy.test ... ok!");
}
},
])
})()