Compare commits

...
7 Commits
Author SHA1 Message Date
shanmite aa9cb68c81 docs: 更新CHANGELOG 2022-01-16 20:18:13 +08:00
shanmite dd1b1db76a feat(update): 优先使用代理更新失败时切回去 2022-01-16 20:12:35 +08:00
shanmite 86e6b7dbc9 feat: 重命名设置sneaktower(#104) 2022-01-16 16:58:49 +08:00
shanmite 731b8475ec docs: 更新CHANGELOG 2022-01-15 14:48:55 +08:00
shanmite 043fee21e7 feat: 新增设置sneaktopic(#104)
偷塔模式不检查是否重复转发
* 偷塔模式: 临近开奖时参与抽奖
`sneaktopic: true`
2022-01-15 14:23:22 +08:00
shanmite ae34c691b1 feat: 新增设置is_repost_then_chat(#103)
转发并评论
2022-01-05 18:13:48 +08:00
shanmite 7496bc58a8 feat: 中奖检查时增加回复信息读取(#102) 2022-01-05 16:37:49 +08:00
11 changed files with 186 additions and 83 deletions
+13
View File
@@ -1,5 +1,18 @@
<!-- markdownlint-disable MD036 MD024-->
# CHANGELOG
## 主要变化(2.4.7)
* dd1b1db feat(update): 优先使用代理更新失败时切回去
* 86e6b7d feat: 重命名设置`sneaktower`(#104)
_如果之前版本小于上一版本,请查看[CHANGELOG](CHANGELOG.md)变更说明_
## 主要变化(2.4.6)
* 043fee2 feat: 新增设置`sneaktopic`(#104)
* ae34c69 feat: 新增设置`is_repost_then_chat`(#103)
* 7496bc5 feat: 中奖检查时增加回复信息读取(#102)
_如果之前版本小于上一版本,请查看[CHANGELOG](CHANGELOG.md)变更说明_
## 主要变化(2.4.5)
* ef969bb feat: 每组显示动态转发数(#97)
* 0cbacd6 feat: 推送携带帐号编号(#98)
+34 -15
View File
@@ -12,23 +12,42 @@ async function isMe(num) {
let desp = '';
const
{ notice_key_words, update_session_wait, get_session_wait, check_session_pages } = config,
UnreadAtNum = await bili.getUnreadAtNum(),
UnreadSessionNum = await bili.getUnreadSessionNum(),
{ follow_unread, unfollow_unread } = UnreadSessionNum || { unfollow_unread: 0, follow_unread: 0 };
if (UnreadAtNum > 0) {
{ at: unread_at_num, reply: unread_reply_num } = await bili.getUnreadNum(),
unread_session_num = await bili.getUnreadSessionNum(),
{ follow_unread, unfollow_unread } = unread_session_num || { unfollow_unread: 0, follow_unread: 0 };
if (unread_at_num) {
log.info('中奖检测', '<-- 正在检查at');
const MyAtInfo = await bili.getMyAtInfo();
MyAtInfo.forEach(async AtInfo => {
const { at_time, up_uname, business, source_content, url } = AtInfo
desp += '## [at]检测结果\n\n'
desp += '----------------------------------------------------------------\n\n'
desp += `发生时间: ${new Date(at_time * 1000).toLocaleString()}\n\n`
desp += `用户: ${up_uname}\n\n`
desp += `${business}中@了你(https://space.bilibili.com/${global_var.get("myUID")})\n\n`
desp += `原内容为: ${source_content}\n\n`
desp += `[直达链接](${url})\n\n`
desp += '----------------------------------------------------------------\n\n'
});
MyAtInfo
.slice(0, unread_at_num)
.forEach(({ at_time, up_uname, business, source_content, url }) => {
desp += '## [at]检测结果\n\n'
desp += '----------------------------------------------------------------\n\n'
desp += `发生时间: ${new Date(at_time * 1000).toLocaleString()}\n\n`
desp += `用户: ${up_uname}\n\n`
desp += `${business}中@了你(https://space.bilibili.com/${global_var.get("myUID")})\n\n`
desp += `原内容为: ${source_content}\n\n`
desp += `[直达链接](${url})\n\n`
desp += '----------------------------------------------------------------\n\n'
});
log.info('中奖检测', '--> OK');
}
if (unread_reply_num) {
log.info('中奖检测', '<-- 正在检查回复');
const replys = await bili.getReplyMsg();
replys
.slice(0, unread_reply_num)
.forEach(({ nickname, uri, source, timestamp }) => {
if (judge(source, notice_key_words)) {
desp += '## 回复检测结果\n\n'
desp += '----------------------------------------------------------------\n\n'
desp += `发生时间: ${new Date(timestamp * 1000).toLocaleString()}\n\n`
desp += `用户: ${nickname}\n\n`
desp += `回复你(https://space.bilibili.com/${global_var.get("myUID")})说:\n${source}\n\n`
desp += `[直达链接](${uri})\n\n`
desp += '----------------------------------------------------------------\n\n'
}
})
log.info('中奖检测', '--> OK');
}
if (follow_unread + unfollow_unread > 0) {
+18 -12
View File
@@ -244,7 +244,7 @@ class Monitor extends Searcher {
/** 所有抽奖信息 */
let alllotteryinfo = [];
const
{ check_if_duplicated, set_lottery_info_url, key_words, model, chatmodel, block_dynamic_type, max_create_time, is_imitator, only_followed, at_users, blockword, blacklist, use_public_blacklist } = config,
{ check_if_duplicated, set_lottery_info_url, sneaktower, key_words, model, chatmodel, block_dynamic_type, max_create_time, is_imitator, only_followed, at_users, blockword, blacklist, use_public_blacklist } = config,
now_ts = Date.now() / 1000;
/**
@@ -308,15 +308,17 @@ class Monitor extends Searcher {
log.debug('正在筛选的动态信息', lottery_info);
/* 遇到转发过就退出 */
if (
((!check_if_duplicated || check_if_duplicated === 2)
&& is_liked)
|| ((check_if_duplicated === 1 || check_if_duplicated === 2)
&& dyids_map.get(dyid))
) {
log.info("筛选动态", `已转发(https://t.bilibili.com/${dyid})`)
return false
if (lottery_info_type.startsWith('sneak') && sneaktower) {
log.info("筛选动态", `偷塔模式不检查是否已转发(https://t.bilibili.com/${dyid})`)
} else {
/* 遇到转发过就退出 */
if (
((!check_if_duplicated || check_if_duplicated === 2) && is_liked)
|| ((check_if_duplicated === 1 || check_if_duplicated === 2) && dyids_map.get(dyid))
) {
log.info("筛选动态", `已转发(https://t.bilibili.com/${dyid})`)
return false
}
}
/* 超过指定时间退出 */
@@ -519,7 +521,7 @@ class Monitor extends Searcher {
let status = 0
const
{ uid, dyid, chat_type, rid, relay_chat, ctrl } = option,
{ chat, check_if_duplicated } = config;
{ chat, check_if_duplicated, is_repost_then_chat } = config;
/* 评论 */
if (rid && chat_type) {
@@ -527,7 +529,11 @@ class Monitor extends Searcher {
status = await retryfn(
5,
[1, 4],
() => bili.sendChat(rid, getRandomOne(chat), chat_type)
() => bili.sendChat(
rid,
is_repost_then_chat ? relay_chat : getRandomOne(chat),
chat_type
)
)
if (status) {
+12
View File
@@ -78,6 +78,12 @@ const config = {
*/
check_if_duplicated: 1,
/**
* 偷塔模式不检查是否重复转发
* * 偷塔模式: 临近开奖时参与抽奖
*/
sneaktower: true,
/**
* 屏蔽动态类型
*
@@ -260,6 +266,12 @@ const config = {
*/
blockword: ["脚本", "抽奖号", "钓鱼"],
/**
* 转发并评论
* - 评论内容与转发内容相同
*/
is_repost_then_chat: false,
/**
* 转发评语
*/
+1
View File
@@ -12,6 +12,7 @@ module.exports = Object.freeze({
FEED_SETUSERFOLLOW: 'https://api.vc.bilibili.com/feed/v1/feed/SetUserFollow',
LOTTERY_SVR_LOTTERY_NOTICE: 'https://api.vc.bilibili.com/lottery_svr/v1/lottery_svr/lottery_notice',
MSGFEED_AT: 'https://api.bilibili.com/x/msgfeed/at',
MSGFEED_REPLAY: 'https://api.bilibili.com/x/msgfeed/reply',
MSGFEED_UNREAD: 'https://api.bilibili.com/x/msgfeed/unread',
READ_CV: 'https://www.bilibili.com/read/cv{{cv}}',
RELATION_BATCH_MODIFY: 'https://api.bilibili.com/x/relation/batch/modify',
+36 -8
View File
@@ -185,22 +185,50 @@ const bili_client = {
}
},
/**
* 获取未读@
* @returns {Promise<number>}
* 获取未读信息数量
* @returns {Promise<{at: number, reply: number}>}
*/
async getUnreadAtNum() {
async getUnreadNum() {
const
responseText = await get({
url: API.MSGFEED_UNREAD
}),
res = strToJson(responseText);
if (res.code === 0) {
const { at } = res.data;
log.info('获取未读@', `成功 数量: ${at}`);
return at;
log.info('获取未读信息', `成功`);
return res.data;
} else {
log.error('获取未读@', `失败\n${responseText}`);
return -1;
log.error('获取未读信息', `失败\n${responseText}`);
return {};
}
},
/**
* 获取一页回复
* @returns {Promise<Array<{nickname: string, source: string, uri: string, timestamp: number}>}>}
*/
async getReplyMsg() {
const
responseText = await get({
url: API.MSGFEED_REPLAY
}),
res = strToJson(responseText);
if (res.code === 0) {
const data = res.data || {},
items = data.items || [];
log.info('获取一页回复', `成功(${items.length})`);
return items
.filter(it => it.item.type === 'reply')
.map(it => {
return {
nickname: it.user.nickname,
source: it.item.source_content,
uri: it.item.uri,
timestamp: it.reply_time
}
});
} else {
log.error('获取一页回复', '失败');
return []
}
},
/**
+54 -43
View File
@@ -2,13 +2,25 @@ const { send } = require('./net/http')
const { strToJson, download, try_for_each } = require('./utils')
const { version, checkVersion, log } = require('./utils')
const
platform = new Map([
['win32', 'win'],
['linux', 'linux'],
['darwin', 'macos']
]).get(process.platform),
arch = new Map([
['x64', 'x64'],
['arm', 'armv7'],
['arm64', 'arm64']
]).get(process.arch);
/**
* 获取下载链接
* @param {string} owner
* @param {string} repo
* @returns {Promise<{ download_url: string[], text: string }>}
* @returns {Promise<{ tag_name:string, assets:Object, text:string }>}
*/
function getLatestReleaseDownloadUrl(owner, repo) {
function getLatestRelease(owner, repo) {
return new Promise((resolve, reject) => {
send({
url: `https://api.github.com/repos/${owner}/${repo}/releases/latest`,
@@ -19,37 +31,9 @@ function getLatestReleaseDownloadUrl(owner, repo) {
retry: false
},
success: ({ body }) => {
const { tag_name, assets, body: text } = strToJson(body)
if (tag_name) {
if (checkVersion(version) < checkVersion(tag_name)) {
const platform = new Map([
['win32', 'win'],
['linux', 'linux'],
['darwin', 'macos']
]).get(process.platform)
const arch = new Map([
['x64', 'x64'],
['arm', 'armv7'],
['arm64', 'arm64']
]).get(process.arch)
if (platform && arch) {
try {
const download_url = assets
.filter(({ name }) => name.includes(platform) && name.includes(arch))
.map(({ browser_download_url }) => browser_download_url)
if (!download_url.length) {
reject(`未找到能在此平台(${process.platform})-(${process.arch})上运行的版本`)
}
resolve({ download_url, text })
} catch (err) {
reject(err)
}
} else {
reject(`未找到能在此平台(${process.platform})-(${process.arch})上运行的版本`)
}
} else {
reject('当前已是最新版本')
}
const release = strToJson(body);
if (release.tag_name) {
resolve(release)
} else {
reject(body)
}
@@ -61,21 +45,48 @@ function getLatestReleaseDownloadUrl(owner, repo) {
});
}
/**
* @param {string} releases
* @return {boolean}
*/
function checkPlatform(releases) {
return releases.includes(platform)
&& releases.includes(arch)
}
/**
* 半自动更新
*/
async function update() {
try {
const { download_url, text } = await getLatestReleaseDownloadUrl('shanmiteko', 'LotteryAutoScript')
await try_for_each(download_url.entries(), async ([i, url]) => {
let proxy_url = new URL(url)
proxy_url.host = 'download.fastgit.org'
await download(proxy_url.href, `latest_version${i}.zip`)
return false
})
log.info('自动下载', '成功下载到当前目录')
log.info('更新说明', '\n' + text + '\n')
const { tag_name, assets, body: text } = await getLatestRelease('shanmiteko', 'LotteryAutoScript')
if (checkVersion(version) < checkVersion(tag_name)) {
const download_url = assets
.filter(({ name }) => checkPlatform(name))
.map(({ browser_download_url }) => browser_download_url)
if (download_url.length) {
const proxy_host = ['download.fastgit.org']
await try_for_each(download_url.entries(), async ([i, url]) => {
let proxy_url = new URL(url)
proxy_url.host = proxy_host[0]
log.warn('自动下载', `切换代理${proxy_host[0]}`)
await download(proxy_url.href, `latest_version${i}.zip`)
.catch(async err => {
log.error('自动下载', err)
proxy_url.host = 'github.com'
log.warn('自动下载', `使用原始链接github.com`)
await download(proxy_url.href, `latest_version${i}.zip`)
})
return false
})
log.info('自动下载', '成功下载到当前目录')
log.info('更新说明', '\n' + text + '\n')
} else {
throw `未找到能在此平台(${process.platform})-(${process.arch})上运行的版本,建议以源码运行`
}
} else {
throw '当前已是最新版本'
}
} catch (error) {
log.error('更新脚本', error)
}
+4 -3
View File
@@ -248,12 +248,13 @@ const utils = {
redirect: true,
retry: false
},
success: ({ resStream }) => {
success: ({ headers, resStream }) => {
const total_len = Number(headers["content-length"]);
let recv_length = 0;
const wtbs = fs.createWriteStream(file_name);
resStream.on('data', chuck => {
recv_length += chuck.length
utils.log.proPrint(`已收到:${recv_length} Bytes`)
utils.log.proPrint(total_len ? `已下载${(recv_length * 100 / total_len + '').slice(0, 5)}%` : `已收到:${recv_length} Bytes`)
})
resStream.pipe(wtbs)
wtbs.on('finish', () => {
@@ -261,7 +262,7 @@ const utils = {
resolve()
}).on('error', error => {
wtbs.destroy()
resolve(error)
reject(error)
})
},
failure: error => {
+1 -1
View File
@@ -88,7 +88,7 @@ async function main() {
}
} else {
log.error('Cookie已失效', '切换账号时不要点击退出账号而应直接删除Cookie退出')
return ''
return
}
} else {
return '请查看README文件, 在env.js指定位置填入cookie'
+12
View File
@@ -92,6 +92,12 @@ module.exports = Object.freeze({
*/
check_if_duplicated: 1,
/**
* 偷塔模式不检查是否重复转发
* * 偷塔模式: 临近开奖时参与抽奖
*/
sneaktower: true,
/**
* 屏蔽动态类型
*
@@ -275,6 +281,12 @@ module.exports = Object.freeze({
*/
blockword: ["脚本", "抽奖号", "钓鱼"],
/**
* 转发并评论
* - 评论内容与转发内容相同
*/
is_repost_then_chat: false,
/**
* 转发评语
*/
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "lottery-auto-script",
"version": "2.4.5",
"version": "2.4.7",
"description": "自动参与B站动态抽奖",
"main": "main.js",
"scripts": {