Compare commits

...
11 Commits
Author SHA1 Message Date
shanmiteko e8b9e05a65 fix: 推送空消息 2021-10-20 16:14:04 +08:00
shanmiteko e298970d3f docs: 更新CHANGELOG 2021-10-20 16:05:02 +08:00
shanmiteko 1eaa188374 feat: 检查动态创建时间(#57)(#58) 2021-10-20 16:00:45 +08:00
shanmiteko b36d24a4d8 feat(check): 简单整理(#56) 2021-10-18 16:19:51 +08:00
shanmiteko 3b73d6a2f5 fix(clear): 非转发动态无源用户(#54) 2021-10-18 15:49:45 +08:00
shanmiteko f851ac1afe docs: 更新CHANGLOG 2021-10-15 20:43:25 +08:00
shanmiteko b53b698930 feat: 遇到过期的cookie跳过(#51) 2021-10-15 17:06:49 +08:00
shanmiteko 08d46c6f5c fix: UP关闭评论区(#52) 2021-10-15 16:46:43 +08:00
shanmiteko 80ae3df933 docs: 更新CHANGLOG 2021-10-14 16:32:19 +08:00
shanmiteko ac397c68ec fix: 未移动分区(#50) 2021-10-14 16:16:10 +08:00
shanmiteko 423bc24939 fix: 修改线路切换逻辑 2021-10-14 16:15:39 +08:00
12 changed files with 170 additions and 76 deletions
+2
View File
@@ -1,4 +1,6 @@
node_modules/
.vscode/
tests/
dyids/
dist/
package-lock.json
+44
View File
@@ -1,3 +1,47 @@
## 主要变化(2.2.8)
- 遇到过期的cookie跳过(#51)
## 问题修复
- UP关闭评论区(#52)
## 较上一版本变化
- `env.js`
- `my_config.js`
**替换可执行文件**
_如果之前版本小于上一版本,请查看[CHANGELOG](CHANGELOG.md)变更说明_
**Full Changelog**: https://github.com/shanmiteko/LotteryAutoScript/compare/v2.2.7...v2.2.8
## 主要变化(2.2.7)
## 问题修复
- 未移动分区(#50)
- 修改线路切换逻辑
## 较上一版本变化
- `env.js`
- `my_config.js`
**替换可执行文件**
_如果之前版本小于上一版本,请查看[CHANGELOG](CHANGELOG.md)变更说明_
**Full Changelog**: https://github.com/shanmiteko/LotteryAutoScript/compare/v2.2.6...v2.2.7
## 主要变化(2.2.6)
- LOG日志显示随机动态内容(#47)
- 增加设置过滤间隔
## 较上一版本变化
- `env.js`
- `my_config.js`增加`filter_wait`
**替换可执行文件和更改配置文件(建议修改)**
_如果之前版本小于上一版本,请查看[CHANGELOG](CHANGELOG.md)变更说明_
**Full Changelog**: https://github.com/shanmiteko/LotteryAutoScript/compare/v2.2.5...v2.2.6
## 主要变化(2.2.5)
## 问题修复
- 因黑名单而关注失败(#45)
+15 -11
View File
@@ -19,12 +19,14 @@ async function isMe() {
const MyAtInfo = await bili.getMyAtInfo();
MyAtInfo.forEach(async AtInfo => {
const { at_time, up_uname, business, source_content, url } = AtInfo
desp += `发生时间: ${new Date(at_time * 1000).toLocaleString()} \n\n`
desp += `用户: ${up_uname} \n\n`
desp += `${business}中@了你(${global_var.get("myUID")}) \n\n`
desp += `原内容为: ${source_content} \n\n`
desp += `[直达链接](${url}) \n\n`
desp += `\n\n`
desp += '## [at]检测结果\n\n'
desp += '----------------------------------------------------------------\n\n'
desp += `发生时间: ${new Date(at_time * 1000).toLocaleString()}\n\n`
desp += `用户: ${up_uname}\n\n`
desp += `${business}中@了你(${global_var.get("myUID")})\n\n`
desp += `原内容为: ${source_content}\n\n`
desp += `[直达链接](${url})\n\n`
desp += '----------------------------------------------------------------\n\n'
});
log.info('中奖检测', '--> OK');
}
@@ -40,11 +42,13 @@ async function isMe() {
bili.updateSessionStatus(talker_id, type, msg_seqno);
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`
desp += `[直达链接](https://message.bilibili.com/#/whisper/mid${sender_uid}) \n\n`
desp += `\n\n`
desp += '## 私信检测结果\n\n'
desp += '----------------------------------------------------------------\n\n'
desp += `发生时间: ${new Date(timestamp * 1000).toLocaleString()}\n\n`
desp += `用户: ${sender_uid}\n\n`
desp += `私信你(${global_var.get("myUID")})说: ${content}\n\n`
desp += `[直达链接](https://message.bilibili.com/#/whisper/mid${sender_uid})\n\n`
desp += '----------------------------------------------------------------\n\n'
}
}
}
+16 -10
View File
@@ -32,7 +32,7 @@ async function getFollowList() {
* 清理动态和关注
*/
async function clear() {
const { clear_white_list, clear_max_day, clear_quick_remove_attention, clear_remove_dynamic, clear_remove_attention, clear_remove_delay, clear_dynamic_type } = config;
const { search_wait, clear_white_list, clear_max_day, clear_quick_remove_attention, clear_remove_dynamic, clear_remove_attention, clear_remove_delay, clear_dynamic_type } = config;
let success = true;
const uid_list = await getFollowList();
if (!uid_list.length) {
@@ -65,19 +65,17 @@ async function clear() {
for (const page of infiniteNumber()) {
log.info('清理动态', `开始读取第${page + 1}`);
const { allModifyDynamicResArray, offset } = await Searcher.checkAllDynamic(MY_UID, 1, 5 * 1000, next_offset);
const { allModifyDynamicResArray, offset } = await Searcher.checkAllDynamic(MY_UID, 1, search_wait, next_offset);
next_offset = offset;
for (const [index, dyinfo] of allModifyDynamicResArray.entries()) {
log.info('清理动态', `${page + 1}页中的第${index + 1}个动态`)
const { type, dynamic_id, createtime } = dyinfo || {};
const { type, dynamic_id, create_time, origin_uid } = dyinfo || {};
if (typeof type !== 'undefined'
&& clear_dynamic_type instanceof Array
? clear_dynamic_type.includes(type)
: clear_dynamic_type === type
) {
const
{ origin_uid } = dyinfo,
days_ago = (Now - createtime) / 86400;
const days_ago = (Now - create_time) / 86400;
if (days_ago > clear_max_day) {
/* 移除动态 */
@@ -96,13 +94,21 @@ async function clear() {
success = await bili.cancelAttention(origin_uid);
}
if (!success) break;
if (!success) {
log.error("清理失败", "出现错误")
break
}
/* 延时 */
await delay(clear_remove_delay);
} else {
log.info('清理动态', `已设置跳过${clear_max_day}天 当前动态发布时间: ${~~days_ago}天前`)
log.info('清理动态', `储存用户(${origin_uid})防止误删`)
before_separate.push(origin_uid)
log.info('清理动态', `已设置跳过${clear_max_day}天 当前动态(${dynamic_id})发布时间: ${~~days_ago}天前`)
if (origin_uid) {
log.info('清理动态', `储存用户(${origin_uid})防止误删`)
before_separate.push(origin_uid)
} else {
log.info('清理动态', `非转发动态`)
}
}
} else {
log.info('清理动态', `此动态类型为${type} != 要清理的动态类型${clear_dynamic_type}`)
+19 -5
View File
@@ -51,7 +51,7 @@ class Monitor extends Searcher {
event_bus.emit('Turn_off_the_Monitor', '评论失败')
break
case 21:
event_bus.emit('Turn_on_the_Monitor')
event_bus.emit('Turn_off_the_Monitor', '关注出错')
break
case 22:
log.warn('账号异常', `UID(${global_var.get('myUID')})异常号只会对部分UP出现关注异常`)
@@ -171,6 +171,9 @@ class Monitor extends Searcher {
*/
async filterLotteryInfo() {
const { lottery_param, LotteryInfoMap, attentionList } = this;
/**
* @type {import("./searcher").LotteryInfo}
*/
let protoLotteryInfo = await LotteryInfoMap.get(lottery_param[0])(lottery_param[1]);
if (protoLotteryInfo === null)
@@ -182,9 +185,13 @@ class Monitor extends Searcher {
/** 所有抽奖信息 */
let alllotteryinfo = [];
const { key_words, model, chatmodel, is_imitator, only_followed, at_users, blockword, blacklist } = config;
const
{ key_words, model, chatmodel, max_create_time, is_imitator, only_followed, at_users, blockword, blacklist } = config,
now_ts = Date.now() / 1000;
/**Map<String, Boolean> */
/**
* @type {Map<String, Boolean>}
*/
let dyids_map = new Map();
/**去重 */
@@ -199,13 +206,16 @@ class Monitor extends Searcher {
/* 检查动态是否满足要求 */
await try_for_each(protoLotteryInfo, async function ({
lottery_info_type, is_liked,
uids, uname, dyid,
uids, uname, dyid, create_time,
ctrl, rid, des, type,
hasOfficialLottery
}) {
/* 遇到转发过就退出 */
if (is_liked) return false;
/* 超过指定时间退出 */
if (now_ts - create_time > max_create_time * 86400) return false;
const
/**判断是转发源动态还是现动态 */
uid = lottery_info_type === 'uid' ? uids[1] : uids[0],
@@ -325,7 +335,7 @@ class Monitor extends Searcher {
* @param {LotteryOptions} option
* @returns {Promise<number>}
* 0 - 成功
* 9 - 评论黑名单
* 9 - 评论黑名单/评论区关闭/动态删除
* 11 - 评论错误
* 19 - 关注黑名单
* 21 - 关注错误
@@ -373,8 +383,12 @@ class Monitor extends Searcher {
status = await bili.autoAttention(u)
switch (status) {
case 0:
if (await bili.movePartition(u, this.tagid)) {
log.error('抽奖信息', `uid: ${u},dyid: ${dyid}`)
}
return false
case -1:
case 2:
log.warn('抽奖信息', `uid: ${u},dyid: ${dyid}`)
return true
default:
+22 -17
View File
@@ -11,14 +11,14 @@ const { log } = utils
* @property {number} uid
* @property {string} uname
* @property {boolean} is_liked
* @property {number} createtime 10
* @property {number} create_time 10
* @property {string} rid_str
* @property {string} dynamic_id
* @property {number} type
* @property {string} description
* @property {boolean} hasOfficialLottery
* @property {Array<Object.<string,string|number>>} ctrl
*
* @property {number} origin_create_time 10
* @property {number} origin_uid
* @property {string} origin_uname
* @property {string} origin_rid_str
@@ -27,6 +27,20 @@ const { log } = utils
* @property {string} origin_description
* @property {boolean} origin_hasOfficialLottery
*
* 整理后的抽奖信息
* @typedef {object} LotteryInfo
* @property {string} lottery_info_type
* @property {number} create_time
* @property {boolean} is_liked
* @property {number[]} uids `[uid,ouid]`
* @property {string} uname
* @property {Array<{}>} ctrl
* @property {string} dyid
* @property {string} rid
* @property {string} des
* @property {number} type
* @property {boolean} hasOfficialLottery 是否官方
*
* @param {object} dynamic_detail_card
* @return {UsefulDynamicInfo}
*/
@@ -46,7 +60,7 @@ function parseDynamicCard(dynamic_detail_card) {
/* 动态是否点过赞 */
obj.is_liked = is_liked > 0
/* 动态的ts10 */
obj.createtime = desc.timestamp
obj.create_time = desc.timestamp
/* 动态类型 */
obj.type = desc.type
/* 用于发送评论 */
@@ -65,6 +79,8 @@ function parseDynamicCard(dynamic_detail_card) {
const { origin_extension, origin } = cardToJson
, originToJson = strToJson(origin)
, { user, item } = originToJson;
/* 源动态的ts10 */
obj.origin_create_time = desc.origin.timestamp;
/* 被转发者的UID */
obj.origin_uid = desc.origin.uid;
/* 被转发者的rid(用于发评论) */
@@ -131,20 +147,6 @@ function modifyDynamicRes(res) {
*/
class Searcher {
constructor() { }
/**
* 整理后的抽奖信息
* @typedef {object} LotteryInfo
* @property {string} lottery_info_type
* @property {boolean} is_liked
* @property {number[]} uids `[uid,ouid]`
* @property {string} uname
* @property {Array<{}>} ctrl
* @property {string} dyid
* @property {string} rid
* @property {string} des
* @property {number} type
* @property {boolean} hasOfficialLottery 是否官方
*/
/**
* 检查指定用户的所有的动态信息
* @param {number} hostuid 指定的用户UID
@@ -247,6 +249,7 @@ class Searcher {
return [...results, {
lottery_info_type: 'uid',
create_time: cur.origin_create_time,
is_liked,
uids: [cur.uid, cur.origin_uid],
uname: cur.origin_uname,
@@ -307,6 +310,7 @@ class Searcher {
const fomatdata = mDRdata.map(o => {
return {
lottery_info_type: 'tag',
create_time: o.create_time,
is_liked: o.is_liked,
uids: [o.uid, o.origin_uid],
uname: o.uname,
@@ -386,6 +390,7 @@ class Searcher {
const fomatdata = dyinfos.map(o => {
return {
lottery_info_type: 'article',
create_time: o.create_time,
is_liked: o.is_liked,
uids: [o.uid, o.origin_uid],
uname: o.uname,
+7 -1
View File
@@ -41,6 +41,12 @@ const config = {
*/
chatmodel: '01',
/**
* - 动态创建时间
* - 多少天前
*/
max_create_time: 60,
/**
* 不加判断的转发所监视的uid转发的动态
*/
@@ -93,7 +99,7 @@ const config = {
* - 检索动态间隔
* - 单位毫秒
*/
search_wait: 1000,
search_wait: 2000,
/**
* - 读取下一页私信间隔
+32 -26
View File
@@ -6,20 +6,23 @@ const API = require('./api.bili');
class Line {
/**
* 智能线路切换
* @typedef {string} ErrorMsg
* @typedef {[ErrorMsg, any]} ResResult
* @param {any} default_value
* @typedef {boolean} iSwitch 是否切换
* @typedef {string} Msg 信息说明
* @typedef {[iSwitch, any, Msg]} ResResult
* @param {string} line_name
* @param {Array<(...arg) => Promise<ResResult | string>>} requests
* @param {(responseText: string) => ResResult} [pub_handler]
*/
constructor(default_value, line_name, requests, pub_handler) {
constructor(line_name, requests, pub_handler) {
this.line_name = line_name
this.requests = requests
this.valid_line = 0
this.switch_times = 0
this.default_value = default_value
if (pub_handler) this.pub_handler = pub_handler
/**
* @type {ResResult}
*/
this.res_result = [false, null, '']
}
/**
@@ -53,26 +56,27 @@ class Line {
*/
async run(...args) {
const
{ line_name, requests, valid_line, default_value } = this,
{ line_name, requests, valid_line } = this,
resp = await requests[valid_line](...args);
let err, value;
if (typeof resp === 'string') {
[err, value] = this.pub_handler(resp)
this.res_result = this.pub_handler(resp)
} else {
[err, value] = resp
this.res_result = resp
}
if (!err) {
const [i_switch, value, msg] = this.res_result
if (!i_switch) {
log.info(line_name, msg)
this.storeLine(valid_line)
return value
}
if (this.switchLine()) {
log.warn(line_name, err)
log.warn(line_name, msg)
log.warn(line_name, `切换线路(${valid_line + 1}/${requests.length})`)
return await this.run()
} else {
log.error(line_name, err)
log.error(line_name, msg)
log.error(line_name, '所有备用线路均连接失败')
return default_value
return value
}
}
}
@@ -463,7 +467,7 @@ const bili_client = {
/**
* 获取粉丝数的所有有效方式
*/
_getUserInfo: new Line(-1, '获取粉丝数', [
_getUserInfo: new Line('获取粉丝数', [
/**
* 线路一
* @param {number} uid
@@ -493,9 +497,9 @@ const bili_client = {
], responseText => {
const res = strToJson(responseText);
if (res.code === 0) {
return [null, res.data.follower];
return [false, res.data.follower, 'ok'];
} else {
return [`出错 可能是访问过频繁\n${responseText}`, null]
return [true, 1, `出错 可能是访问过频繁\n${responseText}`]
}
}),
/**
@@ -534,7 +538,7 @@ const bili_client = {
};
}
},
_autoAttention: new Line(1, '自动关注', [
_autoAttention: new Line('自动关注', [
(uid) => post({
url: API.RELATION_MODIFY,
config: {
@@ -568,16 +572,15 @@ const bili_client = {
const res = strToJson(responseText);
switch (res.code) {
case 0:
log.info('自动关注', '关注+1');
return [null, 0]
return [false, 0, '关注+1']
case 22002:
return ['您已被对方拉入黑名单', -1]
return [false, -1, '您已被对方拉入黑名单']
case 22003:
return ['黑名单用户无法关注', -1]
return [false, -1, '黑名单用户无法关注', -1]
case 22015:
return ['账号异常', 2]
return [false, 2, '账号异常', 2]
default:
return [`未知错误\n${responseText}`, 1]
return [true, 1, `未知错误\n${responseText}`]
}
}),
/**
@@ -835,7 +838,7 @@ const bili_client = {
* @returns {Promise<number>}
* - 成功 0
* - 失败 1
* - 黑名单 -1
* - 黑名单/评论区关闭/动态删除 -1
*/
async sendChat(rid, msg, type) {
const
@@ -855,10 +858,10 @@ const bili_client = {
return 0;
case -404:
log.error('自动评论', '原动态已删除');
return 0;
return -1;
case 12002:
log.error('自动评论', '评论区已关闭');
return 0;
return -1;
case 12015:
log.error('自动评论', '需要输入验证码');
return 1;
@@ -868,6 +871,9 @@ const bili_client = {
case 12053:
log.error('自动评论', '黑名单用户无法互动');
return -1;
case 12061:
log.error('自动评论', 'UP主已关闭评论区');
return -1;
default:
log.error('自动评论', `未知错误\n${responseText}`);
return 1;
+3 -3
View File
@@ -26,7 +26,7 @@
* @property {string} url 完整链接
* @property {boolean} [stream] 是否流式数据
* @property {RequestConfig} [config] 设置
* @property {string} [proxy] 代理 IP:PORT
* @property {string} [proxy] HTTP代理 IP:PORT
* @property {Object.<string, string|number>} [query] 查询选项
* @property {Object.<string, string|number> | string} [contents] 内容
* @property {HttpHeaders} [headers] 请求头
@@ -65,7 +65,7 @@ function send(detail) {
const { timeout, wait, retry, redirect, retry_times } = config;
const thisURL = new URL(url)
, content = formatContents(headers["content-type"], contents)
, request = thisURL.protocol === 'https:' ? https_request : http_request;
, request = (thisURL.protocol === 'https:') && !proxy ? https_request : http_request;
let options = {
timeout,
method: method.toUpperCase(),
@@ -82,7 +82,7 @@ function send(detail) {
if (proxy) {
options.headers.host = thisURL.host;
options.path = thisURL.href;
[options.hostname, options.port] = proxy.split(':');
[options.host, options.port] = proxy.split(':');
}
const req = request(options, res => {
let protodata = '';
+2 -1
View File
@@ -88,7 +88,8 @@ async function main() {
return `提供了错误的[OPTIONS] -> ${mode}\n\n` + help_msg
}
} else {
return 'Cookie已失效, 切换账号时不要点击退出账号而应直接删除Cookie退出'
log.error('Cookie已失效', '切换账号时不要点击退出账号而应直接删除Cookie退出')
return ''
}
} else {
return '请查看README文件, 在env.js指定位置填入cookie'
+7 -1
View File
@@ -53,6 +53,12 @@ module.exports = Object.freeze({
*/
chatmodel: '01',
/**
* - 动态创建时间
* - 多少天前
*/
max_create_time: 60,
/**
* 不加判断的转发所监视的uid转发的动态
*/
@@ -105,7 +111,7 @@ module.exports = Object.freeze({
* - 检索动态间隔
* - 单位毫秒
*/
search_wait: 1000,
search_wait: 2000,
/**
* - 读取下一页私信间隔
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "lottery-auto-script",
"version": "2.2.6",
"version": "2.2.9",
"description": "自动参与B站动态抽奖",
"main": "main.js",
"scripts": {