Compare commits

...
3 Commits
Author SHA1 Message Date
shanmiteko c3c8ffba95 feat: 内置默认设置 2021-10-11 09:32:11 +08:00
shanmiteko ec9a11d5c0 feat: 增加更多时延自定义值(#44) 2021-10-10 21:50:45 +08:00
shanmiteko 1458c800b8 feat: api线路切换具有记忆功能
perf: 重构部分代码
fix: 清理动态时关注列表获取失败
2021-10-10 20:48:17 +08:00
13 changed files with 950 additions and 595 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 12
"ecmaVersion": "latest"
},
"rules": {
}
+2
View File
@@ -26,6 +26,8 @@
- 监控专栏合集
- 自动点赞、评论、乱序转发、@好友、带话题、可选随机动态
- 检测是否中奖
- 已读@
- 已读私信
- 清理动态关注
- 检查更新
- 更多功能设置请参考配置文件
+8 -6
View File
@@ -9,9 +9,11 @@ const bili = require('./net/bili')
*/
async function isMe() {
let desp = '';
const UnreadAtNum = await bili.getUnreadAtNum();
const UnreadSessionNum = await bili.getUnreadSessionNum();
const { follow_unread, unfollow_unread } = UnreadSessionNum || { unfollow_unread: 0, follow_unread: 0 };
const
{ notice_key_words, update_session_wait, get_session_wait } = config,
UnreadAtNum = await bili.getUnreadAtNum(),
UnreadSessionNum = await bili.getUnreadSessionNum(),
{ follow_unread, unfollow_unread } = UnreadSessionNum || { unfollow_unread: 0, follow_unread: 0 };
if (UnreadAtNum > 0) {
log.info('中奖检测', '<-- 正在检查at');
const MyAtInfo = await bili.getMyAtInfo();
@@ -36,8 +38,8 @@ async function isMe() {
session_t = session_ts;
if (unread_count) {
bili.updateSessionStatus(talker_id, type, msg_seqno);
await delay(1000);
if (judge(content, config.notice_key_words)) {
await delay(update_session_wait);
if (judge(content, notice_key_words)) {
desp += `发生时间: ${new Date(timestamp * 1000).toLocaleString()} \n\n`
desp += `用户: ${sender_uid} \n\n`
desp += `私信你(${global_var.get("myUID")})说: ${content} \n\n`
@@ -47,7 +49,7 @@ async function isMe() {
}
}
if (MySession.has_more && index < 16) {
await delay(3e3);
await delay(get_session_wait);
MySession = await bili.getSessionInfo(type, session_t)
} else {
break
+8 -6
View File
@@ -9,20 +9,22 @@ const config = require("./data/config");
* @returns { Promise<number[]> }
*/
async function getFollowList() {
const tagid = await bili.checkMyPartition(config.clear_partition);
const
{ clear_partition, clear_white_list, get_partition_wait } = config,
tagid = await bili.checkMyPartition(clear_partition);
let rmup = [];
if (typeof tagid === 'undefined') {
log.info('获取关注列表', '未能成功获取关注分区id');
return
return rmup
}
let rmup = [];
for (let index = 1; index < 42; index++) {
const uids = await bili.getPartitionUID(tagid, index);
await delay(2e3);
await delay(get_partition_wait);
if (!uids.length) break;
rmup.push(...uids)
}
return config.clear_white_list.length
? rmup.filter(uid => config.clear_white_list.split(',').indexOf(String(uid)) === -1)
return clear_white_list.length
? rmup.filter(uid => clear_white_list.split(',').indexOf(String(uid)) === -1)
: rmup;
}
+39 -41
View File
@@ -83,7 +83,7 @@ class Monitor extends Searcher {
async startLottery() {
const allLottery = await this.filterLotteryInfo()
, len = allLottery.length
, { dy_contents, create_dy, create_dy_mode, wait } = config;
, { create_dy, create_dy_mode, wait } = config;
log.info('筛选动态', `筛选完毕(${len})`);
@@ -332,53 +332,51 @@ class Monitor extends Searcher {
log.info('NOT_GO_LOTTERY', 'ON');
return 0
}
const { uid, dyid, chat_type, rid, relay_chat, ctrl } = option;
/* 评论 */
if (rid && chat_type) {
let status = 0;
const max_retry_times = 5;
for (let times = 0; times < max_retry_times; times++) {
status = await bili.sendChat(rid, utils.getRandomOne(config.chat), chat_type)
if (status === -1) {
log.warn('抽奖信息', `uid: ${uid},dyid: ${dyid}`)
return 0
let status = 0
const
{ chat } = config,
retry = [...new Array(5).keys()],
max_retry_times = retry.length;
await utils.try_for_each(retry, async (times) => {
status = await bili.sendChat(rid, utils.getRandomOne(chat), chat_type)
switch (status) {
case 0:
return true
case -1:
log.warn('抽奖信息', `uid: ${uid},dyid: ${dyid}`)
return true
default:
log.error('抽奖信息', `uid: ${uid},dyid: ${dyid}`)
log.info('自动评论', `将在 ${times + 1} 分钟后再次发送评论(${times + 1}/${max_retry_times})`)
await utils.delay(60 * 1000 * (times + 1))
return false
}
if (!status) {
break
}
log.error('抽奖信息', `uid: ${uid},dyid: ${dyid}`)
log.info('自动评论', `将在 ${times + 1} 分钟后再次发送评论(${times + 1}/${max_retry_times})`)
await utils.delay(60 * 1000 * (times + 1))
}
if (status) return 11;
})
if (status) return 10 + status;
}
/* 关注 */
const [u1, u2] = uid
if (u1) {
let status = await bili.autoAttention(u1)
if (status) {
log.error('抽奖信息', `uid: ${uid},dyid: ${dyid}`)
return 20 + status
};
status = await bili.movePartition(u1, this.tagid)
if (status) {
log.error('抽奖信息', `uid: ${uid},dyid: ${dyid}`)
return 20 + status
};
if (u2) {
utils.delay(5000)
status = await bili.autoAttention(u2)
if (status) {
log.error('抽奖信息', `uid: ${uid},dyid: ${dyid}`)
return 20 + status
};
status = await bili.movePartition(u2, this.tagid)
if (status) {
log.error('抽奖信息', `uid: ${uid},dyid: ${dyid}`)
return 20 + status
};
}
if (uid.length) {
let status = 0
await utils.try_for_each(uid, async (u) => {
status = await bili.autoAttention(u)
switch (status) {
case 0:
return false
case -1:
log.warn('抽奖信息', `uid: ${u},dyid: ${dyid}`)
return true
default:
log.error('抽奖信息', `uid: ${u},dyid: ${dyid}`)
return true
}
})
if (status) return 20 + status
}
/* 点赞 */
+12 -7
View File
@@ -215,7 +215,9 @@ class Searcher {
*/
async getLotteryInfoByUID(UID) {
log.info('获取动态', `开始获取用户${UID}的动态信息`);
const { allModifyDynamicResArray } = await Searcher.checkAllDynamic(UID, config.uid_scan_page, config.search_wait);
const
{ uid_scan_page, search_wait, get_dynamic_detail_wait } = config,
{ allModifyDynamicResArray } = await Searcher.checkAllDynamic(UID, uid_scan_page, search_wait);
let { length } = allModifyDynamicResArray
@@ -239,7 +241,7 @@ class Searcher {
const card = await bili.getOneDynamicByDyid(origin_dynamic_id)
if (card) {
await utils.delay(2000)
await utils.delay(get_dynamic_detail_wait)
const { is_liked } = parseDynamicCard(card)
@@ -273,6 +275,7 @@ class Searcher {
*/
async getLotteryInfoByTag(tag_name) {
const
{ tag_scan_page, search_wait } = config,
tag_id = await bili.getTagIDByTagName(tag_name),
hotdy = await bili.getHotDynamicInfoByTagID(tag_id),
modDR = modifyDynamicRes(hotdy);
@@ -288,7 +291,7 @@ class Searcher {
let mDRdata = modDR.modifyDynamicResArray;
let next_offset = modDR.nextinfo.next_offset;
for (let index = 0; index < config.tag_scan_page; index++) {
for (let index = 0; index < tag_scan_page; index++) {
log.info('获取动态', `读取第${index + 1}页动态`);
const
newdy = await bili.getOneDynamicInfoByTag(tag_name, next_offset),
@@ -299,7 +302,7 @@ class Searcher {
mDRdata.push.apply(mDRdata, _modify.modifyDynamicResArray);
next_offset = _modify.nextinfo.next_offset;
await utils.delay(config.search_wait);
await utils.delay(search_wait);
}
const fomatdata = mDRdata.map(o => {
return {
@@ -326,7 +329,9 @@ class Searcher {
*/
async getLotteryInfoByArticle(key_words) {
log.info('获取动态', `开始获取含关键词${key_words}的专栏信息`);
const cvs = (await bili.searchArticlesByKeyword(key_words)).slice(0, config.article_scan_page);
const
{ article_scan_page, not_check_article, get_dynamic_detail_wait } = config,
cvs = (await bili.searchArticlesByKeyword(key_words)).slice(0, article_scan_page);
/**存储所有专栏中的dyid */
let dyinfos = [];
@@ -354,7 +359,7 @@ class Searcher {
const card = await bili.getOneDynamicByDyid(dyid)
if (card) {
await utils.delay(2000)
await utils.delay(get_dynamic_detail_wait)
const parsed_card = parseDynamicCard(card)
, { is_liked } = parsed_card;
@@ -364,7 +369,7 @@ class Searcher {
_weight += 1;
}
if (_weight >= weight && !config.not_check_article) {
if (_weight >= weight && !not_check_article) {
log.warn('获取动态', `1/2动态曾经转过,该专栏或已查看,故中止`)
_dyinfos = []
break
+284 -1
View File
@@ -1,6 +1,286 @@
const { config_file } = require('../utils');
const config = {
/**
* 监视更转的用户uid
*/
UIDs: [],
/**
* 监视的专栏关键词
*/
Articles: [],
/**
* 监视的tag
*/
TAGs: [],
/**
* 动态中的关键词(表示须同时满足以下条件)
* 符合js正则表达式的字符串
*/
key_words: [
"[抽奖]",
"[转关].*[转关]"
],
/**
* - '00' 关闭自动抽奖
* - '10' 只转发官方抽奖
* - '01' 只转发非官方抽奖
* - '11' 都转
*/
model: '11',
/**
* - '00'关闭自动评论
* - '10'只评论官抽
* - '01'只评论非官抽
* - '11'都评论
*/
chatmodel: '01',
/**
* 不加判断的转发所监视的uid转发的动态
*/
is_imitator: false,
/**
* - 在uid里检索的页数
*/
uid_scan_page: 3,
/**
* - 在tag里检索的页数
*/
tag_scan_page: 3,
/**
* - 获取专栏数量
*/
article_scan_page: 3,
/**
* - 不检查专栏是否看过,若选择检查可以提高检测效率
* - 默认false(检查)
*/
not_check_article: false,
/**
* - 开奖时间距离现在的最大天数
* - 默认不限制
*/
maxday: Infinity,
/**
* - 循环等待时间(指所有操作完毕后的休眠时间)
* - 单位毫秒
*/
lottery_loop_wait: 0,
check_loop_wait: 0,
clear_loop_wait: 0,
update_loop_wait: 0,
/**
* - 转发间隔时间
* - 单位毫秒
* - 上下浮动50%
*/
wait: 30 * 1000,
/**
* - 检索动态间隔
* - 单位毫秒
*/
search_wait: 1000,
/**
* - 读取下一页私信间隔
* - 单位毫秒
*/
get_session_wait: 3000,
/**
* - 已读私信间隔
* - 单位毫秒
*/
update_session_wait: 1000,
/**
* - 读取下一页关注列表间隔
* - 单位毫秒
*/
get_partition_wait: 2000,
/**
* - 获取动态细节间隔
* - 单位毫秒
*/
get_dynamic_detail_wait: 2000,
/**
* - 随机动态间隔
* - 单位毫秒
*/
random_dynamic_wait: 2000,
/**
* - up主粉丝数限制
*/
minfollower: 1000,
/**
* - 只转发已关注的
*/
only_followed: false,
/**
* - 是否发送随机动态(防止被开奖机过滤)
*/
create_dy: false,
/**
* 随机动态类型
* - 0 自定义文字与图片
* - 1 推荐视频
* - -1 混合
*/
create_dy_type: 0,
/**
* - 结束运行时发送随机动态的数量
*/
create_dy_num: 1,
/**
* - 随机动态内容
* - 类型 `content[]`
* @typedef Picture
* @property {string} img_src 站内源
* @property {number} img_width
* @property {number} img_height
* @param { string | Picture[] } content
*/
dy_contents: ['[doge]', '[doge][doge]'],
/**
* - 每转发x条抽奖动态就发送x条随机动态
* - @example [[10,11,9],[6,8,9]] 每转发9,10,11条抽奖动态就发送6,8,9条随机动态
*/
create_dy_mode: [[0], [0]],
/**
* 转发时[at]的用户
*/
at_users: [['转发抽奖娘', 294887687], ['你的工具人老公', 100680137]],
/**
* - 自动同步 https://gitee.com/shanmite/lottery-notice/raw/master/notice.json
* - 英文逗号分隔 如: 1,2,3
*/
blacklist: '',
/**
* 屏蔽词
*/
blockword: ["脚本抽奖", "恭喜", "结果", "抽奖号", "钓鱼", "涨粉"],
/**
* 转发评语
*/
relay: ['转发动态'],
/**
* 评论内容
*/
chat: [
'[OK]', '[星星眼]', '[歪嘴]', '[喜欢]', '[偷笑]', '[笑]', '[喜极而泣]', '[辣眼睛]', '[吃瓜]', '[奋斗]',
'永不缺席 永不中奖 永不放弃!', '万一呢', '在', '冲吖~', '来了', '万一', '[保佑][保佑]', '从未中,从未停', '[吃瓜]', '[抠鼻][抠鼻]',
'来力', '秋梨膏', '[呲牙]', '从不缺席', '分子', '可以', '恰', '不会吧', '1', '好',
'rush', '来来来', 'ok', '冲', '凑热闹', '我要我要[打call]', '我还能中!让我中!!!', '大家都散了吧,已经抽完了,是我的', '我是天选之子', '给我中一次吧!',
'坚持不懈,迎难而上,开拓创新!', '[OK][OK]', '我来抽个奖', '中中中中中中', '[doge][doge][doge]', '我我我',
],
/**
* - 抽奖UP用户分组id(网页端点击分区后地址栏中的tagid)
* - 自动获取
*/
partition_id: 0,
/**
* 是否关注异常
*/
is_exception: false,
/**
* - 中奖通知关键词(满足一个就推送)
* - 符合js正则表达式的字符串
* - 若以 ~ 开头则表示为黑名单规则
*/
notice_key_words: [
"中奖|获得|填写|写上|提供|收货地址|支付宝账号|码|大会员",
"~有奖预约通知"
],
/**
* - 清理白名单uid或dyid
* - 英文逗号分隔 如: 1,2,3
*/
clear_white_list: '',
/**
* - 取关分区
* - 默认为: 此处存放因抽奖临时关注的up
*/
clear_partition: '',
/**
* 清理多少天之前的动态或关注
*/
clear_max_day: 30,
/**
* - 快速移除关注
* - 不加判断只去除关注
*/
clear_quick_remove_attention: false,
/**
* 是否移除动态
*/
clear_remove_dynamic: true,
/**
* 是否移除关注
*/
clear_remove_attention: true,
/**
* 清除动态延时(毫秒)
*/
clear_remove_delay: 8000,
/**
* 清除动态类型
*
* | 动态类型 | type值 |
* | :------- |:----- |
* | 无 | `0` |
* | 转发 | `1` |
* | 含图片 | `2` |
* | 无图纯文字 | `4` |
* | 视频 | `8` |
* | 番剧 | `512` |
* | 活动 | `2048` |
* | 专栏 | `64` |
*
* @example
* 1
* [1,2,4]
*/
clear_dynamic_type: [1],
/**
* 原始设置
* @returns {Object}
@@ -9,6 +289,7 @@ const config = {
delete require.cache[config_file];
return require(config_file)
},
/**
* @param {string} n
*/
@@ -18,10 +299,12 @@ const config = {
this.setObject(new_config)
}
},
init() {
this.setObject(this.raw_config()["default_config"])
},
setObject(o) {
setObject(o = {}) {
Object.entries(o).forEach(([k, v]) => this[k] = v)
}
};
+2 -3
View File
@@ -1,4 +1,4 @@
const { getRemoteConfig, createDir, createFile } = require("../utils");
const { getRemoteConfig } = require("../utils");
const config = require("../data/config");
const key_map = new Map([['DedeUserID', 'myUID'], ['bili_jct', 'csrf']]);
@@ -15,9 +15,8 @@ let global_var = {
* 全局变量初始化
* 更新config
* @param {string} cookie
* @param {number} n
*/
async init(cookie, n) {
async init(cookie) {
if (cookie) {
config.updata(process.env.NUMBER);
+3 -3
View File
@@ -8,12 +8,12 @@ const utils = require("../utils");
* @returns
*/
async function randomDynamic(num) {
const { create_dy_type, dy_contents } = config;
const { create_dy_type, dy_contents, random_dynamic_wait } = config;
if (create_dy_type === -1 || create_dy_type === 0 || typeof create_dy_type === 'undefined') {
for (let index = 0; index < num; index++) {
await bili.createDynamic(utils.getRandomOne(dy_contents));
await utils.delay(2000);
await utils.delay(random_dynamic_wait);
}
}
@@ -26,7 +26,7 @@ async function randomDynamic(num) {
await utils.try_for_each(videos, async ([uid, aid]) => {
if (num--) {
await bili.shareVideo(uid, aid)
await utils.delay(2000)
await utils.delay(random_dynamic_wait)
return false
} else {
return true
+558 -524
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -77,10 +77,10 @@ const utils = {
},
/**
* 延时函数
* @param {number} time ms
* @param {number} [time] ms
* @returns {Promise<void>}
*/
delay(time) {
delay(time = 1000) {
utils.log.info('时延', `${~~time}ms`);
return new Promise(resolve => {
setTimeout(() => {
+30
View File
@@ -107,6 +107,36 @@ module.exports = Object.freeze({
*/
search_wait: 1000,
/**
* - 读取下一页私信间隔
* - 单位毫秒
*/
get_session_wait: 3000,
/**
* - 已读私信间隔
* - 单位毫秒
*/
update_session_wait: 1000,
/**
* - 读取下一页关注列表间隔
* - 单位毫秒
*/
get_partition_wait: 2000,
/**
* - 获取动态细节间隔
* - 单位毫秒
*/
get_dynamic_detail_wait: 2000,
/**
* - 随机动态间隔
* - 单位毫秒
*/
random_dynamic_wait: 2000,
/**
* - up主粉丝数限制
*/
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "lottery-auto-script",
"version": "2.2.3",
"version": "2.2.4",
"description": "自动参与B站动态抽奖",
"main": "main.js",
"scripts": {