mirror of
https://github.com/shanmiteko/LotteryAutoScript.git
synced 2026-07-22 21:13:47 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6dbb9854c8 | ||
|
|
2fbd292e7a | ||
|
|
484f2e9ba9 | ||
|
|
266ecf75a9 | ||
|
|
4d90d83b67 | ||
|
|
c56ec7a2c2 | ||
|
|
aa9cb68c81 | ||
|
|
dd1b1db76a | ||
|
|
86e6b7dbc9 | ||
|
|
731b8475ec | ||
|
|
043fee21e7 | ||
|
|
ae34c691b1 | ||
|
|
7496bc58a8 | ||
|
|
7c455aff9c | ||
|
|
ef969bb2c2 | ||
|
|
0cbacd6ddf | ||
|
|
da75c8c17b | ||
|
|
548ad4b589 | ||
|
|
922dd989bc | ||
|
|
c486abf0ed | ||
|
|
4bbbfc89a7 | ||
|
|
aba17ed0ad | ||
|
|
5a23043466 | ||
|
|
76f715248d | ||
|
|
0d4185d02a | ||
|
|
2ff4ec812b | ||
|
|
20c423fc09 | ||
|
|
6851f29f75 |
@@ -37,5 +37,5 @@ jobs:
|
||||
with:
|
||||
file: "dist/*.zip"
|
||||
delete_file: "dist/*.zip"
|
||||
tag_name: "v*.*.*"
|
||||
tag_name: "v2"
|
||||
overwrite: true
|
||||
|
||||
@@ -3,6 +3,7 @@ node_modules/
|
||||
tests/
|
||||
dyids/
|
||||
dist/
|
||||
.env
|
||||
*.log
|
||||
package-lock.json
|
||||
env.js
|
||||
|
||||
@@ -1,5 +1,57 @@
|
||||
<!-- markdownlint-disable MD036 MD024-->
|
||||
# CHANGELOG
|
||||
## 主要变化(2.4.9)
|
||||
* 2fbd292 feat: 自动评语中可用up主昵称`${uname}`变量(#118)
|
||||
|
||||
_如果之前版本小于上一版本,请查看[CHANGELOG](CHANGELOG.md)变更说明_
|
||||
|
||||
## 主要变化(2.4.8)
|
||||
* 266ecf7 feat: 添加Qmsg酱推送(#115)
|
||||
* 4d90d83 feat: 日志细节优化
|
||||
* c56ec7a merge: 更新readme(#110)
|
||||
|
||||
_如果之前版本小于上一版本,请查看[CHANGELOG](CHANGELOG.md)变更说明_
|
||||
|
||||
## 主要变化(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)
|
||||
* da75c8c feat: 增加设置屏蔽动态类型`block_dynamic_type`(#99)
|
||||
* 548ad4b fix: pushplus更新域名(#93)
|
||||
|
||||
_如果之前版本小于上一版本,请查看[CHANGELOG](CHANGELOG.md)变更说明_
|
||||
|
||||
## 主要变化(2.4.4)
|
||||
* c486abf fix: 黑名单不起作用(#92)
|
||||
|
||||
_如果之前版本小于上一版本,请查看[CHANGELOG](CHANGELOG.md)变更说明_
|
||||
|
||||
## 主要变化(2.4.3)
|
||||
* aba17ed feat: 提示关键词修改建议
|
||||
* 5a23043 feat: 只通过是否点赞判断时点赞
|
||||
* 76f7152 fix: 黑名单匹配(#90)
|
||||
* 0d4185d fix(Searcher): getLotteryInfoByUID(#89)
|
||||
|
||||
_如果之前版本小于上一版本,请查看[CHANGELOG](CHANGELOG.md)变更说明_
|
||||
|
||||
## 主要变化(2.4.2)
|
||||
* 20c423f fix: "公共黑名单"显示错误(#87)
|
||||
* 6851f29 fix: 描述中出现undefined(#88)
|
||||
|
||||
_如果之前版本小于上一版本,请查看[CHANGELOG](CHANGELOG.md)变更说明_
|
||||
|
||||
## 主要变化(2.4.1)
|
||||
* 0ba6ace feat: check_if_duplicated可同时使用多种方式
|
||||
* dd99426 fix: 只转已关注功能失效
|
||||
|
||||
@@ -266,29 +266,31 @@ $ tree
|
||||
|
||||
以下是支持的推送方式
|
||||
|
||||
| Name | 归属 | 属性 | 说明 |
|
||||
| :---------------: | :--------------------------------------------------------------------------------: | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `SCKEY` | 微信server酱推送(于2021/4月下线) | 非必须 | server酱的微信通知[官方文档](http://sc.ftqq.com/3.version) |
|
||||
| `SENDKEY` | 微信server酱(Turbo版)推送 | 非必须 | [获取SENDKEY](https://sct.ftqq.com/sendkey) [选择消息通道](https://sct.ftqq.com/forward) |
|
||||
| `BARK_PUSH` | [BARK推送](https://apps.apple.com/us/app/bark-customed-notifications/id1403753865) | 非必须 | IOS用户下载BARK这个APP,填写内容是app提供的`设备码`,例如:<https://api.day.app/123> ,那么此处的设备码就是`123`,再不懂看 [这个图](https://gitee.com/shanmite/LotteryAutoScript/raw/main/doc/pic/bark.jpg)(注:支持自建填完整链接即可) |
|
||||
| `BARK_SOUND` | [BARK推送](https://apps.apple.com/us/app/bark-customed-notifications/id1403753865) | 非必须 | bark推送声音设置,例如`choo`,具体值请在`bark`-`推送铃声`-`查看所有铃声` |
|
||||
| `TG_BOT_TOKEN` | telegram推送 | 非必须 | tg推送(需设备可连接外网),`TG_BOT_TOKEN`和`TG_USER_ID`两者必需,填写自己申请[@BotFather](https://t.me/BotFather)的Token,如`10xxx4:AAFcqxxxxgER5uw` , [具体教程](doc/TG_PUSH.md) |
|
||||
| `TG_USER_ID` | telegram推送 | 非必须 | tg推送(需设备可连接外网),`TG_BOT_TOKEN`和`TG_USER_ID`两者必需,填写[@getuseridbot](https://t.me/getuseridbot)中获取到的纯数字ID, [具体教程](doc/TG_PUSH.md) |
|
||||
| `TG_PROXY_HOST` | Telegram 代理的 IP | 非必须 | 代理类型为 http。例子:http代理 <http://127.0.0.1:1080> 则填写 127.0.0.1 |
|
||||
| `TG_PROXY_PORT` | Telegram 代理的端口 | 非必须 | 例子:http代理 <http://127.0.0.1:1080> 则填写 1080 |
|
||||
| `DD_BOT_TOKEN` | 钉钉推送 | 非必须 | 钉钉推送(`DD_BOT_TOKEN`和`DD_BOT_SECRET`两者必需)[官方文档](https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq) ,只需`https://oapi.dingtalk.com/robot/send?access_token=XXX` 等于`=`符号后面的XXX即可 |
|
||||
| `DD_BOT_SECRET` | 钉钉推送 | 非必须 | (`DD_BOT_TOKEN`和`DD_BOT_SECRET`两者必需) ,密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的`SECXXXXXXXXXX`等字符 , 注:钉钉机器人安全设置只需勾选`加签`即可,其他选项不要勾选,再不懂看 [这个图](https://gitee.com/shanmite/LotteryAutoScript/raw/main/doc/pic/DD_bot.png) |
|
||||
| `IGOT_PUSH_KEY` | iGot推送 | 非必须 | iGot聚合推送,支持多方式推送,确保消息可达。 [参考文档](https://wahao.github.io/Bark-MP-helper ) |
|
||||
| `QQ_SKEY` | 酷推(Cool Push)推送 | 非必须 | 推送所需的Skey,登录后获取Skey [参考文档](https://cp.xuthus.cc/) |
|
||||
| `QQ_MODE` | 酷推(Cool Push)推送 | 非必须 | 推送方式(send或group或者wx,默认send) [参考文档](https://cp.xuthus.cc/) |
|
||||
| `QYWX_KEY` | 企业微信推送 | 非必须 | 密钥,企业微信推送 webhook 后面的 key [详见官方说明文档](https://work.weixin.qq.com/api/doc/90000/90136/91770) |
|
||||
| `PUSH_PLUS_TOKEN` | pushplus推送 | 非必须 | 微信扫码登录后一对一推送或一对多推送下面的token(您的Token) [官方网站](http://pushplus.hxtrip.com/) |
|
||||
| `PUSH_PLUS_USER` | pushplus推送 | 非必须 | 一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码)注:(1、需订阅者扫描二维码 2、如果您是创建群组所属人,也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送),只填`PUSH_PLUS_TOKEN`默认为一对一推送 |
|
||||
| `SMTP_HOST` | 电子邮件 | 非必须 | smtp服务器的主机名 如: `smtp.qq.com` |
|
||||
| `SMTP_PORT` | 电子邮件 | 非必须 | smtp服务器的端口 如: `465` |
|
||||
| `SMTP_USER` | 电子邮件 | 非必须 | 发送方的电子邮件 如: `xxxxxxxxx@qq.com` |
|
||||
| `SMTP_PASS` | 电子邮件 | 非必须 | smtp服务对应的授权码 |
|
||||
| `SMTP_TO_USER` | 电子邮件 | 非必须 | 接收方电子邮件 |
|
||||
| Name | 归属 | 说明 |
|
||||
| :---------------: | :--------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `SCKEY` | 微信server酱推送(于2021/4月下线) | server酱的微信通知[官方文档](http://sc.ftqq.com/3.version) |
|
||||
| `SENDKEY` | 微信server酱(Turbo版)推送 | [获取SENDKEY](https://sct.ftqq.com/sendkey) [选择消息通道](https://sct.ftqq.com/forward) |
|
||||
| `BARK_PUSH` | [BARK推送](https://apps.apple.com/us/app/bark-customed-notifications/id1403753865) | IOS用户下载BARK这个APP,填写内容是app提供的`设备码`,例如:<https://api.day.app/123> ,那么此处的设备码就是`123`,再不懂看 [这个图](https://gitee.com/shanmite/LotteryAutoScript/raw/main/doc/pic/bark.jpg)(注:支持自建填完整链接即可) |
|
||||
| `BARK_SOUND` | [BARK推送](https://apps.apple.com/us/app/bark-customed-notifications/id1403753865) | bark推送声音设置,例如`choo`,具体值请在`bark`-`推送铃声`-`查看所有铃声` |
|
||||
| `TG_BOT_TOKEN` | telegram推送 | tg推送(需设备可连接外网),`TG_BOT_TOKEN`和`TG_USER_ID`两者必需,填写自己申请[@BotFather](https://t.me/BotFather)的Token,如`10xxx4:AAFcqxxxxgER5uw` , [具体教程](doc/TG_PUSH.md) |
|
||||
| `TG_USER_ID` | telegram推送 | tg推送(需设备可连接外网),`TG_BOT_TOKEN`和`TG_USER_ID`两者必需,填写[@getuseridbot](https://t.me/getuseridbot)中获取到的纯数字ID, [具体教程](doc/TG_PUSH.md) |
|
||||
| `TG_PROXY_HOST` | Telegram 代理的 IP | 代理类型为 http。例子:http代理 <http://127.0.0.1:1080> 则填写 127.0.0.1 |
|
||||
| `TG_PROXY_PORT` | Telegram 代理的端口 | 例子:http代理 <http://127.0.0.1:1080> 则填写 1080 |
|
||||
| `DD_BOT_TOKEN` | 钉钉推送 | 钉钉推送(`DD_BOT_TOKEN`和`DD_BOT_SECRET`两者必需)[官方文档](https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq) ,只需`https://oapi.dingtalk.com/robot/send?access_token=XXX` 等于`=`符号后面的XXX即可 |
|
||||
| `DD_BOT_SECRET` | 钉钉推送 | (`DD_BOT_TOKEN`和`DD_BOT_SECRET`两者必需) ,密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的`SECXXXXXXXXXX`等字符 , 注:钉钉机器人安全设置只需勾选`加签`即可,其他选项不要勾选,再不懂看 [这个图](https://gitee.com/shanmite/LotteryAutoScript/raw/main/doc/pic/DD_bot.png) |
|
||||
| `IGOT_PUSH_KEY` | iGot推送 | iGot聚合推送,支持多方式推送,确保消息可达。 [参考文档](https://wahao.github.io/Bark-MP-helper ) |
|
||||
| `QQ_SKEY` | 酷推(Cool Push)推送 | 推送所需的Skey,登录后获取Skey [参考文档](https://cp.xuthus.cc/) |
|
||||
| `QQ_MODE` | 酷推(Cool Push)推送 | 推送方式(send或group或者wx,默认send) [参考文档](https://cp.xuthus.cc/) |
|
||||
| `QYWX_KEY` | 企业微信推送 | 密钥,企业微信推送 webhook 后面的 key [详见官方说明文档](https://work.weixin.qq.com/api/doc/90000/90136/91770) |
|
||||
| `PUSH_PLUS_TOKEN` | pushplus推送 | 微信扫码登录后一对一推送或一对多推送下面的token(您的Token) [官方网站](http://pushplus.hxtrip.com/) |
|
||||
| `PUSH_PLUS_USER` | pushplus推送 | 一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码)注:(1、需订阅者扫描二维码 2、如果您是创建群组所属人,也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送),只填`PUSH_PLUS_TOKEN`默认为一对一推送 |
|
||||
| `QMSG_KEY` | [Qmsg酱](https://qmsg.zendee.cn)私聊推送 | [Qmsg注册](https://qmsg.zendee.cn/login.html) |
|
||||
| `QMSG_QQ` | 私聊消息推送接口,指定需要接收消息的QQ | 指定的QQ号必须在你的[管理台](https://qmsg.zendee.cn/me.html)已添加 |
|
||||
| `SMTP_HOST` | 电子邮件 | smtp服务器的主机名 如: `smtp.qq.com` |
|
||||
| `SMTP_PORT` | 电子邮件 | smtp服务器的端口 如: `465` |
|
||||
| `SMTP_USER` | 电子邮件 | 发送方的电子邮件 如: `xxxxxxxxx@qq.com` |
|
||||
| `SMTP_PASS` | 电子邮件 | smtp服务对应的授权码 |
|
||||
| `SMTP_TO_USER` | 电子邮件 | 接收方电子邮件 |
|
||||
|
||||
----------------------------------------
|
||||
|
||||
@@ -301,5 +303,6 @@ $ tree
|
||||
## Awesome
|
||||
相关项目
|
||||
|
||||
- [LotteryAutoScript_Station](https://github.com/spiritLHL/LotteryAutoScript_Station) - @spiritLHL
|
||||
- [sync_lottery](https://github.com/spiritLHL/sync_lottery) - @spiritLHL
|
||||
- [LotteryAutoScript_Station](https://github.com/spiritLHL/LotteryAutoScript_Station) - [@spiritLHL](https://github.com/spiritLHL)
|
||||
- [sync_lottery](https://github.com/spiritLHL/sync_lottery) - [@spiritLHL](https://github.com/spiritLHL)
|
||||
- [BDSF](https://github.com/spiritLHL/BDSF) - [@spiritLHL](https://github.com/spiritLHL)
|
||||
|
||||
@@ -61,6 +61,8 @@ module.exports = Object.freeze({
|
||||
IGOT_PUSH_KEY: "",
|
||||
PUSH_PLUS_TOKEN: "",
|
||||
PUSH_PLUS_USER: "",
|
||||
QMSG_KEY: "",
|
||||
QMSG_QQ: "",
|
||||
SMTP_HOST: "",
|
||||
SMTP_PORT: "",
|
||||
SMTP_USER: "",
|
||||
|
||||
+38
-18
@@ -6,28 +6,48 @@ const bili = require('./net/bili')
|
||||
|
||||
/**
|
||||
* 是否中奖
|
||||
* @param {number} num
|
||||
*/
|
||||
async function isMe() {
|
||||
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}中@了你(${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) {
|
||||
@@ -46,7 +66,7 @@ async function isMe() {
|
||||
desp += '----------------------------------------------------------------\n\n'
|
||||
desp += `发生时间: ${new Date(timestamp * 1000).toLocaleString()}\n\n`
|
||||
desp += `用户: ${sender_uid}\n\n`
|
||||
desp += `私信你(${global_var.get("myUID")})说:\n${content}\n\n`
|
||||
desp += `私信你(https://space.bilibili.com/${global_var.get("myUID")})说:\n${content}\n\n`
|
||||
desp += `[直达链接](https://message.bilibili.com/#/whisper/mid${sender_uid})\n\n`
|
||||
desp += '----------------------------------------------------------------\n\n'
|
||||
}
|
||||
@@ -75,7 +95,7 @@ async function isMe() {
|
||||
if (desp) {
|
||||
desp += '中奖了别忘给脚本(https://github.com/shanmiteko/LotteryAutoScript)点一个Star哦, 赞助一两块也不是不可以_(:з」∠)_\n\n'
|
||||
log.info('可能中奖了', desp);
|
||||
await sendNotify('可能中奖了', desp);
|
||||
await sendNotify(`帐号${num}可能中奖了`, desp);
|
||||
} else {
|
||||
log.info('中奖检测', "暂未中奖");
|
||||
}
|
||||
|
||||
+81
-42
@@ -103,11 +103,12 @@ class Monitor extends Searcher {
|
||||
|
||||
if (len) {
|
||||
let
|
||||
status = 0,
|
||||
is_exception = 0,
|
||||
is_outof_maxfollow = 0;
|
||||
is_outof_maxfollow = 0,
|
||||
relayed_nums = 0;
|
||||
for (const [index, lottery] of shuffle(allLottery).entries()) {
|
||||
let status = 0;
|
||||
|
||||
let is_shutdown = false;
|
||||
if (
|
||||
is_outof_maxfollow
|
||||
&& lottery.uid.length
|
||||
@@ -121,7 +122,8 @@ class Monitor extends Searcher {
|
||||
let { ts } = await bili.getLotteryNotice(lottery.dyid);
|
||||
const ts_10 = Date.now() / 1000;
|
||||
if (ts < 0) {
|
||||
return 6001
|
||||
status = 6001
|
||||
break;
|
||||
}
|
||||
if (ts < ts_10) {
|
||||
log.info('过滤', '已过开奖时间')
|
||||
@@ -140,7 +142,8 @@ class Monitor extends Searcher {
|
||||
if (minfollower > 0) {
|
||||
const followerNum = await bili.getUserInfo(lottery.uid[0]);
|
||||
if (followerNum < 0) {
|
||||
return 7001
|
||||
status = 7001
|
||||
break;
|
||||
}
|
||||
if (followerNum < minfollower) {
|
||||
log.info('过滤', `粉丝数(${followerNum})小于指定数量`)
|
||||
@@ -165,6 +168,8 @@ class Monitor extends Searcher {
|
||||
status = await this.go(lottery)
|
||||
switch (status) {
|
||||
case 0:
|
||||
relayed_nums += 1
|
||||
break;
|
||||
case 1002:
|
||||
case 1003:
|
||||
case 1004:
|
||||
@@ -190,17 +195,20 @@ class Monitor extends Searcher {
|
||||
case 2001:
|
||||
case 3001:
|
||||
case 5001:
|
||||
return status
|
||||
is_shutdown = true
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_shutdown) break
|
||||
|
||||
d_storage.updateDyid(lottery.dyid)
|
||||
|
||||
await delay(wait * (Math.random() + 0.5));
|
||||
}
|
||||
log.info('抽奖', '开始转发下一组动态');
|
||||
log.info('抽奖', `本轮共转发${relayed_nums}条`);
|
||||
return is_exception
|
||||
|| is_outof_maxfollow
|
||||
|| 0
|
||||
|| status
|
||||
} else {
|
||||
log.info('抽奖', '无未转发抽奖');
|
||||
return 0
|
||||
@@ -215,8 +223,9 @@ class Monitor extends Searcher {
|
||||
* @property {boolean} isOfficialLottery 是否官方抽奖
|
||||
* @property {string} relay_chat 转发词
|
||||
* @property {string} ctrl 定位@
|
||||
* @property {string} rid 评论标识
|
||||
* @property {string} [rid] 评论标识
|
||||
* @property {number} chat_type 评论类型
|
||||
* @property {string} [chat] 评论词
|
||||
*/
|
||||
/**
|
||||
* @returns {Promise<LotteryOptions[]>}
|
||||
@@ -236,7 +245,7 @@ class Monitor extends Searcher {
|
||||
/** 所有抽奖信息 */
|
||||
let alllotteryinfo = [];
|
||||
const
|
||||
{ check_if_duplicated, set_lottery_info_url, key_words, model, chatmodel, 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, chat: chats, relay: relays, block_dynamic_type, max_create_time, is_imitator, only_followed, at_users, blockword, blacklist, use_public_blacklist } = config,
|
||||
now_ts = Date.now() / 1000;
|
||||
|
||||
/**
|
||||
@@ -300,15 +309,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
|
||||
}
|
||||
}
|
||||
|
||||
/* 超过指定时间退出 */
|
||||
@@ -338,9 +349,32 @@ class Monitor extends Searcher {
|
||||
isSendChat =
|
||||
(is_imitator && lottery_info_type === 'uid' && chatmodel !== '00')
|
||||
|| (hasOfficialLottery && chatmodel[0] === '1')
|
||||
|| (!hasOfficialLottery && chatmodel[1] === '1');
|
||||
|| (!hasOfficialLottery && chatmodel[1] === '1'),
|
||||
{ blacklist: remote_blacklist } = use_public_blacklist === false
|
||||
? { blacklist: "" }
|
||||
: global_var.get("remoteconfig"),
|
||||
/**
|
||||
* 获取黑名单并去重合并
|
||||
* @type {string[]}
|
||||
*/
|
||||
new_blacklist = remote_blacklist
|
||||
? [
|
||||
...new Set([...blacklist.split(','),
|
||||
...remote_blacklist.split(',')])
|
||||
]
|
||||
: blacklist.split(','),
|
||||
keys = [dyid, m_uid, ori_uid];
|
||||
|
||||
log.debug("筛选动态", { real_uid, mIsFollowed, oriIsFollowed, realIsFollowed, needAt, needTopic, isRelayDynamic, key_words, has_key_words, blockword, isBlock, isLottery, isSendChat })
|
||||
log.debug("筛选动态", { real_uid, mIsFollowed, oriIsFollowed, realIsFollowed, needAt, needTopic, type, isRelayDynamic, key_words, has_key_words, blockword, isBlock, isLottery, isSendChat })
|
||||
|
||||
if (block_dynamic_type.includes(type)) {
|
||||
log.warn("筛选动态", `屏蔽动态类型 ${type}`)
|
||||
return false
|
||||
}
|
||||
|
||||
if (!has_key_words && description) {
|
||||
log.warn("筛选动态", `无关键词动态的描述: ${description}\n\n考虑是否修改设置key_words:\n${key_words.join('\n')}`)
|
||||
}
|
||||
|
||||
/**屏蔽词 */
|
||||
if (isBlock) {
|
||||
@@ -356,25 +390,21 @@ class Monitor extends Searcher {
|
||||
return false
|
||||
}
|
||||
|
||||
const
|
||||
{ blacklist: remote_blacklist } = use_public_blacklist === false
|
||||
? { blacklist: "" }
|
||||
: global_var.get("remoteconfig"),
|
||||
/* 获取黑名单并去重合并 */
|
||||
new_blacklist = remote_blacklist
|
||||
? [
|
||||
...new Set([...blacklist.split(','),
|
||||
...remote_blacklist.split(',')])
|
||||
].join()
|
||||
: blacklist;
|
||||
|
||||
if ((new RegExp(dyid + '|' + m_uid + '|' + ori_uid)).test(new_blacklist)) {
|
||||
log.info("筛选动态", `公共黑名单用户(https://t.bilibili.com/${dyid})`)
|
||||
if (
|
||||
new_blacklist.some(id => keys.some(key => {
|
||||
if (key + '' === id) {
|
||||
log.info("筛选动态", `黑名单匹配(${id})(https://t.bilibili.com/${dyid})`)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}))
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
if (isLottery) {
|
||||
const { uname_map = {} } = global_var.get("remoteconfig")
|
||||
let onelotteryinfo = {};
|
||||
|
||||
onelotteryinfo.isOfficialLottery = hasOfficialLottery;
|
||||
@@ -390,7 +420,8 @@ class Monitor extends Searcher {
|
||||
|
||||
let
|
||||
/**转发评语 */
|
||||
RandomStr = getRandomOne(config.relay),
|
||||
RandomStr = getRandomOne(relays)
|
||||
.replaceAll('${uname}', uname_map[real_uid] || uname),
|
||||
/**控制字段 */
|
||||
new_ctrl = [];
|
||||
|
||||
@@ -447,7 +478,11 @@ class Monitor extends Searcher {
|
||||
: 0;
|
||||
|
||||
/* 是否评论 */
|
||||
if (isSendChat) onelotteryinfo.rid = rid;
|
||||
if (isSendChat) {
|
||||
onelotteryinfo.rid = rid
|
||||
onelotteryinfo.chat = getRandomOne(chats)
|
||||
.replaceAll('${uname}', uname_map[real_uid] || uname)
|
||||
}
|
||||
|
||||
alllotteryinfo.push(onelotteryinfo);
|
||||
} else {
|
||||
@@ -492,8 +527,8 @@ class Monitor extends Searcher {
|
||||
|
||||
let status = 0
|
||||
const
|
||||
{ uid, dyid, chat_type, rid, relay_chat, ctrl } = option,
|
||||
{ chat, check_if_duplicated } = config;
|
||||
{ uid, dyid, chat_type, rid, relay_chat, ctrl, chat } = option,
|
||||
{ check_if_duplicated, is_repost_then_chat } = config;
|
||||
|
||||
/* 评论 */
|
||||
if (rid && chat_type) {
|
||||
@@ -501,7 +536,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 : chat,
|
||||
chat_type
|
||||
)
|
||||
)
|
||||
|
||||
if (status) {
|
||||
@@ -530,7 +569,7 @@ class Monitor extends Searcher {
|
||||
}
|
||||
|
||||
/* 点赞 */
|
||||
if (!check_if_duplicated || check_if_duplicated === 2) {
|
||||
if (!check_if_duplicated) {
|
||||
status = await retryfn(
|
||||
5,
|
||||
[1, 2, 3],
|
||||
|
||||
+28
-31
@@ -75,10 +75,10 @@ function parseDynamicCard(dynamic_detail_card) {
|
||||
obj.ctrl = (extend_json && strToJson(extend_json).ctrl) || [];
|
||||
/* 是否有官方抽奖 */
|
||||
obj.hasOfficialLottery = extension && extension.lott && true;
|
||||
/* 转发者的描述 后两个分别是视频动态的描述和视频本身的描述*/
|
||||
/* 转发者的描述 纯文字内容 图片动态描述 后两个分别是视频动态的描述和视频本身的描述*/
|
||||
obj.description =
|
||||
(item && (item.content + item.description))
|
||||
|| (cardToJson.dynamic + cardToJson.desc)
|
||||
(item && (item.content || '' + item.description || ''))
|
||||
|| (cardToJson.dynamic || '' + cardToJson.desc || '')
|
||||
|| '';
|
||||
if (obj.type === 1) {
|
||||
const { origin_extension, origin } = cardToJson
|
||||
@@ -98,8 +98,8 @@ function parseDynamicCard(dynamic_detail_card) {
|
||||
obj.origin_uname = (user && (user.name || user.uname)) || '';
|
||||
/* 被转发者的描述 */
|
||||
obj.origin_description =
|
||||
(item && (item.content + item.description))
|
||||
|| (originToJson.dynamic + originToJson.desc)
|
||||
(item && (item.content || '' + item.description || ''))
|
||||
|| (originToJson.dynamic || '' + originToJson.desc || '')
|
||||
|| '';
|
||||
}
|
||||
|
||||
@@ -241,38 +241,35 @@ class Searcher {
|
||||
}
|
||||
})
|
||||
.reduce(async (pre, cur) => {
|
||||
const results = await pre
|
||||
, { origin_dynamic_id } = cur;
|
||||
|
||||
const card = await bili.getOneDynamicByDyid(origin_dynamic_id)
|
||||
|
||||
if (card) {
|
||||
await utils.delay(get_dynamic_detail_wait)
|
||||
|
||||
const { is_liked } = parseDynamicCard(card)
|
||||
let
|
||||
results = await pre,
|
||||
{ origin_dynamic_id } = cur,
|
||||
is_liked = false;
|
||||
|
||||
if (!check_if_duplicated || check_if_duplicated === 2) {
|
||||
const card = await bili.getOneDynamicByDyid(origin_dynamic_id)
|
||||
log.info('获取动态', `查看源动态(${origin_dynamic_id})是否点赞 (${length--})`)
|
||||
if (is_liked) {
|
||||
log.info('获取动态', `动态(${origin_dynamic_id})已转发过`)
|
||||
} else {
|
||||
return [...results, {
|
||||
lottery_info_type: 'uid',
|
||||
create_time: cur.origin_create_time,
|
||||
is_liked,
|
||||
uids: [cur.uid, cur.origin_uid],
|
||||
uname: cur.origin_uname,
|
||||
ctrl: [],
|
||||
dyid: cur.origin_dynamic_id,
|
||||
rid: cur.origin_rid_str,
|
||||
des: cur.origin_description,
|
||||
type: cur.orig_type,
|
||||
hasOfficialLottery: cur.origin_hasOfficialLottery
|
||||
}]
|
||||
if (card) {
|
||||
({ is_liked } = parseDynamicCard(card))
|
||||
}
|
||||
await utils.delay(get_dynamic_detail_wait)
|
||||
}
|
||||
|
||||
return results
|
||||
results.push({
|
||||
lottery_info_type: 'uid',
|
||||
create_time: cur.origin_create_time,
|
||||
is_liked,
|
||||
uids: [cur.uid, cur.origin_uid],
|
||||
uname: cur.origin_uname,
|
||||
ctrl: [],
|
||||
dyid: cur.origin_dynamic_id,
|
||||
rid: cur.origin_rid_str,
|
||||
des: cur.origin_description,
|
||||
type: cur.orig_type,
|
||||
hasOfficialLottery: cur.origin_hasOfficialLottery
|
||||
})
|
||||
|
||||
return results
|
||||
}, Promise.resolve([]))
|
||||
|
||||
log.info('获取动态', `成功获取用户${UID}的动态信息`);
|
||||
|
||||
+29
-2
@@ -49,8 +49,8 @@ const config = {
|
||||
* 符合js正则表达式的字符串
|
||||
*/
|
||||
key_words: [
|
||||
"[抽奖送]",
|
||||
"[转关评]"
|
||||
"[抽奖送揪]|福利",
|
||||
"[转关评粉]|参与"
|
||||
],
|
||||
|
||||
/**
|
||||
@@ -78,6 +78,27 @@ const config = {
|
||||
*/
|
||||
check_if_duplicated: 1,
|
||||
|
||||
/**
|
||||
* 偷塔模式不检查是否重复转发
|
||||
* * 偷塔模式: 临近开奖时参与抽奖
|
||||
*/
|
||||
sneaktower: true,
|
||||
|
||||
/**
|
||||
* 屏蔽动态类型
|
||||
*
|
||||
* | 动态类型 | type值 |
|
||||
* | :------- |:----- |
|
||||
* | 转发 | `1` |
|
||||
* | 含图片 | `2` |
|
||||
* | 无图纯文字 | `4` |
|
||||
* | 视频 | `8` |
|
||||
* | 番剧 | `512` |
|
||||
* | 活动 | `2048` |
|
||||
* | 专栏 | `64` |
|
||||
*/
|
||||
block_dynamic_type: [0],
|
||||
|
||||
/**
|
||||
* - 动态创建时间
|
||||
* - 多少天前
|
||||
@@ -245,6 +266,12 @@ const config = {
|
||||
*/
|
||||
blockword: ["脚本", "抽奖号", "钓鱼"],
|
||||
|
||||
/**
|
||||
* 转发并评论
|
||||
* - 评论内容与转发内容相同
|
||||
*/
|
||||
is_repost_then_chat: false,
|
||||
|
||||
/**
|
||||
* 转发评语
|
||||
*/
|
||||
|
||||
+72
-21
@@ -60,6 +60,10 @@ let IGOT_PUSH_KEY = '';
|
||||
let PUSH_PLUS_TOKEN = '';
|
||||
let PUSH_PLUS_USER = '';
|
||||
|
||||
// ===========================================QMSG===========================================
|
||||
let QMSG_KEY = '';
|
||||
let QMSG_QQ = '';
|
||||
|
||||
// ===========================================邮件推送===============================================
|
||||
let SMTP_HOST = '';
|
||||
let SMTP_PORT = '';
|
||||
@@ -136,6 +140,14 @@ if (process.env.PUSH_PLUS_USER) {
|
||||
PUSH_PLUS_USER = process.env.PUSH_PLUS_USER;
|
||||
}
|
||||
|
||||
if (process.env.QMSG_KEY) {
|
||||
QMSG_KEY = process.env.QMSG_KEY;
|
||||
}
|
||||
|
||||
if (process.env.QMSG_QQ) {
|
||||
QMSG_QQ = process.env.QMSG_QQ;
|
||||
}
|
||||
|
||||
if (process.env.SMTP_HOST) {
|
||||
SMTP_HOST = process.env.SMTP_HOST;
|
||||
}
|
||||
@@ -177,6 +189,8 @@ async function sendNotify(text, desp, params = {}) {
|
||||
iGotNotify(text, desp, params),
|
||||
//QQ酷推
|
||||
coolPush(text, desp),
|
||||
// Qmsg
|
||||
qmsg(text, desp),
|
||||
//电子邮件
|
||||
email(text, desp)
|
||||
])
|
||||
@@ -216,8 +230,8 @@ function serverNotify(text, desp) {
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
log.error('发送通知', 'server酱 发送通知调用API失败!!')
|
||||
throw new Error(err);
|
||||
log.error('发送通知', 'server酱 发送通知调用API失败!!' + err)
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -258,8 +272,8 @@ function serverNotifyTurbo(text, desp) {
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
log.error('发送通知', 'server酱(Turbo版) 发送通知调用API失败!!')
|
||||
throw new Error(err);
|
||||
log.error('发送通知', 'server酱(Turbo版) 发送通知调用API失败!!' + err)
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -314,8 +328,8 @@ function coolPush(text, desp) {
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
log.error('发送通知', `酷推 发送${pushMode(QQ_MODE)}通知调用API失败!!`)
|
||||
throw new Error(err);
|
||||
log.error('发送通知', `酷推 发送${pushMode(QQ_MODE)}通知调用API失败!!${err}`)
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -356,9 +370,8 @@ function barkNotify(text, desp, params = {}) {
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
log.error('发送通知', 'Bark APP发送通知调用API失败!!');
|
||||
log.error('发送通知', 'Bark APP发送通知调用API失败!!' + err);
|
||||
resolve();
|
||||
throw new Error(err)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -404,9 +417,8 @@ function tgBotNotify(text, desp) {
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
log.error('发送通知', 'telegram发送通知消息失败!!')
|
||||
log.error('发送通知', 'telegram发送通知消息失败!!' + err)
|
||||
resolve()
|
||||
throw new Error(err)
|
||||
}
|
||||
}
|
||||
if (TG_PROXY_HOST && TG_PROXY_PORT) {
|
||||
@@ -467,8 +479,8 @@ function ddBotNotify(text, desp) {
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
log.error('发送通知', '钉钉发送通知消息失败!!')
|
||||
throw new Error(err);
|
||||
log.error('发送通知', '钉钉发送通知消息失败!!' + err)
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
} else if (DD_BOT_TOKEN) {
|
||||
@@ -506,9 +518,8 @@ function ddBotNotify(text, desp) {
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
log.error('发送通知', '钉钉发送通知消息失败!!');
|
||||
log.error('发送通知', '钉钉发送通知消息失败!!' + err);
|
||||
resolve();
|
||||
throw new Error(err)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -552,9 +563,8 @@ function qywxBotNotify(text, desp) {
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
log.error('发送通知', '企业微信发送通知消息失败!!');
|
||||
log.error('发送通知', '企业微信发送通知消息失败!!' + err);
|
||||
resolve();
|
||||
throw new Error(err)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -604,9 +614,8 @@ function iGotNotify(text, desp, params = {}) {
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
log.error('发送通知', 'iGot 发送通知调用API失败!!')
|
||||
log.error('发送通知', 'iGot 发送通知调用API失败!!' + err)
|
||||
resolve();
|
||||
throw new Error(err)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -621,7 +630,7 @@ function pushPlusNotify(text, desp) {
|
||||
if (PUSH_PLUS_TOKEN) {
|
||||
send({
|
||||
method: 'POST',
|
||||
url: 'https://pushplus.hxtrip.com/send',
|
||||
url: 'http://www.pushplus.plus/send',
|
||||
contents: {
|
||||
token: PUSH_PLUS_TOKEN,
|
||||
title: text,
|
||||
@@ -650,9 +659,8 @@ function pushPlusNotify(text, desp) {
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
log.error('发送通知', `push+发送${PUSH_PLUS_USER ? '一对多' : '一对一'}通知消息失败!!`)
|
||||
log.error('发送通知', `push+发送${PUSH_PLUS_USER ? '一对多' : '一对一'}通知消息失败!!${err}`)
|
||||
resolve();
|
||||
throw new Error(err)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -662,6 +670,49 @@ function pushPlusNotify(text, desp) {
|
||||
})
|
||||
}
|
||||
|
||||
async function qmsg(text, desp) {
|
||||
return new Promise(resolve => {
|
||||
if (QMSG_KEY) {
|
||||
send({
|
||||
method: 'POST',
|
||||
url: 'https://qmsg.zendee.cn/send/' + QMSG_KEY,
|
||||
contents: {
|
||||
msg: text + "\n\n" + desp,
|
||||
qq: QMSG_QQ
|
||||
},
|
||||
config: {
|
||||
retry: false
|
||||
},
|
||||
headers: {
|
||||
accept: 'application/json, text/plain, */*',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
success: res => {
|
||||
try {
|
||||
const data = JSON.parse(res.body);
|
||||
if (data.code === 200) {
|
||||
log.info('发送通知', `qmsg发送通知消息完成。`)
|
||||
} else {
|
||||
log.error('发送通知', `qmsg通知消息失败: ${data.reason}`)
|
||||
}
|
||||
} catch (e) {
|
||||
log.error('发送通知', e);
|
||||
} finally {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
log.error('发送通知', `qmsg通知消息失败!!` + err)
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
} else {
|
||||
log.debug('发送通知', '您未提供qmsg推送所需的QMSG_KEY,取消qmsg推送消息通知');
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function email(text, desp) {
|
||||
if (SMTP_HOST && SMTP_PORT && SMTP_USER && SMTP_PASS && SMTP_TO_USER) {
|
||||
try {
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
+34
-21
@@ -103,11 +103,7 @@ const utils = {
|
||||
*/
|
||||
delay(time = 1000) {
|
||||
utils.log.info('时延', `${~~time}ms`);
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, time);
|
||||
});
|
||||
return new Promise(resolve => setTimeout(resolve, time));
|
||||
},
|
||||
/**
|
||||
* 计数器 0..Infinity
|
||||
@@ -185,13 +181,19 @@ const utils = {
|
||||
},
|
||||
/**日志 */
|
||||
log: {
|
||||
level: 3,
|
||||
_level: 3,
|
||||
_colors: [
|
||||
chalk.hex('#64B3FF'), chalk.grey, chalk.hex('#FFA500'),
|
||||
chalk.hex('#0070BB'), chalk.hex('#48BB31'), chalk.hex('#BBBB23'), chalk.hex('#FF0006')
|
||||
],
|
||||
_iso_time: () => new Date(Date.now() + 288e5).toISOString().slice(0, -1) + '+08'
|
||||
,
|
||||
/**
|
||||
* 初始化默认level为3
|
||||
*/
|
||||
init() {
|
||||
let _level = Number(process.env.LOTTERY_LOG_LEVEL);
|
||||
this.level = isNaN(_level) ? 3 : _level;
|
||||
this._level = isNaN(_level) ? 3 : _level;
|
||||
},
|
||||
/**
|
||||
* @param {String|Array<String>} msg
|
||||
@@ -211,26 +213,36 @@ const utils = {
|
||||
const
|
||||
colors = ['red', 'yellow', 'green', 'cyan', 'blue', 'magenta'],
|
||||
colorsCount = colors.length;
|
||||
|
||||
this.proPrint(msg.map(it => it.split('').map((l, i) => chalk[colors[i % colorsCount]](l)).join('')), '\n')
|
||||
},
|
||||
/**
|
||||
* @param {number} done
|
||||
* @param {number} total
|
||||
* @param {number} size
|
||||
*/
|
||||
progress_bar(done, total, size = 30) {
|
||||
let perc = done >= total ? 1 : done / total,
|
||||
bar = ~~(perc * size),
|
||||
status_bar = `\r[${"=".repeat(bar) + ">" + " ".repeat(size - bar)}] ${(perc * 100 + ' ').slice(0, 4)}%`
|
||||
process.stdout.write(status_bar)
|
||||
},
|
||||
debug(context, msg) {
|
||||
if (this.level > 3) {
|
||||
if (this._level > 3) {
|
||||
if (msg instanceof Object) msg = JSON.stringify(msg, null, 4);
|
||||
this.proPrint([chalk.hex('#64B3FF')(`[${new Date(Date.now() + 288e5).toISOString()}]`), chalk.grey("[Debug]"), chalk.hex('#FFA500')(`[${context}]`), chalk.hex('#0070BB')(`[\n${msg}\n]`)])
|
||||
this.proPrint([this._colors[0](`[${this._iso_time()}]`), this._colors[1]("[Debug]"), this._colors[2](`[${context}]`), this._colors[3](`[\n${msg}\n]`)])
|
||||
}
|
||||
},
|
||||
info(context, msg) {
|
||||
if (this.level > 2)
|
||||
this.proPrint([chalk.hex('#64B3FF')(`[${new Date(Date.now() + 288e5).toISOString()}]`), chalk.grey("[Info]"), chalk.hex('#FFA500')(`[${context}]`), chalk.hex('#48BB31')(`[${msg}]`)])
|
||||
if (this._level > 2)
|
||||
this.proPrint([this._colors[0](`[${this._iso_time()}]`), this._colors[1]("[Info]"), this._colors[2](`[${context}]`), this._colors[4](`[${msg}]`)])
|
||||
},
|
||||
warn(context, msg) {
|
||||
if (this.level > 1)
|
||||
this.proPrint([chalk.hex('#64B3FF')(`[${new Date(Date.now() + 288e5).toISOString()}]`), chalk.grey("[Warn]"), chalk.hex('#FFA500')(`[${context}]`), chalk.hex('#BBBB23')(`[\n${msg}\n]`)])
|
||||
if (this._level > 1)
|
||||
this.proPrint([this._colors[0](`[${this._iso_time()}]`), this._colors[1]("[Warn]"), this._colors[2](`[${context}]`), this._colors[5](`[\n${msg}\n]`)])
|
||||
},
|
||||
error(context, msg) {
|
||||
if (this.level > 0)
|
||||
this.proPrint([chalk.hex('#64B3FF')(`[${new Date(Date.now() + 288e5).toISOString()}]`), chalk.grey("[Error]"), chalk.hex('#FFA500')(`[${context}]`), chalk.hex('#FF0006')(`[\n${msg}\n]`)])
|
||||
if (this._level > 0)
|
||||
this.proPrint([this._colors[0](`[${this._iso_time()}]`), this._colors[1]("[Error]"), this._colors[2](`[${context}]`), this._colors[6](`[\n${msg}\n]`)])
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -248,12 +260,13 @@ const utils = {
|
||||
redirect: true,
|
||||
retry: false
|
||||
},
|
||||
success: ({ resStream }) => {
|
||||
success: ({ headers, resStream }) => {
|
||||
const total_len = Number(headers["content-length"]) || 16000000;
|
||||
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.progress_bar(recv_length, total_len)
|
||||
})
|
||||
resStream.pipe(wtbs)
|
||||
wtbs.on('finish', () => {
|
||||
@@ -261,7 +274,7 @@ const utils = {
|
||||
resolve()
|
||||
}).on('error', error => {
|
||||
wtbs.destroy()
|
||||
resolve(error)
|
||||
reject(error)
|
||||
})
|
||||
},
|
||||
failure: error => {
|
||||
@@ -290,12 +303,12 @@ const utils = {
|
||||
if (body.node_msg) utils.log.info('公告', '\n' + body.node_msg + '\n');
|
||||
resolve(body.config)
|
||||
} catch (error) {
|
||||
resolve(JSON.parse('{}'))
|
||||
resolve({})
|
||||
}
|
||||
},
|
||||
failure: err => {
|
||||
utils.log.error('获取远程设置', '获取远程设置错误: ' + err);
|
||||
resolve(JSON.parse('{}'));
|
||||
resolve({})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -65,7 +65,7 @@ async function main() {
|
||||
case 'check':
|
||||
log.info('中奖检测', '检查是否中奖');
|
||||
loop_wait = check_loop_wait;
|
||||
await isMe();
|
||||
await isMe(NUMBER);
|
||||
break;
|
||||
case 'clear':
|
||||
if (CLEAR) {
|
||||
@@ -88,7 +88,7 @@ async function main() {
|
||||
}
|
||||
} else {
|
||||
log.error('Cookie已失效', '切换账号时不要点击退出账号而应直接删除Cookie退出')
|
||||
return ''
|
||||
return
|
||||
}
|
||||
} else {
|
||||
return '请查看README文件, 在env.js指定位置填入cookie'
|
||||
|
||||
+34
-2
@@ -63,8 +63,8 @@ module.exports = Object.freeze({
|
||||
* 符合js正则表达式的字符串
|
||||
*/
|
||||
key_words: [
|
||||
"[抽奖送]",
|
||||
"[转关评]"
|
||||
"[抽奖送揪]|福利",
|
||||
"[转关评粉]|参与"
|
||||
],
|
||||
|
||||
/**
|
||||
@@ -92,6 +92,27 @@ module.exports = Object.freeze({
|
||||
*/
|
||||
check_if_duplicated: 1,
|
||||
|
||||
/**
|
||||
* 偷塔模式不检查是否重复转发
|
||||
* * 偷塔模式: 临近开奖时参与抽奖
|
||||
*/
|
||||
sneaktower: true,
|
||||
|
||||
/**
|
||||
* 屏蔽动态类型
|
||||
*
|
||||
* | 动态类型 | type值 |
|
||||
* | :------- |:----- |
|
||||
* | 转发 | `1` |
|
||||
* | 含图片 | `2` |
|
||||
* | 无图纯文字 | `4` |
|
||||
* | 视频 | `8` |
|
||||
* | 番剧 | `512` |
|
||||
* | 活动 | `2048` |
|
||||
* | 专栏 | `64` |
|
||||
*/
|
||||
block_dynamic_type: [0],
|
||||
|
||||
/**
|
||||
* - 动态创建时间
|
||||
* - 多少天前
|
||||
@@ -244,6 +265,7 @@ module.exports = Object.freeze({
|
||||
at_users: [['转发抽奖娘', 294887687], ['你的工具人老公', 100680137]],
|
||||
|
||||
/**
|
||||
* - 动态dyid或UID
|
||||
* - 英文逗号分隔 如: 1,2,3
|
||||
*/
|
||||
blacklist: '',
|
||||
@@ -259,13 +281,23 @@ module.exports = Object.freeze({
|
||||
*/
|
||||
blockword: ["脚本", "抽奖号", "钓鱼"],
|
||||
|
||||
/**
|
||||
* 转发并评论
|
||||
* - 评论内容与转发内容相同
|
||||
*/
|
||||
is_repost_then_chat: false,
|
||||
|
||||
/**
|
||||
* 转发评语
|
||||
* 支持变量${uname}
|
||||
*/
|
||||
relay: ['转发动态'],
|
||||
|
||||
/**
|
||||
* 评论内容
|
||||
* 支持变量${uname}
|
||||
* @example
|
||||
* "祝${uname}早日百大!"
|
||||
*/
|
||||
chat: [
|
||||
'[OK]', '[星星眼]', '[歪嘴]', '[喜欢]', '[偷笑]', '[笑]', '[喜极而泣]', '[辣眼睛]', '[吃瓜]', '[奋斗]',
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lottery-auto-script",
|
||||
"version": "2.4.1",
|
||||
"version": "2.4.9",
|
||||
"description": "自动参与B站动态抽奖",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user