diff --git a/.github/Issue_Template_CN.md b/.github/ISSUE_TEMPLATE/Issue_Template_CN.md similarity index 100% rename from .github/Issue_Template_CN.md rename to .github/ISSUE_TEMPLATE/Issue_Template_CN.md diff --git a/.github/Issue_Template_EN.md b/.github/ISSUE_TEMPLATE/Issue_Template_EN.md similarity index 100% rename from .github/Issue_Template_EN.md rename to .github/ISSUE_TEMPLATE/Issue_Template_EN.md diff --git a/.github/workflows/build_image_bhp.yml b/.github/workflows/build_image_bhp.yml new file mode 100644 index 0000000..1bf3977 --- /dev/null +++ b/.github/workflows/build_image_bhp.yml @@ -0,0 +1,22 @@ +name: "BiliHelper-personal Docker Image Buildx Stable Github" +on: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + name: Build BiliHelper-personal Docker Image Build Stable Github + steps: + - name: Checkout master + uses: actions/checkout@master + - name: Build and publish image + uses: ilteoood/docker_buildx@master + with: + publish: true + imageName: lkeme/bilihelper-personal + dockerFile: docker/Dockerfile + platform: linux/amd64,linux/arm64,linux/arm/v7 + # platform: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8 + tag: latest + dockerUser: ${{ secrets.DOCKER_USERNAME }} + dockerPassword: ${{ secrets.DOCKER_PASSWORD }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index dc788fa..e72cf9c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,14 +17,23 @@ gen /configs/ /tests/ config -/conf/user*.conf +/conf/user*.ini *.log Traits/ README1.md -conf/user.conf -conf/user1.conf -/conf/user.conf -/conf/test.conf -/conf/test1.conf +conf/user.ini +conf/user1.ini +/conf/user.ini +/conf/test.ini +/conf/test1.ini /log/ -/src/backup/ \ No newline at end of file +/src/backup/ +script.php + +# ignore all files in lib/ +task/* +# except for .gitkeep +!.gitkeep +# ignore TODO file in root directory,not subdir/TODO +/TODO +/Todo \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 87482ad..4a6ad3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,198 @@ # Release Notes + # 本项目Log +[comment]: <> (
) + +[comment]: <> ( 更新历史latest) + +[comment]: <> (
) + +## v0.9.7.210714 alpha (2021-07-14) + +### Added + +- 添加脚本模式 `php index.php -?` +- + +### Changed + +- 省略 +- + +### Fixed + +- 省略 +- + +### Remarks + +- 注意配置文件有些许改动 +- 注意需要重新进行`composer update`操作 +- + +## v0.9.6.210625 alpha (2021-06-25) + +### Added + +- + +### Changed + +- 优化动态过滤 +- 优化过滤关键字 +- 优化短信登录流程 +- + +### Fixed + +- 修复动态转发 +- + +### Remarks + +- 注意配置文件有些许改动 +- + +## v0.9.5.210624 alpha (2021-06-24) + +### Added + +- + +### Changed + +- 更新动态转发 +- 更新基础环境参数 +- + +### Fixed + +- + +### Remarks + +- 注意配置文件有些许改动 +- + +## v0.9.4.210623 alpha (2021-06-23) + +### Added + +- + +### Changed + +- 更新部分仓库文件 +- 更新基础环境参数 +- + +### Fixed + +- 修复PC端银瓜子兑换硬币 +- 修复主站投币任务 +- 修复点亮勋章特殊情况 +- + +### Remarks + +- + +## v0.9.3.210616 alpha (2021-06-16) + +### Added + +- 任务排程 +- + +### Changed + +- 配置热更新 +- + +### Fixed + +- 修复弹幕 +- 修复独立监控 +- + +### Remarks + +- + +## v0.9.2.210602 alpha (2021-06-02) + +### Added + +- + +### Changed + +- 更新DcokerFile +- 更新每日点亮勋章(100亲密度) +- + +### Fixed + +- + +### Remarks + +- + +## v0.9.1.210518 alpha (2021-05-18) + +### Added + +- + +### Changed + +- 删除过期活动 +- 更新风纪委员 +- 更新银瓜子兑换硬币 +- 更新点亮勋章 +- 更新部分日志打印输出 +- + +### Fixed + +- 修复已知BUG +- + +### Remarks + +- + +## v0.9.0.210517 alpha (2021-05-17) + +### Added + +- 重大更新 +- + +### Changed + +- 懒得写描述 +- + +### Fixed + +- 配置文件有变动 +- + +### Remarks + +- 请重新配置 +- + ## v0.8.1.210423 alpha (2021-04-23) ### Added - ### Changed + - 更新天选敏感词 - 更新活动列表 - 优化直播间心跳 @@ -21,12 +207,14 @@ ## v0.8.0.210327 alpha (2021-03-27) ### Added + - 增加直播扭蛋抽奖活动(可自定义) - 增加主站九宫格抽奖活动(可自定义) - 增加多个推送消息通道 - ### Changed + - 更新过滤词独立 - 更新请求中心 - 更新日志打印 @@ -43,13 +231,15 @@ - ### Fixed + - 修复小心心心跳错误 - 修复部分推送错误 - 修复银瓜子换银币日志错误 - ### Remarks -- 结构大更新,务必进行Composer等操作 + +- 结构大更新,务必进行Composer等操作 - ## v0.6.7.201117 alpha (2020-11-17) @@ -58,6 +248,7 @@ - ### Changed + - 调整WS读取数据大小 - 调整弹幕发送时间 - 更新天选之子日志打印 @@ -65,52 +256,61 @@ - ### Fixed + - 修复小心心心跳错误 -- +- ## v0.6.5.200808 alpha (2020-08-08) ### Added + - 添加小心心支持 - 添加活动抽奖 - ### Changed + - 去掉无效双端观看 - 过期小心心赠送 ### Fixed + - 修复小心心心跳错误 - ## v0.6.0.200730 alpha (2020-07-30) ### Added + - 添加小心心支持 -- +- ### Changed + - 更新天选过滤关键词 - ### Fixed + - 修复节奏风暴逻辑错误 - ## v0.5.0.200625 alpha (2020-06-25) ### Added + - 添加破产机(赔到破产) - 添加推送KEY到期通知 - 添加天选自动取关(测试) - 添加收益统计 - 添加关注投币模式 -- +- ### Changed + - 更新部分信息输出 - 修改日志打印前缀 -- 更新活跃弹幕延迟 +- 更新活跃弹幕延迟 - 重构部分统计代码 - 更新视频投币逻辑 - 更新实物抽奖API @@ -119,10 +319,11 @@ - ### Fixed + - 修复日志输出错误 - 修复每日送礼异常 - 修复赛事逻辑错误 -- 修复部分已知问题 +- 修复部分已知问题 - ## v0.4.0.200505 alpha (2020-05-05) @@ -131,15 +332,17 @@ - ### Changed + - 关闭已结束的LPL赛事任务 - ### Fixed + - 修复日志回调空格解析异常 - 修复节奏风暴回显过滤错误 - 修复活动抽奖重复请求问题 - 修复主站任务获取AID异常 -- +- ## v0.4.0.200428 alpha (2020-04-28) @@ -150,49 +353,58 @@ - ### Fixed + - 修复赠送礼物逻辑 - ## v0.4.0.200426 alpha (2020-04-26) ### Added + - 赛事助手 (签到、分享) -- +- ### Changed - ### Fixed + - 修复休眠机制 - ## v0.3.0.200425 alpha (2020-04-25) ### Added + - 添加调用函数 - ### Changed + - 取消一处请求头 - ### Fixed + - 修复休眠机制 - ## v0.3.0.200424 alpha (2020-04-24) ### Added + - 抽出独立小黑屋 - 提前引入BV2AV - ### Changed + - 优化监控推送 - 优化登录参数 - 同步黑屋提醒 ### Fixed + - 修复监控输出 - @@ -205,6 +417,7 @@ - ### Fixed + - 修复节奏风暴回显 - 修复分区监控异常 - 修复获取勋章异常 @@ -216,10 +429,12 @@ - ### Changed + - 去除主监控 - ### Fixed + - 修复风暴回显过滤 - 修复一处舰长处理 - 修复中奖记录通知 @@ -236,6 +451,7 @@ - ### Fixed + - 修复备用监控无法获取 - 修复获取分区ID异常 - @@ -243,6 +459,7 @@ ## v0.3.0.200404 alpha (2020-04-04) ### Added + - 添加ISSUE模板 - 添加处理监控端命令 - @@ -251,6 +468,7 @@ - ### Fixed + - 修复主监控内存溢出 - 修复活动礼物提醒 - @@ -258,10 +476,12 @@ ## v0.3.0.200318 alpha (2020-03-18) ### Added + - 添加日常任务定时执行(AM10:00) -- +- ### Changed + - Sleep->Schedule - 优化异常通知 - 优化异常重试数 @@ -270,6 +490,7 @@ - ### Fixed + - 修复日志回调 - 修复response为null - 修复PC端心跳 @@ -279,13 +500,15 @@ ## v0.3.0.200316 alpha (2020-03-16) ### Added + - 添加异常处理(通知) -- +- ### Changed - ### Fixed + - 修复活跃弹幕 - 修复风纪测试 - 修复部分已知 @@ -294,16 +517,19 @@ ## v0.3.0.200312 alpha (2020-03-12) ### Added + - 引入风纪 (不稳定测试) - 引入新库 (需要重新Composer) -- +- ### Changed + - 重构部分公用方法 - 重构CURL请求 - ### Fixed + - 修复登录繁忙 - 修复实物抽奖 - 修复日志输出 @@ -319,18 +545,21 @@ - ### Fixed + - 修复节奏风暴 - 修复双端心跳 -- +- ## v0.2.0.200224 alpha (2020-02-24) ### Added + - 新增工具类 - 引入新库(需要重新Composer) -- +- ### Changed + - 优化数据过滤条件 - 更新PC端心跳API - 优化实物抽奖 @@ -338,9 +567,10 @@ - ### Fixed + - 修复内存异常 - 修复重复投币 -- +- ## v0.2.0.200214 alpha (2020-02-14) @@ -348,10 +578,12 @@ - ### Changed + - 优化实物抽奖流程 - 优化延迟礼物抽奖 ### Fixed + - 修正部分函数名称 - 尝试减少静态占用 - @@ -359,20 +591,24 @@ ## v0.2.0.200208 alpha (2020-02-08) ### Added + - 哔哩哔哩漫画助手(可选) - ### Changed + - 补充部分过滤关键字 - ### Fixed + - 修复一处内存异常 - ## v0.1.0.200111 alpha (2020-01-11) ### Added + - 天选时刻奖品过滤 - @@ -385,6 +621,7 @@ ## v0.1.0.200128 alpha (2020-01-28) ### Added + - 增加推送消息过滤 - @@ -392,12 +629,14 @@ - ### Fixed + - 修复抽奖推送错误 - ## v0.1.0.200111 alpha (2020-01-11) ### Added + - 天选时刻奖品过滤 - @@ -410,40 +649,47 @@ ## v0.1.0.200103 alpha (2020-01-03) ### Added + - 增加并发请求 - ### Changed + - 更新抽奖逻辑 - 更新部分API - 减少重复请求 - ### Fixed + - 修复部分回显错误 - ## v0.1.0.200101 alpha (2020-01-01) ### Added + - 任务逻辑引入协程 ### Changed - ### Fixed + - 修复礼物赠送异常 - ## v0.1.0.191227 alpha (2019-12-27) ### Added + - 新增备用官方分区监控 - 新增按勋章亲密度赠送 - 新增天选时刻获奖推送 - ### Changed + - 优化部分架构 - 优化独立监控 - 优化监控逻辑 @@ -453,6 +699,7 @@ - ### Fixed + - 修复部分日志显示 - 修复数据统计异常 - 修复瓜子宝箱异常 @@ -462,7 +709,7 @@ - 修复部分已知BUG - 修复获奖推送通知 - 修复休眠中心异常 -- 修复礼物赠送异常 +- 修复礼物赠送异常 - ## v0.0.5.191223 alpha (2019-12-23) diff --git a/DOC.md b/DOC.md index 85879fc..d6ed401 100644 --- a/DOC.md +++ b/DOC.md @@ -1,68 +1,24 @@ +

-

+[comment]: <> (

) -

- - -

+
+[![](https://img.shields.io/badge/Author-Lkeme-blueviolet "作者")](https://github.com/lkeme/ ) +![](https://img.shields.io/badge/dynamic/json?label=GitHub%20Followers&query=%24.data.totalSubs&url=https%3A%2F%2Fapi.spencerwoo.com%2Fsubstats%2F%3Fsource%3Dgithub%26queryKey%3Dlkeme&labelColor=282c34&color=181717&logo=github&longCache=true "关注数量") +![](https://img.shields.io/github/stars/lkeme/BiliHelper-personal.svg?style=plastic&logo=appveyor "Star数量") +![](https://img.shields.io/github/forks/lkeme/BiliHelper-personal.svg?style=plastic&logo=stackshare "Fork数量") +![](https://img.shields.io/github/contributors/lkeme/BiliHelper-personal "贡献者") -# BiliHelper - -B 站直播实用脚本 - -## 功能组件 - -|plugin |version |description | -|--------------------|--------------------|--------------------| -|Login |21.03.27 |账号登录 | -|Schedule |21.03.27 |休眠控制 | -|MainSite |21.03.27 |主站助手 | -|Daily |21.03.27 |每日礼包 | -|Heart |21.03.27 |双端心跳 | -|DailyTask |21.03.27 |每日任务 | -|Silver |21.03.27 |银瓜子宝箱 | -|Barrage |21.03.27 |活跃弹幕 | -|Silver2Coin |21.03.27 |银瓜子换硬币 | -|GiftSend |21.03.27 |礼物赠送 | -|Judge |21.03.27 |风纪 | -|GroupSignIn |21.03.27 |友爱社签到 | -|ManGa |21.03.27 |漫画签到分享 | -|GameMatch |21.03.27 |赛事签到分享 | -|GiftHeart |21.03.27 |心跳礼物 | -|MaterialObject |21.03.27 |实物抽奖 | -|AloneTcpClient |21.03.27 |独立监控 | -|ZoneTcpClient |21.03.27 |分区监控 | -|StormRaffle |21.03.27 |节奏风暴 | -|GiftRaffle |21.03.27 |活动礼物 | -|PkRaffle |21.03.27 |大乱斗 | -|GuardRaffle |21.03.27 |舰长总督 | -|AnchorRaffle |21.03.27 |天选时刻 | -|AwardRecord |21.03.27 |获奖通知 | -|Statistics |21.03.27 |数据统计 | -|Competition |21.03.27 |赛事竞猜 | -|SmallHeart |21.03.27 |小心心 | -|ActivityLottery |21.03.27 |主站活动 | -|CapsuleLottery |21.03.27 |直播扭蛋活动 | -|Forward |21.03.27 |动态抽奖转发 | - -## 打赏赞助 - -![](https://i.loli.net/2019/07/13/5d2963e5cc1eb22973.png) - -> 待添加 - -## 未完成功能 - -|待续 | -|-----------| -|多用户 | +
## 环境依赖 +通常使用 `composer` 工具会自动检测以下依赖问题。 + |Requirement | |--------------------| -|PHP >=7.0 | +|PHP >=7.3 | |php_curl | |php_sockets | |php_openssl | @@ -70,83 +26,162 @@ B 站直播实用脚本 |php_zlib | |php_mbstring | -通常使用 `composer` 工具会自动检测上述依赖问题。 - ## Composer -* 项目 `composer.lock` 基于阿里云Composer镜像生成 -+ 阿里云(推荐) -``` + ++ [Composer 安装与使用](https://www.runoob.com/w3cnote/composer-install-and-usage.html) + ++ [Composer 下载](https://getcomposer.org/download/) + ++ 当前项目 `composer.lock` 基于阿里云 Composer镜像生成 + ++ 阿里云(全量镜像) + +```bash # 使用帮助 -https://developer.aliyun.com/composer +> https://developer.aliyun.com/composer # 使用命令 > composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ ``` -* 腾讯云(备用) + ++ 恢复默认镜像|Composer.phar加速下载 + +```bash +> composer config -g --unset repos.packagist + +> https://mirrors.cloud.tencent.com/composer/composer.phar +> https://mirrors.aliyun.com/composer/composer.phar ``` + +
+其余镜像 展开查看 +

++ cnpkg(全量镜像)
+```bash
 # 使用帮助
-https://mirrors.cloud.tencent.com/composer/
+> https://php.cnpkg.org/
 # 使用命令
-composer config -g repos.packagist composer https://mirrors.cloud.tencent.com/composer/
+> composer config -g repos.packagist composer https://php.cnpkg.org
 ```
 
++ 腾讯云(全量镜像)
 
+```bash
+# 使用帮助
+> https://mirrors.cloud.tencent.com/help/composer.html
+# 使用命令
+> composer config -g repos.packagist composer https://mirrors.cloud.tencent.com/composer/
+```
+
++ phpcomposer(全量镜像)
+
+```bash
+# 使用帮助
+> https://pkg.phpcomposer.com/
+# 使用命令
+> composer config -g repo.packagist composer https://packagist.phpcomposer.com
+```
+
++ 华为云(全量镜像)
+
+```bash
+# 使用帮助
+> https://mirrors.huaweicloud.com/repository/php/
+# 使用命令
+> composer config -g repos.packagist composer https://mirrors.huaweicloud.com/repository/php/
+```
+
++ 交通大学(非全量镜像)
+
+```bash
+# 使用帮助
+> https://packagist.mirrors.sjtug.sjtu.edu.cn/
+# 使用命令
+> composer config -g repos.packagist composer https://packagist.mirrors.sjtug.sjtu.edu.cn
+```
+
+
+
## 使用指南 - 1. 下载(克隆)项目代码,初始化项目 +1. 下载(克隆)项目代码,初始化项目 + ``` $ git clone https://github.com/lkeme/BiliHelper-personal.git $ cd BiliHelper-personal/conf -$ cp user.conf.example user.conf +$ cp user.ini.example user.ini ``` - 2. 使用 [composer](https://getcomposer.org/download/) 工具进行安装 + +2. 使用 [composer](https://getcomposer.org/download/) 工具进行安装 + ``` $ composer install ``` - 3. 按照说明修改配置文件 `user.conf` + +[comment]: <> (composer dump-autoload (-o)) + +[comment]: <> (composer dumpautoload (-o)) + +3. 按照说明修改配置文件 `user.ini` + ``` # 默认只需填写帐号密码,按需求开启其他功能即可 ``` - 4. 运行测试 + +4. 运行测试 + ``` $ php index.php ``` -> 以下是`多账户多开方案`,单个账户可以无视 - 5. 复制一份example配置文件,修改账号密码即可 - ``` - $ php index.php example.conf - ``` - 6. 请保证配置文件存在,否则默认加载`user.conf`配置文件 -

+> 以下是`多账户多开方案`,单个账户可以无视 + +5. 复制一份example配置文件,修改账号密码即可 + + ``` + $ php index.php example.ini + ``` + +6. 请保证配置文件存在,否则默认加载`user.ini`配置文件 + +

+ +[comment]: <> (

) ## Docker使用指南 - 1. 安装好[Docker](https://yeasy.gitbooks.io/docker_practice/content/install/) - 2. 直接命令行拉取镜像后运行 - +1. 安装好[Docker](https://yeasy.gitbooks.io/docker_practice/content/install/) +2. 直接命令行拉取镜像后运行 ### 传入的参数方式有两种(二选一,如果同时传入则优先选择配置文件) - 通过环境变量进行传入 ```shell script - docker run -itd --rm -e USER_NAME=你的B站登录账号 -e USER_PASSWORD=你的B站密码 zsnmwy/bilihelper-personal +$ docker run -itd --rm -e USER_NAME=你的B站登录账号 -e USER_PASSWORD=你的B站密码 lkeme/bilihelper-personal ``` -- 通过配置文件进行传入 +- 通过配置文件进行传入(能保留登录状态,自定义配置) -1. 下载[配置文件](https://raw.githubusercontent.com/lkeme/BiliHelper-personal/master/conf/user.conf.example) +1. 下载[配置文件](https://raw.githubusercontent.com/lkeme/BiliHelper-personal/master/conf/user.ini.example) 2. 修改 3. 通过下面的命令进行挂载并运行 ```shell script -docker run -itd --rm -v /path/to/your/confFileName.conf:/app/conf/user.conf zsnmwy/bilihelper-personal +$ docker run -itd --rm -v /path/to/your/confFileName.ini:/app/conf/user.ini lkeme/bilihelper-personal ``` -``` -相关参数 +- 使用github镜像加速 +```bash +$ -e MIRRORS=0 # 使用 github.com +$ -e MIRRORS=1 # 使用 ghproxy.com +$ -e MIRRORS=2 # 使用 github.com.cnpmjs.org +``` + +- 相关参数 + +```ps -it 前台运行 -itd 后台运行 -v 本地文件:容器内部文件 ==> 挂载本地文件到容器中。本地文件路径随便变,容器内部文件路径不能变。 @@ -155,20 +190,29 @@ docker run -itd --rm -v /path/to/your/confFileName.conf:/app/conf/user.conf zsnm - 注意: Docker镜像已经包含了所有所需的运行环境,无需在本地环境弄composer。每次启动容器时,都会与项目进行同步以确保版本最新。 ## 升级指南 + > 注意新版本的配置文件是否变动,则需要重新覆盖配置文件,并重新填写设置 - 1. 进入项目目录 + +1. 进入项目目录 + ``` $ cd BiliHelper-personal ``` - 2. 拉取最新代码 + +2. 拉取最新代码 + ``` $ git pull ``` - 3. 更新依赖库 + +3. 更新依赖库 + ``` $ composer install ``` - 4. 如果使用 systemd 等,需要重启服务 + +4. 如果使用 systemd 等,需要重启服务 + ``` $ systemctl restart bilibili ``` @@ -178,10 +222,11 @@ $ systemctl restart bilibili 如果你将 BiliHelper-personal 部署到线上服务器时,则需要配置一个进程监控器来监测 `php index.php` 命令,在它意外退出时自动重启。 通常可以使用以下的方式 - - systemd (推荐) - - Supervisor - - screen (自用) - - nohup + +- systemd (推荐) +- Supervisor +- screen (自用) +- nohup ## systemd 脚本 @@ -189,7 +234,7 @@ $ systemctl restart bilibili # /usr/lib/systemd/system/bilibili.service [Unit] -Description=Bili Helper Manager +Description=BiliHelper Manager Documentation=https://github.com/lkeme/BiliHelper-personal After=network.target @@ -223,6 +268,7 @@ stdout_logfile=/tmp/bilibili.log |TelegramBot|https://core.telegram.org/bots/api| 示范如下 + ``` # Server酱 # 自行替换 @@ -235,10 +281,9 @@ APP_CALLBACK="https://api.telegram.org/bot/sendMessage?chat_id=& `{message}` 部分会自动替换成错误信息,接口采用 get 方式发送 - ## 直播间 ID 问题 -文件 `user.conf` 里 +文件 `user.ini` 里 `ROOM_ID` 配置,填写此项可以清空临过期礼物给指定直播间。 @@ -249,11 +294,13 @@ APP_CALLBACK="https://api.telegram.org/bot/sendMessage?chat_id=& `SOCKET_ROOM_ID` 配置,监控使用,暂时没用到。 通常可以在直播间页面的 url 获取到它 + ``` http://live.bilibili.com/9522051 ``` 长位直播间ID获取 + ``` https://api.live.bilibili.com/room/v1/Room/room_init?id=3 ``` @@ -261,24 +308,3 @@ https://api.live.bilibili.com/room/v1/Room/room_init?id=3 所有直播间号码小于 1000 的直播间为短号,部分4位直播间也为短号, 该脚本在每次启动会自动修正部分功能,特殊标注的请留意。 - -## 相关 - - > [BilibiliHelper](https://github.com/metowolf/BilibiliHelper) - - > [BiliHelper](https://github.com/lkeme/BiliHelper) - - > [Github](https://github.com/) - - -## License 许可证 - -BiliHelper is under the MIT license. - -本项目基于 MIT 协议发布,并增加了 SATA 协议。 - -当你使用了使用 SATA 的开源软件或文档的时候,在遵守基础许可证的前提下,你必须马不停蹄地给你所使用的开源项目 “点赞” ,比如在 GitHub 上 star,然后你必须感谢这个帮助了你的开源项目的作者,作者信息可以在许可证头部的版权声明部分找到。 - -本项目的所有代码文件、配置项,除另有说明外,均基于上述介绍的协议发布,具体请看分支下的 LICENSE。 - -此处的文字仅用于说明,条款以 LICENSE 文件中的内容为准。 diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 282022c..0000000 --- a/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM php:alpine - -MAINTAINER zsnmwy - -ENV USER_NAME='' \ - USER_PASSWORD='' \ - CONIFG_PATH='/app/conf/user.conf' \ - Green="\\033[32m" \ - Red="\\033[31m" \ - GreenBG="\\033[42;37m" \ - RedBG="\\033[41;37m" \ - Font="\\033[0m" \ - Green_font_prefix="\\033[32m" \ - Green_background_prefix="\\033[42;37m" \ - Font_color_suffix="\\033[0m" \ - Info="${Green}[信息]${Font}" \ - OK="${Green}[OK]${Font}" \ - Error="${Red}[错误]${Font}" - -WORKDIR /app - -#RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories -RUN docker-php-ext-install sockets - -RUN apk add --no-cache git && \ - git clone https://github.com/lkeme/BiliHelper-personal.git --depth=1 /app && \ - php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" && \ - php composer-setup.php && \ - php composer.phar install && \ - rm -r /var/cache/apk && \ - rm -r /usr/share/man - -ENTRYPOINT echo -e "\n ======== \n ${Info} ${GreenBG} 正使用 git pull 同步项目 ${Font} \n ======== \n" && \ - git pull && \ - echo -e "\n ======== \n ${Info} ${GreenBG} 安装/更新 项目运行依赖 ${Font} \n ======== \n" && \ - php composer.phar install && \ - echo -e "\n \n \n \n" && \ - if [[ -f ${CONIFG_PATH} ]]; then echo -e "\n ======== \n ${GreenBG} 正在使用外部配置文件 ${Font} \n ======== \n" && php index.php ; else echo -e "${OK} ${GreenBG} 正在使用传入的环境变量进行用户配置。\n 如果需要配置更多选择项,请通过挂载配置文件来传入。具体参考项目中的README。\n https://github.com/lkeme/BiliHelper-personal.git ${Font} \n ======== \n " && cp /app/conf/user.conf.example /app/conf/user.conf && sed -i ''"$(cat /app/conf/user.conf -n | grep "APP_USER=" | awk '{print $1}')"'c '"$(echo "APP_USER=${USER_NAME}")"'' ${CONIFG_PATH} && sed -i ''"$(cat /app/conf/user.conf -n | grep "APP_PASS=" | awk '{print $1}')"'c '"$(echo "APP_PASS=${USER_PASSWORD}")"'' ${CONIFG_PATH} && php index.php; fi diff --git a/README.md b/README.md index c26e1bc..078c81e 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,138 @@ -# BiliHelper -B 站直播实用脚本 +

-## 交流 +[comment]: <> (

) -Group: [55308141](https://jq.qq.com/?_wv=1027&k=5AIDaJg) | **仅用于BUG提交反馈** +
-## 公告 +[![](https://img.shields.io/badge/Author-Lkeme-blueviolet "作者")](https://github.com/lkeme/ ) +![](https://img.shields.io/badge/dynamic/json?label=GitHub%20Followers&query=%24.data.totalSubs&url=https%3A%2F%2Fapi.spencerwoo.com%2Fsubstats%2F%3Fsource%3Dgithub%26queryKey%3Dlkeme&labelColor=282c34&color=181717&logo=github&longCache=true "关注数量") +![](https://img.shields.io/github/stars/lkeme/BiliHelper-personal.svg?style=plastic&logo=appveyor "Star数量") +![](https://img.shields.io/github/forks/lkeme/BiliHelper-personal.svg?style=plastic&logo=stackshare "Fork数量") +![](https://img.shields.io/github/contributors/lkeme/BiliHelper-personal "贡献者") +![](https://img.shields.io/github/repo-size/lkeme/BiliHelper-personal?style=flat-square&label=files&color=cf8ef4&labelColor=373e4dl "文件大小") +[![Docker Pulls](https://img.shields.io/docker/pulls/lkeme/bilihelper-personal?style=flat-square)](https://hub.docker.com/r/lkeme/bilihelper-personal) -> Personal Edition **0.8.1.210423 alpha** +
+ +

+ + + + + + +

+ +## 公告通知 + +代码开源,本地化99.9%,项目不收集或使用任何敏感信息,兴趣所致,一切只为学习。 ```notice ---- 免费的东西总是得不到人的珍惜。 ---- 只有花大价钱去买到的东西,才会令人信任。 ``` +## 🖥️星图 -## 文档 -> 有疑问一定要先看看文档或Issue里是否存在相同的问题,再考虑其他渠道咨询。 +[![Stargazers over time](https://starchart.cc/lkeme/BiliHelper-personal.svg)](https://starchart.cc/lkeme/BiliHelper-personal) +[![Stargazers over time](https://starchart.cc/lkeme/BiliHelper.svg)](https://starchart.cc/lkeme/BiliHelper) + +## 功能组件 + +以下任务都是按设定周期自动执行,`true`为正常使用,`false`为暂停使用或抛弃。 + +| plugin | status | version | cycle | description | +|-----------------|--------|----------|--------|---------------------------------------------| +| CheckUpdate | true | 21.07.14 | 待整理 | 程序检查更新 | +| Login | true | 21.07.14 | 待整理 | 账号登录、刷新、维持 | +| Schedule | true | 21.07.14 | 待整理 | 控制插件运行周期 | +| MainSite | true | 21.07.14 | 待整理 | 投币、观看、分享视频 (速升6级不是梦) | +| DailyBag | true | 21.07.14 | 待整理 | 双端领取日常/周常礼包 | +| ManGa | true | 21.07.14 | 待整理 | 漫画签到、分享 | +| ActivityLottery | true | 21.07.14 | 待整理 | 主站活动九宫格抽奖 | +| Competition | true | 21.07.14 | 待整理 | 游戏赛事竞猜 | +| DoubleHeart | true | 21.07.14 | 待整理 | 双端心跳 (姥爷直播经验) | +| DailyTask | true | 21.07.14 | 待整理 | 直播每日任务(签到、观看) | +| Barrage | true | 21.07.14 | 待整理 | 保持活跃弹幕 | +| Silver2Coin | true | 21.07.14 | 待整理 | 银瓜子兑换硬币 | +| Judge | true | 21.07.14 | 待整理 | 风纪委员投票 | +| GiftSend | true | 21.07.14 | 待整理 | 礼物赠送、维持每日勋章亲密度 | +| GroupSignIn | true | 21.07.14 | 待整理 | 友爱社签到 | +| GiftHeart | true | 21.07.14 | 待整理 | 日常心跳每日礼包礼物 | +| SmallHeart | true | 21.07.14 | 待整理 | 直播挂机,每日24个小心心 | +| MaterialObject | true | 21.07.14 | 待整理 | 直播金色宝箱实物抽奖 | +| AloneTcpClient | true | 21.07.14 | 待整理 | 作者的独立直播监控(可支持本项目哦) | +| ZoneTcpClient | true | 21.07.14 | 待整理 | 官方的分区直播监控 | +| StormRaffle | true | 21.07.14 | 待整理 | 直播节奏风暴抽奖、亿元 | +| GiftRaffle | true | 21.07.14 | 待整理 | 直播礼物抽奖 | +| PkRaffle | true | 21.07.14 | 待整理 | 直播大乱斗抽奖 | +| GuardRaffle | true | 21.07.14 | 待整理 | 直播大航海抽奖 | +| AnchorRaffle | true | 21.07.14 | 待整理 | 直播天选时刻抽奖 | +| GiftRaffle | true | 21.07.14 | 待整理 | 直播礼物抽奖 | +| AwardRecord | true | 21.07.14 | 待整理 | 最新的中奖纪录通知 | +| Forward | true | 21.07.14 | 待整理 | 主站动态抽奖转发 | +| CapsuleLottery | true | 21.07.14 | 待整理 | 直播扭蛋活动抽奖 | +| PolishTheMedal | true | 21.07.14 | 待整理 | 每日自动点亮灰色勋章 | +| CapsuleLottery | true | 21.07.14 | 待整理 | 直播扭蛋活动抽奖 | +| VipPrivilege | true | 21.07.14 | 待整理 | 每月领取年度大会员特权(B币券、会员购优惠券) | +| BpConsumption | true | 21.07.14 | 待整理 | 每月消费使用年度大会员特权的B币券 | +| Statistics | true | 21.07.14 | 待整理 | 全局抽奖结果统计 | +| Silver | false | 21.03.27 | 待整理 | 直播银瓜子自动开启宝箱 | + + +## 交流反馈 + +Group: [55308141](https://jq.qq.com/?_wv=1027&k=5AIDaJg) | **请不要来问如何使用, 文档齐全, 仅用于BUG提交反馈** + +## 相关文档 + +有疑问一定要先看看文档或Issue里是否存在相同的问题,再考虑其他渠道咨询。 + +[comment]: <> (:cherry_blossom: :gift: :gift_heart: :confetti_ball:) * [使用文档 / DOC.md](./DOC.md) * [更新日志 / CHANGELOG.md](./CHANGELOG.md) * [配置文档 / WIKI.md](https://github.com/lkeme/BiliHelper-personal/wiki/%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%AF%A6%E8%A7%A3) * [常见问题 / WIKI.md](https://github.com/lkeme/BiliHelper-personal/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) -## 打赏 +## 打赏支持 -![](https://i.loli.net/2019/07/13/5d2963e5cc1eb22973.png) +如果觉得本项目好用,对你有所帮助,欢迎打赏支持本项目哦。 -## 效果 +

-![](https://i.loli.net/2019/07/13/5d296961a4bae41364.png) +[comment]: <> (![Image](https://i.loli.net/2019/07/13/5d2963e5cc1eb22973.png)) + +## 运行效果 + +效果图不代表当前版本,请以当前最新版本运行结果为准。 + +

+ +[comment]: <> (![Image](https://i.loli.net/2019/07/13/5d296961a4bae41364.png)) + +## 项目相关 + +* [BilibiliHelper](https://github.com/metowolf/BilibiliHelper) +* [BiliHelper](https://github.com/lkeme/BiliHelper) +* [Github](https://github.com/) + +## 致谢 + +感谢 `JetBrains` 提供优秀的IDE。 + + + + + +## License 许可证 + +BiliHelper is under the MIT license. + +本项目基于 MIT 协议发布,并增加了 SATA 协议。 + +当你使用了使用 SATA 的开源软件或文档的时候,在遵守基础许可证的前提下,你必须马不停蹄地给你所使用的开源项目 “点赞” ,比如在 GitHub 上 +star,然后你必须感谢这个帮助了你的开源项目的作者,作者信息可以在许可证头部的版权声明部分找到。 + +本项目的所有代码文件、配置项,除另有说明外,均基于上述介绍的协议发布,具体请看分支下的 LICENSE。 + +此处的文字仅用于说明,条款以 LICENSE 文件中的内容为准。 diff --git a/composer.json b/composer.json index 1ad3703..cb19581 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "B 站自动领瓜子、直播助手、直播挂机脚本、主站助手 - PHP 版(Personal)", "type": "project", "require": { - "php": ">=7.0.0", + "php": ">=7.3.0", "ext-curl": "*", "ext-openssl": "*", "ext-sockets": "*", @@ -13,12 +13,15 @@ "monolog/monolog": "^1.26.0", "bramus/monolog-colored-line-formatter": "^2.0.3", "clue/socket-raw": "^1.5.0", - "vlucas/phpdotenv": "^4.2.0", "amphp/amp": "^2.5.2", "guzzlehttp/guzzle": "^6.5.5", "mathieuviossat/arraytotexttable": "^1.0.8", "klkvsk/json-decode-stream": "^1.0", - "sven/file-config": "^3.1" + "sven/file-config": "^3.1", + "hassankhan/config": "^2.2", + "lkeme/inifile": "^3.4", + "adhocore/cli": "^0.9.0", + "vanilla/garden-cli": "^3.1" }, "license": "MIT", "authors": [ @@ -34,7 +37,10 @@ "BiliHelper\\Plugin\\": "src/plugin", "BiliHelper\\Util\\": "src/util", "BiliHelper\\Tool\\": "src/tool", - "BiliHelper\\Backup\\": "src/backup" - } + "BiliHelper\\Script\\": "src/script" + }, + "files": [ + "src/core/Helpers.php" + ] } } diff --git a/composer.lock b/composer.lock index 6f574d2..4ea622f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,80 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a9407272d4bb9ca1632a2aa728429bf0", + "content-hash": "0678ecd04eed6db66de4668ffffec283", "packages": [ + { + "name": "adhocore/cli", + "version": "0.9.0", + "source": { + "type": "git", + "url": "https://github.com/adhocore/php-cli.git", + "reference": "319c7dd0092c0346d9ad03366cc13d3491b57e34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/adhocore/php-cli/zipball/319c7dd0092c0346d9ad03366cc13d3491b57e34", + "reference": "319c7dd0092c0346d9ad03366cc13d3491b57e34", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ahc\\Cli\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jitendra Adhikari", + "email": "jiten.adhikary@gmail.com" + } + ], + "description": "Command line interface library for PHP", + "keywords": [ + "PHP7", + "argument-parser", + "argv-parser", + "cli", + "cli-action", + "cli-app", + "cli-color", + "cli-option", + "cli-writer", + "command", + "console", + "console-app", + "php-cli", + "stream-input", + "stream-output" + ], + "support": { + "issues": "https://github.com/adhocore/php-cli/issues", + "source": "https://github.com/adhocore/php-cli/tree/0.9.0" + }, + "funding": [ + { + "url": "https://paypal.me/ji10", + "type": "custom" + } + ], + "time": "2021-01-06T00:25:50+00:00" + }, { "name": "amphp/amp", "version": "v2.5.2", @@ -460,16 +532,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.8.1", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "35ea11d335fd638b5882ff1725228b3d35496ab1" + "reference": "dc960a912984efb74d0a90222870c72c87f10c91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/35ea11d335fd638b5882ff1725228b3d35496ab1", - "reference": "35ea11d335fd638b5882ff1725228b3d35496ab1", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91", + "reference": "dc960a912984efb74d0a90222870c72c87f10c91", "shasum": "", "mirrors": [ { @@ -535,22 +607,90 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.8.1" + "source": "https://github.com/guzzle/psr7/tree/1.8.2" }, - "time": "2021-03-21T16:25:00+00:00" + "time": "2021-04-26T09:17:50+00:00" }, { - "name": "klkvsk/json-decode-stream", - "version": "v1.0.2", + "name": "hassankhan/config", + "version": "2.2.0", "source": { "type": "git", - "url": "https://github.com/klkvsk/json-decode-stream.git", - "reference": "76cbcd9eb9f1860293b82b4f071e76826bc90c82" + "url": "https://github.com/hassankhan/config.git", + "reference": "62b0fd17540136efa94ab6b39f04044c6dc5e4a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/klkvsk/json-decode-stream/zipball/76cbcd9eb9f1860293b82b4f071e76826bc90c82", - "reference": "76cbcd9eb9f1860293b82b4f071e76826bc90c82", + "url": "https://api.github.com/repos/hassankhan/config/zipball/62b0fd17540136efa94ab6b39f04044c6dc5e4a7", + "reference": "62b0fd17540136efa94ab6b39f04044c6dc5e4a7", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.36 || ~5.7 || ~6.5 || ~7.5", + "scrutinizer/ocular": "~1.1", + "squizlabs/php_codesniffer": "~2.2", + "symfony/yaml": "~3.4" + }, + "suggest": { + "symfony/yaml": "~3.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Noodlehaus\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Hassan Khan", + "homepage": "http://hassankhan.me/", + "role": "Developer" + } + ], + "description": "Lightweight configuration file loader that supports PHP, INI, XML, JSON, and YAML files", + "homepage": "http://hassankhan.me/config/", + "keywords": [ + "config", + "configuration", + "ini", + "json", + "microphp", + "unframework", + "xml", + "yaml", + "yml" + ], + "support": { + "issues": "https://github.com/hassankhan/config/issues", + "source": "https://github.com/hassankhan/config/tree/2.2.0" + }, + "time": "2020-12-07T16:04:15+00:00" + }, + { + "name": "klkvsk/json-decode-stream", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/klkvsk/json-decode-stream.git", + "reference": "831b5310b42b51705a2d6ae5353bba7aaa302358" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/klkvsk/json-decode-stream/zipball/831b5310b42b51705a2d6ae5353bba7aaa302358", + "reference": "831b5310b42b51705a2d6ae5353bba7aaa302358", "shasum": "", "mirrors": [ { @@ -595,9 +735,9 @@ ], "support": { "issues": "https://github.com/klkvsk/json-decode-stream/issues", - "source": "https://github.com/klkvsk/json-decode-stream/tree/v1.0.2" + "source": "https://github.com/klkvsk/json-decode-stream/tree/v1.0.3" }, - "time": "2021-03-23T14:26:50+00:00" + "time": "2021-06-29T23:00:36+00:00" }, { "name": "laminas/laminas-servicemanager", @@ -694,16 +834,16 @@ }, { "name": "laminas/laminas-stdlib", - "version": "3.3.1", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-stdlib.git", - "reference": "d81c7ffe602ed0e6ecb18691019111c0f4bf1efe" + "reference": "e89c2268c9cad25099f562f7f015c28c5dd383c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/d81c7ffe602ed0e6ecb18691019111c0f4bf1efe", - "reference": "d81c7ffe602ed0e6ecb18691019111c0f4bf1efe", + "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/e89c2268c9cad25099f562f7f015c28c5dd383c9", + "reference": "e89c2268c9cad25099f562f7f015c28c5dd383c9", "shasum": "", "mirrors": [ { @@ -720,9 +860,11 @@ "zendframework/zend-stdlib": "^3.2.1" }, "require-dev": { - "laminas/laminas-coding-standard": "~1.0.0", + "laminas/laminas-coding-standard": "~2.3.0", "phpbench/phpbench": "^0.17.1", - "phpunit/phpunit": "~9.3.7" + "phpunit/phpunit": "~9.3.7", + "psalm/plugin-phpunit": "^0.16.0", + "vimeo/psalm": "^4.7" }, "type": "library", "autoload": { @@ -754,7 +896,7 @@ "type": "community_bridge" } ], - "time": "2020-11-19T20:18:59+00:00" + "time": "2021-06-28T21:37:31+00:00" }, { "name": "laminas/laminas-text", @@ -824,16 +966,16 @@ }, { "name": "laminas/laminas-zendframework-bridge", - "version": "1.2.0", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-zendframework-bridge.git", - "reference": "6cccbddfcfc742eb02158d6137ca5687d92cee32" + "reference": "13af2502d9bb6f7d33be2de4b51fb68c6cdb476e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6cccbddfcfc742eb02158d6137ca5687d92cee32", - "reference": "6cccbddfcfc742eb02158d6137ca5687d92cee32", + "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/13af2502d9bb6f7d33be2de4b51fb68c6cdb476e", + "reference": "13af2502d9bb6f7d33be2de4b51fb68c6cdb476e", "shasum": "", "mirrors": [ { @@ -888,7 +1030,71 @@ "type": "community_bridge" } ], - "time": "2021-02-25T21:54:58+00:00" + "time": "2021-06-24T12:49:22+00:00" + }, + { + "name": "lkeme/inifile", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/lkeme/inifile.git", + "reference": "bebdcced93b92ad929f6b05cb7cc305d72169a37" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lkeme/inifile/zipball/bebdcced93b92ad929f6b05cb7cc305d72169a37", + "reference": "bebdcced93b92ad929f6b05cb7cc305d72169a37", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "4.8.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Jelix\\IniFile\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "Laurent Jouanneau", + "email": "laurent@jelix.org" + }, + { + "name": "Loic Mathaud" + }, + { + "name": "Riccardo Mazzei", + "email": "riccardo.mazzei@gmail.com" + }, + { + "name": "Lkeme", + "email": "Useri@live.cn" + } + ], + "description": "classes to read and modify ini files by preserving comments and empty lines", + "homepage": "https://github.com/lkeme/inifile", + "keywords": [ + "files", + "ini" + ], + "support": { + "source": "https://github.com/lkeme/inifile/tree/v3.4.0" + }, + "time": "2021-05-13T10:44:17+00:00" }, { "name": "mathieuviossat/arraytotexttable", @@ -949,16 +1155,16 @@ }, { "name": "monolog/monolog", - "version": "1.26.0", + "version": "1.26.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "2209ddd84e7ef1256b7af205d0717fb62cfc9c33" + "reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/2209ddd84e7ef1256b7af205d0717fb62cfc9c33", - "reference": "2209ddd84e7ef1256b7af205d0717fb62cfc9c33", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c6b00f05152ae2c9b04a448f99c7590beb6042f5", + "reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5", "shasum": "", "mirrors": [ { @@ -1025,7 +1231,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/1.26.0" + "source": "https://github.com/Seldaek/monolog/tree/1.26.1" }, "funding": [ { @@ -1037,82 +1243,7 @@ "type": "tidelift" } ], - "time": "2020-12-14T12:56:38+00:00" - }, - { - "name": "phpoption/phpoption", - "version": "1.7.5", - "source": { - "type": "git", - "url": "https://github.com/schmittjoh/php-option.git", - "reference": "994ecccd8f3283ecf5ac33254543eb0ac946d525" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/994ecccd8f3283ecf5ac33254543eb0ac946d525", - "reference": "994ecccd8f3283ecf5ac33254543eb0ac946d525", - "shasum": "", - "mirrors": [ - { - "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", - "preferred": true - } - ] - }, - "require": { - "php": "^5.5.9 || ^7.0 || ^8.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.4.1", - "phpunit/phpunit": "^4.8.35 || ^5.7.27 || ^6.5.6 || ^7.0 || ^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7-dev" - } - }, - "autoload": { - "psr-4": { - "PhpOption\\": "src/PhpOption/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Johannes M. Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Graham Campbell", - "email": "graham@alt-three.com" - } - ], - "description": "Option Type for PHP", - "keywords": [ - "language", - "option", - "php", - "type" - ], - "support": { - "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.7.5" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", - "type": "tidelift" - } - ], - "time": "2020-07-20T17:29:33+00:00" + "time": "2021-05-28T08:32:12+00:00" }, { "name": "psr/container", @@ -1229,16 +1360,16 @@ }, { "name": "psr/log", - "version": "1.1.3", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "", "mirrors": [ { @@ -1268,7 +1399,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for logging libraries", @@ -1279,9 +1410,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.3" + "source": "https://github.com/php-fig/log/tree/1.1.4" }, - "time": "2020-03-23T09:12:05+00:00" + "time": "2021-05-03T11:20:27+00:00" }, { "name": "ralouphie/getallheaders", @@ -1394,103 +1525,18 @@ }, "time": "2021-01-19T12:14:40+00:00" }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.22.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", - "shasum": "", - "mirrors": [ - { - "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", - "preferred": true - } - ] - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-01-07T16:49:33+00:00" - }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "2d63434d922daf7da8dd863e7907e67ee3031483" + "reference": "65bd267525e82759e7d8c4e8ceea44f398838e65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/2d63434d922daf7da8dd863e7907e67ee3031483", - "reference": "2d63434d922daf7da8dd863e7907e67ee3031483", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/65bd267525e82759e7d8c4e8ceea44f398838e65", + "reference": "65bd267525e82759e7d8c4e8ceea44f398838e65", "shasum": "", "mirrors": [ { @@ -1510,7 +1556,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1554,7 +1600,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.23.0" }, "funding": [ { @@ -1570,20 +1616,20 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2021-05-27T09:27:20+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248" + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/43a0283138253ed1d48d352ab6d0bdb3f809f248", - "reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", "shasum": "", "mirrors": [ { @@ -1601,7 +1647,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1644,7 +1690,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0" }, "funding": [ { @@ -1660,20 +1706,20 @@ "type": "tidelift" } ], - "time": "2021-01-22T09:19:47+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9" + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", - "reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", + "reference": "9a142215a36a3888e30d0a9eeea9766764e96976", "shasum": "", "mirrors": [ { @@ -1688,7 +1734,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1726,7 +1772,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.23.0" }, "funding": [ { @@ -1742,20 +1788,20 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-05-27T09:17:38+00:00" }, { - "name": "vlucas/phpdotenv", - "version": "v4.2.0", + "name": "vanilla/garden-cli", + "version": "v3.1.2", "source": { "type": "git", - "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "da64796370fc4eb03cc277088f6fede9fde88482" + "url": "https://github.com/vanilla/garden-cli.git", + "reference": "d9844c47f4f2812259ee1b583aa66e7b6b5d85c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/da64796370fc4eb03cc277088f6fede9fde88482", - "reference": "da64796370fc4eb03cc277088f6fede9fde88482", + "url": "https://api.github.com/repos/vanilla/garden-cli/zipball/d9844c47f4f2812259ee1b583aa66e7b6b5d85c5", + "reference": "d9844c47f4f2812259ee1b583aa66e7b6b5d85c5", "shasum": "", "mirrors": [ { @@ -1765,68 +1811,45 @@ ] }, "require": { - "php": "^5.5.9 || ^7.0 || ^8.0", - "phpoption/phpoption": "^1.7.3", - "symfony/polyfill-ctype": "^1.17" + "ext-json": "*", + "php": ">=7.2", + "psr/log": "^1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4.1", - "ext-filter": "*", - "ext-pcre": "*", - "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20" + "ergebnis/composer-normalize": "^2.8", + "phpdocumentor/reflection-docblock": "^4.3", + "phpunit/phpunit": "^8", + "vanilla/garden-container": "^3.0", + "vanilla/standards": "^1.3", + "vimeo/psalm": "^3.16" }, "suggest": { - "ext-filter": "Required to use the boolean validator.", - "ext-pcre": "Required to use most of the library." + "ext-pdo": "Required for the DbUtils class.", + "phpdocumentor/reflection-docblock": "Required for the CliApplication functionality.", + "vanilla/garden-container": "Required for the CliApplication functionality." }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.1-dev" - } - }, "autoload": { "psr-4": { - "Dotenv\\": "src/" + "Garden\\Cli\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Graham Campbell", - "email": "graham@alt-three.com", - "homepage": "https://gjcampbell.co.uk/" - }, - { - "name": "Vance Lucas", - "email": "vance@vancelucas.com", - "homepage": "https://vancelucas.com/" + "name": "Todd Burry", + "email": "todd@vanillaforums.com" } ], - "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", - "keywords": [ - "dotenv", - "env", - "environment" - ], + "description": "A full-featured, yet ridiculously simple commandline parser for your next php cli script. Stop fighting with getopt().", "support": { - "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v4.2.0" + "issues": "https://github.com/vanilla/garden-cli/issues", + "source": "https://github.com/vanilla/garden-cli/tree/v3.1.2" }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", - "type": "tidelift" - } - ], - "time": "2021-01-20T15:11:48+00:00" + "time": "2020-10-25T13:36:44+00:00" } ], "packages-dev": [], @@ -1836,7 +1859,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.0.0", + "php": ">=7.3.0", "ext-curl": "*", "ext-openssl": "*", "ext-sockets": "*", @@ -1845,5 +1868,5 @@ "ext-mbstring": "*" }, "platform-dev": [], - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.1.0" } diff --git a/conf/ConfigGenerator.php b/conf/ConfigGenerator.php index 381b5be..055500c 100644 --- a/conf/ConfigGenerator.php +++ b/conf/ConfigGenerator.php @@ -14,7 +14,7 @@ class ConfigGenerator public $filename; public $template; private $options = ['APP_USER', 'APP_PASS']; - private $default_filename = 'user.conf.example'; + private $default_filename = 'user.ini.example'; /** * ConfigGenerator constructor. @@ -64,8 +64,8 @@ class ConfigGenerator $value = $this->cliInput("请输入{$option}: "); $this->template = $this->envReplace($option, $value, $this->template); } - file_put_contents(__DIR__ . "\\$this->filename.conf", $this->template); - echo "生成配置文件 $this->filename.conf 成功~"; + file_put_contents(__DIR__ . "\\$this->filename.ini", $this->template); + echo "生成配置文件 $this->filename.ini 成功~"; } } diff --git a/conf/user.conf.example b/conf/user.conf.example deleted file mode 100644 index 710e46a..0000000 --- a/conf/user.conf.example +++ /dev/null @@ -1,196 +0,0 @@ -####################### -# 账户设置 # -####################### - -# 帐号|密码 -APP_USER= -APP_PASS= - -# 登录模式|[1.账密模式 2.短信验证码模式 3.行为验证码模式(暂未开放)] -LOGIN_MODE=1 - -# 令牌(自动生成) -ACCESS_TOKEN= -REFRESH_TOKEN= -COOKIE= - -####################### -# 功能设置 # -####################### - -# 主站每日任务(每日登录、观看、投币、分享) -USE_MAIN_SITE=true - -# 直播大乱斗 -USE_PK=true - -# 直播箱子实物抽奖 -USE_LIVE_BOX=true - -# 每日24个小心心|依赖加密心跳服务器 -USE_HEARTBEAT=true - -# 直播扭蛋活动抽奖|依赖加密心跳服务器 -USE_CAPSULE=true - -# 主站九宫格抽奖活动助手 -USE_ACTIVITY=true - -# 银瓜子兑换硬币 -USE_SILVER2COIN=true - -# 风纪委员 -USE_JUDGE=false - -# 直播统一活动 -USE_ACTIVE=false - -# 直播舰长总督 -USE_GUARD=false - -# 漫画助手 -USE_MANGA=false - -# 赛事助手 -USE_MATCH=false - -# 节奏风暴|丢弃率(0-100)|尝试数(范围值) -USE_STORM=false -STORM_DROPRATE=0 -STORM_ATTEMPT=10,20 - -# 破产机|每日竞猜次数|每次竞猜硬币(1-10)|下注(1.压大,2.压小,3.随机) -USE_COMPETITION=false -COMPET_MAX_NUM=20 -COMPET_MAX_COIN=10 -COMPET_STAKE=1 - -# 天选时刻|抽取类型(0: 无限制; 1: 关注主播; 2: 粉丝勋章; 3大航海; 4用户等级;5主站等级)|自动取关(测试功能)|过滤关键词|逗号分隔 -USE_ANCHOR=false -ANCHOR_UNFOLLOW=false -ANCHOR_TYPE=0,1 -ANCHOR_FILTER_WORDS= - -# 活跃弹幕|弹幕房间(为空则随机)|弹幕内容(为空则随机) -USE_DANMU=true -DANMU_ROOMID=9522051 -DANMU_CONTENT= - -# 视频投币|random(随机热门)/fixed(关注列表)|投币稿件数(每日任务最大5) -USE_ADD_COIN=false -ADD_COIN_MODE=random -ADD_COIN_NUM=5 - -# 自动转发抽奖动态 -AUTO_DYNAMIC = false -# 自动取关未中奖动态 -CLEAR_DYNAMIC = false -# 强制清除抽奖组关注 -CLEAR_GROUP_FOLLOW = false -# 更改自动回复语言 -AUTO_REPLY_TEXT = 从未中奖,从未放弃[doge] - -# 休眠时间|时间区间(0-23)|逗号分隔 -USE_SLEEP=true -SLEEP_SECTION=2,3,4,5,6 - -####################### -# 通知设置 # -####################### - -# 消息推送|消息推送过滤词|逗号分割|优先级从上到下 -USE_NOTIFY=false -NOTIFY_FILTER_WORDS= -## Dingtalk机器人|token|依赖USE_NOTIFY -NOTIFY_DINGTALK_TOKEN= -## Tele机器人|token|chatid|依赖USE_NOTIFY -NOTIFY_TELE_BOTTOKEN= -NOTIFY_TELE_CHATID= -## Pushplus酱|token|依赖USE_NOTIFY -NOTIFY_PUSHPLUS_TOKEN= -## Sever酱(原版)|令牌Key|依赖USE_NOTIFY -NOTIFY_SCKEY= -## Server酱(Turbo版)|令牌Key|依赖USE_NOTIFY -NOTIFY_SCTKEY= -## GoCqhttp|url|token|qq|依赖USE_NOTIFY -NOTIFY_CQ_URL= -NOTIFY_CQ_TOKEN= -NOTIFY_CQ_QQ= - -####################### -# 基础设置 # -####################### - -# 独立推送服务(主)|主备冲突 -USE_ALONE_SERVER=false -ALONE_SERVER_ADDR=tcp://livecmt-1.mudew.com:10088 -ALONE_SERVER_KEY= - -# 分区推送服务(备)|主备冲突 -USE_ZONE_SERVER=true -ZONE_SERVER_ADDR=tcp://broadcastlv.chat.bilibili.com:2243/sub - -# 加密心跳服务器(开源)|如失效自行搭建 -ENC_SERVER=http://heartbeat-1.mudew.com:3000/enc - -####################### -# 房间设置 # -####################### - -# 直播间ID,用于礼物赠送 -ROOM_ID=9522051 - -# 勋章亲密度,测试功能,有短位使用短位反之长位,左侧优先,仅支持辣条和亿元 -# 当列表中所有ID都已达到每日上限,剩余礼物赠送ROOM_ID指定的直播间 -# 是否填满(按时间投喂正常礼物,否则过期礼物)|直播间ID列表|逗号分隔| -FEED_FILL=false -ROOM_LIST=9522051 - -# 弹幕监控房间(为空则随机) -SOCKET_ROOM_ID=9522051 - -####################### -# 网络设置 # -####################### - -# 验证SSL证书|请求时验证SSL证书行为 -VERIFY_SSL=true - -# 是否使用代理|(http\https) -USE_PROXY=false -NETWORK_PROXY=http://127.0.0.1:8888 - -####################### -# 程序设置 # -####################### - -# 写入日志 -APP_WRITE_LOG=false - -# 日志路径 -APP_LOG_PATH=log - -# 调试模式 -APP_DEBUG=false - -# 用户名,可自定义 -APP_UNAME= - -# 多账号区别输出 -APP_MULTIPLE=false - -# 账号别名,如果为空则默认使用登录账号作为标示 -APP_USER_IDENTITY= - -# 日志回调地址 -APP_CALLBACK="http://www.example.com/api.send?text={account}[{level}]: {message}" - -# 错误回调级别 -# -# DEBUG 100 -# INFO 200 -# NOTICE 250 -# WARNING 300 -# ERROR 400 -# -APP_CALLBACK_LEVEL=400 \ No newline at end of file diff --git a/conf/user.ini.example b/conf/user.ini.example new file mode 100644 index 0000000..f5efb82 --- /dev/null +++ b/conf/user.ini.example @@ -0,0 +1,290 @@ +####################### +# 账户设置 # +####################### + +[login.account] +; 帐号|密码 +username = "" +password = "" + +; 登录模式|[1.账密模式 2.短信验证码模式 3.行为验证码模式(暂未开放)] +[login.mode] +mode = 1 + +; 国家代码|mode=2触发|例:大陆86 澳大利亚61 +[login.country] +country_code = 86 + +; 校验|mode=2触发|校验国内手机号|国外手机号关闭校验 +[login.check] +phone = true + +; UID|CSRF|令牌|(当前区域自动生成) +[login.auth] +uid = +csrf = +cookie = +access_token = +refresh_token = + +####################### +# 功能设置 # +####################### + +; 主站每日任务(每日登录、观看、投币、分享) +[main_site] +enable = true +; 每日观看 +watch = true +; 每日分享 +share = true +; 每日视频投币|random(随机热门)/fixed(关注列表)|投币稿件数(每日任务最大5) +add_coin = true +add_coin_mode = random +add_coin_num = 5 + +; 日常/周常礼物 +[daily_bag] +enable = true + +; 双端心跳 +[double_heart] +enable = true + +; 友爱社签到 +[love_club] +enable = true + +; 领取心跳礼物 +[gift_heart] +enable = true + +; 直播每日任务|每日签到|每日登录 +[daily_task] +enable = true + +; 直播箱子实物抽奖 +[live_box] +enable = true + +; 每日24个小心心|依赖加密心跳服务器 +[small_heart] +enable = true + +; 直播扭蛋活动抽奖|依赖加密心跳服务器 +[live_capsule] +enable = true + +; 点亮灰色勋章|100亲密度|每日或者只点亮灰色 +[polish_the_medal] +enable = true +everyday = false + +; 主站九宫格抽奖活动助手 +[main_activity] +enable = true + +; 银瓜子兑换硬币 +[silver2coin] +enable = true + +; 直播大乱斗 +[live_pk] +enable = false + +; 直播舰长总督 +[live_guard] +enable = false + +; 直播其他礼物 +[live_gift] +enable = false + +; 直播节奏风暴|丢弃率(0-100)|尝试次数(范围值) +[live_storm] +enable = false +drop_rate = 0 +attempt = "5,10" + +; 直播天选时刻|抽取类型(0: 无限制; 1: 关注主播; 2: 粉丝勋章; 3大航海; 4用户等级;5主站等级)|自动取关(测试功能)|过滤关键词|逗号分隔 +[live_anchor] +enable = false +limit_type = "0,1" +auto_unfollow = true +filter_words = + +; 获取最新的中奖纪录 +[award_record] +enable = true + +; 活跃弹幕|弹幕房间(为空则随机)|弹幕内容(为空则随机) +[barrage] +enable = true +room_id = 9522051 +content = + +; 漫画助手 +[manga] +enable = false + +; 风纪委员投票|需要实名认证 +[judgement] +enable = false + +; 大会员权益|年度大会员专享 +[vip_privilege] +enable = false + +; B币券消费|年度大会员专享|每月默认充值数量5B币|消费方式优先级从上到下 +[bp_consumption] +enable = false +# 消费B币充电|充电的目标UID|可充值自己的UID +bp2charge = false +bp2charge_uid = 6580464 +# 消费B币充值金瓜子|5000金瓜子 +bp2gold = false + +; 自动转发抽奖动态|自动取关未中奖动态|强制清除抽奖组关注|过滤低于多少粉丝|自定义回复|过滤词|逗号分割 +[dynamic] +enable = false +clear_dynamic = false +clear_group_follow = false +min_fans_num = 15000 +auto_reply_text = +filter_words = + +; 游戏赛事竞猜预测|破产机|每日竞猜次数|每次竞猜硬币(1-10)|下注(1.压大,2.压小,3.随机) +[match_forecast] +enable = false +max_num = 20 +max_coin = 10 +bet = 1 + +; 休眠时间|时间区间(0-23)|逗号分隔 +[sleep] +enable = true +section = "2,3,4,5,6" + +####################### +# 通知设置 # +####################### + +; 消息推送|消息推送过滤词|逗号分割|优先级从上到下 +[notify] +enable = false +filter_words = + +; Dingtalk机器人|token|依赖USE_NOTIFY +[notify.dingtalk] +token = + +; Tele机器人|token|chatid|依赖USE_NOTIFY +[notify.telegram] +bottoken = +chatid = + +; Pushplus酱|token|依赖USE_NOTIFY +[notify.pushplus] +token = + +; Sever酱(原版)|令牌Key|依赖USE_NOTIFY +[notify.sc] +sckey = + +; Server酱(Turbo版)|令牌Key|依赖USE_NOTIFY +[notify.sct] +sctkey = + +; GoCqhttp|url|token|目标qq|依赖USE_NOTIFY +[notify.gocqhttp] +url = "" +token = +target_qq = + +; Debug|个人调试推送|url|token| +[notify.debug] +url = "" +token = + +####################### +# 基础设置 # +####################### + +; 独立推送服务(主)|主备冲突 +[alone_monitor] +enable = false +server_addr = "tcp://livecmt-1.mudew.com:10088" +server_key = "" + +; 分区推送服务(备)|主备冲突 +[zone_monitor] +enable = true +server_addr = "tcp://broadcastlv.chat.bilibili.com:2243/sub" + +; 加密心跳服务器(开源)|如失效自行搭建 +[heartbeat_enc] +server = "http://heartbeat-1.mudew.com:3000/enc" + +####################### +# 房间设置 # +####################### + +; 直播间ID,全局房间,用于礼物赠送、心跳等等. +[global_room] +room_id = 9522051 + +; 弹幕监控房间(为空则随机) +[socket] +room_id = 9522051 + +; 勋章亲密度,测试功能,有短位使用短位反之长位,左侧优先,仅支持辣条和亿元 +; 当列表中所有ID都已达到每日上限,剩余礼物赠送ROOM_ID指定的直播间 +; 是否填满(按时间投喂正常礼物,否则过期礼物)|直播间ID列表|逗号分隔| +[intimacy] +feed_fill = false +room_list = 9522051 + +####################### +# 网络设置 # +####################### + +; 验证SSL证书|请求时验证SSL证书行为 +[network.ssl] +verify_ssl = true + +; 是否使用代理|(http\https) +[network.proxy] +enable = false +proxy = "http://127.0.0.1:8888" + +####################### +# 程序设置 # +####################### + +; 调试模式|采集完整日志 +[debug] +enable = false + +; 记录日志|日志路径|日志回调地址 +[log] +enable = false +path = log +callback = "http://www.example.com/api.send?text={account}[{level}]: {message}" +# 错误回调级别 +# +# DEBUG 100 +# INFO 200 +# NOTICE 250 +# WARNING 300 +# ERROR 400 +# +callback_level = 400 + +; app设置 +[print] +; 用户名,可自定义 +uname = +; 账号别名,如果为空则默认使用登录账号作为标示 +user_identity = +; 多账号区别输出 +multiple = false diff --git a/data/activity_infos.json b/data/activity_infos.json index 90c1d60..9b50c37 100644 --- a/data/activity_infos.json +++ b/data/activity_infos.json @@ -31,62 +31,6 @@ "share": "true", "draw_times": 1, "expire_at": "2021-07-15 11:59:59" - }, - { - "url": "https://www.bilibili.com/blackboard/activity-nA2uYrmpfA.html", - "title": "哥斯拉金刚你站谁", - "description": "活动期间每天分享页面,新增一次机会。", - "sid": "f851e27a-858e-11eb-8597-246e966235d8", - "login": "true", - "follow": "false", - "share": "true", - "draw_times": 2, - "expire_at": "2021-05-23 11:59:59" - }, - { - "url": "https://www.bilibili.com/blackboard/activity-QEya2bouhQ.html", - "title": "春日嗑糖大作战", - "description": "活动期间每天分享页面,新增一次机会。", - "sid": "20b0dfaf-8bcd-11eb-8597-246e966235d8", - "login": "true", - "follow": "false", - "share": "true", - "draw_times": 2, - "expire_at": "2021-05-05 23:59:59" - }, - { - "url": "https://www.bilibili.com/blackboard/gaming_on_bilibili.html", - "title": "上B站看电竞", - "description": "活动期间每天分享页面,新增一次机会。", - "sid": "0b87bd83-8565-11eb-8597-246e966235d8", - "login": "true", - "follow": "false", - "share": "true", - "draw_times": 1, - "expire_at": "2021-05-30 23:59:59", - "remarks": "时间不名,暂定一个月。" - }, - { - "url": "https://www.bilibili.com/blackboard/activity-aT7zphkwF1.html", - "title": "初夏逛吃大会", - "description": "活动期间每天分享页面,新增一次机会。", - "sid": "01aff78a-9e1a-11eb-8597-246e966235d8", - "login": "true", - "follow": "false", - "share": "true", - "draw_times": 1, - "expire_at": "2021-06-10 23:59:59" - }, - { - "url": "https://www.bilibili.com/blackboard/activity-oGiWFe0YTz.html", - "title": "京东超市超有young", - "description": "活动期间每天分享页面,新增一次机会。", - "sid": "4eb728e2-a0d7-11eb-8597-246e966235d8", - "login": "true", - "follow": "false", - "share": "true", - "draw_times": 1, - "expire_at": "2021-04-25 23:59:59" } ] } \ No newline at end of file diff --git a/data/capsule_infos.json b/data/capsule_infos.json index 09fcb31..1554e38 100644 --- a/data/capsule_infos.json +++ b/data/capsule_infos.json @@ -5,9 +5,9 @@ "data": [ { "_url": "注释: 活动地址", - "url": "https://www.bilibili.com/blackboard/activity-c_fu2inm-.html", + "url": "https://www.bilibili.com/blackboard/activity-kiOl0D1nF8.html", "_title": "注释: 活动标题", - "title": "原神1.4版本「风花的邀约」激励计划", + "title": "原神1.6版本UP主激励计划", "_description": "注释: 活动描述", "description": "每日在原神分区任意直播间观看,20分钟1张、1小时2张、2小时3张,每日最高6张。", "_room_id": "注释: 活动直播间,如果为0,则取分区随机一个", @@ -17,25 +17,15 @@ "_parent_area_id": "注释: 主分区id", "parent_area_id": 3, "_coin_id": "注释: 抽奖id", - "coin_id": 112, + "coin_id": 165, + "_pool_id": "注释: 抽奖id", + "pool_id": 179, "_watch_time": "注释: 观看时长 单位秒", "watch_time": 7320, "_draw_times": "注释: 抽奖次数", - "draw_times": 1, + "draw_times": 6, "_expire_at": "注释: 活动有效时间", - "expire_at": "2021-04-27 23:59:59" - }, - { - "url": "https://www.bilibili.com/blackboard/activity-MHRISE.html", - "title": "《怪物猎人:崛起》直播挑战", - "description": "每日在怪物猎人分区任意直播间观看,10分钟1张、30分钟3张、60分钟5张", - "room_id": 0, - "area_id": 412, - "parent_area_id": 6, - "coin_id": 121, - "watch_time": 3720, - "draw_times": 2, - "expire_at": "2021-04-26 23:59:59" + "expire_at": "2021-07-20 23:59:59" }, { "url": "https://live.bilibili.com/11218604", @@ -44,10 +34,11 @@ "room_id": 11218604, "area_id": 0, "parent_area_id": 2, - "coin_id": 129, + "coin_id": 170, + "pool_id": 183, "watch_time": 3720, "draw_times": 3, - "expire_at": "2021-05-31 23:59:59" + "expire_at": "2021-06-27 23:59:59" }, { "url": "https://live.bilibili.com/6", @@ -63,7 +54,7 @@ }, { "url": "https://live.bilibili.com/23", - "title": "PEI亚洲邀请赛", + "title": "PEL和平精英职业联赛", "description": "每日在PEL直播间观看,5分钟1张", "room_id": 13242892, "area_id": 0, @@ -71,7 +62,7 @@ "coin_id": 109, "watch_time": 3720, "draw_times": 2, - "expire_at": "2021-05-31 23:59:59" + "expire_at": "2021-06-13 23:59:59" } ] } \ No newline at end of file diff --git a/data/filter_library.json b/data/filter_library.json new file mode 100644 index 0000000..2279335 --- /dev/null +++ b/data/filter_library.json @@ -0,0 +1,727 @@ +{ + "MaterialObject": { + "sensitive": [ + "测试", + "加密", + "test", + "TEST", + "钓", + "实验", + "炸鱼", + "调试", + "123", + "1111", + "测试", + "測試", + "Test", + "测一测", + "ce-shi", + "test", + "T-E-S-T", + "lala", + "我是抽奖标题", + "压测", + "測一測", + "t-e-s-t" + ] + }, + "Anchor": { + "default": [ + "拉黑", + "黑名单", + "脸皮厚", + "没有奖品", + "无奖", + "脸皮厚", + "ceshi", + "测试", + "测试", + "测试", + "脚本", + "抽奖号", + "星段位", + "星段位", + "圣晶石", + "圣晶石", + "水晶", + "水晶", + "万兴神剪手", + "万兴神剪手", + "自付邮费", + "自付邮费", + "test", + "Test", + "TEST", + "加密", + "QQ", + "测试", + "測試", + "VX", + "vx", + "ce", + "shi", + "这是一个", + "lalall", + "第一波", + "第二波", + "第三波", + "测试用", + "抽奖标题", + "策是", + "房间抽奖", + "CESHI", + "ceshi", + "奖品A", + "奖品B", + "奖品C", + "硬币", + "无奖品", + "白名单", + "我是抽奖", + "五毛二", + "一分", + "一毛", + "0.52", + "0.66", + "0.01", + "0.77", + "0.16", + "照片", + "穷", + "0.5", + "0.88", + "双排", + "1毛", + "1分", + "1角", + "P口罩", + "素颜", + "写真", + "图包", + "五毛", + "一角", + "冥币", + "自拍", + "日历", + "0.22", + "加速器", + "越南盾", + "毛", + "分", + "限", + "0.", + "角", + "〇点", + "①元", + "一起玩", + "不包邮", + "邮费", + "续期卡", + "儿时", + "闪宠", + "大师球", + "一元", + "两元", + "两块", + "赛车", + "代币", + "一块", + "一局", + "好友位", + "通话", + "首胜", + "代金券", + "辣条", + "补贴", + "抵用券", + "主播素颜照", + "武器箱棺材板", + "游戏道具", + "优惠券", + "日元", + "发音课", + "壹元", + "零点", + "舰长五折券", + "上车", + "没有钱", + "女装", + "肥宅快乐水", + "哥斯拉", + "公主连结", + "pokemmo", + "宝可>梦", + "明日方舟", + "雪碧", + "公主连接", + "专属头衔", + "FF14", + "韩元", + "空洞骑士", + "老婆饼", + "稀世时装", + "洛克衣服", + "帮过图", + "证件照", + "自抽号", + "晶耀之星", + "伊洛纳", + "〇.", + "②元", + "③元", + "0·", + "繁华美化", + "喵喵喵", + "闪伊布", + "①圆", + "o点", + "金达摩", + "嗷呜", + "游戏位", + "S-追光者", + "OWL", + "勾玉", + "跟yo宝游戏", + "三元", + "怡宝", + "蛋闪迷>你冰", + "哥伦比亚比索", + "油条", + "代金卷", + "小堂包", + "返现券", + "上舰", + "舰长", + "开舰", + "帅照", + "靓照", + "1元红包", + "红包3.3元", + "5.2元红包", + "2.33元红包", + "测试", + "钓鱼", + "炸鱼", + "黑屋", + "脚本", + "空气", + "大航海", + "上船", + "舰长", + "返现", + "抵用", + "代金", + "上车", + "上反船", + "照片", + "素颜", + "自拍", + "皂片", + "开舰", + "上舰", + "自画像", + "封面", + "取关", + "美照", + "随机照", + "女装照", + "日常照", + "好友", + "给主播", + "照骗", + "连麦", + "情书", + "一局", + "舰涨优惠卷", + "开黑", + "test", + "Test", + "金币", + "元宝", + "代打", + "上分", + "上段", + "台历", + "一毛", + "五毛", + "王者荣耀", + "玩游戏", + "encrypt", + "壁纸", + "相片", + "排位", + "语音", + "车位", + "网剧", + "一起玩", + "一次", + "专属头衔", + "手游", + "宠物", + "蒸汽", + "月饼", + "加速", + "挂件", + "渔夫", + "小黑屋", + "头像", + "许愿码", + "电池", + "赛车", + "保底", + "代币", + "越南盾", + "网点", + "机器", + "话梅", + "志愿", + "令牌", + "永久", + "第五人格", + "大蒜", + "唢呐", + "皇冠", + "徽章", + "铜牌", + "动物园", + "植物", + "钻石", + "宝石", + "尖叫", + "扭蛋机", + "点播", + "数字版月历", + "点歌一首", + "体验", + "点歌", + "三次取关", + "大航海", + "3块钱之前的巨款", + "礼金" + ] + }, + "CapsuleLottery": { + "default": [ + "谢谢参与", + "未中奖", + "辣条" + ] + }, + "ActivityLottery": { + "default": [ + "谢谢参与", + "未中奖", + "辣条" + ] + }, + "Notice": { + "default": [ + "谢谢参与", + "未中奖", + "辣条" + ] + }, + "DynamicForward": { + "default": [ + "一毛", + "结果", + "test", + "元宝", + "晒出", + "原石", + "代打", + "上分", + "测试", + "闹着玩", + "猫粮", + "钓鱼", + "加密", + "好友", + "视频下转发", + "签名照", + "全部答对", + "弹幕", + "评论下方投稿视频", + "炸鱼", + "黑屋", + "照片", + "素颜", + "自拍", + "皂片", + "自画像", + "封面", + "取关", + "随机照", + "宝石", + "真情实感", + "给主播", + "照骗", + "连麦", + "加群", + "钓鱼", + "脚本", + "代金券", + "体验卡", + "门票", + "渲染券", + "机器", + "给视频", + "投票", + "取关", + "视频转发", + "视频分享", + "于视频内", + "视频评论", + "分享视频", + "转发视频", + "评论视频", + "进入直播间", + "平时售价", + "体验名额", + "评论区点赞前", + "上直播", + "参与直播抽奖", + "堆jqr", + "AI转", + "AI来", + "bot来", + "堆bot", + "jqr来", + "有jqr", + "有bot", + "jqr", + "bot" + ] + }, + "Common": { + "default": [ + "禁言", + "测试", + "vcf", + "体验中奖", + "中奖的感觉", + "赶脚", + "感脚", + "感jio", + "黑名单", + "拉黑", + "脸皮厚", + "没有奖品", + "无奖", + "ceshi", + "脚本", + "抽奖号", + "不要脸", + "至尊vip会员7天", + "高级会员7天", + "万兴神剪手", + "加密", + "test", + "TEST", + "钓鱼", + "炸鱼", + "调试", + "编曲", + "作词", + "半价", + "打折", + "机器", + "禁言", + "vcf", + "体验中奖", + "中奖的感觉", + "录歌", + "混音", + "一毛", + "1角", + "0.5元", + "5毛", + "赶脚", + "感脚", + "曲风", + "专辑封面", + "一元红包", + "感jio", + "名片赞", + "黑名单", + "拉黑", + "脸皮厚", + "没有奖品", + "无奖", + "脚本", + "抽奖号", + "不要脸", + "至尊vip会员7天", + "高级会员7天", + "加密", + "test", + "TEST", + "钓鱼", + "炸鱼", + "调试", + "歌曲定制", + "学习视频", + "修图视频", + "免费编曲", + "后期制作", + "编曲搬家", + "内容自定", + "音乐人一个", + "私人唱歌", + "作业", + "八字", + "算命", + "万兴神剪手", + "学习修图", + "写一首歌", + "ceshi", + "管饱", + "dong tai ga", + "电话唱歌", + "感谢转发", + "非独家使用权", + "前排沙发", + "琴谱", + "有就送", + "什么也不给", + "什么都没有", + "租赁", + "伴奏", + "定制beat", + "定制logo", + "惊喜软件", + "加群", + "第一批粉丝", + "内部群", + "老粉", + "仅我关注", + "打字粉丝ID", + "手打粉丝ID", + "人声采集", + "采样包", + "约稿", + "remix", + "明信片", + "感受中奖", + "快落", + "中奖的快乐", + "单曲", + "主题创作", + "猎妈", + "签名照", + "数字专辑", + "除夕夜", + "专辑", + "励志的话", + "亲笔签名", + "扫码进群", + "粉丝群", + "签名写真", + "纹身", + "祝你", + "红包雨", + "电子书", + "好友位", + "豪车优惠", + "星段位", + "圣晶石", + "水晶", + "QQ", + "自付邮费", + "Test", + "测试用", + "VX", + "vx", + "ce", + "shi", + "这是一个", + "lalall", + "第一波", + "第二波", + "策是", + "照片", + "穷", + "0.5", + "一角", + "冥币", + "加速器", + "无奖品", + "白名单", + "五毛", + "第三波", + "五毛二", + "一分", + "0.52", + "0.66", + "0.01", + "0.77", + "0.16", + "0.88", + "双排", + "1毛", + "1分", + "P口罩", + "素颜", + "写真", + "图包", + "自拍", + "日历", + "0.22", + "CESHI", + "奖品A", + "抽奖标题", + "測試", + "越南盾", + "啥都没有", + "哈哈哈", + "作曲", + "一首", + "手绘", + "学霸", + "buff", + "头像", + "剩的", + "Ziyoda", + "Hilola", + "beden", + "新专", + "采样", + "音频", + "海报", + "粉丝ID", + "微博", + "互粉", + "真心话", + "回答", + "签名海报", + "不想要", + "抱抱", + "拥抱", + "WAV", + "邀请函", + "你猜猜", + "什么也没有", + "什么都", + "什么也", + "这不是抽奖", + "使用权", + "曲谱", + "啥也没有", + "木有", + "车载音乐", + "会员歌曲", + "一首歌", + "必唱", + "发文件", + "词作", + "购买资格", + "粉群", + "折扣", + "hoholive", + "surat", + "hisyat", + "免费观", + "免费演", + "免费门", + "谢谢参与", + "vx call u", + "新婚快乐", + "歌曲使用权", + "普通mp3使用权", + "破解版", + "土嗨", + "给你写", + "普通mp3", + "啥也不是", + "歌曲大礼包", + "歌手大礼包", + "无损wav", + "mp3使用权", + "wav使用权", + "曲谱", + "抽个寂寞", + "儿子", + "送我" + ], + "uid_list": [ + 28008897, + 28272016, + 140389827, + 24598781, + 28008860, + 28008880, + 28008743, + 28008948, + 28009292, + 319696958, + 90138218, + 28272000, + 28272047, + 28271978, + 8831288, + 175979009, + 3177443, + 486780865, + 403048135, + 474325039, + 455274996, + 477519424, + 292671666, + 448873224, + 22498938, + 1770865, + 444796995, + 306112375, + 320193786, + 606637517, + 305276429, + 204487541, + 404761800, + 186914127, + 99439379, + 457697569, + 270886929, + 477519424, + 401575, + 201296348, + 206804212, + 333584926, + 34679178, + 699923691, + 392689522, + 178700744, + 272882445, + 350977368, + 487168411, + 22682842, + 444949061, + 523974463, + 192231907, + 503908324, + 383189098, + 252909207, + 336467750, + 264875137, + 90721742, + 452299642, + 677739290, + 441522918, + 8766623, + 698327474, + 5439672, + 483247863, + 237055308, + 95404163, + 202052696, + 1309889741, + 627942060, + 455030741, + 406353670, + 18036870, + 470220612, + 432013403, + 1346052604, + 501312931 + ] + } +} diff --git a/data/filter_words.json b/data/filter_words.json deleted file mode 100644 index b5eb8ec..0000000 --- a/data/filter_words.json +++ /dev/null @@ -1,324 +0,0 @@ -{ - "MaterialObject": { - "sensitive": [ - "测试", - "加密", - "test", - "TEST", - "钓鱼", - "炸鱼", - "调试", - "123", - "1111", - "测试", - "測試", - "Test", - "测一测", - "ce-shi", - "test", - "T-E-S-T", - "lala", - "我是抽奖标题", - "压测", - "測一測", - "t-e-s-t" - ] - }, - "Anchor": { - "default": [ - "拉黑", - "黑名单", - "脸皮厚", - "没有奖品", - "无奖", - "脸皮厚", - "ceshi", - "测试", - "测试", - "测试", - "脚本", - "抽奖号", - "星段位", - "星段位", - "圣晶石", - "圣晶石", - "水晶", - "水晶", - "万兴神剪手", - "万兴神剪手", - "自付邮费", - "自付邮费", - "test", - "Test", - "TEST", - "加密", - "QQ", - "测试", - "測試", - "VX", - "vx", - "ce", - "shi", - "这是一个", - "lalall", - "第一波", - "第二波", - "第三波", - "测试用", - "抽奖标题", - "策是", - "房间抽奖", - "CESHI", - "ceshi", - "奖品A", - "奖品B", - "奖品C", - "硬币", - "无奖品", - "白名单", - "我是抽奖", - "0.1", - "五毛二", - "一分", - "一毛", - "0.52", - "0.66", - "0.01", - "0.77", - "0.16", - "照片", - "穷", - "0.5", - "0.88", - "双排", - "1毛", - "1分", - "1角", - "P口罩", - "素颜", - "写真", - "图包", - "五毛", - "一角", - "冥币", - "自拍", - "日历", - "0.22", - "加速器", - "越南盾", - "毛", - "分", - "限", - "0.", - "角", - "〇点", - "①元", - "一起玩", - "不包邮", - "邮费", - "续期卡", - "儿时", - "闪宠", - "大师球", - "一元", - "两元", - "两块", - "赛车", - "代币", - "一块", - "一局", - "好友位", - "通话", - "首胜", - "代金券", - "辣条", - "补贴", - "抵用券", - "主播素颜照", - "武器箱棺材板", - "游戏道具", - "优惠券", - "日元", - "发音课", - "壹元", - "零点", - "舰长五折券", - "上车", - "没有钱", - "女装", - "肥宅快乐水", - "哥斯拉", - "公主连结", - "pokemmo", - "宝可>梦", - "明日方舟", - "雪碧", - "公主连接", - "专属头衔", - "FF14", - "韩元", - "空洞骑士", - "老婆饼", - "稀世时装", - "洛克衣服", - "帮过图", - "证件照", - "自抽号", - "晶耀之星", - "伊洛纳", - "〇.", - "②元", - "③元", - "0·", - "繁华美化", - "喵喵喵", - "闪伊布", - "①圆", - "o点", - "金达摩", - "嗷呜", - "游戏位", - "S-追光者", - "OWL", - "勾玉", - "跟yo宝游戏", - "三元", - "怡宝", - "蛋闪迷>你冰", - "哥伦比亚比索", - "油条", - "代金卷", - "小堂包", - "返现券", - "上舰", - "舰长", - "开舰", - "帅照", - "靓照", - "1元红包", - "红包3.3元", - "5.2元红包", - "2.33元红包", - "测试", - "钓鱼", - "炸鱼", - "黑屋", - "脚本", - "空气", - "大航海", - "上船", - "舰长", - "返现", - "抵用", - "代金", - "上车", - "上反船", - "照片", - "素颜", - "自拍", - "皂片", - "开舰", - "上舰", - "自画像", - "封面", - "取关", - "美照", - "随机照", - "女装照", - "日常照", - "好友", - "给主播", - "照骗", - "连麦", - "情书", - "一局", - "舰涨优惠卷", - "开黑", - "test", - "Test", - "金币", - "元宝", - "代打", - "上分", - "上段", - "台历", - "一毛", - "五毛", - "王者荣耀", - "玩游戏", - "encrypt", - "壁纸", - "相片", - "排位", - "语音", - "车位", - "网剧", - "一起玩", - "一次", - "专属头衔", - "手游", - "宠物", - "蒸汽", - "月饼", - "加速", - "挂件", - "渔夫", - "小黑屋", - "头像", - "许愿码", - "电池", - "赛车", - "保底", - "代币", - "越南盾", - "网点", - "机器", - "话梅", - "志愿", - "令牌", - "永久", - "第五人格", - "大蒜", - "唢呐", - "皇冠", - "徽章", - "铜牌", - "动物园", - "植物", - "钻石", - "宝石", - "尖叫", - "扭蛋机", - "点播", - "数字版月历", - "点歌一首", - "体验", - "点歌", - "三次取关", - "大航海", - "3块钱之前的巨款", - "礼金" - ] - }, - "CapsuleLottery": { - "default": [ - "谢谢参与", - "未中奖", - "辣条" - ] - }, - "ActivityLottery": { - "default": [ - "谢谢参与", - "未中奖", - "辣条" - ] - }, - "Notice": { - "default": [ - "谢谢参与", - "未中奖", - "辣条" - ] - } -} \ No newline at end of file diff --git a/data/latest_version.json b/data/latest_version.json new file mode 100644 index 0000000..ea47efc --- /dev/null +++ b/data/latest_version.json @@ -0,0 +1,11 @@ +{ + "code": 0, + "project":"BiliHelper-personal", + "branch": "master", + "source": "https://github.com/lkeme/BiliHelper-personal", + "raw_url": "https://cdn.jsdelivr.net/gh/lkeme/BiliHelper-personal@master/data/latest_version.json", + "purge_url": "https://purge.jsdelivr.net/gh/lkeme/BiliHelper-personal@master/data/latest_version.json", + "version": "0.9.7.210714", + "des": "程序有更新,请及时线上查看更新哦~", + "time": "2021年7月14日11:40:35" +} \ No newline at end of file diff --git a/data/reply_words.json b/data/reply_words.json new file mode 100644 index 0000000..1380ede --- /dev/null +++ b/data/reply_words.json @@ -0,0 +1,175 @@ +{ + "DynamicForward": { + "default": [ + "从未中奖,从未放弃[doge]", + "来当分母= =", + "让我中一次吧QAQ", + "继续分母", + "转发动态", + "单纯想中次奖", + "我我我", + "不错", + "来了来了", + "爱了", + "(;¬_¬)", + "(~_~;)", + "= =!", + "╮(╯▽╰)╭", + "(シ_ _)シ", + ">_<", + "(๑• _ •๑)", + "(:3_ヽ)_", + "(⌒▽⌒)", + "(`・ω・´)", + "(◦˙▽˙◦)", + "(=・ω・=)", + "_Σ:з」∠)シ", + "o(∩_∩)o", + "(〜 ̄▽ ̄)〜", + "(๑• ▽ •๑)", + "哔哩哔哩干杯~", + "Bilibili 干杯~", + "bilibili 干杯~", + "[doge][doge][doge]", + "冲冲冲[打call][打call]", + "[doge]", + "万一可能呢", + "我的", + "[打call]", + "就看欧不欧啦", + "来了", + "中", + "好诶", + "好耶", + "拉低中奖率", + "重在拉低中奖率[doge]", + "分母", + "评论", + "成为一个分母,希望成为分子", + "[藏狐]我来", + "重在参与[OK]", + "就是我[给心心][打call]", + "抽起来!!!", + "我也要中奖", + "冲", + "[拥抱]", + "万一呢?", + "我来了", + "欧欧欧", + "冲冲冲", + "谢谢给我一个中奖的机会", + "奖励不重要,重要的是心[doge]", + "许愿", + "分母报道", + "大吉大利", + "欧气满满", + "不想再当分母", + "吸欧气", + "中!!!", + "", + "好运来", + "啊~", + "哈哈哈", + "抽奖奖(⌒▽⌒)", + "中奖绝缘体", + "绝缘体", + "求脱非入欧", + "好运", + "中奖绝缘体表示想中!", + "呜呜呜非洲人来了", + "选我吧", + "一定会中", + "好运bufff", + "滴滴滴", + "哇哇哇哇", + "万一呢", + "非酋日常", + "加油", + "抽中吧", + "我要", + "想欧一次!", + "拉低中奖率233", + "想要...", + "路过拉低中奖率", + "希望有个好运气", + "中奖", + "什么时候才会抽到我呢?", + "试试水,看看能不能中", + "过来水一手", + "这辈子都不可能中奖的", + "先拉低中奖率23333", + "先抽奖,抽不到再说", + "嘤嘤嘤", + "捞一把", + "我就想中一次", + "拉低拉低", + "试一试", + "搞一搞", + "中奖什么的不可能的( ̄▽ ̄)", + "听说我中奖了?", + "脱非转欧", + "emm", + "无聊.。。。。", + "[星星眼]", + "[妙啊]", + "[辣眼睛]", + "[吃瓜][吃瓜]", + "[滑稽]", + "[呲牙]", + "[打call][打call]", + "[哈欠][哈欠]", + "[吃瓜]不嫌事大", + "[口罩]", + "[思考]", + "[冷][冷][冷]", + "次次参加", + "从来没中过", + "让我中吧", + "来中个吧", + "送妹子多好", + "再送个小姐姐咋样", + "忍不住抽", + " (* ̄︶ ̄)", + "如影随形", + "参加够多就能中奖", + "参加够多就能当分子", + "[喜极而泣]", + "我是天选之子", + "中一次吧!", + "坚持不懈,迎难而上,开拓创新!", + "[OK][OK]", + "抽个奖和寂寞", + "中中", + "坚持不懈,迎难而上!", + "呵呵", + "我一般不抽奖,除非忍不住。", + "[OK]", + "[喜欢]", + "[偷笑]", + "[笑]", + "[吃瓜]", + "[奋斗]", + "在", + "冲吖~", + "[保佑][保佑]", + "从未中,从未停", + "[抠鼻][抠鼻]", + "来力", + "秋梨膏", + "从不缺席", + "分子", + "1", + "好", + "rush", + "来来来", + "ok", + "凑热闹", + "我要我要[打call]", + "我还能中!让我中!!!", + "大家都散了吧,已经抽完了,是我的", + "给我中一次吧!", + "我来抽个奖", + "[doge][doge][doge]" + ] + } +} \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..cc80e58 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,45 @@ +FROM php:alpine + +#MAINTAINER zsnmwy +LABEL AUTHOR = "Lkeme " + +ENV USER_NAME='' \ + USER_PASSWORD='' \ + REPO_URL='https://github.com/' \ + MIRRORS="0" \ + CONIFG_PATH='/app/conf/user.ini' \ + Green="\\033[32m" \ + Red="\\033[31m" \ + GreenBG="\\033[42;37m" \ + RedBG="\\033[41;37m" \ + Font="\\033[0m" \ + Green_font_prefix="\\033[32m" \ + Green_background_prefix="\\033[42;37m" \ + Font_color_suffix="\\033[0m" \ + Info="${Green}[信息]${Font}" \ + OK="${Green}[OK]${Font}" \ + Error="${Red}[错误]${Font}" + +WORKDIR /app + +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories +#RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories +RUN docker-php-ext-install sockets + +#RUN if [ "${CN}" = true ]; then export REPO_URL="https://github.com.cnpmjs.org"; fi + +#RUN set -ex \ +# && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ +# && echo "Asia/Shanghai" > /etc/timezone \ + +RUN apk add --no-cache git && \ + git clone ${REPO_URL}/lkeme/BiliHelper-personal.git --depth=1 /app && \ + cp -f /app/docker/entrypoint.sh /usr/local/bin/entrypoint.sh && \ + chmod 777 /usr/local/bin/entrypoint.sh && \ + php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" && \ + php composer-setup.php && \ + php composer.phar install && \ + rm -r /var/cache/apk && \ + rm -r /usr/share/man + +ENTRYPOINT ["entrypoint.sh"] \ No newline at end of file diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 0000000..e2af4dd --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,43 @@ +#!/bin/sh +set -e + +# 源切换 +case ${MIRRORS} in +"0") + echo -e "\n ======== \n ${Info} ${GreenBG} 切换源-github.com ${Font} \n ======== \n" + git remote set-url origin https://github.com/lkeme/BiliHelper-personal.git + ;; +"1") + echo -e "\n ======== \n ${Info} ${GreenBG} 切换源-ghproxy.com ${Font} \n ======== \n" + git remote set-url origin https://ghproxy.com/https://github.com/lkeme/BiliHelper-personal.git + ;; +"2") + echo -e "\n ======== \n ${Info} ${GreenBG} 切换源-github.com.cnpmjs.org ${Font} \n ======== \n" + git remote set-url origin https://github.com.cnpmjs.org/lkeme/BiliHelper-personal.git + ;; +*) + echo -e "\n ======== \n ${Info} ${GreenBG} 切换源-github.com ${Font} \n ======== \n" + git remote set-url origin https://github.com/lkeme/BiliHelper-personal.git + ;; +esac + +# 拉取更新 +echo -e "\n ======== \n ${Info} ${GreenBG} 正使用 git pull 同步项目 ${Font} \n ======== \n" +git pull + +# 安装依赖 +echo -e "\n ======== \n ${Info} ${GreenBG} 安装/更新 项目运行依赖 ${Font} \n ======== \n" +php composer.phar install +echo -e "\n \n \n \n" + +# 判断类型 +if [[ -f ${CONIFG_PATH} ]]; then + echo -e "\n ======== \n ${GreenBG} 正在使用外部配置文件 ${Font} \n ======== \n" +else + echo -e "${OK} ${GreenBG} 正在使用传入的环境变量进行用户配置。\n 如果需要配置更多选择项,请通过挂载配置文件来传入。具体参考项目中的README。\n https://github.com/lkeme/BiliHelper-personal.git ${Font} \n ======== \n " + cp /app/conf/user.ini.example /app/conf/user.ini + sed -i ''"$(cat /app/conf/user.ini -n | grep "username = \"\"" | awk '{print $1}')"'c '"$(echo "username = \"${USER_NAME}\"")"'' ${CONIFG_PATH} + sed -i ''"$(cat /app/conf/user.ini -n | grep "password = \"\"" | awk '{print $1}')"'c '"$(echo "password = \"${USER_PASSWORD}\"")"'' ${CONIFG_PATH} +fi + +php index.php diff --git a/index.php b/index.php index c977764..dd2a4b3 100644 --- a/index.php +++ b/index.php @@ -11,9 +11,7 @@ require 'vendor/autoload.php'; - -$filename = isset($argv[1]) ? $argv[1] : 'user.conf'; - $app = new BiliHelper\Core\App(__DIR__); -$app->load($filename); -$app->start(); +$app->load($argv) + ->inspect() + ->start(); diff --git a/src/core/App.php b/src/core/App.php index fccc7d2..749bf3e 100644 --- a/src/core/App.php +++ b/src/core/App.php @@ -12,11 +12,12 @@ namespace BiliHelper\Core; use Amp\Loop; use function Amp\asyncCall; -use BiliHelper\Plugin\Notice; - class App { + private $script_mode = false; + private $loop_mode = true; + /** * App constructor. * @param string $app_path @@ -26,55 +27,84 @@ class App define('APP_CONF_PATH', $app_path . "/conf/"); define('APP_DATA_PATH', $app_path . "/data/"); define('APP_LOG_PATH', $app_path . "/log/"); + define('APP_TASK_PATH', $app_path . "/task/"); + } + + /** + * @use 检查环境 + * @return $this + */ + public function inspect(): App + { (new Env())->inspect_configure()->inspect_extension(); + return $this; } /** * @use 加载配置 - * @param string $load_file + * @param $argv * @return $this */ - public function load($load_file = 'user.conf') + public function load($argv): App { - Config::load($load_file); + $args = (new Command($argv))->run(); + $filename = $args->getArg(0) ?? 'user.ini'; + $this->script_mode = $args->getOpt('script'); + + Config::load($filename); return $this; } /** * @use 新任务 * @param string $taskName + * @param string $dir */ - public function newTask(string $taskName) + public function newTask(string $taskName, string $dir) { - asyncCall(function () use ($taskName) { + asyncCall(function () use ($taskName, $dir) { while (true) { try { - call_user_func(array('BiliHelper\Plugin\\' . $taskName, 'run'), []); + call_user_func(array("BiliHelper\\$dir\\" . $taskName, 'run'), []); } catch (\Throwable $e) { $error_msg = "MSG: {$e->getMessage()} CODE: {$e->getCode()} FILE: {$e->getFile()} LINE: {$e->getLine()}"; Log::error($error_msg); // Notice::push('error', $error_msg); } - yield call_user_func(array('BiliHelper\Plugin\\' . $taskName, 'Delayed'), []); + yield call_user_func(array("BiliHelper\\$dir\\" . $taskName, 'Delayed'), []); } }); } /** - * @use 核心运行 + * @use Script模式 */ - public function start() + private function script_m() + { + $scripts = [ + 'UnFollow' => '批量取消关注(暂测试)', + 'DelDynamic' => '批量清理动态(未完成)' + ]; + + $choice = \BiliHelper\Script\BaseTask::choice($scripts, 'UnFollow'); + $this->newTask($choice, 'Script'); + } + + /** + * @use Loop模式 + */ + private function loop_m() { $plugins = [ + 'CheckUpdate', 'Login', 'Schedule', 'MainSite', - 'Daily', + 'DailyBag', 'ManGa', - 'GameMatch', 'ActivityLottery', 'Competition', - 'Heart', + 'DoubleHeart', 'DailyTask', 'Barrage', 'Silver2Coin', @@ -92,15 +122,34 @@ class App 'GuardRaffle', 'AnchorRaffle', 'AwardRecord', - 'Statistics', 'Forward', 'CapsuleLottery', - // 'Silver', + 'PolishTheMedal', + 'VipPrivilege', + 'BpConsumption', + // 'Silver', // Abandoned + 'Statistics', ]; foreach ($plugins as $plugin) { - $this->newTask($plugin); + $this->newTask($plugin, 'Plugin'); } Loop::run(); } + + + /** + * @use 核心运行 + */ + public function start() + { + // Todo 模式名称需要优化 + if ($this->script_mode) { + Log::info('执行Script模式'); + $this->script_m(); + } else { + Log::info('执行Loop模式'); + $this->loop_m(); + } + } } diff --git a/src/core/Command.php b/src/core/Command.php new file mode 100644 index 0000000..be5a97c --- /dev/null +++ b/src/core/Command.php @@ -0,0 +1,52 @@ +argv = $argv; + } + + /** + * @return \Garden\Cli\Args + */ + public function run(): Args + { + $cli = new Cli(); + + $cli->description('BHP命令行工具.') + ->opt('script:s', '执行的Script模式.', false, 'bool'); + + try { + $args = $cli->parse($this->argv, true); + } catch (\Exception $e) { + die('解析命令行参数错误'); + } + return $args; + } + +} + + + + diff --git a/src/core/Config.php b/src/core/Config.php index 1b8ce99..627034c 100644 --- a/src/core/Config.php +++ b/src/core/Config.php @@ -10,16 +10,17 @@ namespace BiliHelper\Core; -use Dotenv\Dotenv; - +use Jelix\IniFile\IniModifier; class Config { private static $app_config; + private static $load_file; + private static $last_time; private static $config_path; private static $instance; - public static function getInstance() + private static function getInstance(): Config { if (is_null(self::$instance)) { self::$instance = new static; @@ -27,72 +28,78 @@ class Config return self::$instance; } - - public static function load($load_file) - { - return self::getInstance()::_load($load_file); - } - - public static function put($key, $val = null) - { - return self::getInstance()::_put($key, $val); - } - - public static function get($key = null) - { - return self::getInstance()::_get($key); - } - /** - * @use 加载配置文件 + * @use 加载配置 * @param string $load_file */ - private static function _load($load_file) + public static function load(string $load_file) { $config_path = str_replace("\\", "/", APP_CONF_PATH . $load_file); if (!is_file($config_path)) { die("配置文件 {$load_file} 加载错误,请参照文档添加配置文件!"); } - $app_config = Dotenv::createImmutable(dirname($config_path), $load_file); - $app_config->load(); - self::$app_config = $app_config; + // 给静态参数赋值 + self::$load_file = $load_file; self::$config_path = $config_path; + // $config_path = dirname($config_path).DIRECTORY_SEPARATOR.$load_file; + self::$app_config = new IniModifier(self::$config_path); + self::$last_time = fileatime(self::$config_path); } - /** - * @use 写入配置 - * @param $key - * @param $val - * @return bool - */ - private static function _put($key, $val) + public static function _set($name, $value, $section = 0, $key = null) { - if (!is_null($val)) { - if (!empty(self::$config_path)) { - file_put_contents(self::$config_path, preg_replace( - '/^' . $key . '=\S*/m', - $key . '=' . $val, - file_get_contents(self::$config_path) - )); - } + $_instance = self::getInstance(); + $_instance::$app_config->setValue($name, $value, $section, $key); + $_instance::$app_config->save(); + // 保存修改时间 + $_instance::$last_time = fileatime($_instance::$config_path); + } + + public static function _get($name, $section = 0, $key = null) + { + $_instance = self::getInstance(); + // 判断是否被修改 重新加载文件 + // echo $_instance::$last_time.PHP_EOL; + // echo fileatime($_instance::$config_path); + if (fileatime($_instance::$config_path) != $_instance::$last_time) { + $_instance::load($_instance::$load_file); } - putenv($key . '=' . $val); - // self::$app_config->load(); - return true; + return $_instance::$app_config->getValue($name, $section, $key); + } + + public static function _put() + { + $_instance = self::getInstance(); + + } + + public static function _del() + { + $_instance = self::getInstance(); + } /** - * @use 读出配置 - * @param string|null $key - * @return mixed|null + * 不允许从外部调用以防止创建多个实例 + * 要使用单例,必须通过 Singleton::getInstance() 方法获取实例 */ - private static function _get($key) + private function __construct() { - if (self::$app_config->required($key)) { - return getenv($key); - } - return null; } + /** + * 防止实例被克隆(这会创建实例的副本) + */ + private function __clone() + { + } + + /** + * 防止反序列化(这将创建它的副本) + */ + public function __wakeup() + { + + } } \ No newline at end of file diff --git a/src/core/Curl.php b/src/core/Curl.php index cd47744..d5edcb0 100644 --- a/src/core/Curl.php +++ b/src/core/Curl.php @@ -92,7 +92,7 @@ class Curl * @param int $timeout * @return array */ - public static function async($os, $url, $tasks = [], $headers = [], $timeout = 30) + public static function async($os, $url, $tasks = [], $headers = [], $timeout = 30): array { self::$async_opt = [ 'tasks' => $tasks, @@ -155,7 +155,7 @@ class Curl ); $result = $url ? @file_get_contents($url, false, stream_context_create($options)) : null; Log::debug($result); - return $result ? $result : null; + return $result ?: null; } /** @@ -167,18 +167,16 @@ class Curl self::$async_opt['counter']++; return; } - # 请求结束! + // 请求结束 self::$async_opt = []; } - /** * @use 请求中心异常处理 * @param string $url * @param string $method * @param array $options * @return mixed - * @throws \Exception */ private static function clientHandle(string $url, string $method, array $options) { @@ -209,17 +207,17 @@ class Curl * @param float $timeout * @return array */ - private static function getClientOpt(array $add_options, array $headers = [], float $timeout = 30.0) + private static function getClientOpt(array $add_options, array $headers = [], float $timeout = 30.0): array { self::$client = new \GuzzleHttp\Client(); $default_options = [ 'headers' => $headers, 'timeout' => $timeout, 'http_errors' => false, - 'verify' => getenv('VERIFY_SSL') == 'false' ? false : true, + 'verify' => getConf('verify_ssl', 'network.ssl'), ]; - if (getenv('USE_PROXY') == 'true') { - $default_options['proxy'] = getenv('NETWORK_PROXY'); + if (getConf('enable', 'network.proxy')) { + $default_options['proxy'] = getConf('proxy', 'network.proxy'); } return array_merge($default_options, $add_options); } @@ -245,7 +243,7 @@ class Curl 'Connection' => 'keep-alive', // 'Content-Type' => 'application/x-www-form-urlencoded', // 'User-Agent' => 'Mozilla/5.0 BiliDroid/5.51.1 (bbcallen@gmail.com)', - 'User-Agent' => 'Mozilla/5.0 BiliDroid/6.20.5 (bbcallen@gmail.com) os/android model/MuMu mobi_app/android build/6205500 channel/bili innerVer/6205500 osVer/6.0.1 network/2', + 'User-Agent' => 'Mozilla/5.0 BiliDroid/6.32.0 (bbcallen@gmail.com) os/android model/MuMu mobi_app/android build/6320200 channel/bili innerVer/6320200 osVer/7.1.2 network/2', // 'Referer' => 'https://live.bilibili.com/', ]; $pc_headers = [ @@ -259,37 +257,14 @@ class Curl $other_headers = [ 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4450.0 Safari/537.36', ]; - $default_headers = isset(${$os . "_headers"}) ? ${$os . "_headers"} : $other_headers; - if (in_array($os, ['app', 'pc']) && getenv('COOKIE') != "") { - $default_headers['Cookie'] = getenv('COOKIE'); + $default_headers = ${$os . "_headers"} ?? $other_headers; + if (in_array($os, ['app', 'pc']) && getCookie() != "") { + $default_headers['Cookie'] = getCookie(); } // return self::formatHeaders(array_merge($default_headers, $headers)); return array_merge($default_headers, $headers); } - /** - * @use 格式化Headers - * @param $headers - * @return array - */ - private static function formatHeaders(array $headers): array - { - return array_map(function ($k, $v) { - return $k . ': ' . $v; - }, array_keys($headers), $headers); - } - - /** - * @use 字符串or其他 - * @return array - */ - private static function getResult() - { - $result = self::$result; - self::$result = []; - return array_shift($result); - } - /** * @use 数组 * @return array @@ -336,4 +311,27 @@ class Curl Log::debug("获取Headers"); return $request->getHeaders(); } + + /** + * @use 格式化Headers + * @param array $headers + * @return array + */ + private static function formatHeaders(array $headers): array + { + return array_map(function ($k, $v) { + return $k . ': ' . $v; + }, array_keys($headers), $headers); + } + + /** + * @use 字符串or其他 + * @return array + */ + private static function getResult(): array + { + $result = self::$result; + self::$result = []; + return array_shift($result); + } } diff --git a/src/core/Env.php b/src/core/Env.php index 6015082..11b1fb5 100644 --- a/src/core/Env.php +++ b/src/core/Env.php @@ -10,10 +10,17 @@ namespace BiliHelper\Core; +use Noodlehaus\Config; + class Env { - private $app_name = 'BiliHelper Personal'; - private $app_version = '0.8.1.*'; + private $app_name; + private $app_version; + private $app_branch; + private $app_source; + + private $repository = APP_DATA_PATH . 'latest_version.json'; + /** * Env constructor. @@ -26,6 +33,8 @@ class Env date_default_timezone_set('Asia/Shanghai'); ini_set('display_errors', 'on'); error_reporting(E_ALL); + + $this->loadJsonData(); } /** @@ -38,7 +47,7 @@ class Env if (!extension_loaded($extension)) { Log::error("检查到项目依赖 {$extension} 扩展未加载。"); Log::error("请在 php.ini中启用 {$extension} 扩展后重试。"); - Log::error("程序常见问题请移步 https://github.com/lkeme/BiliHelper-personal 文档部分查看。"); + Log::error("程序常见问题请移步 {$this->app_source} 文档部分查看。"); exit(); } } @@ -47,20 +56,32 @@ class Env /** * @use 检查环境 */ - public function inspect_configure() + public function inspect_configure(): Env { - Log::info("欢迎使用 {$this->app_name} 当前版本 {$this->app_version}"); - Log::info("使用说明请移步 https://github.com/lkeme/BiliHelper-personal 查看。"); + Log::info("欢迎使用 项目: {$this->app_name}@{$this->app_branch} 版本: {$this->app_version}"); + Log::info("使用说明请移步 {$this->app_source} 查看"); if (PHP_SAPI != 'cli') { die("Please run this script from command line ."); } - if (version_compare(PHP_VERSION, '7.0.0', '<')) { - die("Please upgrade PHP version > 7.0.0 ."); + if (version_compare(PHP_VERSION, '7.3.0', '<')) { + die("Please upgrade PHP version > 7.3.0 ."); } // if (version_compare(PHP_VERSION, '8.0.0', '>')) { // die("Please upgrade PHP version < 8.0.0 ."); // } return $this; } + + /** + * @use 加载本地JSON DATA + */ + private function loadJsonData() + { + $conf = new Config($this->repository); + $this->app_name = $conf->get('project'); + $this->app_version = $conf->get('version'); + $this->app_branch = $conf->get('branch'); + $this->app_source = $conf->get('source'); + } } diff --git a/src/core/Helpers.php b/src/core/Helpers.php new file mode 100644 index 0000000..74b12e2 --- /dev/null +++ b/src/core/Helpers.php @@ -0,0 +1,117 @@ +ch = curl_init(); + $this->url = $url; + curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false); //忽略 HTTPS 证书错误 + $this->setUA("Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36"); + } + + function __destruct() + { + //防止内存泄露 + curl_close($this->ch); + } + + /** + * @use 设置UA + * @param string $ua + * @return $this + */ + public function setUA(string $ua): HttpClient + { + curl_setopt($this->ch, CURLOPT_USERAGENT, $ua); //设置 UA + return $this; + } + + /** + * @use 添加Header + * @param string $header + * @return $this + */ + public function addHeader(string $header): HttpClient + { + array_push($this->headers, $header); + return $this; + } + + /** + * @use 添加Headers + * @param array $headers + * @return $this + */ + public function addHeaders(array $headers): HttpClient + { + foreach ($headers as $key => $value) { + array_push($this->headers, "{$key}: {$value}"); + } + return $this; + } + + /** + * @use 设置Cookie + * @param string $cookie + * @return $this + */ + public function setCookie(string $cookie): HttpClient + { + curl_setopt($this->ch, CURLOPT_COOKIE, $cookie); + return $this; + } + + /** + * @use 设置 url 参数 + */ + public function buildQuery(array $query): HttpClient + { + $this->query = http_build_query($query); + return $this; + } + + /** + * @use 自动将 json 文本解码 + */ + public function asJSON(): object + { + return json_decode($this->ret); + } + + /** + * @use 获取返回结果 + */ + public function asString(): string + { + return $this->ret; + } + + /** + * @use 构造POST表单 + * @param array $form + * @return $this + */ + public function buildPostForm(array $form): HttpClient + { + $this->form = http_build_query($form); + + return $this; + } + + /** + * @use 发送 Get 请求 + */ + public function get(): HttpClient + { + curl_setopt($this->ch, CURLOPT_URL, $this->url . "?" . $this->query); + curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); //返回内容储存到变量中 + curl_setopt($this->ch, CURLOPT_HEADER, $this->headers); + $this->ret = curl_exec($this->ch); + return $this; + } + + /** + * @use 发送 POST 请求 + * @param string|null $data 要 POST 的数据 + * @return \HttpClient + */ + public function post(string $data = null): HttpClient + { + curl_setopt($this->ch, CURLOPT_URL, $this->url . "?" . $this->query); + curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); //返回内容储存到变量中 + curl_setopt($this->ch, CURLOPT_POST, true); // 发送 POST 请求 + curl_setopt($this->ch, CURLOPT_HEADER, $this->headers); + curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data); + $this->ret = curl_exec($this->ch); + return $this; + } + + + /** + * @use POST表单 + * @param array $form + * @return $this + */ + public function postForm(array $form): HttpClient + { + return $this->post(http_build_query($form)); + } +} + diff --git a/src/core/Log.php b/src/core/Log.php index 10d6a55..5a7c627 100644 --- a/src/core/Log.php +++ b/src/core/Log.php @@ -18,6 +18,9 @@ class Log { protected static $instance; + /** + * @use 实体 + */ static public function getLogger() { if (!self::$instance) { @@ -26,53 +29,79 @@ class Log return self::$instance; } + /** + * @use 单例 + */ private static function configureInstance() { $logger = new Logger('BH'); - $handler = new StreamHandler('php://stdout', getenv('APP_DEBUG') == 'true' ? Logger::DEBUG : Logger::INFO); + $handler = new StreamHandler('php://stdout', getConf('enable', 'debug') ? Logger::DEBUG : Logger::INFO); $handler->setFormatter(new ColoredLineFormatter()); $logger->pushHandler($handler); self::$instance = $logger; } - private static function prefix() + /** + * @use 前缀 + * @return string + */ + private static function prefix(): string { - if (getenv('APP_MULTIPLE') == 'true') { - return '[' . (empty($t = getenv('APP_USER_IDENTITY')) ? getenv('APP_USER') : $t) . ']'; + if (getConf('multiple', 'print')) { + return '[' . getConf('user_identity', 'print') ?? getConf('username', 'login.account') . ']'; } return ''; } + /** + * @use 写日志 + * @param $type + * @param $message + */ private static function writeLog($type, $message) { - if (getenv('APP_WRITE_LOG') == 'true') { - if ($type == 'DEBUG' && getenv("APP_DEBUG") != 'true') { + if (getConf('enable', 'log')) { + if ($type == 'DEBUG' && !getConf('enable', 'debug')) { return; } - $path = './' . getenv("APP_LOG_PATH") . '/'; + $path = './' . getConf('path', 'log') . '/'; if (!file_exists($path)) { mkdir($path); chmod($path, 0777); } - $filename = $path . getenv('APP_USER') . ".log"; + $filename = $path . getConf('username', 'login.account') . ".log"; $date = date('[Y-m-d H:i:s] '); $data = $date . ' Log.' . $type . ' ' . $message . PHP_EOL; file_put_contents($filename, $data, FILE_APPEND); } } + /** + * @use 堆栈 + * @return string + */ private static function backtrace(): string { $backtraces = debug_backtrace(); return "(" . pathinfo(basename($backtraces[1]['file']))['filename'] . ") => "; } + /** + * @use 调试 + * @param $message + * @param array $context + */ public static function debug($message, array $context = []) { self::writeLog('DEBUG', $message); self::getLogger()->addDebug($message, $context); } + /** + * @use 信息 + * @param $message + * @param array $context + */ public static function info($message, array $context = []) { $message = self::prefix() . self::backtrace() . $message; @@ -81,6 +110,11 @@ class Log self::callback(Logger::INFO, 'INFO', $message); } + /** + * @use 提醒 + * @param $message + * @param array $context + */ public static function notice($message, array $context = []) { $message = self::prefix() . self::backtrace() . $message; @@ -89,6 +123,11 @@ class Log self::callback(Logger::NOTICE, 'NOTICE', $message); } + /** + * @use 警告 + * @param $message + * @param array $context + */ public static function warning($message, array $context = []) { $message = self::prefix() . self::backtrace() . $message; @@ -97,6 +136,11 @@ class Log self::callback(Logger::WARNING, 'WARNING', $message); } + /** + * @use 错误 + * @param $message + * @param array $context + */ public static function error($message, array $context = []) { $message = self::prefix() . self::backtrace() . $message; @@ -105,11 +149,18 @@ class Log self::callback(Logger::ERROR, 'ERROR', $message); } + /** + * @use 回调 + * @param $levelId + * @param $level + * @param $message + */ public static function callback($levelId, $level, $message) { - $callback_level = (('APP_CALLBACK_LEVEL') == '') ? (Logger::ERROR) : intval(getenv('APP_CALLBACK_LEVEL')); + // $callback_level = Logger::ERROR ?? getConf('callback_level', 'log'); + $callback_level = getConf('callback_level', 'log') ?? Logger::ERROR; if ($levelId >= $callback_level) { - $url = str_replace('{account}', self::prefix(), getenv('APP_CALLBACK')); + $url = str_replace('{account}', self::prefix(), getConf('callback', 'log')); $url = str_replace('{level}', $level, $url); $url = str_replace('{message}', urlencode($message), $url); Curl::request('get', str_replace(' ', '%20', $url)); diff --git a/src/core/Task.php b/src/core/Task.php new file mode 100644 index 0000000..5f6a4b4 --- /dev/null +++ b/src/core/Task.php @@ -0,0 +1,104 @@ + time() || getenv('USE_ACTIVITY') == 'false') { + if (self::getLock() > time() || !getEnable('main_activity')) { return; } self::allotTasks(); @@ -35,7 +41,6 @@ class ActivityLottery } } - /** * @use 分配任务 * @return bool @@ -86,7 +91,7 @@ class ActivityLottery * @use 执行任务 * @return bool */ - private static function workTask() + private static function workTask(): bool { if (self::$work_status['work_completed'] == date("Y/m/d")) { return false; @@ -110,7 +115,10 @@ class ActivityLottery self::addTimes($task['act']->sid, $task['act']->url, 3); break; case 'draw': - self::doLottery($task['act']->sid, $task['act']->url, 0); + // 有抽奖机会才抽奖 + if (self::initTimes($task['act']->sid, $task['act']->url, false)) { + self::doLottery($task['act']->sid, $task['act']->url, 0); + } break; default: Log::info("当前 {$task['act']->title} #{$task['operation']} 任务不存在哦"); @@ -119,14 +127,14 @@ class ActivityLottery return true; } - /** * @use 获取抽奖机会 * @param string $sid * @param string $referer + * @param bool $init * @return bool */ - private static function initTimes(string $sid, string $referer): bool + private static function initTimes(string $sid, string $referer, bool $init = true): bool { $url = 'https://api.bilibili.com/x/activity/lottery/mytimes'; $headers = [ @@ -139,12 +147,25 @@ class ActivityLottery $raw = Curl::get('pc', $url, $payload, $headers); $de_raw = json_decode($raw, true); // {"code":0,"message":"0","ttl":1,"data":{"times":2}} + // {"code":0,"message":"0","ttl":1,"data":{"times":3}} + if ($init) { + if ($de_raw['code'] == 0) { + Log::notice("剩余抽奖次数 {$de_raw['data']['times']}"); + return true; + } + Log::warning("获取抽奖次数失败 {$raw}"); + return false; + } if ($de_raw['code'] == 0) { - Log::info("获取抽奖机会成功 {$raw}"); + Log::notice("剩余抽奖次数 {$de_raw['data']['times']}"); + if ($de_raw['data']['times'] <= 0) { + return false; + } return true; } - Log::warning("获取抽奖机会失败 {$raw}"); + Log::warning("获取抽奖次数失败 {$raw}"); return false; + } /** @@ -161,17 +182,19 @@ class ActivityLottery 'origin' => 'https://www.bilibili.com', 'referer' => $referer ]; - $user_info = User::parseCookies(); // $action_type 4 关注 3 分享 $payload = [ 'sid' => $sid, 'action_type' => $action_type, - 'csrf' => $user_info['token'] + 'csrf' => getCsrf() ]; $raw = Curl::post('pc', $url, $payload, $headers); - $de_raw = json_decode($raw, true); - Log::info("增加抽奖机会#{$action_type} {$raw}"); + // {"code":75405,"message":"抽奖机会用尽啦","ttl":1} + // {"code":75003,"message":"活动已结束","ttl":1} // {"code":0,"message":"0","ttl":1} + $de_raw = json_decode($raw, true); + Log::notice("增加抽奖机会#{$action_type} {$raw}"); + if ($de_raw['code'] == 0) { return true; } @@ -192,11 +215,10 @@ class ActivityLottery 'origin' => 'https://www.bilibili.com', 'referer' => $referer ]; - $user_info = User::parseCookies(); $payload = [ 'sid' => $sid, 'type' => 1, - 'csrf' => $user_info['token'] + 'csrf' => getCsrf() ]; $raw = Curl::post('pc', $url, $payload, $headers); $de_raw = json_decode($raw, true); diff --git a/src/plugin/AloneTcpClient.php b/src/plugin/AloneTcpClient.php index a4c6e3d..da3f3c7 100644 --- a/src/plugin/AloneTcpClient.php +++ b/src/plugin/AloneTcpClient.php @@ -32,7 +32,7 @@ class AloneTcpClient */ public static function run() { - if (self::getLock() > time() || getenv('USE_ALONE_SERVER') == 'false') { + if (self::getLock() > time() || !getEnable('alone_monitor')) { return; } self::setPauseStatus(); @@ -41,36 +41,33 @@ class AloneTcpClient self::receive(); } - /** * @use 初始化 */ private static function init() { - if (empty(getenv('ALONE_SERVER_ADDR')) || empty(getenv('ALONE_SERVER_KEY'))) { + if (empty(getConf('server_addr', 'alone_monitor')) || empty(getConf('server_key', 'alone_monitor'))) { exit('推送服务器信息不完整, 请检查配置文件!'); } if (!self::$server_addr || !self::$server_key) { - self::$server_addr = getenv('ALONE_SERVER_ADDR'); - self::$server_key = getenv('ALONE_SERVER_KEY'); + self::$server_addr = getConf('server_addr', 'alone_monitor'); + self::$server_key = getConf('server_key', 'alone_monitor'); } if (!self::$client) { self::openConnect(); } } - /** * @use 数据封装 * @param $value * @param $fmt * @return string */ - private static function packMsg($value, $fmt = "N") + private static function packMsg($value, $fmt = "N"): string { $head = pack($fmt, strlen($value)); - $data = $head . $value; - return $data; + return $head . $value; } /** @@ -117,7 +114,7 @@ class AloneTcpClient /** * @use 读数据 * @param $length - * @return array|bool|false + * @return array|bool */ private static function reader($length) { @@ -142,7 +139,7 @@ class AloneTcpClient * @param $data * @return bool */ - private static function writer($data) + private static function writer($data): bool { $status = false; try { @@ -157,7 +154,6 @@ class AloneTcpClient return $status; } - /** * @use 打开连接 */ @@ -202,7 +198,6 @@ class AloneTcpClient self::$client = null; } - /** * @use 读取数据 */ @@ -216,8 +211,8 @@ class AloneTcpClient Log::debug("(len=$len_body)"); $body = self::reader($len_body); $raw_data = json_decode($body, true); - // 人气值(或者在线人数或者类似)以及心跳 - $data_type = $raw_data['type']; + // 数据可能出现不全 DECODE返回NULL 索引错误 交给default处理 + $data_type = is_null($raw_data) ? "unknown" : $raw_data['type']; switch ($data_type) { case 'raffle': // 抽奖推送 @@ -260,16 +255,16 @@ class AloneTcpClient // 服务器发布命令 Log::error("服务器发布退出命令 {$raw_data['data']['msg']}"); exit(); - break; default: // 未知信息 var_dump($raw_data); Log::info("出现未知信息 {$body}"); + // 出现未知信息 处理重连 防止内存益处 + self::reConnect(); break; } } - /** * @use 写入log * @param $message @@ -281,7 +276,7 @@ class AloneTcpClient mkdir($path); chmod($path, 0777); } - $filename = $path . getenv('APP_USER') . ".log"; + $filename = $path . getConf('username', 'login.account') . ".log"; $date = date('[Y-m-d H:i:s] '); $data = "[{$date}]{$message}" . PHP_EOL; file_put_contents($filename, $data, FILE_APPEND); diff --git a/src/plugin/AnchorRaffle.php b/src/plugin/AnchorRaffle.php index 5d44579..85ef140 100644 --- a/src/plugin/AnchorRaffle.php +++ b/src/plugin/AnchorRaffle.php @@ -12,13 +12,12 @@ namespace BiliHelper\Plugin; use BiliHelper\Core\Log; use BiliHelper\Core\Curl; -use BiliHelper\Util\TimeLock; use BiliHelper\Util\BaseRaffle; class AnchorRaffle extends BaseRaffle { const ACTIVE_TITLE = '天选时刻'; - const ACTIVE_SWITCH = 'USE_ANCHOR'; + const ACTIVE_SWITCH = 'live_anchor'; protected static $wait_list = []; protected static $finish_list = []; @@ -62,10 +61,10 @@ class AnchorRaffle extends BaseRaffle $tags = User::fetchTags(); $tag_id = array_search(self::$group_name, $tags); // 如果不存在则调用创建 - self::$group_id = $tag_id ? $tag_id : User::createRelationTag(self::$group_name); + self::$group_id = $tag_id ?: User::createRelationTag(self::$group_name); } // 获取需要关注的 - $data = Live::getRoomInfo($room_id); + $data = Live::getRoomInfoV1($room_id); if ($data['code'] == 0 && isset($data['data'])) { $need_follow_uid = $data['data']['uid']; } else { @@ -102,7 +101,6 @@ class AnchorRaffle extends BaseRaffle self::$wait_un_follows = $new_list; } - /** * @use 获取默认关注 * @return array @@ -120,7 +118,6 @@ class AnchorRaffle extends BaseRaffle return self::$default_follows; } - /** * @use 过滤奖品 * @param string $prize_name @@ -129,7 +126,7 @@ class AnchorRaffle extends BaseRaffle protected static function filterPrizeWords(string $prize_name): bool { $default_words = self::$store->get("Anchor.default"); - $custom_words = empty(getenv('ANCHOR_FILTER_WORDS')) ? [] : explode(',', getenv('ANCHOR_FILTER_WORDS')); + $custom_words = empty($words = getConf('filter_words', 'live_anchor')) ? [] : explode(',', $words); $total_words = array_merge($default_words, $custom_words); foreach ($total_words as $word) { if (strpos($prize_name, $word) !== false) { @@ -160,7 +157,7 @@ class AnchorRaffle extends BaseRaffle return false; } // 过滤抽奖范围 - self::$filter_type = empty(self::$filter_type) ? explode(',', getenv('ANCHOR_TYPE')) : self::$filter_type; + self::$filter_type = empty(self::$filter_type) ? explode(',', getConf('limit_type', 'live_anchor')) : self::$filter_type; if (!in_array((string)$de_raw['require_type'], self::$filter_type)) { return false; } @@ -173,7 +170,7 @@ class AnchorRaffle extends BaseRaffle return false; } // 分组操作 - if (getenv('ANCHOR_UNFOLLOW') == 'true' && $de_raw['require_text'] == '关注主播') { + if (getConf('auto_unfollow', 'live_anchor') && $de_raw['require_text'] == '关注主播') { self::addToGroup($room_id, $de_raw['id'], time() + $de_raw['time'] + 5); } // 推入列表 @@ -189,7 +186,6 @@ class AnchorRaffle extends BaseRaffle return true; } - /** * @use 创建抽奖任务 * @param array $raffles @@ -199,15 +195,13 @@ class AnchorRaffle extends BaseRaffle { $url = 'https://api.live.bilibili.com/xlive/lottery-interface/v1/Anchor/Join'; $tasks = []; - $results = []; - $user_info = User::parseCookies(); foreach ($raffles as $raffle) { $payload = [ 'id' => $raffle['raffle_id'], 'roomid' => $raffle['room_id'], 'platform' => 'pc', - 'csrf_token' => $user_info['token'], - 'csrf' => $user_info['token'], + 'csrf_token' => getCsrf(), + 'csrf' => getCsrf(), 'visit_id' => '' ]; array_push($tasks, [ @@ -219,15 +213,14 @@ class AnchorRaffle extends BaseRaffle ] ]); } - $results = Curl::async('app', $url, $tasks); // print_r($results); - return $results; + return Curl::async('app', $url, $tasks); } /** * @use 解析抽奖信息 * @param array $results - * @return mixed|void + * @return void */ protected static function parseLottery(array $results) { diff --git a/src/plugin/AwardRecord.php b/src/plugin/AwardRecord.php index 3a30903..cd775eb 100644 --- a/src/plugin/AwardRecord.php +++ b/src/plugin/AwardRecord.php @@ -25,10 +25,9 @@ class AwardRecord private static $gift_lock = 0; private static $gift_list = []; - public static function run() { - if (self::getLock() > time()) { + if (self::getLock() > time() || !getEnable('award_record')) { return; } if (self::$anchor_lock < time()) { @@ -43,7 +42,6 @@ class AwardRecord self::setLock(5 * 60); } - /** * @use 获取天选时刻中奖纪录 */ @@ -83,7 +81,7 @@ class AwardRecord } if (in_array($wait_un_follow['anchor_id'], self::$anchor_list)) { AnchorRaffle::delToGroup($wait_un_follow['uid'], $wait_un_follow['anchor_id'], false); - }else{ + } else { AnchorRaffle::delToGroup($wait_un_follow['uid'], $wait_un_follow['anchor_id'], true); } } @@ -91,7 +89,6 @@ class AwardRecord self::$anchor_lock = time() + 6 * 60 * 60; } - /** * @use 获取实物抽奖中奖纪录 */ @@ -129,7 +126,6 @@ class AwardRecord self::$raffle_lock = time() + 6 * 60 * 60; } - /** * @use 获取活动礼物中奖纪录 */ diff --git a/src/plugin/Barrage.php b/src/plugin/Barrage.php index dd8d674..fb777ec 100644 --- a/src/plugin/Barrage.php +++ b/src/plugin/Barrage.php @@ -20,69 +20,41 @@ class Barrage public static function run() { - if (self::getLock() > time() || getenv('USE_DANMU') == 'false') { + if (self::getLock() > time() || !getEnable('barrage')) { return; } self::setPauseStatus(); - $room_id = empty(getenv('DANMU_ROOMID')) ? Live::getUserRecommend() : Live::getRealRoomID(getenv('DANMU_ROOMID')); - $msg = empty(getenv('DANMU_CONTENT')) ? self::getMsgInfo() : getenv('DANMU_CONTENT'); - - $info = [ - 'roomid' => $room_id, - 'content' => $msg, - ]; - - if (self::privateSendMsg($info)) { - self::setLock(mt_rand(40, 60) * 60); + if (self::sendMsg()) { + self::setLock(mt_rand(40, 80) * 60); return; } - - self::setLock(30); + self::setLock(15 * 60); } /** - * @use 获取颜文字信息 + * 获取一言api消息 + * @param bool $sep * @return string */ - private static function getEmojiMsg(): string - { - $emoji_list = [ - "(⌒▽⌒)", "( ̄▽ ̄)", "(=・ω・=)", "(`・ω・´)", "(〜 ̄△ ̄)〜", "(・∀・)", - "(°∀°)ノ", "( ̄3 ̄)", "╮( ̄▽ ̄)╭", "_(:3」∠)_", "( ´_ゝ`)", "←_←", "→_→", - "(<_<)", "(>_>)", "(;¬_¬)", '("▔□▔)/', "(゚Д゚≡゚д゚)!?", "Σ(゚д゚;)", "Σ(  ̄□ ̄||)", - "(´;ω;`)", "(/TДT)/", "(^・ω・^ )", "(。・ω・。)", "(● ̄(エ) ̄●)", "ε=ε=(ノ≧∇≦)ノ", - "(´・_・`)", "(-_-#)", "( ̄へ ̄)", "( ̄ε(# ̄) Σ", "ヽ(`Д´)ノ", "(#-_-)┯━┯", - "(╯°口°)╯(┴—┴", "←◡←", "( ♥д♥)", "Σ>―(〃°ω°〃)♡→", "⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄", - "(╬゚д゚)▄︻┻┳═一", "・*・:≡( ε:)", "(打卡)", "(签到)" - ]; - shuffle($emoji_list); - return $emoji_list[array_rand($emoji_list)]; - } - - - /** - * @use 获取一言api消息 - * @return string - */ - private static function getMsgInfo():string + private static function getMsgInfo(bool $sep = true): string { /** * 整理一部分API,收集于网络,侵权麻烦联系我删除. * 如果设置项不能用可以选择,只保证代码发布时正常. * 格式全部为TEXT,可以自己替换. */ - $punctuations = [',', ',', '。', '!', '.', ';', '——']; + $punctuations = $sep ? [',', ',', '。', '!', '.', ';', '——'] : []; $apis = [ - 'https://api.ly522.com/yan.php?format=text', 'https://v1.hitokoto.cn/?encode=text', + 'https://api.ly522.com/Api/YiYan?format=text', 'https://api.jysafe.cn/yy/', 'https://api.imjad.cn/hitokoto/', 'https://www.ly522.com/hitokoto/', 'https://api.guoch.xyz/', 'https://api.gushi.ci/rensheng.txt', 'https://api.itswincer.com/hitokoto/v2/', -// 'http://www.ooomg.cn/dutang/', -// 'http://api.dsecret.com/yiyan/', + // 'http://www.ooomg.cn/dutang/', + // 'http://api.dsecret.com/yiyan/', ]; shuffle($apis); try { @@ -102,45 +74,24 @@ class Barrage } } - /** - * @use 弹幕通用模块 - * @param $info - * @return array - */ - private static function sendMsg($info): array - { - $user_info = User::parseCookies(); - $url = 'https://api.live.bilibili.com/msg/send'; - $data = Live::getRoomInfo($info['roomid']); - $payload = [ - 'color' => '16777215', - 'fontsize' => 25, - 'mode' => 1, - 'msg' => $info['content'], - 'rnd' => 0, - 'roomid' => $data['data']['room_id'], - 'csrf' => $user_info['token'], - 'csrf_token' => $user_info['token'], - ]; - $raw = Curl::post('app', $url, Sign::common($payload)); - return json_decode($raw, true) ?? ['code' => 404, 'msg' => '上层数据为空!']; - } - - /** - * @use 发送弹幕模块 - * @param $info + * @use 活跃弹幕 * @return bool */ - private static function privateSendMsg($info): bool + private static function sendMsg(): bool { - //TODO 短期功能 有需求就修改 - $response = self::sendMsg($info); - if (isset($response['code']) && $response['code'] == 0) { - Log::info('弹幕发送成功'); + $room_id = empty($room_id = getConf('room_id', 'barrage')) ? Live::getUserRecommend() : Live::getRealRoomID($room_id); + $content = empty($msg = getConf('content', 'barrage')) ? self::getMsgInfo() : $msg; + + $response = Live::sendBarragePC($room_id, $content); + // {"code":0,"data":[],"message":"","msg":""} + // {"code":0,"message":"你被禁言啦","msg":"你被禁言啦"} + // Todo 长度限制 + if (isset($response['code']) && $response['code'] == 0 && isset($response['data'])) { + Log::notice("在直播间@{$room_id} 发送活跃弹幕成功 CODE -> {$response['code']}"); return true; } else { - Log::warning("弹幕发送失败, CODE -> {$response['code']} MSG -> {$response['msg']} "); + Log::warning("在直播间@{$room_id} 发送活跃弹幕失败 CODE -> {$response['code']} MSG -> {$response['message']} "); return false; } } diff --git a/src/plugin/BpConsumption.php b/src/plugin/BpConsumption.php new file mode 100644 index 0000000..ca34fd3 --- /dev/null +++ b/src/plugin/BpConsumption.php @@ -0,0 +1,148 @@ + time() || !getEnable('bp_consumption')) { + return; + } + // 定时14点 + 随机120分钟| 根据逻辑前置 + self::setLock(self::timing(14) + mt_rand(1, 120) * 60); + + // 如果为年度大会员 + if (User::isYearVip()) { + // 获取B币余额 + $bp_balance = self::getUserWallet(); + // 最大支持5 + if ($bp_balance != 5) return; + // 消费B币充电 + if (getConf('bp2charge', 'bp_consumption')) { + // UID为空就切换成自己的 + $uid = empty($uid = getConf('bp2charge_uid', 'bp_consumption')) ? getUid() : $uid; + self::BP2charge($uid, $bp_balance); + return; + } + // 消费B币充值金瓜子 + if (getConf('bp2gold', 'bp_consumption')) { + self::BP2gold($bp_balance); + return; + } + } + } + + /** + * @use 获取钱包B币券余额 + * @return int + */ + private static function getUserWallet(): int + { + $url = 'https://pay.bilibili.com/paywallet/wallet/getUserWallet'; + $headers = [ + 'Content-Type' => 'application/json;charset=utf-8', + 'origin' => 'https://pay.bilibili.com', + 'referer' => 'https://pay.bilibili.com/paywallet-fe/bb_balance.html' + ]; + $ts = Common::getMillisecond(); + $payload = [ + 'panelType' => 3, + 'platformType' => 3, + 'timestamp' => $ts, + 'traceId' => $ts, + 'version' => "1.0", + ]; + $raw = Curl::put('pc', $url, $payload, $headers); + // {"errno":0,"msg":"SUCCESS","showMsg":"","errtag":0,"data":{"mid":1234,"totalBp":5.00,"defaultBp":0.00,"iosBp":0.00,"couponBalance":5.00,"availableBp":5.00,"unavailableBp":0.00,"unavailableReason":"苹果设备上充值的B币不能在其他平台的设备上进行使用","tip":null}} + $de_raw = json_decode($raw, true); + if ($de_raw['errno'] == 0 && isset($de_raw['data']['couponBalance'])) { + Log::notice('获取钱包成功 B币券余额剩余' . $de_raw['data']['couponBalance']); + return intval($de_raw['data']['couponBalance']); + } else { + Log::warning("获取钱包失败 {$raw}"); + return 0; + } + } + + /** + * @use B币充电 + * @param int $uid + * @param int $num + */ + private static function BP2charge(int $uid, int $num = 5) + { + $url = 'https://api.bilibili.com/x/ugcpay/web/v2/trade/elec/pay/quick'; + $payload = [ + 'bp_num' => $num, // 数量 + 'is_bp_remains_prior' => true, // 是否优先扣除B币余额 + 'up_mid' => $uid, // 目标UID + 'otype' => 'up', // 来源 up:空间充电 archive:视频充电 + 'oid' => $uid, // 目标UID or 稿件avid + 'csrf' => getCsrf() + ]; + $raw = Curl::post('pc', $url, $payload); + // {"code":0,"message":"0","ttl":1,"data":{"mid":12324,"up_mid":1234,"order_no":"ABCD","bp_num":2,"exp":2,"status":4,"msg":""}} + $de_raw = json_decode($raw, true); + if ($de_raw['code'] == 0) { + // data.status 4 成功 -2:低于20电池下限 -4:B币不足 + if ($de_raw['data']['status'] == 4) { + Log::notice("给{$uid}B币充电成功 NUM -> {$de_raw['data']['elec_num']} ORDER -> {$de_raw['data']['order_no']}"); + } else { + Log::warning("给{$uid}B币充电失败 STATUS -> {$de_raw['data']['status']} MSG -> {$de_raw['data']['msg']}"); + } + } else { + Log::warning("给{$uid}B币充电失败 CODE -> {$de_raw['code']} MSG -> {$de_raw['message']} "); + } + } + + /** + * B币充值金瓜子 + * @param int $num + */ + private static function BP2gold(int $num) + { + $url = 'https://api.live.bilibili.com/xlive/revenue/v1/order/createOrder'; + $headers = [ + 'origin' => 'https://link.bilibili.com', + 'referer' => 'https://link.bilibili.com/p/center/index' + ]; + $payload = [ + 'platform' => 'pc', + 'pay_bp' => $num * 1000, // 瓜子数量 + 'context_id' => 1, // 直播间 + 'context_type' => 11, + 'goods_id' => 1, // 商品ID + 'goods_num' => $num, // B币数量 + 'csrf_token' => getCsrf(), + 'csrf' => getCsrf(), + 'visit_id' => '', + ]; + $raw = Curl::post('pc', $url, $payload, $headers); + // {"code":1300014,"message":"b币余额不足","ttl":1,"data":null} + // {"code":0,"message":"0","ttl":1,"data":{"status":2,"order_id":"1234171134577071132741234","gold":0,"bp":5000}} + $de_raw = json_decode($raw, true); + if ($de_raw['code'] == 0) { + Log::notice("B币充值金瓜子成功 NUM -> {$de_raw['data']['bp']} ORDER -> {$de_raw['data']['order_id']}"); + } else { + Log::warning("B币充值金瓜子失败 CODE -> {$de_raw['code']} MSG -> {$de_raw['message']}"); + } + } + +} \ No newline at end of file diff --git a/src/plugin/CapsuleLottery.php b/src/plugin/CapsuleLottery.php index fac5266..fe65cb4 100644 --- a/src/plugin/CapsuleLottery.php +++ b/src/plugin/CapsuleLottery.php @@ -13,6 +13,7 @@ namespace BiliHelper\Plugin; use BiliHelper\Core\Log; use BiliHelper\Core\Curl; +use BiliHelper\Tool\Common; use BiliHelper\Util\AllotTasks; use BiliHelper\Util\TimeLock; use BiliHelper\Util\XliveHeartBeat; @@ -35,7 +36,7 @@ class CapsuleLottery */ public static function run() { - if (self::getLock() > time() || getenv('USE_CAPSULE') == 'false') { + if (self::getLock() > time() || !getEnable('live_capsule')) { return; } self::allotTasks(); @@ -46,7 +47,6 @@ class CapsuleLottery } } - /** * @use 分配任务 * @return bool @@ -87,7 +87,6 @@ class CapsuleLottery return true; } - /** * @use 执行任务 * @return bool @@ -109,12 +108,16 @@ class CapsuleLottery Log::info("执行 {$task['act']->title} #{$task['operation']} 任务"); // 执行任务 switch ($task['operation']) { + // Todo 观看 分享 签到任务 case 'watch': - $interval = self::xliveHeartBeatTask($task['act']->room_id,999,999); + $interval = self::xliveHeartBeatTask($task['act']->room_id, 999, 999); self::$interval = $interval == 0 ? 60 : $interval; break; case 'draw': - self::doLottery($task['act']->coin_id, $task['act']->url, 0); + // 抽奖次数 > 0 开始抽奖 + if (self::getLuckyNum($task['act']->coin_id, $task['act']->url)) { + self::doLottery($task['act']->coin_id, $task['act']->url, 0); + } break; default: Log::info("当前 {$task['act']->title} #{$task['operation']} 任务不存在哦"); @@ -137,15 +140,14 @@ class CapsuleLottery 'origin' => 'https://live.bilibili.com', 'referer' => $referer ]; - $user_info = User::parseCookies(); $payload = [ 'id' => $coin_id, 'count' => 1, 'type' => 1, 'platform' => 'web', '_' => time() * 1000, - 'csrf' => $user_info['token'], - 'csrf_token' => $user_info['token'], + 'csrf' => getCsrf(), + 'csrf_token' => getCsrf(), 'visit_id' => '' ]; $raw = Curl::post('pc', $url, $payload, $headers); @@ -161,4 +163,140 @@ class CapsuleLottery } + /** + * @use 分享任务 + * @param int $act_id + * @param string $referer + */ + private static function taskShare(int $act_id, string $referer) + { + $url = 'https://api.live.bilibili.com/xlive/activity-interface/v1/task/UserShare'; + $headers = [ + 'origin' => 'https://live.bilibili.com', + 'referer' => 'https://live.bilibili.com/' + ]; + $payload = [ + 'act_id' => $act_id, + 'share_type' => 1, + 'csrf_token' => getCsrf(), + 'csrf' => getCsrf(), + 'visit_id' => '', + ]; + $raw = Curl::post('pc', $url, $payload, $headers); + // {"code":0,"message":"0","ttl":1,"data":{"status":1}} + $de_raw = json_decode($raw, true); + } + + /** + * @use 获取扭蛋池子信息 + * @param int $pool_id + * @param string $referer + */ + private static function getPoolDetail(int $pool_id, string $referer) + { + $url = 'https://api.live.bilibili.com/xlive/web-ucenter/v1/capsule/get_pool_detail'; + $headers = [ + 'origin' => 'https://live.bilibili.com', + 'referer' => $referer + ]; + $payload = [ + 'pool_id' => $pool_id, + '_' => Common::getMillisecond() + ]; + $raw = Curl::get('pc', $url, $payload); + // {"code":0,"message":"0","ttl":1,"data":{"id":145,"coin":3,"coin_id":131,"title":"OWL2021","open_num_1":1,"open_num_2":10,"open_num_3":100,"status":0,"gift_list":[{"id":1237,"name":"谢谢参与","num":1,"web_url":"https://i0.hdslb.com/bfs/live/b0fccfb3bac2daae35d7e514a8f6d31530b9add2.png","mobile_url":"https://i0.hdslb.com/bfs/live/b0fccfb3bac2daae35d7e514a8f6d31530b9add2.png","usage":{"text":"谢谢参与","url":""},"type":32,"expire":"当天","gift_type":"7290bc172e5ab9e151eb141749adb9dd"},{"id":1238,"name":"杭州闪电队主场队服","num":1,"web_url":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","mobile_url":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","usage":{"text":"新款杭州闪电队队服","url":""},"type":100024,"expire":"当天","gift_type":"895ff9e63081033072a1bc5694d10095"},{"id":1239,"name":"上海龙之队主场队服","num":1,"web_url":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","mobile_url":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","usage":{"text":"新款上海龙之队队服","url":""},"type":100024,"expire":"当天","gift_type":"a314efd84276f0be571492823b1c0edb"},{"id":1240,"name":"广州冲锋队主场队服","num":1,"web_url":"https://i0.hdslb.com/bfs/live/cdc33523a1b018ee6af447f528c56848f5556eb8.png","mobile_url":"https://i0.hdslb.com/bfs/live/cdc33523a1b018ee6af447f528c56848f5556eb8.png","usage":{"text":"新款广州冲锋队队服","url":""},"type":100024,"expire":"当天","gift_type":"6d46360bc93b8b07b4c64efb9350579a"},{"id":1241,"name":"谢谢参与","num":1,"web_url":"https://i0.hdslb.com/bfs/live/b0fccfb3bac2daae35d7e514a8f6d31530b9add2.png","mobile_url":"https://i0.hdslb.com/bfs/live/b0fccfb3bac2daae35d7e514a8f6d31530b9add2.png","usage":{"text":"谢谢参与","url":""},"type":32,"expire":"当天","gift_type":"7290bc172e5ab9e151eb141749adb9dd"},{"id":1242,"name":"成都猎人队主场队服","num":1,"web_url":"https://i0.hdslb.com/bfs/live/625c55aa7a020040466cc7a842ea0c57ac4f484c.png","mobile_url":"https://i0.hdslb.com/bfs/live/625c55aa7a020040466cc7a842ea0c57ac4f484c.png","usage":{"text":"新款成都猎人队队服","url":""},"type":100024,"expire":"当天","gift_type":"51ecabc603848979410202a93391cd35"},{"id":1243,"name":"随机战队客场队服","num":1,"web_url":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","mobile_url":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","usage":{"text":"随机一件OWL战队客场队服","url":""},"type":100024,"expire":"当天","gift_type":"b2ec92156e57708caf923b1c18309fea"},{"id":1244,"name":"哔哩哔哩月度大会员","num":1,"web_url":"https://i0.hdslb.com/bfs/live/49b6d12eadc81acf68d5378b257df78ec38b4355.png","mobile_url":"https://i0.hdslb.com/bfs/live/49b6d12eadc81acf68d5378b257df78ec38b4355.png","usage":{"text":"bilibili月度大会员","url":""},"type":100024,"expire":"当天","gift_type":"78db25f308b8b8db86ba1a172c2deb35"}],"is_login":true,"list":[{"num":1,"gift":"哔哩哔哩月度大会员","date":"2021-05-10","name":"初夏的戏匣子","web_image":"https://i0.hdslb.com/bfs/live/49b6d12eadc81acf68d5378b257df78ec38b4355.png","mobile_image":"https://i0.hdslb.com/bfs/live/49b6d12eadc81acf68d5378b257df78ec38b4355.png","count":1},{"num":1,"gift":"杭州闪电队主场队服","date":"2021-05-10","name":"hentaiDIAO","web_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","mobile_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","count":1},{"num":1,"gift":"随机战队客场队服","date":"2021-05-10","name":"哗哗はな","web_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","mobile_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","count":10},{"num":1,"gift":"杭州闪电队主场队服","date":"2021-05-10","name":"Promissio小约定","web_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","mobile_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","count":1},{"num":1,"gift":"上海龙之队主场队服","date":"2021-05-10","name":"小新笔记","web_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","mobile_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","count":10},{"num":1,"gift":"广州冲锋队主场队服","date":"2021-05-10","name":"晚来天欲雪yyy","web_image":"https://i0.hdslb.com/bfs/live/cdc33523a1b018ee6af447f528c56848f5556eb8.png","mobile_image":"https://i0.hdslb.com/bfs/live/cdc33523a1b018ee6af447f528c56848f5556eb8.png","count":1},{"num":1,"gift":"成都猎人队主场队服","date":"2021-05-10","name":"Histo2y","web_image":"https://i0.hdslb.com/bfs/live/625c55aa7a020040466cc7a842ea0c57ac4f484c.png","mobile_image":"https://i0.hdslb.com/bfs/live/625c55aa7a020040466cc7a842ea0c57ac4f484c.png","count":1},{"num":1,"gift":"随机战队客场队服","date":"2021-05-10","name":"蜀黍我最怕亏钱啦","web_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","mobile_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","count":1},{"num":1,"gift":"上海龙之队主场队服","date":"2021-05-10","name":"国王大道修车师傅","web_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","mobile_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","count":10},{"num":1,"gift":"杭州闪电队主场队服","date":"2021-05-10","name":"丁马的早晨","web_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","mobile_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","count":10},{"num":1,"gift":"随机战队客场队服","date":"2021-05-10","name":"丁马的早晨","web_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","mobile_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","count":10},{"num":1,"gift":"上海龙之队主场队服","date":"2021-05-10","name":"-St-John","web_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","mobile_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","count":10},{"num":1,"gift":"哔哩哔哩月度大会员","date":"2021-05-03","name":"那个臭打游戏的","web_image":"https://i0.hdslb.com/bfs/live/49b6d12eadc81acf68d5378b257df78ec38b4355.png","mobile_image":"https://i0.hdslb.com/bfs/live/49b6d12eadc81acf68d5378b257df78ec38b4355.png","count":1},{"num":1,"gift":"成都猎人队主场队服","date":"2021-05-03","name":"金小伍","web_image":"https://i0.hdslb.com/bfs/live/625c55aa7a020040466cc7a842ea0c57ac4f484c.png","mobile_image":"https://i0.hdslb.com/bfs/live/625c55aa7a020040466cc7a842ea0c57ac4f484c.png","count":1},{"num":1,"gift":"广州冲锋队主场队服","date":"2021-05-03","name":"不灵梦Blame","web_image":"https://i0.hdslb.com/bfs/live/cdc33523a1b018ee6af447f528c56848f5556eb8.png","mobile_image":"https://i0.hdslb.com/bfs/live/cdc33523a1b018ee6af447f528c56848f5556eb8.png","count":1},{"num":1,"gift":"随机战队客场队服","date":"2021-05-03","name":"幻化叶之韵","web_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","mobile_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","count":10},{"num":1,"gift":"上海龙之队主场队服","date":"2021-05-03","name":"-莉娅菠萝-","web_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","mobile_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","count":10},{"num":1,"gift":"杭州闪电队主场队服","date":"2021-05-03","name":"康斯坦丁Constantine.","web_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","mobile_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","count":1},{"num":1,"gift":"随机战队客场队服","date":"2021-05-03","name":"夜魅三清","web_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","mobile_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","count":1},{"num":1,"gift":"上海龙之队主场队服","date":"2021-05-03","name":"夜魅三清","web_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","mobile_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","count":1},{"num":1,"gift":"随机战队客场队服","date":"2021-05-03","name":"蓝岚染","web_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","mobile_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","count":10},{"num":1,"gift":"杭州闪电队主场队服","date":"2021-05-03","name":"用了五级经验卡","web_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","mobile_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","count":1},{"num":1,"gift":"上海龙之队主场队服","date":"2021-05-03","name":"蜀黍我最怕亏钱啦","web_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","mobile_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","count":10},{"num":1,"gift":"杭州闪电队主场队服","date":"2021-05-03","name":"aii01992","web_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","mobile_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","count":10},{"num":1,"gift":"哔哩哔哩月度大会员","date":"2021-04-26","name":"妄想逃离现实的星轨君","web_image":"https://i0.hdslb.com/bfs/live/49b6d12eadc81acf68d5378b257df78ec38b4355.png","mobile_image":"https://i0.hdslb.com/bfs/live/49b6d12eadc81acf68d5378b257df78ec38b4355.png","count":1},{"num":1,"gift":"杭州闪电队主场队服","date":"2021-04-26","name":"乌鲁乌鲁崽","web_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","mobile_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","count":1},{"num":1,"gift":"上海龙之队主场队服","date":"2021-04-26","name":"思维回廊","web_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","mobile_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","count":1},{"num":1,"gift":"随机战队客场队服","date":"2021-04-26","name":"思维回廊","web_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","mobile_image":"https://i0.hdslb.com/bfs/live/2198f9659645d28a7fc20c15e93f050a30706016.png","count":1},{"num":1,"gift":"上海龙之队主场队服","date":"2021-04-26","name":"LilPank","web_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","mobile_image":"https://i0.hdslb.com/bfs/live/1e53fc5f1f13c1e2e30eaa7504bc0d939e77df42.png","count":10},{"num":1,"gift":"杭州闪电队主场队服","date":"2021-04-26","name":"一日学滴滴","web_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","mobile_image":"https://i0.hdslb.com/bfs/live/e7cc2043c85c43f8bdd338a693eef3fe3fc18757.png","count":10}]}} + $de_raw = json_decode($raw, true); + } + + /** + * @use 获取扭蛋信息 + * @param int $coin_id + * @param string $referer + * @return array + */ + private static function getCapsuleInfo(int $coin_id, string $referer): array + { + $url = 'https://api.live.bilibili.com/xlive/web-ucenter/v1/capsule/get_capsule_info_v3'; + $headers = [ + 'origin' => 'https://live.bilibili.com', + 'referer' => $referer + ]; + $payload = [ + 'id' => $coin_id, + 'from' => 'web', + '-' => Common::getMillisecond() + ]; + $raw = Curl::get('pc', $url, $payload, $headers); + // data -> status 0||2 + // {"code":0,"message":"0","ttl":1,"data":{"coin":9,"rule":"2020年英雄联盟职业联赛春季赛抽奖奖池","gift_list":[{"name":"辣条","num":1,"web_url":"https://i0.hdslb.com/bfs/live/48605b0fe9eca5aba87f93da0fa0aa361c419835.png","mobile_url":"https://i0.hdslb.com/bfs/live/8e7a4dc8de374faee22fca7f9a3f801a1712a36b.png","usage":{"text":"辣条是一种直播虚拟礼物,可以在直播间送给自己喜爱的主播哦~","url":""},"type":1,"expire":"3天","gift_type":"325a347f91903c0353385e343dd358f0"},{"name":"3天头衔续期卡","num":1,"web_url":"https://i0.hdslb.com/bfs/live/48aecec2d7243b6f8bd17f20ff715db89f9adcec.png","mobile_url":"https://i0.hdslb.com/bfs/live/48aecec2d7243b6f8bd17f20ff715db89f9adcec.png","usage":{"text":"3天头衔续期卡*1","url":""},"type":21,"expire":"1周","gift_type":"4bda2f960342d86a426ebc067d3633ed"},{"name":"LPL2020助威","num":1,"web_url":"https://i0.hdslb.com/bfs/live/d9ee9558fcc438c99deb00ed1f6bd3707bac3452.png","mobile_url":"https://i0.hdslb.com/bfs/live/d9ee9558fcc438c99deb00ed1f6bd3707bac3452.png","usage":{"text":"2020LPL限定头衔","url":""},"type":2,"expire":"1周","gift_type":"b114c47920fce2aca5fca7a27cca5915"},{"name":"随机英雄联盟角色手办","num":1,"web_url":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_url":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","usage":{"text":"随机英雄联盟角色手办*1","url":""},"type":100024,"expire":"当天","gift_type":"6a4ae5853753d67d07cea2b1750795f4"},{"name":"2020LPL彩色弹幕","num":1,"web_url":"https://i0.hdslb.com/bfs/live/9a571f9d82c2a8cbbe869fd92796e70b19f9c2cc.png","mobile_url":"https://i0.hdslb.com/bfs/live/9a571f9d82c2a8cbbe869fd92796e70b19f9c2cc.png","usage":{"text":"LPL专属彩色弹幕","url":""},"type":20,"expire":"3天","gift_type":"14e40c6949800b5d840011e47e54d0c5"},{"name":"7天头衔续期卡","num":1,"web_url":"https://i0.hdslb.com/bfs/live/a2ffb62dc90d4896ddc3d1dcdbe83ac5d1dd7328.png","mobile_url":"https://i0.hdslb.com/bfs/live/a2ffb62dc90d4896ddc3d1dcdbe83ac5d1dd7328.png","usage":{"text":"7天头衔续期卡*1","url":""},"type":21,"expire":"1周","gift_type":"bbfc114b65126486a40c81daedd911e5"},{"name":"2020LPL春季赛助威券","num":1,"web_url":"https://i0.hdslb.com/bfs/live/be4cdecc4809caf8aa21817880a3283672b5a477.png","mobile_url":"https://i0.hdslb.com/bfs/live/be4cdecc4809caf8aa21817880a3283672b5a477.png","usage":{"text":"再来一次!(✪ω✪)","url":""},"type":22,"expire":"当天","gift_type":"96d2b8187ec6564fa40733153a41ac14"},{"name":"30天头衔续期卡","num":1,"web_url":"https://i0.hdslb.com/bfs/live/fc49e08115db6edd0276fba69ed8835a64714441.png","mobile_url":"https://i0.hdslb.com/bfs/live/fc49e08115db6edd0276fba69ed8835a64714441.png","usage":{"text":"30天头衔续期卡*1","url":""},"type":21,"expire":"1周","gift_type":"02810fd04244c47952bd4ed0b35617db"},{"name":"辣条","num":233,"web_url":"https://i0.hdslb.com/bfs/live/48605b0fe9eca5aba87f93da0fa0aa361c419835.png","mobile_url":"https://i0.hdslb.com/bfs/live/8e7a4dc8de374faee22fca7f9a3f801a1712a36b.png","usage":{"text":"辣条是一种直播虚拟礼物,可以在直播间送给自己喜爱的主播哦~","url":""},"type":1,"expire":"3天","gift_type":"a6d260760dfb1fe9f5375b3c8c7bd7ad"},{"name":"随机提伯斯熊毛绒公仔","num":1,"web_url":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_url":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","usage":{"text":"提伯斯熊毛绒公仔*1","url":""},"type":100024,"expire":"当天","gift_type":"2df71ff3306a4a2b4a627889cbd63c5b"}],"change_num":10000,"status":0,"is_login":true,"user_score":90000,"list":[{"num":1,"gift":"随机英雄联盟角色手办","date":"2020-04-23","name":"nXBo7p0svjm","web_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","count":1},{"num":1,"gift":"随机提伯斯熊毛绒公仔","date":"2020-04-20","name":"z98rwt","web_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","count":1},{"num":1,"gift":"随机英雄联盟角色手办","date":"2020-04-18","name":"wBQW6Z6jgbb","web_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","count":1},{"num":1,"gift":"随机提伯斯熊毛绒公仔","date":"2020-04-13","name":"dU9449p1zkz","web_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","count":1},{"num":1,"gift":"随机英雄联盟角色手办","date":"2020-04-10","name":"ckcs8151","web_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","count":1},{"num":1,"gift":"随机提伯斯熊毛绒公仔","date":"2020-04-06","name":"l1d9fgn1gl","web_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","count":1},{"num":1,"gift":"随机提伯斯熊毛绒公仔","date":"2020-03-31","name":"rlBF7ivbffe","web_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","count":1},{"num":1,"gift":"随机英雄联盟角色手办","date":"2020-03-29","name":"卟要悔","web_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","count":1},{"num":1,"gift":"随机提伯斯熊毛绒公仔","date":"2020-03-23","name":"就这样8丶","web_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","count":1},{"num":1,"gift":"随机英雄联盟角色手办","date":"2020-03-17","name":"bIud77Vsory","web_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","count":1}]}} + return json_decode($raw, true); + } + + /** + * @获取剩余抽奖次数 + * @param int $coin_id + * @param string $referer + * @return int + */ + private static function getLuckyNum(int $coin_id, string $referer): int + { + $capsule_info = self::getCapsuleInfo($coin_id, $referer); + if ($capsule_info['code'] == 0) { + Log::info("获取剩余抽奖次数成功 {$capsule_info['data']['coin']}"); + return $capsule_info['data']['coin']; + } + Log::warning("获取剩余抽奖次数失败 {$capsule_info}"); + return 0; + } + + + /** + * @use 获取用户活动任务 + * @param int $act_id + * @param string $referer + */ + private static function userActTask(int $act_id, string $referer) + { + $url = 'https://api.live.bilibili.com/xlive/activity-interface/v1/activitytask/user_acttask/info'; + $headers = [ + 'origin' => 'https://live.bilibili.com', + 'referer' => $referer + ]; + $payload = [ + 'act_id' => $act_id, + ]; + $raw = Curl::get('pc', $url, $payload, $headers); + // {"code":0,"message":"0","ttl":1,"data":{"act_info":{"id":30008,"title":"OWL2021","desc":"","start_time":0,"end_time":0,"sys_time":1621059078,"act_status":0},"task_list":[{"task_id":19,"task_name":"分享有礼","task_desc":"每日首次分享赛事直播间","task_cycle_type":0,"task_cycle_id":20210515,"progress":{"list":[{"progress_list":[{"task_id":19,"task_type":4,"task_level":1,"target_num":1,"current_num":0,"progress_status":0,"task_status":0,"real_num":0}],"reward_list":["OWL2021补给券"],"task_status":0,"draw_status":0,"task_title":"分享有礼","task_desc":"每日首次分享赛事直播间"}],"task_map":{"4":{"task_id":19,"task_type":4,"task_level":1,"target_num":1,"current_num":0,"progress_status":0,"task_status":0,"real_num":0}},"level":0,"is_finish":0}},{"task_id":18,"task_name":"关注有礼","task_desc":"每日首次关注任意3位推荐主播","task_cycle_type":0,"task_cycle_id":20210515,"progress":{"list":[{"progress_list":[{"task_id":18,"task_type":5,"task_level":1,"target_num":3,"current_num":0,"progress_status":0,"task_status":0,"real_num":0}],"reward_list":["OWL2021补给券"],"task_status":0,"draw_status":0,"task_title":"关注有礼","task_desc":"每日首次关注任意3位推荐主播"}],"task_map":{"5":{"task_id":18,"task_type":5,"task_level":1,"target_num":3,"current_num":0,"progress_status":0,"task_status":0,"real_num":0}},"level":0,"is_finish":0}}]}} + $de_raw = json_decode($raw, true); + } + + /** + * @use 领取任务奖励 + * @param int $act_id + * @param int $task_id + * @param int $level_id + * @param int $cycle_id + * @param string $referer + */ + private static function getTaskAward(int $act_id, int $task_id, int $level_id, int $cycle_id, string $referer) + { + $url = 'https://api.live.bilibili.com/xlive/activity-interface/v1/activitytask/user_acttask/getaward'; + $headers = [ + 'origin' => 'https://live.bilibili.com', + 'referer' => $referer + ]; + $payload = [ + 'act_id' => $act_id, + 'task_id' => $task_id, + 'level_id' => 1, + 'cycle_id' => $cycle_id, + 'csrf' => getCsrf(), + 'csrf_token' => getCsrf(), + 'visit_id' => '' + ]; + $raw = Curl::post('pc', $url, $payload, $headers); + // {"code":0,"message":"0","ttl":1,"data":{}} + $de_raw = json_decode($raw, true); + + } } \ No newline at end of file diff --git a/src/plugin/CheckUpdate.php b/src/plugin/CheckUpdate.php new file mode 100644 index 0000000..53d40da --- /dev/null +++ b/src/plugin/CheckUpdate.php @@ -0,0 +1,90 @@ + time()) { + return; + } + self::check(); + self::setLock(8 * 60 * 60); + } + + /** + * @use 检查 + */ + private static function check() + { + Log::info('开始检查项目更新'); + self::loadJsonData(); + Log::info('拉取线上最新配置'); + self::fetchLatest(); + if (!self::compareVersion()) { + Log::info('项目已是最新版本'); + } else { + Log::notice('项目有更新'); + // Todo 完善提示信息 + $time = self::$latest_conf->get('time'); + $version = self::$latest_conf->get('version'); + $des = self::$latest_conf->get('des'); + $info = "最新版本-{$version}, {$des}"; + Notice::push('update', $info); + } + } + + /** + * @use 拉取最新 + */ + private static function fetchLatest() + { + $url = self::$current_conf->get('raw_url'); + $payload = []; + $raw = Curl::get('other', $url, $payload); + self::$latest_conf = Config::load($raw, new Json, true); + } + + /** + * @use 加载本地JSON DATA + */ + private static function loadJsonData() + { + self::$current_conf = Config::load(self::$repository); + } + + /** + * @use 比较版本号 + * @return bool + */ + private static function compareVersion(): bool + { + $current_version = self::$current_conf->get('version'); + $latest_version = self::$latest_conf->get('version'); + // true 有更新 false 无更新 + return !($current_version == $latest_version); + } + +} \ No newline at end of file diff --git a/src/plugin/Competition.php b/src/plugin/Competition.php index 8475ae0..3b5de39 100644 --- a/src/plugin/Competition.php +++ b/src/plugin/Competition.php @@ -23,22 +23,20 @@ class Competition */ public static function run() { - if (getenv('USE_COMPETITION') == 'false' || self::getLock() > time()) { + if (self::getLock() > time() || !getEnable('match_forecast')) { return; } self::startStake(); - - self::setLock(self::timing(1,30)); + self::setLock(self::timing(1, 30)); } - /** * @use 开始破产 */ private static function startStake() { $questions = self::fetchQuestions(); - $max_guess = intval(getenv('COMPET_MAX_NUM')); + $max_guess = getConf('max_num', 'match_forecast'); foreach ($questions as $index => $question) { if ($index >= $max_guess) { break; @@ -56,7 +54,6 @@ class Competition { Log::info($guess['title']); Log::info($guess['estimate']); - $user_info = User::parseCookies(); $url = 'https://api.bilibili.com/x/esports/guess/add'; $payload = [ 'oid' => $guess['oid'], @@ -64,7 +61,7 @@ class Competition 'detail_id' => $guess['detail_id'], 'count' => $guess['count'], 'is_fav' => 0, - 'csrf' => $user_info['token'] + 'csrf' => getCsrf() ]; $headers = [ 'origin' => 'https://www.bilibili.com', @@ -80,7 +77,6 @@ class Competition } } - /** * @use 预计猜测结果 * @param array $question @@ -92,13 +88,13 @@ class Competition $guess['oid'] = $question['contest']['id']; $guess['main_id'] = $question['questions'][0]['id']; $details = $question['questions'][0]['details']; - $guess['count'] = intval(in_array(getenv('COMPET_MAX_COIN'), range(1, 10)) ? getenv('COMPET_MAX_COIN') : 10); + $guess['count'] = ($count = getConf('max_coin', 'match_forecast') <= 10) ? $count : 10; $guess['title'] = $question['questions'][0]['title']; foreach ($details as $detail) { $guess['title'] .= " 队伍: {$detail['option']} 赔率: {$detail['odds']}"; } array_multisort(array_column($details, "odds"), SORT_ASC, $details); - switch (intval(getenv('COMPET_STAKE'))) { + switch (getConf('bet', 'match_forecast')) { case 1: // 压大 $detail = array_pop($details); diff --git a/src/plugin/Daily.php b/src/plugin/Daily.php deleted file mode 100644 index 5a85b1c..0000000 --- a/src/plugin/Daily.php +++ /dev/null @@ -1,47 +0,0 @@ - time()) { - return; - } - self::dailyBag(); - self::setLock(8 * 60 * 60); - } - - /** - * @use 领取每日包裹 - */ - private static function dailyBag() - { - $url = 'https://api.live.bilibili.com/gift/v2/live/receive_daily_bag'; - $payload = []; - $data = Curl::get('app', $url, Sign::common($payload)); - $data = json_decode($data, true); - - if (isset($data['code']) && $data['code']) { - Log::warning('每日礼包领取失败!', ['msg' => $data['message']]); - } else { - Log::notice('每日礼包领取成功'); - } - } - -} diff --git a/src/plugin/DailyBag.php b/src/plugin/DailyBag.php new file mode 100644 index 0000000..9113d90 --- /dev/null +++ b/src/plugin/DailyBag.php @@ -0,0 +1,67 @@ + time() || !getEnable('daily_bag')) { + return; + } + self::dailyBagPC(); + self::dailyBagAPP(); + self::setLock(12 * 60 * 60); + } + + /** + * @use 领取每日包裹PC + */ + private static function dailyBagPC() + { + sleep(1); + $url = 'https://api.live.bilibili.com/gift/v2/live/receive_daily_bag'; + $payload = []; + $data = Curl::get('app', $url, Sign::common($payload)); + $data = json_decode($data, true); + + if (isset($data['code']) && $data['code']) { + Log::warning('[PC] 日常/周常礼包领取失败', ['msg' => $data['message']]); + } else { + Log::notice('[PC] 日常/周常礼包领取成功'); + } + } + + /** + * @use 领取每日包裹APP + */ + private static function dailyBagAPP() + { + sleep(1); + $url = 'https://api.live.bilibili.com/AppBag/sendDaily'; + $payload = []; + $data = Curl::get('app', $url, Sign::common($payload)); + $data = json_decode($data, true); + + if (isset($data['code']) && $data['code']) { + Log::warning('[APP] 日常/周常礼包领取失败', ['msg' => $data['message']]); + } else { + Log::notice('[APP] 日常/周常礼包领取成功'); + } + } + +} diff --git a/src/plugin/DailyTask.php b/src/plugin/DailyTask.php index 3274374..368735b 100644 --- a/src/plugin/DailyTask.php +++ b/src/plugin/DailyTask.php @@ -20,7 +20,7 @@ class DailyTask public static function run() { - if (self::getLock() > time()) { + if (self::getLock() > time() || !getEnable('daily_task')) { return; } @@ -31,8 +31,7 @@ class DailyTask if (isset($data['data']['sign_info'])) { self::sign_info($data['data']['sign_info']); } - - self::setLock(8 * 60 * 60); + self::setLock(mt_rand(8, 12) * 60 * 60); } /** @@ -43,13 +42,12 @@ class DailyTask { $url = 'https://api.live.bilibili.com/i/api/taskInfo'; $payload = []; - $data = Curl::get('app',$url, Sign::common($payload)); + $data = Curl::get('app', $url, Sign::common($payload)); $data = json_decode($data, true); Log::info('正在检查每日任务...'); if (isset($data['code']) && $data['code']) { Log::warning('每日任务检查失败!', ['msg' => $data['message']]); } - return $data; } @@ -65,16 +63,22 @@ class DailyTask Log::notice('该任务已完成'); return; } + $url = 'https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/DoSign'; + $headers = [ + 'origin' => 'https://link.bilibili.com', + 'referer' => 'https://link.bilibili.com/p/center/index' + ]; $url = 'https://api.live.bilibili.com/sign/doSign'; $payload = []; - $data = Curl::get('app',$url, Sign::common($payload)); + $data = Curl::get('app', $url, Sign::common($payload)); $data = json_decode($data, true); // {"code":1011040,"message":"今日已签到过,无法重复签到","ttl":1,"data":null} + // {"code":0,"message":"0","ttl":1,"data":{"text":"3000点用户经验,2根辣条","specialText":"再签到3天可以获得666银瓜子","allDays":31,"hadSignDays":2,"isBonusDay":0}} // {"code":0,"message":"0","ttl":1,"data":{"text":"3000点用户经验,2根辣条,50根辣条","specialText":"","allDays":31,"hadSignDays":20,"isBonusDay":1}} if (isset($data['code']) && $data['code']) { Log::warning("签到失败: {$data['message']}"); } else { - Log::info("签到成功: {$data['data']['text']}"); + Log::notice("签到成功: {$data['data']['text']}"); // 推送签到信息 Notice::push('todaySign', $data['data']['text']); } @@ -100,7 +104,7 @@ class DailyTask $payload = [ 'task_id' => 'double_watch_task', ]; - $data = Curl::post('app',$url, Sign::common($payload)); + $data = Curl::post('app', $url, Sign::common($payload)); $data = json_decode($data, true); if (isset($data['code']) && $data['code']) { diff --git a/src/plugin/DataTreating.php b/src/plugin/DataTreating.php index 1faef3b..20732e1 100644 --- a/src/plugin/DataTreating.php +++ b/src/plugin/DataTreating.php @@ -12,7 +12,7 @@ namespace BiliHelper\Plugin; class DataTreating { - // TODO 独立分发 Push||Pull数据 + // Todo 独立分发 Push||Pull数据 /** * @use 抽奖分发 * @param array $data diff --git a/src/plugin/Heart.php b/src/plugin/DoubleHeart.php similarity index 67% rename from src/plugin/Heart.php rename to src/plugin/DoubleHeart.php index e8cec6f..5979ca6 100644 --- a/src/plugin/Heart.php +++ b/src/plugin/DoubleHeart.php @@ -14,13 +14,13 @@ use BiliHelper\Core\Log; use BiliHelper\Core\Curl; use BiliHelper\Util\TimeLock; -class Heart +class DoubleHeart { use TimeLock; public static function run() { - if (self::getLock() > time()) { + if (self::getLock() > time() || !getEnable('double_heart')) { return; } self::setPauseStatus(); @@ -36,23 +36,22 @@ class Heart { User::webGetUserInfo(); $url = 'https://api.live.bilibili.com/User/userOnlineHeart'; - $user_info = User::parseCookies(); $payload = [ - 'csrf' => $user_info['token'], - 'csrf_token' => $user_info['token'], - 'room_id' => getenv('ROOM_ID'), + 'csrf' => getCsrf(), + 'csrf_token' => getCsrf(), + 'room_id' => getConf('room_id', 'global_room'), '_' => time() * 1000, ]; $headers = [ - 'Referer' => 'https://live.bilibili.com/' . getenv('ROOM_ID') + 'Referer' => 'https://live.bilibili.com/' . $payload['room_id'], ]; $data = Curl::post('app', $url, $payload, $headers); $data = json_decode($data, true); if (isset($data['code']) && $data['code']) { - Log::warning('WEB端 发送心跳异常!', ['msg' => $data['message']]); + Log::warning('[PC] 发送在线心跳失败', ['msg' => $data['message']]); } else { - Log::info('WEB端 发送心跳正常!'); + Log::notice('[PC] 发送在线心跳成功'); } } @@ -64,15 +63,15 @@ class Heart User::appGetUserInfo(); $url = 'https://api.live.bilibili.com/mobile/userOnlineHeart'; $payload = [ - 'room_id' => getenv('ROOM_ID'), + 'room_id' => getConf('room_id', 'global_room'), ]; $data = Curl::post('app', $url, Sign::common($payload)); $data = json_decode($data, true); if (isset($data['code']) && $data['code']) { - Log::warning('APP端 发送心跳异常!', ['msg' => $data['message']]); + Log::warning('[APP] 发送在线心跳失败', ['msg' => $data['message']]); } else { - Log::info('APP端 发送心跳正常!'); + Log::notice('[APP] 发送在线心跳成功'); } } } diff --git a/src/plugin/Dynamic.php b/src/plugin/Dynamic.php index c2ddd58..fefa5e5 100644 --- a/src/plugin/Dynamic.php +++ b/src/plugin/Dynamic.php @@ -8,11 +8,19 @@ namespace BiliHelper\Plugin; - use BiliHelper\Core\Curl; +use BiliHelper\Core\Log; +use BiliHelper\Util\FilterWords; class Dynamic { + use FilterWords; + + // Todo 活动订阅 + // https://www.bilibili.com/blackboard/activity-WeqT10t1ep.html + // https://api.vc.bilibili.com/topic_svr/v1/topic_svr/fetch_dynamics?topic_name=%E4%BA%92%E5%8A%A8%E6%8A%BD%E5%A5%96&sortby=2 + private static $tags = ['互动抽奖', '抽奖', '转发抽奖', '动态抽奖', '关注+转发']; + // 228584 14027 434405 7019788 3230836 private static $topic_list = [ 3230836 => '', @@ -26,7 +34,7 @@ class Dynamic /** * 获取抽奖话题下的帖子 */ - public static function getAwardTopic() + public static function getAwardTopic(): array { foreach (self::$topic_list as $t_id => $t_name) { @@ -37,23 +45,42 @@ class Dynamic // new foreach ($data['data']['cards'] as $article) { $article_id = $article['desc']['dynamic_id']; + // 获取 description + $card = json_decode($article['card'], true); + if (array_key_exists("description", $card['item'])) { + // 主动态 + $description = $card['item']['description']; + } elseif (array_key_exists("content", $card['item'])) { + // 子动态 + // Todo 暂时跳过 需要合适的处理方法 + // description = $card['item']['content']; + continue; + } else { + // 链接到视频的动态 少数 跳过 + // print_r($card); + continue; + } $item = [ 'uid' => $article['desc']['uid'], 'rid' => $article['desc']['rid'], 'did' => $article_id, 'tm' => $article['desc']['timestamp'], + 'desc' => $description ]; - + // 过滤为true 就跳过 + if (self::filterLayer($item)) continue; + // 不要原始desc + unset($item['desc']); self::$article_list[$article_id] = $item; } -// $has_more = 0; + // $has_more = 0; // more ?? // https://api.vc.bilibili.com/topic_svr/v1/topic_svr/topic_history?topic_name=转发抽奖&offset_dynamic_id=454347930068783808 } + print_r(count(self::$article_list)); return self::$article_list; } - /** * 动态转发 * @param $rid @@ -64,12 +91,11 @@ class Dynamic * @param string $extension * @return bool */ - public static function dynamicRepost($rid, $content = "", $type = 1, $repost_code = 3000, $from = "create.comment", $extension = '{"emoji_type":1}') + public static function dynamicRepost($rid, string $content = "", int $type = 1, int $repost_code = 3000, string $from = "create.comment", string $extension = '{"emoji_type":1}'): bool { - $user_info = User::parseCookies(); $url = "https://api.vc.bilibili.com/dynamic_repost/v1/dynamic_repost/reply"; $payload = [ - "uid" => $user_info['uid'], + "uid" => getUid(), "rid" => $rid, "type" => $type, "content" => $content, @@ -85,7 +111,6 @@ class Dynamic return false; } - /** * 发表评论 * @param int $rid @@ -94,16 +119,15 @@ class Dynamic * @param int $plat * @return bool */ - public static function dynamicReplyAdd($rid, $message = "", $type = 11, $plat = 1) + public static function dynamicReplyAdd(int $rid, string $message = "", int $type = 11, int $plat = 1): bool { - $user_info = User::parseCookies(); $url = "https://api.bilibili.com/x/v2/reply/add"; $payload = [ "oid" => $rid, "plat" => $plat, "type" => $type, "message" => $message, - "csrf" => $user_info['token'], + "csrf" => getCsrf(), ]; $raw = Curl::post('app', $url, $payload); $de_raw = json_decode($raw, true); @@ -113,19 +137,17 @@ class Dynamic return false; } - /** * 删除指定动态 * @param $did * @return bool */ - public static function removeDynamic($did) + public static function removeDynamic($did): bool { - $user_info = User::parseCookies(); $url = 'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/rm_dynamic'; $payload = [ "dynamic_id" => $did, - "csrf_token" => $user_info['token'], + "csrf_token" => getCsrf(), ]; $raw = Curl::post('app', $url, $payload); $de_raw = json_decode($raw, true); @@ -135,16 +157,14 @@ class Dynamic return false; } - /** * 获取个人发布的动态 * @param int $uid - * @return mixed + * @return array */ - public static function getMyDynamic($uid = 0) + public static function getMyDynamic(int $uid = 0): array { - $user_info = User::parseCookies(); - $uid = $uid == 0 ? $user_info['uid'] : $uid; + $uid = $uid == 0 ? getUid() : $uid; $url = "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/space_history"; $offset = ''; $has_more = true; @@ -185,7 +205,6 @@ class Dynamic } - /** * 获取抽奖动态信息 * @param $did @@ -207,10 +226,9 @@ class Dynamic * @param int $type_list * @return array|mixed */ - public static function getDynamicTab($uid = 0, $type_list = 268435455) + public static function getDynamicTab(int $uid = 0, int $type_list = 268435455) { - $user_info = User::parseCookies(); - $uid = $uid == 0 ? $user_info['uid'] : $uid; + $uid = $uid == 0 ? getUid() : $uid; $url = "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new"; $offset = ''; $has_more = true; @@ -233,6 +251,38 @@ class Dynamic } } return $card_list; + } + /** + * @use 过滤层 + * @param array $item + * @return bool + */ + protected static function filterLayer(array $item): bool + { + self::loadJsonData(); + // 过滤描述 + $default_words = self::$store->get("DynamicForward.default"); + $common_words = self::$store->get("Common.default"); + $custom_words = empty($words = getConf('filter_words', 'dynamic')) ? [] : explode(',', $words); + $total_words = array_merge($default_words, $custom_words, $common_words); + foreach ($total_words as $word) { + if (strpos($item['desc'], $word) !== false) { + Log::warning("当前动态#{$item['did']}触发关键字过滤 {$word}"); + return true; + } + } + // 过滤UID + $uid_list = self::$store->get("Common.uid_list"); + if (array_key_exists((int)$item['uid'], $uid_list)) { + Log::warning("当前动态#{$item['did']}触发UP黑名单过滤 {$item['uid']}"); + return true; + } + // 过滤粉丝数量 + if (($num = Live::getMidFollower((int)$item['uid'])) < getConf('min_fans_num', 'dynamic')) { + Log::warning("当前动态#{$item['did']}触发UP粉丝数量过滤 {$num}"); + return true; + } + return false; } } \ No newline at end of file diff --git a/src/plugin/Forward.php b/src/plugin/Forward.php index 5e93fb0..14e3e41 100644 --- a/src/plugin/Forward.php +++ b/src/plugin/Forward.php @@ -12,18 +12,16 @@ * @Blog http://blog.jianxiaodai.com * @author 菜如狗怎么了 * @date 2020-12 - */ - -/** + * * 2021-3-14 FEAT:增加自动回复语言更改 * @author:zymooll */ namespace BiliHelper\Plugin; - use BiliHelper\Core\Log; use BiliHelper\Util\TimeLock; +use Noodlehaus\Config; class Forward { @@ -40,10 +38,10 @@ class Forward private static $group_id = null; - private static $msg = '从未中奖,从未放弃[doge]'; - private static $draw_follow = []; + private static $repository = APP_DATA_PATH . 'reply_words.json'; + public static function run() { @@ -60,38 +58,24 @@ class Forward } - public static function start() + public static function start(): bool { - //更改自动回复 - if (getenv('AUTO_REPLY_TEXT') != self::$msg) { - self::changeReply(); - } // 取关未中奖 - if (getenv('CLEAR_DYNAMIC') == 'true') { + if (getConf('clear_group_follow', 'dynamic')) { self::clearDynamic(); } // 自动转发关注评论 - if (getenv('AUTO_DYNAMIC') == 'true') { + if (getConf('enable', 'dynamic')) { self::autoRepost(); } // 强制清除抽奖关注组 - if (getenv('CLEAR_GROUP_FOLLOW') == 'true') { + if (getConf('clear_group_follow', 'dynamic')) { self::clearAllDynamic(); self::clearFollowGroup(); } return true; } - /** - *更改自动回复 - */ - public static function changeReply() - { - self::$msg = getenv('AUTO_REPLY_TEXT'); - $msg = self::$msg; - Log::info("已将自动回复改为\"{$msg}\""); - } - /** * 自动转发抽奖 */ @@ -107,10 +91,10 @@ class Forward } // 评论 Log::info("[动态抽奖]-评论: {$did} {$article['rid']}"); - if (Dynamic::dynamicReplyAdd($article['rid'], self::$msg)) { + if (Dynamic::dynamicReplyAdd($article['rid'], self::getReplyMsg())) { // 转发 Log::info("[动态抽奖]-转发: {$did}"); - if (Dynamic::dynamicRepost($did, self::$msg)) { + if (Dynamic::dynamicRepost($did, self::getReplyMsg())) { // 关注 Log::info("[动态抽奖]-关注: {$did} {$article['uid']}"); self::addToGroup($article['uid']); // @@ -121,7 +105,6 @@ class Forward } } - /** * 清理无效的动态 */ @@ -198,6 +181,9 @@ class Forward } } + /** + * @use 取关 + */ private static function clearFollowGroup() { $tags = User::fetchTags(); @@ -214,20 +200,25 @@ class Forward } + /** + * @use 清理动态 + */ private static function clearAllDynamic() { $dynamicList = Dynamic::getMyDynamic(); + $msg_list = self::getReplyMsgList(); foreach ($dynamicList as $dynamic) { $did = $dynamic['desc']['dynamic_id']; $card = json_decode($dynamic['card'], true); - if (strpos($card['item']['content'], self::$msg) !== false) { - Log::info("[删除所有动态] 删除动态 {$did}"); - Dynamic::removeDynamic($did); + foreach ($msg_list as $msg) { + if (strpos($card['item']['content'], $msg) !== false) { + Log::info("[删除所有动态] 删除动态 {$did}"); + Dynamic::removeDynamic($did); + } } } } - /** * @use 添加分组 * @param int $need_follow_uid @@ -241,7 +232,7 @@ class Forward $tags = User::fetchTags(); $tag_id = array_search(self::$group_name, $tags); // 如果不存在则调用创建 - self::$group_id = $tag_id ? $tag_id : User::createRelationTag(self::$group_name); + self::$group_id = $tag_id ?: User::createRelationTag(self::$group_name); } // 是否在关注里 $default_follows = self::getDefaultFollows(); @@ -256,7 +247,7 @@ class Forward * @use 获取默认关注 * @return array */ - private static function getDefaultFollows() + private static function getDefaultFollows(): array { if (!empty(self::$default_follows)) { return self::$default_follows; @@ -268,4 +259,35 @@ class Forward } return self::$default_follows; } + + /** + * @use 获取回复 all + * @return array + */ + private static function getReplyMsgList(): array + { + $data = Config::load(self::$repository); + $data = $data->get("DynamicForward.default"); + array_push($data, getConf('auto_reply_text', 'dynamic')); + return $data; + } + + /** + * @use 获取回复 1 + * @return string + */ + private static function getReplyMsg(): string + { + //更改自动回复 + if (getConf('auto_reply_text', 'dynamic') != '') { + $msg = getConf('auto_reply_text', 'dynamic'); + } else { + $data = self::getReplyMsgList(); + shuffle($data); + $msg = array_pop($data); + } + Log::info("已将自动回复改为\"{$msg}\""); + return $msg; + } + } diff --git a/src/plugin/GameMatch.php b/src/plugin/GameMatch.php deleted file mode 100644 index be0c7df..0000000 --- a/src/plugin/GameMatch.php +++ /dev/null @@ -1,355 +0,0 @@ - [ -// 'type_id' => 25, -// 'room_id' => 7734200, -// 'short_room_id' => 6, -// 'lottery_id' => 46, -// 'status' => true -// ], -// 'OW' => [ -// 'type_id' => 26, -// 'room_id' => 14073662, -// 'short_room_id' => 76, -// 'lottery_id' => 52, -// 'status' => true -// ], -// 'KPL' => [ -// 'type_id' => 27, -// 'room_id' => 21144080, -// 'short_room_id' => 55, -// 'lottery_id' => 55, -// 'status' => true -// ], - ]; - - public static function run() - { - if (self::getLock() > time() || getenv('USE_MATCH') == 'false') { - return; - } - // TODO 赛事访问拒绝 - self::initTask(); - self::filterTask(); - self::workTask(); - self::setLock(3600); - } - - - /** - * @use 初始化任务 - */ - private static function initTask() - { - // 检查有效性 - if (!self::$check_status) { - foreach (self::$room_infos as $title => $room) { - $status = self::getCapsuleStatus($room['lottery_id'], $room['short_room_id']); - if (!$status) { - self::$room_infos[$title]['status'] = false; - } - } - self::$check_status = true; - } - } - - - /** - * @use 过滤任务 - */ - private static function filterTask() - { - // 签到任务 - foreach (self::$room_infos as $title => $room) { - if (!$room['status']) { - continue; - } - $status = self::getSignTask($room['type_id'], $room['room_id'], $room['short_room_id']); - if ($status) { - self::$room_infos[$title]['sign'] = true; - } else { - self::$room_infos[$title]['sign'] = false; - } - } - // 分享任务 - foreach (self::$room_infos as $title => $room) { - if (!$room['status']) { - continue; - } - $status = self::getShareTask($room['type_id'], $room['room_id'], $room['short_room_id']); - if ($status) { - self::$room_infos[$title]['share'] = true; - } else { - self::$room_infos[$title]['share'] = false; - } - } - } - - - /** - * @use 运行任务 - */ - private static function workTask() - { - foreach (self::$room_infos as $title => $room) { - if (!$room['status']) { - continue; - } - if (in_array('sign', $room) && $room['sign']) { - self::matchSign($room['type_id'], $room['room_id'], $room['short_room_id']); - } - if (in_array('share', $room) && $room['share']) { - self::matchShare($room['type_id'], $room['room_id'], $room['short_room_id']); - } - } - } - - - /** - * @use 获取签到任务 - * @param int $type_id - * @param int $room_id - * @param int $short_room_id - * @return bool - */ - private static function getSignTask(int $type_id, int $room_id, int $short_room_id): bool - { - $url = 'https://api.live.bilibili.com/xlive/general-interface/v1/lpl-task/GetSignTask'; - $payload = [ - 'game_type' => $type_id, - ]; - $headers = [ - 'origin' => 'https://live.bilibili.com', - 'referer' => "https://live.bilibili.com/{$short_room_id}" - ]; - $raw = Curl::get('pc', $url, $payload, $headers); - $de_raw = json_decode($raw, true); - // 成功 {"code":0,"message":"0","ttl":1,"data":{"id":601,"status":6,"day":30,"awards":[{"title":"彩色弹幕","cover":"https://i0.hdslb.com/bfs/live/9a571f9d82c2a8cbbe869fd92796e70b19f9c2cc.png"},{"title":"助威券","cover":"https://i0.hdslb.com/bfs/activity-plat/static/20200421/158d9f5e9553556421d8e1f652483400/ticket2.png"},{"title":"定制头衔","cover":"https://i0.hdslb.com/bfs/live/928598bde311f01364885ea14658476402eff99f.png"}]}} - // 默认 {"code":0,"message":"0","ttl":1,"data":{"id":601,"status":3,"day":30,"awards":[{"title":"彩色弹幕","cover":"https://i0.hdslb.com/bfs/live/9a571f9d82c2a8cbbe869fd92796e70b19f9c2cc.png"},{"title":"助威券","cover":"https://i0.hdslb.com/bfs/activity-plat/static/20200421/158d9f5e9553556421d8e1f652483400/ticket2.png"},{"title":"定制头衔","cover":"https://i0.hdslb.com/bfs/live/928598bde311f01364885ea14658476402eff99f.png"}]}} - if (isset($de_raw['data']['status']) && $de_raw['code'] == 0 && $de_raw['data']['status'] == 3) { - return true; - } - return false; - } - - - /** - * @use 获取弹幕任务 - * @param int $type_id - * @param int $room_id - * @param int $short_room_id - * @return bool - */ - private static function getDanmuTask(int $type_id, int $room_id, int $short_room_id): bool - { - $url = 'https://api.live.bilibili.com/xlive/general-interface/v1/lpl-task/GetDanmuTask'; - $payload = [ - 'game_type' => $type_id, - '_' => Live::getMillisecond() - ]; - $headers = [ - 'origin' => 'https://live.bilibili.com', - 'referer' => "https://live.bilibili.com/{$short_room_id}" - ]; - $raw = Curl::get('pc', $url, $payload, $headers); - $de_raw = json_decode($raw, true); - // 错误 {"code":1002002,"message":"参数错误","ttl":1,"data":{"id":0,"status":0,"awards":null,"progress":null}} - // 默认 {"code":0,"message":"0","ttl":1,"data":{"id":620,"status":3,"awards":null,"progress":{"cur":0,"max":3}}} - // 完成 {"code":0,"message":"0","ttl":1,"data":{"id":620,"status":6,"awards":null,"progress":{"cur":3,"max":3}}} - if (isset($de_raw['data']['status']) && $de_raw['code'] == 0 && $de_raw['data']['status'] == 3) { - return true; - } - return false; - } - - - /** - * @use 获取分享任务 - * @param int $type_id - * @param int $room_id - * @param int $short_room_id - * @return bool - */ - private static function getShareTask(int $type_id, int $room_id, int $short_room_id): bool - { - $url = 'https://api.live.bilibili.com/xlive/general-interface/v1/lpl-task/GetShareTask'; - $payload = [ - 'game_type' => $type_id, - 'room_id' => $short_room_id, - '_' => Live::getMillisecond() - ]; - $headers = [ - 'origin' => 'https://live.bilibili.com', - 'referer' => "https://live.bilibili.com/{$short_room_id}" - ]; - $raw = Curl::get('pc', $url, $payload, $headers); - $de_raw = json_decode($raw, true); - // 成功 {"code":0,"message":"0","ttl":1,"data":{"id":600,"status":6,"awards":null}} - // 默认 {"code":0,"message":"0","ttl":1,"data":{"id":600,"status":3,"awards":null}} - if (isset($de_raw['data']['status']) && $de_raw['code'] == 0 && $de_raw['data']['status'] == 3) { - return true; - } - return false; - } - - - /** - * @use 获取观看任务 - * @param int $type_id - * @param int $room_id - * @param int $short_room_id - * @return bool - */ - private static function getWatchTask(int $type_id, int $room_id, int $short_room_id): bool - { - $url = 'https://api.live.bilibili.com/xlive/general-interface/v1/lpl-task/GetWatchTask'; - $payload = [ - 'game_type' => $type_id, - 'room_id' => $room_id, - '_' => Live::getMillisecond() - ]; - $headers = [ - 'origin' => 'https://live.bilibili.com', - 'referer' => "https://live.bilibili.com/{$short_room_id}" - ]; - $raw = Curl::get('pc', $url, $payload, $headers); - $de_raw = json_decode($raw, true); - // 错误 {"code":1002002,"message":"系统繁忙,请稍后再试","ttl":1,"data":{"id":0,"status":0,"progress":null,"awards":null}} - // 默认 {"code":0,"message":"0","ttl":1,"data":{"id":606,"status":3,"progress":{"cur":0,"max":1800},"awards":null}} - if (isset($de_raw['data']['status']) && $de_raw['code'] == 0 && $de_raw['data']['status'] == 3) { - return true; - } - return false; - } - - - /** - * @use 检查奖池状态 - * @param int $lottery_id - * @param int $short_room_id - * @return bool - */ - private static function getCapsuleStatus(int $lottery_id, int $short_room_id): bool - { - $url = 'https://api.live.bilibili.com/xlive/web-ucenter/v1/capsule/get_capsule_info_v3'; - $payload = [ - 'id' => $lottery_id, - 'from' => 'web', - '-' => Live::getMillisecond() - ]; - $headers = [ - 'origin' => 'https://live.bilibili.com', - 'referer' => "https://live.bilibili.com/{$short_room_id}" - ]; - $raw = Curl::get('pc', $url, $payload, $headers); - $de_raw = json_decode($raw, true); - // data -> status 0||2 - // {"code":0,"message":"0","ttl":1,"data":{"coin":9,"rule":"2020年英雄联盟职业联赛春季赛抽奖奖池","gift_list":[{"name":"辣条","num":1,"web_url":"https://i0.hdslb.com/bfs/live/48605b0fe9eca5aba87f93da0fa0aa361c419835.png","mobile_url":"https://i0.hdslb.com/bfs/live/8e7a4dc8de374faee22fca7f9a3f801a1712a36b.png","usage":{"text":"辣条是一种直播虚拟礼物,可以在直播间送给自己喜爱的主播哦~","url":""},"type":1,"expire":"3天","gift_type":"325a347f91903c0353385e343dd358f0"},{"name":"3天头衔续期卡","num":1,"web_url":"https://i0.hdslb.com/bfs/live/48aecec2d7243b6f8bd17f20ff715db89f9adcec.png","mobile_url":"https://i0.hdslb.com/bfs/live/48aecec2d7243b6f8bd17f20ff715db89f9adcec.png","usage":{"text":"3天头衔续期卡*1","url":""},"type":21,"expire":"1周","gift_type":"4bda2f960342d86a426ebc067d3633ed"},{"name":"LPL2020助威","num":1,"web_url":"https://i0.hdslb.com/bfs/live/d9ee9558fcc438c99deb00ed1f6bd3707bac3452.png","mobile_url":"https://i0.hdslb.com/bfs/live/d9ee9558fcc438c99deb00ed1f6bd3707bac3452.png","usage":{"text":"2020LPL限定头衔","url":""},"type":2,"expire":"1周","gift_type":"b114c47920fce2aca5fca7a27cca5915"},{"name":"随机英雄联盟角色手办","num":1,"web_url":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_url":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","usage":{"text":"随机英雄联盟角色手办*1","url":""},"type":100024,"expire":"当天","gift_type":"6a4ae5853753d67d07cea2b1750795f4"},{"name":"2020LPL彩色弹幕","num":1,"web_url":"https://i0.hdslb.com/bfs/live/9a571f9d82c2a8cbbe869fd92796e70b19f9c2cc.png","mobile_url":"https://i0.hdslb.com/bfs/live/9a571f9d82c2a8cbbe869fd92796e70b19f9c2cc.png","usage":{"text":"LPL专属彩色弹幕","url":""},"type":20,"expire":"3天","gift_type":"14e40c6949800b5d840011e47e54d0c5"},{"name":"7天头衔续期卡","num":1,"web_url":"https://i0.hdslb.com/bfs/live/a2ffb62dc90d4896ddc3d1dcdbe83ac5d1dd7328.png","mobile_url":"https://i0.hdslb.com/bfs/live/a2ffb62dc90d4896ddc3d1dcdbe83ac5d1dd7328.png","usage":{"text":"7天头衔续期卡*1","url":""},"type":21,"expire":"1周","gift_type":"bbfc114b65126486a40c81daedd911e5"},{"name":"2020LPL春季赛助威券","num":1,"web_url":"https://i0.hdslb.com/bfs/live/be4cdecc4809caf8aa21817880a3283672b5a477.png","mobile_url":"https://i0.hdslb.com/bfs/live/be4cdecc4809caf8aa21817880a3283672b5a477.png","usage":{"text":"再来一次!(✪ω✪)","url":""},"type":22,"expire":"当天","gift_type":"96d2b8187ec6564fa40733153a41ac14"},{"name":"30天头衔续期卡","num":1,"web_url":"https://i0.hdslb.com/bfs/live/fc49e08115db6edd0276fba69ed8835a64714441.png","mobile_url":"https://i0.hdslb.com/bfs/live/fc49e08115db6edd0276fba69ed8835a64714441.png","usage":{"text":"30天头衔续期卡*1","url":""},"type":21,"expire":"1周","gift_type":"02810fd04244c47952bd4ed0b35617db"},{"name":"辣条","num":233,"web_url":"https://i0.hdslb.com/bfs/live/48605b0fe9eca5aba87f93da0fa0aa361c419835.png","mobile_url":"https://i0.hdslb.com/bfs/live/8e7a4dc8de374faee22fca7f9a3f801a1712a36b.png","usage":{"text":"辣条是一种直播虚拟礼物,可以在直播间送给自己喜爱的主播哦~","url":""},"type":1,"expire":"3天","gift_type":"a6d260760dfb1fe9f5375b3c8c7bd7ad"},{"name":"随机提伯斯熊毛绒公仔","num":1,"web_url":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_url":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","usage":{"text":"提伯斯熊毛绒公仔*1","url":""},"type":100024,"expire":"当天","gift_type":"2df71ff3306a4a2b4a627889cbd63c5b"}],"change_num":10000,"status":0,"is_login":true,"user_score":90000,"list":[{"num":1,"gift":"随机英雄联盟角色手办","date":"2020-04-23","name":"nXBo7p0svjm","web_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","count":1},{"num":1,"gift":"随机提伯斯熊毛绒公仔","date":"2020-04-20","name":"z98rwt","web_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","count":1},{"num":1,"gift":"随机英雄联盟角色手办","date":"2020-04-18","name":"wBQW6Z6jgbb","web_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","count":1},{"num":1,"gift":"随机提伯斯熊毛绒公仔","date":"2020-04-13","name":"dU9449p1zkz","web_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","count":1},{"num":1,"gift":"随机英雄联盟角色手办","date":"2020-04-10","name":"ckcs8151","web_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","count":1},{"num":1,"gift":"随机提伯斯熊毛绒公仔","date":"2020-04-06","name":"l1d9fgn1gl","web_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","count":1},{"num":1,"gift":"随机提伯斯熊毛绒公仔","date":"2020-03-31","name":"rlBF7ivbffe","web_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","count":1},{"num":1,"gift":"随机英雄联盟角色手办","date":"2020-03-29","name":"卟要悔","web_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","count":1},{"num":1,"gift":"随机提伯斯熊毛绒公仔","date":"2020-03-23","name":"就这样8丶","web_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","mobile_image":"https://i0.hdslb.com/bfs/live/61414ab727c55cd1de8fb5c1c79a5a05dada3a55.png","count":1},{"num":1,"gift":"随机英雄联盟角色手办","date":"2020-03-17","name":"bIud77Vsory","web_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","mobile_image":"https://i0.hdslb.com/bfs/live/4a2f604ef7b3dad583c054d4ffdb30e37f37ad9c.png","count":1}]}} - if (isset($de_raw['data']['status']) && $de_raw['code'] == 0 && $de_raw['data']['status'] == 0) { - return true; - } - return false; - } - - - /** - * @use 分享任务 - * @param int $type_id - * @param int $room_id - * @param int $short_room_id - * @return bool - */ - private static function matchShare(int $type_id, int $room_id, int $short_room_id): bool - { - $user_info = User::parseCookies(); - $url = 'https://api.live.bilibili.com/xlive/general-interface/v1/lpl-task/MatchShare'; - $payload = [ - 'game_type' => $type_id, - 'csrf_token' => $user_info['token'], - 'csrf' => $user_info['token'], - 'visit_id' => '' - ]; - $headers = [ - 'Content-Type' => 'application/x-www-form-urlencoded', - 'Origin' => 'https://live.bilibili.com', - 'Referer' => "https://live.bilibili.com/{$short_room_id}" - ]; - // {"code":0,"message":"0","ttl":1,"data":{"status":1}} - $raw = Curl::post('pc', $url, $payload, $headers); - $de_raw = json_decode($raw, true); - if ($de_raw['code'] == 0) { - Log::notice("房间 {$short_room_id} 赛事 {$type_id} 分享成功~"); - return true; - } - Log::warning("房间 {$short_room_id} 赛事 {$type_id} 分享失败~"); - return false; - } - - - /** - * @use 签到任务 - * @param int $type_id - * @param int $room_id - * @param int $short_room_id - * @return bool - */ - private static function matchSign(int $type_id, int $room_id, int $short_room_id): bool - { - $user_info = User::parseCookies(); - $url = 'https://api.live.bilibili.com/xlive/general-interface/v1/lpl-task/MatchSign'; - $payload = [ - 'room_id' => $room_id, - 'game_type' => $type_id, - 'csrf_token' => $user_info['token'], - 'csrf' => $user_info['token'], - 'visit_id' => '' - ]; - $headers = [ - 'Content-Type' => 'application/x-www-form-urlencoded', - 'Origin' => 'https://live.bilibili.com', - 'Referer' => "https://live.bilibili.com/{$short_room_id}" - ]; - // {"code":0,"message":"0","ttl":1,"data":{"status":1,"awards":[{"title":"彩色弹幕","cover":"https://i0.hdslb.com/bfs/live/9a571f9d82c2a8cbbe869fd92796e70b19f9c2cc.png","num":1}],"is_focus":1}} - $raw = Curl::post('pc', $url, $payload, $headers); - $de_raw = json_decode($raw, true); - if ($de_raw['code'] == 0) { - Log::notice("房间 {$short_room_id} 赛事 {$type_id} 签到成功~"); - return true; - } - Log::warning("房间 {$short_room_id} 赛事 {$type_id} 签到失败~"); - return false; - } - - private static function matchDanmu() - { - - } - - private static function matchWatch() - { - - } - - -} \ No newline at end of file diff --git a/src/plugin/GiftHeart.php b/src/plugin/GiftHeart.php index d7ae5ce..4d32bad 100644 --- a/src/plugin/GiftHeart.php +++ b/src/plugin/GiftHeart.php @@ -20,7 +20,7 @@ class GiftHeart public static function run() { - if (self::getLock() > time()) { + if (self::getLock() > time() || !getEnable('gift_heart')) { return; } self::setPauseStatus(); @@ -31,7 +31,6 @@ class GiftHeart self::setLock(5 * 60); } - /** * @use 礼物心跳 * @return bool @@ -40,7 +39,7 @@ class GiftHeart { $url = 'https://api.live.bilibili.com/gift/v2/live/heart_gift_receive'; $payload = [ - 'roomid' => getenv('ROOM_ID'), + 'roomid' => getConf('room_id', 'global_room'), ]; $raw = Curl::get('app', $url, Sign::common($payload)); $de_raw = json_decode($raw, true); diff --git a/src/plugin/GiftRaffle.php b/src/plugin/GiftRaffle.php index 72fc944..e85f3dc 100644 --- a/src/plugin/GiftRaffle.php +++ b/src/plugin/GiftRaffle.php @@ -12,13 +12,12 @@ namespace BiliHelper\Plugin; use BiliHelper\Core\Log; use BiliHelper\Core\Curl; -use BiliHelper\Util\TimeLock; use BiliHelper\Util\BaseRaffle; class GiftRaffle extends BaseRaffle { const ACTIVE_TITLE = '活动礼物'; - const ACTIVE_SWITCH = 'USE_ACTIVE'; + const ACTIVE_SWITCH = 'live_gift'; protected static $wait_list = []; protected static $finish_list = []; @@ -62,7 +61,6 @@ class GiftRaffle extends BaseRaffle return true; } - /** * @use 创建抽奖任务 * @param array $raffles @@ -75,15 +73,13 @@ class GiftRaffle extends BaseRaffle // $url = 'https://api.live.bilibili.com/gift/v4/smalltv/getAward'; $url = 'https://api.live.bilibili.com/xlive/lottery-interface/v5/smalltv/join'; $tasks = []; - $results = []; - $user_info = User::parseCookies(); foreach ($raffles as $raffle) { $payload = [ 'id' => $raffle['raffle_id'], 'roomid' => $raffle['room_id'], 'type' => $raffle['type'], - 'csrf_token' => $user_info['token'], - 'csrf' => $user_info['token'], + 'csrf_token' => getCsrf(), + 'csrf' => getCsrf(), 'visit_id' => '' ]; array_push($tasks, [ @@ -95,15 +91,14 @@ class GiftRaffle extends BaseRaffle ] ]); } - $results = Curl::async('app', $url, $tasks); // print_r($results); - return $results; + return Curl::async('app', $url, $tasks); } /** * @use 解析抽奖信息 * @param array $results - * @return mixed|void + * @return void */ protected static function parseLottery(array $results) { diff --git a/src/plugin/GiftSend.php b/src/plugin/GiftSend.php index fd2f588..e4a9d71 100644 --- a/src/plugin/GiftSend.php +++ b/src/plugin/GiftSend.php @@ -10,7 +10,6 @@ namespace BiliHelper\Plugin; - use BiliHelper\Core\Log; use BiliHelper\Core\Curl; use BiliHelper\Util\TimeLock; @@ -51,11 +50,10 @@ class GiftSend } } - /** * @use 方案1 */ - protected static function procOne() + protected static function procOne(): bool { if (!self::setTargetList()) { return false; @@ -63,7 +61,7 @@ class GiftSend self::getMedalList(); foreach (self::$medal_list as $room_id => $total_intimacy) { $bag_list = self::fetchBagList(); - if (getenv('FEED_FILL') == 'false') { + if (!getConf('feed_fill', 'intimacy')) { $bag_list = self::checkExpireGift($bag_list); } if (count($bag_list)) { @@ -116,13 +114,12 @@ class GiftSend */ protected static function setTargetList(): bool { - $temp = empty(getenv('ROOM_LIST')) ? null : getenv('ROOM_LIST'); + $temp = empty($temp = getConf('room_list', 'intimacy')) ? null : $temp; if (is_null($temp)) return false; - self::$room_list = explode(',', getenv('ROOM_LIST')); + self::$room_list = explode(',', $temp); return true; } - /** * @use 获取背包列表 * @return array @@ -156,7 +153,6 @@ class GiftSend return $new_bag_list; } - /** * @use 查找过期礼物 * @param array $bag_list @@ -173,7 +169,6 @@ class GiftSend return $expire_gift_list; } - /** * @use 获取勋章列表(过滤无勋章或已满) */ @@ -200,7 +195,6 @@ class GiftSend } } - /** * @use 获取UID */ @@ -213,7 +207,7 @@ class GiftSend if (isset($data['code']) && $data['code']) { Log::warning('获取帐号信息失败!', ['msg' => $data['message']]); Log::warning('清空礼物功能禁用!'); - self::$lock = time() + 100000000; + self::setLock(100000000); return; } self::$uid = $data['data']['uid']; @@ -225,12 +219,12 @@ class GiftSend protected static function getRoomInfo() { Log::info('正在生成直播间信息...'); - $room_id = empty(self::$tid) ? getenv('ROOM_ID') : self::$tid; - $data = Live::getRoomInfo($room_id); + $room_id = empty(self::$tid) ? getConf('room_id', 'global_room') : self::$tid; + $data = Live::getRoomInfoV1($room_id); if (isset($data['code']) && $data['code']) { Log::warning('获取主播房间号失败!', ['msg' => $data['message']]); Log::warning('清空礼物功能禁用!'); - self::$lock = time() + 100000000; + self::setLock(100000000); return; } Log::info('直播间信息生成完毕!'); @@ -239,7 +233,6 @@ class GiftSend self::$short_id = $data['data']['short_id'] ? (string)$data['data']['short_id'] : self::$room_id; } - /** * @use 计算赠送数量 * @param array $gift @@ -258,7 +251,6 @@ class GiftSend return ($amt < 1) ? 1 : $amt; } - /** * @use 赠送礼物 * @param array $value diff --git a/src/plugin/GroupSignIn.php b/src/plugin/GroupSignIn.php index 92e3304..65d809a 100644 --- a/src/plugin/GroupSignIn.php +++ b/src/plugin/GroupSignIn.php @@ -20,7 +20,7 @@ class GroupSignIn public static function run() { - if (self::getLock() > time()) { + if (self::getLock() > time() || !getEnable('love_club')) { return; } @@ -34,10 +34,9 @@ class GroupSignIn self::signInGroup($group); } - self::setLock(8 * 60 * 60); + self::setLock(mt_rand(8, 12) * 60 * 60); } - /** * @use 获取友爱社列表 * @return array @@ -50,13 +49,12 @@ class GroupSignIn $de_raw = json_decode($raw, true); if (empty($de_raw['data']['list'])) { - Log::notice('你没有需要签到的应援团!'); + Log::warning('你没有需要签到的应援团!'); return []; } return $de_raw['data']['list']; } - /** * @use 签到 * @param array $groupInfo @@ -73,14 +71,20 @@ class GroupSignIn $de_raw = json_decode($raw, true); if ($de_raw['code'] != '0') { - Log::warning('在应援团{' . $groupInfo['group_name'] . '}中签到失败, 原因待查'); - // TODO 任务失败原因 + // Todo 任务失败原因 + // {"code": 710001, "msg": "应援失败>_<", "message": "应援失败>_<", "ttl": "1", "data": {"add_num": 0, "status": 0}} + if ($de_raw['code'] == '710001') { + Log::warning('在应援团{' . $groupInfo['group_name'] . '}中签到失败, 亲密度已达上限'); + } else { + print_r($de_raw); + Log::warning('在应援团{' . $groupInfo['group_name'] . '}中签到失败, 原因待查'); + } return false; } if ($de_raw['data']['status'] == '0') { - Log::info('在应援团{' . $groupInfo['group_name'] . '}中签到成功,增加{' . $de_raw['data']['add_num'] . '点}亲密度'); + Log::notice('在应援团{' . $groupInfo['group_name'] . '}中签到成功,增加{' . $de_raw['data']['add_num'] . '点}亲密度'); } else { - Log::notice('在应援团{' . $groupInfo['group_name'] . '}中不要重复签到'); + Log::warning('在应援团{' . $groupInfo['group_name'] . '}中不要重复签到'); } return true; diff --git a/src/plugin/GuardRaffle.php b/src/plugin/GuardRaffle.php index c9cc437..e8a2bc4 100644 --- a/src/plugin/GuardRaffle.php +++ b/src/plugin/GuardRaffle.php @@ -12,19 +12,17 @@ namespace BiliHelper\Plugin; use BiliHelper\Core\Log; use BiliHelper\Core\Curl; -use BiliHelper\Util\TimeLock; use BiliHelper\Util\BaseRaffle; class GuardRaffle extends BaseRaffle { const ACTIVE_TITLE = '总督舰长'; - const ACTIVE_SWITCH = 'USE_GUARD'; + const ACTIVE_SWITCH = 'live_guard'; protected static $wait_list = []; protected static $finish_list = []; protected static $all_list = []; - /** * @use 解析数据 * @param int $room_id @@ -80,7 +78,6 @@ class GuardRaffle extends BaseRaffle return true; } - /** * @use 创建抽奖任务 * @param array $raffles @@ -90,15 +87,13 @@ class GuardRaffle extends BaseRaffle { $url = 'https://api.live.bilibili.com/xlive/lottery-interface/v3/guard/join'; $tasks = []; - $results = []; - $user_info = User::parseCookies(); foreach ($raffles as $raffle) { $payload = [ 'id' => $raffle['raffle_id'], 'roomid' => $raffle['room_id'], "type" => "guard", - 'csrf_token' => $user_info['token'], - 'csrf' => $user_info['token'], + 'csrf_token' => getCsrf(), + 'csrf' => getCsrf(), 'visit_id' => '' ]; array_push($tasks, [ @@ -110,15 +105,14 @@ class GuardRaffle extends BaseRaffle ] ]); } - $results = Curl::async('app', $url, $tasks); // print_r($results); - return $results; + return Curl::async('app', $url, $tasks); } /** * @use 解析抽奖信息 * @param array $results - * @return mixed|void + * @return void */ protected static function parseLottery(array $results) { diff --git a/src/plugin/Judge.php b/src/plugin/Judge.php index 40cc2cc..f6c8a9e 100644 --- a/src/plugin/Judge.php +++ b/src/plugin/Judge.php @@ -26,25 +26,28 @@ class Judge public static function run() { - if (self::getLock() > time() || self::$retry_time > time() || getenv('USE_JUDGE') == 'false') { + // https://www.bilibili.com/judgement/index + if (self::getLock() > time() || self::$retry_time > time() || !getEnable('judgement')) { return; } - # https://www.bilibili.com/judgement/index - $case_id = self::$wait_case_id ? self::$wait_case_id : self::caseObtain(); + $case_id = self::$wait_case_id ?: self::caseObtain(); if (!self::judgeCase($case_id)) { self::setLock(1 * 60 + 5); return; } // self::judgementIndex(); - self::setLock(mt_rand(15, 30) * 60); + // 如果没有设置时间 就设置个默认时间 可能在一秒钟内处理完 所以 <= + if (self::getLock() <= time()) { + self::setLock(mt_rand(15, 30) * 60); + } } /** - * @use 判案 TODO: 处理案例已满(MAX20例) + * @use 判案 Todo: 处理案例已满(MAX20例) * @param $case_id * @return bool */ - private static function judgeCase($case_id) + private static function judgeCase($case_id): bool { if (is_null($case_id) || $case_id == 0) { return true; @@ -95,7 +98,7 @@ class Judge * @param $pct * @return int|null */ - private static function judgeAdvice($num_judged, $pct) + private static function judgeAdvice($num_judged, $pct): ?int { if ($num_judged >= 300) { # 认为这里可能出现了较多分歧,抬一手 @@ -137,8 +140,7 @@ class Judge */ private static function juryVote($case_id, $decision) { - $user_info = User::parseCookies(); - $url = 'http://api.bilibili.com/x/credit/jury/vote'; + $url = 'https://api.bilibili.com/x/credit/jury/vote'; $payload = [ "jsonp" => "jsonp", "cid" => $case_id, @@ -147,9 +149,10 @@ class Judge "likes" => "", "hates" => "", "attr" => "1", - "csrf" => $user_info['token'], + "csrf" => getCsrf(), ]; $raw = Curl::post('pc', $url, $payload); + // {"code":25012,"message":"请勿重复投票","ttl":1} $de_raw = json_decode($raw, true); if (isset($de_raw['code']) && $de_raw['code']) { Log::warning("案件 {$case_id} 投票失败 {$raw}"); @@ -158,32 +161,39 @@ class Judge } } - /** * @use 案件获取 - * @return |null + * @return mixed|null */ private static function caseObtain() { - $user_info = User::parseCookies(); - $url = 'http://api.bilibili.com/x/credit/jury/caseObtain'; + $url = 'https://api.bilibili.com/x/credit/jury/caseObtain'; $payload = [ "jsonp" => "jsonp", - "csrf" => $user_info['token'] + "csrf" => getCsrf() ]; $raw = Curl::post('pc', $url, $payload); $de_raw = json_decode($raw, true); // {"code":25008,"message":"真给力 , 移交众裁的举报案件已经被处理完了","ttl":1} // {"code":25014,"message":"25014","ttl":1} // {"code":25005,"message":"请成为风纪委员后再试","ttl":1} - if (isset($de_raw['code']) && $de_raw['code'] == 25005) { - Log::warning($de_raw['message']); - self::setLock(self::timing(10)); - return null; - } if (isset($de_raw['code']) && $de_raw['code']) { - Log::info("没有获取到案件~ {$raw}"); - return null; + switch ($de_raw['code']) { + case 25005: + Log::warning($de_raw['message']); + self::setLock(self::timing(10)); + return null; + case 25008: + Log::info("暂时没有新的案件需要审理~ {$raw}"); + return null; + case 25014: + Log::info("今日案件已审满,感谢您对社区的贡献!明天再来看看吧~"); + self::setLock(self::timing(7, 0, 0, true)); + return null; + default: + Log::info("获取案件失败~ {$raw}"); + return null; + } } else { $case_id = $de_raw['data']['id']; Log::info("获取到案件 {$case_id} ~"); @@ -196,7 +206,7 @@ class Judge * @param $case_id * @return array */ - private static function judgementVote($case_id) + private static function judgementVote($case_id): array { $url = 'https://api.bilibili.com/x/credit/jury/juryCase'; $headers = [ @@ -227,6 +237,31 @@ class Judge ]; } + /** + * @use 随机整数 + * @param int $max + * @return string + */ + private static function randInt(int $max = 17): string + { + $temp = []; + foreach (range(1, $max) as $_) { + array_push($temp, mt_rand(0, 9)); + } + return implode("", $temp); + } + + /** + * @use 初始化参数 + */ + private static function initParams() + { + self::$retry_time = 0; + self::$wait_case_id = 0; + self::$wait_time = 0; + self::$min_ok_pct = 1; + self::$max_ok_pct = 0; + } /** * @use 获取案例数据|风纪检测 @@ -273,31 +308,4 @@ class Judge Log::info("今日投票{$sum_cases}({$valid_cases}票有效(非弃权),{$judging_cases}票还在进行中)"); return true; } - - - /** - * @use 随机整数 - * @param int $max - * @return string - */ - private static function randInt(int $max = 17): string - { - $temp = []; - foreach (range(1, $max) as $index) { - array_push($temp, mt_rand(0, 9)); - } - return implode("", $temp); - } - - /** - * @use 初始化参数 - */ - private static function initParams() - { - self::$retry_time = 0; - self::$wait_case_id = 0; - self::$wait_time = 0; - self::$min_ok_pct = 1; - self::$max_ok_pct = 0; - } } \ No newline at end of file diff --git a/src/plugin/Live.php b/src/plugin/Live.php index 5f3300e..28d7978 100644 --- a/src/plugin/Live.php +++ b/src/plugin/Live.php @@ -41,7 +41,6 @@ class Live return $areas; } - /** * @use AREA_ID转ROOM_ID * @param $area_id @@ -77,12 +76,11 @@ class Live return $area_info; } - /** * @use 获取随机直播房间号 * @return int */ - public static function getUserRecommend() + public static function getUserRecommend(): int { $url = 'https://api.live.bilibili.com/room/v1/Area/getListByAreaID'; $payload = [ @@ -93,21 +91,21 @@ class Live ]; $raw = Curl::get('other', $url, $payload); $de_raw = json_decode($raw, true); + print_r($de_raw); if ($de_raw['code'] != '0') { return 23058; } return $de_raw['data'][mt_rand(1, 29)]['roomid']; } - /** * @use 获取直播房间号 * @param $room_id - * @return bool + * @return false|mixed */ public static function getRealRoomID($room_id) { - $data = self::getRoomInfo($room_id); + $data = self::getRoomInfoV1($room_id); if (!isset($data['code']) || !isset($data['data'])) { return false; } @@ -132,7 +130,7 @@ class Live * @param $room_id * @return array */ - public static function getRoomInfo($room_id): array + public static function getRoomInfoV1($room_id): array { $url = 'https://api.live.bilibili.com/room/v1/Room/room_init'; $payload = [ @@ -142,6 +140,21 @@ class Live return json_decode($raw, true); } + /** + * @use 获取直播间信息 + * @param $room_id + * @return array + */ + public static function getRoomInfoV2($room_id): array + { + $url = ' https://api.live.bilibili.com/room/v1/Room/get_info_by_id'; + $payload = [ + 'ids[]' => $room_id + ]; + $raw = Curl::get('other', $url, $payload); + return json_decode($raw, true); + } + /** * @use 获取弹幕配置 * @param $room_id @@ -159,7 +172,6 @@ class Live return json_decode($raw, true); } - /** * @use 获取配置信息 * @param $room_id @@ -172,11 +184,11 @@ class Live $server = $data['data']['host_server_list'][0]; $addr = "tcp://{$server['host']}:{$server['port']}/sub"; } else { - $addr = getenv('ZONE_SERVER_ADDR'); + $addr = getConf('server_addr', 'zone_monitor'); } return [ 'addr' => $addr, - 'token' => isset($data['data']['token']) ? $data['data']['token'] : '', + 'token' => $data['data']['token'] ?? '', ]; } @@ -208,7 +220,6 @@ class Live return true; } - /** * @use 访问直播间 * @param $room_id @@ -225,27 +236,18 @@ class Live return true; } - /** - * @use 获取毫秒 - * @return float - */ - public static function getMillisecond() - { - list($t1, $t2) = explode(' ', microtime()); - return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000); - } - - - /** - * @use 发送弹幕 + * @use 发送弹幕pc * @param int $room_id * @param string $content * @return array */ - public static function sendBarrage(int $room_id, string $content): array + public static function sendBarragePC(int $room_id, string $content): array { - $user_info = User::parseCookies(); + $room_id = self::getRealRoomID($room_id); + if (!$room_id) { + return ['code' => 404, 'message' => '直播间数据异常']; + } $url = 'https://api.live.bilibili.com/msg/send'; $payload = [ 'color' => '16777215', @@ -255,17 +257,44 @@ class Live 'rnd' => 0, 'bubble' => 0, 'roomid' => $room_id, - 'csrf' => $user_info['token'], - 'csrf_token' => $user_info['token'], + 'csrf' => getCsrf(), + 'csrf_token' => getCsrf(), ]; $headers = [ 'origin' => 'https://live.bilibili.com', 'referer' => "https://live.bilibili.com/{$room_id}" ]; $raw = Curl::post('pc', $url, $payload, $headers); + // {"code":0,"data":[],"message":"","msg":""} return json_decode($raw, true) ?? ['code' => 404, 'msg' => '上层数据为空!']; } + /** + * @use 发送弹幕app + * @param int $room_id + * @param string $content + * @return array + */ + public static function sendBarrageAPP(int $room_id, string $content): array + { + $room_id = self::getRealRoomID($room_id); + if (!$room_id) { + return ['code' => 404, 'message' => '直播间数据异常']; + } + $url = 'https://api.live.bilibili.com/msg/send'; + $payload = [ + 'color' => '16777215', + 'fontsize' => 25, + 'mode' => 1, + 'msg' => $content, + 'rnd' => 0, + 'roomid' => $room_id, + 'csrf' => getCsrf(), + 'csrf_token' => getCsrf(), + ]; + $raw = Curl::post('app', $url, Sign::common($payload)); + return json_decode($raw, true) ?? ['code' => 404, 'msg' => '上层数据为空!']; + } /** * @use 获取勋章列表 @@ -276,6 +305,7 @@ class Live { $metal_list = []; for ($i = 1; $i <= 10; $i++) { + // $url = 'https://api.live.bilibili.com/fans_medal/v5/live_fans_medal/iApiMedal'; $url = 'https://api.live.bilibili.com/i/api/medal'; $payload = [ 'page' => $i, @@ -347,9 +377,8 @@ class Live public static function sendGift(array $guest, array $gift, int $num) { $url = 'https://api.live.bilibili.com/gift/v2/live/bag_send'; - $user_info = User::parseCookies(); $payload = [ - 'uid' => $user_info['uid'], // 自己的UID + 'uid' => getUid(), // 自己的UID 'gift_id' => $gift['gift_id'], 'ruid' => $guest['uid'], // UP的UID 'send_ruid' => 0, @@ -362,8 +391,8 @@ class Live 'storm_beat_id' => 0, 'metadata' => '', 'price' => 0, - 'csrf' => $user_info['token'], - 'csrf_token' => $user_info['token'] + 'csrf' => getCsrf(), + 'csrf_token' => getCsrf() ]; // {"code":0,"msg":"success","message":"success","data":{"tid":"1595419985112400002","uid":4133274,"uname":"沙奈之朵","face":"https://i2.hdslb.com/bfs/face/eb101ef90ebc4e9bf79f65312a22ebac84946700.jpg","guard_level":0,"ruid":893213,"rcost":30834251,"gift_id":30607,"gift_type":5,"gift_name":"小心心","gift_num":1,"gift_action":"投喂","gift_price":5000,"coin_type":"silver","total_coin":5000,"pay_coin":5000,"metadata":"","fulltext":"","rnd":"1595419967","tag_image":"","effect_block":1,"extra":{"wallet":null,"gift_bag":{"bag_id":210196588,"gift_num":20},"top_list":[],"follow":null,"medal":null,"title":null,"pk":{"pk_gift_tips":"","crit_prob":0},"fulltext":"","event":{"event_score":0,"event_redbag_num":0},"capsule":null},"blow_switch":0,"send_tips":"赠送成功","gift_effect":{"super":0,"combo_timeout":0,"super_gift_num":0,"super_batch_gift_num":0,"batch_combo_id":"","broadcast_msg_list":[],"small_tv_list":[],"beat_storm":null,"smallTVCountFlag":true},"send_master":null,"crit_prob":0,"combo_stay_time":3,"combo_total_coin":0,"demarcation":2,"magnification":1,"combo_resources_id":1,"is_special_batch":0,"send_gift_countdown":6}} $data = Curl::post('app', $url, Sign::common($payload)); @@ -375,7 +404,6 @@ class Live } } - /** * @use 获取分区直播间 * @param int $parent_area_id @@ -383,7 +411,7 @@ class Live * @param int $page * @return array */ - public static function getAreaRoomList(int $parent_area_id, int $area_id, int $page=1): array + public static function getAreaRoomList(int $parent_area_id, int $area_id, int $page = 1): array { $url = 'https://api.live.bilibili.com/xlive/web-interface/v1/second/getList'; $payload = [ @@ -404,4 +432,60 @@ class Live } return $room_ids; } + + /** + * @use 获取用户卡片 + * @param int $mid + * @return array + */ + public static function getMidCard(int $mid): array + { + $url = 'https://api.bilibili.com/x/web-interface/card'; + $payload = [ + 'mid' => $mid, + ]; + //{"code":0,"message":"0","ttl":1,"data":{"card":{"mid":"1","name":"bishi","approve":false,"sex":"男","rank":"10000","face":"http://i1.hdslb.com/bfs/face/34c5b30a990c7ce4a809626d8153fa7895ec7b63.gif","DisplayRank":"0","regtime":0,"spacesta":0,"birthday":"","place":"","description":"","article":0,"attentions":[],"fans":154167,"friend":5,"attention":5,"sign":"","level_info":{"current_level":4,"current_min":0,"current_exp":0,"next_exp":0},"pendant":{"pid":0,"name":"","image":"","expire":0,"image_enhance":"","image_enhance_frame":""},"nameplate":{"nid":0,"name":"","image":"","image_small":"","level":"","condition":""},"Official":{"role":0,"title":"","desc":"","type":-1},"official_verify":{"type":-1,"desc":""},"vip":{"type":2,"status":1,"due_date":1727625600000,"vip_pay_type":1,"theme_type":0,"label":{"path":"","text":"年度大会员","label_theme":"annual_vip","text_color":"#FFFFFF","bg_style":1,"bg_color":"#FB7299","border_color":""},"avatar_subscript":1,"nickname_color":"#FB7299","role":3,"avatar_subscript_url":"http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png","vipType":2,"vipStatus":1}},"following":false,"archive_count":2,"article_count":0,"follower":154167}} + $raw = Curl::get('other', $url, $payload); + return json_decode($raw, true); + } + + /** + * @use 获取用户状态 + * @param int $mid + * @return array + */ + public static function getMidStat(int $mid): array + { + $url = 'https://api.bilibili.com/x/relation/stat'; + $payload = [ + 'vmid' => $mid, + ]; + // {"code":0,"message":"0","ttl":1,"data":{"mid":50329118,"following":62,"whisper":0,"black":0,"follower":7610241}} + $raw = Curl::get('other', $url, $payload); + return json_decode($raw, true); + } + + /** + * @use 获取用户关注数 + * @param int $mid + * @return int + */ + public static function getMidFollower(int $mid): int + { + $follower = 0; + // root->data->follower + if (mt_rand(0, 10) > 5) { + $data = self::getMidStat($mid); + } else { + $data = self::getMidCard($mid); + } + + if (isset($data['code']) && $data['code']) { + Log::warning("获取用户资料卡片失败: CODE -> {$data['code']} MSG -> {$data['message']} "); + } else { + // root->data->follower + $follower = $data['data']['follower']; + } + return $follower; + } } diff --git a/src/plugin/Login.php b/src/plugin/Login.php index 0fd04ab..53c9b51 100644 --- a/src/plugin/Login.php +++ b/src/plugin/Login.php @@ -11,11 +11,9 @@ namespace BiliHelper\Plugin; use BiliHelper\Core\Log; use BiliHelper\Core\Curl; -use BiliHelper\Core\Config; use BiliHelper\Util\TimeLock; use BiliHelper\Tool\Common; - class Login { use TimeLock; @@ -31,14 +29,13 @@ class Login return; } Log::info('启动登录程序'); - if (getenv('ACCESS_TOKEN') == "") { + if (getAccessToken() == '') { Log::info('准备载入登录令牌'); self::login(); } - Log::info('检查登录令牌有效性'); if (!self::checkToken()) { - Log::warning('登录令牌即将过期'); + Log::warning('登录令牌失效或即将过期'); Log::info('申请更换登录令牌中'); if (!self::refreshToken()) { Log::warning('无效的登录令牌,尝试重新申请'); @@ -48,14 +45,13 @@ class Login self::setLock(3600); } - /** * @use 登录控制中心 */ private static function login() { self::checkLogin(); - switch (intval(getenv('LOGIN_MODE'))) { + switch (getConf('mode', 'login.mode')) { case 1: // 账密模式 self::accountLogin(); @@ -69,7 +65,6 @@ class Login // self::captchaLogin(); Log::error('此登录模式暂未开放'); die(); - break; default: Log::error('登录模式配置错误'); die(); @@ -81,23 +76,22 @@ class Login */ private static function checkLogin() { - $user = getenv('APP_USER'); - $pass = getenv('APP_PASS'); - if (empty($user) || empty($pass)) { + $username = getConf('username', 'login.account'); + $password = getConf('password', 'login.account'); + if (empty($username) || empty($password)) { Log::error('空白的帐号和口令'); die(); } self::clearAccount(); - self::$username = $user; - self::$password = self::publicKeyEnc($pass); + self::$username = $username; + self::$password = self::publicKeyEnc($password); } - /** * @use 保持认证 * @return bool */ - private static function keepAuth() + private static function keepAuth(): bool { if (self::getLock() > time()) { return true; @@ -119,32 +113,32 @@ class Login * @use 获取令牌信息 * @return bool */ - private static function checkToken() + private static function checkToken(): bool { $url = 'https://passport.bilibili.com/api/v2/oauth2/info'; $payload = [ - 'access_token' => getenv('ACCESS_TOKEN'), + 'access_token' => getAccessToken(), ]; $data = Curl::get('app', $url, Sign::common($payload)); + // {"ts":1234,"code":0,"data":{"mid":1234,"access_token":"1234","expires_in":7759292}} $data = json_decode($data, true); if (isset($data['code']) && $data['code']) { Log::error('检查令牌失败', ['msg' => $data['message']]); return false; } - Log::info('令牌有效期: ' . date('Y-m-d H:i:s', $data['ts'] + $data['data']['expires_in'])); + Log::notice('令牌有效期: ' . date('Y-m-d H:i:s', $data['ts'] + $data['data']['expires_in'])); return $data['data']['expires_in'] > 14400; } - /** * @use 刷新Token */ - private static function refreshToken() + private static function refreshToken(): bool { $url = 'https://passport.bilibili.com/api/v2/oauth2/refresh_token'; $payload = [ - 'access_token' => getenv('ACCESS_TOKEN'), - 'refresh_token' => getenv('REFRESH_TOKEN'), + 'access_token' => getAccessToken(), + 'refresh_token' => getRefreshToken(), ]; $raw = Curl::post('app', $url, Sign::common($payload)); $de_raw = json_decode($raw, true); @@ -153,45 +147,10 @@ class Login Log::error('重新生成令牌失败', ['msg' => $de_raw['message']]); return false; } - Log::info('重新令牌生成完毕'); - $access_token = $de_raw['data']['token_info']['access_token']; - $refresh_token = $de_raw['data']['token_info']['refresh_token']; - self::saveConfig('ACCESS_TOKEN', $access_token); - self::saveConfig('REFRESH_TOKEN', $refresh_token); - self::saveCookie($de_raw); - Log::info('重置信息配置完毕'); + self::refreshSuccess($de_raw); return true; } - /** - * @use 检查Cookie - */ - private static function checkCookie() - { - - } - - - /** - * @use 刷新Cookie - */ - private static function refreshCookie() - { - $url = 'https://passport.bilibili.com/api/login/sso'; - $payload = [ - 'gourl' => 'https%3A%2F%2Faccount.bilibili.com%2Faccount%2Fhome' - ]; - $response = Curl::headers('app', $url, Sign::common($payload)); - $headers = $response['Set-Cookie']; - $cookies = []; - foreach ($headers as $header) { - preg_match_all('/^(.*);/iU', $header, $cookie); - array_push($cookies, $cookie[0][0]); - } - return implode("", array_reverse($cookies)); - } - - /** * @use 公钥加密 * @param $plaintext @@ -218,7 +177,6 @@ class Login return base64_encode($crypt); } - /** * @use 获取验证码 * @return array|string[] @@ -254,7 +212,7 @@ class Login */ private static function ocrCaptcha(array $captcha): array { - $url = 'http://captcha-v1.mudew.com:19951/'; + $url = 'https://captcha-v1.mudew.com:19951/'; $payload = [ 'type' => 'gt3', 'gt' => $captcha['gt'], @@ -273,18 +231,6 @@ class Login ]; } - - /** - * @use 验证码登录 - * @param string $mode - */ - private static function captchaLogin(string $mode = '验证码模式') - { - $captcha_ori = self::getCaptcha(); - $captcha = self::ocrCaptcha($captcha_ori); - self::accountLogin($captcha['validate'], $captcha['challenge'], $mode); - } - /** * @use 账密登录 * @param string $validate @@ -293,8 +239,8 @@ class Login */ private static function accountLogin(string $validate = '', string $challenge = '', string $mode = '账密模式') { - Log::info("尝试{$mode}登录"); -// $url = 'https://passport.bilibili.com/api/v3/oauth2/login'; + Log::info("尝试 {$mode} 登录"); + // $url = 'https://passport.bilibili.com/api/v3/oauth2/login'; $url = 'https://passport.bilibili.com/x/passport-login/oauth2/login'; $payload = [ 'seccode' => $validate ? "{$validate}|jordan" : '', @@ -314,50 +260,7 @@ class Login // {"ts":1593082432,"code":0,"data":{"status":0,"token_info":{"mid":123456,"access_token":"123123","refresh_token":"123123","expires_in":2592000},"cookie_info":{"cookies":[{"name":"bili_jct","value":"123123","http_only":0,"expires":1595674432},{"name":"DedeUserID","value":"123456","http_only":0,"expires":1595674432},{"name":"DedeUserID__ckMd5","value":"123123","http_only":0,"expires":1595674432},{"name":"sid","value":"bd6aagp7","http_only":0,"expires":1595674432},{"name":"SESSDATA","value":"6d74d850%123%2Cf0e36b61","http_only":1,"expires":1595674432}],"domains":[".bilibili.com",".biligame.com",".bigfunapp.cn"]},"sso":["https://passport.bilibili.com/api/v2/sso","https://passport.biligame.com/api/v2/sso","https://passport.bigfunapp.cn/api/v2/sso"]}} // {"ts":1610254019,"code":0,"data":{"status":2,"url":"https://passport.bilibili.com/account/mobile/security/managephone/phone/verify?tmp_token=2bc5dd260df7158xx860565fxx0d5311&requestId=dffcfxx052fe11xxa9c8e2667739c15c&source=risk","message":"您的账号存在高危异常行为,为了您的账号安全,请验证手机号后登录帐号"}} // https://passport.bilibili.com/mobile/verifytel_h5.html - switch ($de_raw['code']) { - case 0: - // 二次判断 - switch ($de_raw['data']['status']) { - case 0: - // 正常登录 - Log::info("{$mode}登录成功"); - $access_token = $de_raw['data']['token_info']['access_token']; - $refresh_token = $de_raw['data']['token_info']['refresh_token']; - self::saveConfig('ACCESS_TOKEN', $access_token); - self::saveConfig('REFRESH_TOKEN', $refresh_token); - self::saveCookie($de_raw); - Log::info('信息配置完毕'); - break; - case 2: - // 异常高危 - Log::error('登录失败', ['msg' => $de_raw['data']['message']]); - die(); - default: - Log::error('登录失败', ['msg' => '未知错误: ' . $de_raw['data']['message']]); - die(); - break; - } - break; - case -105: - // 需要验证码 - Log::error('登录失败', ['msg' => '此次登录需要验证码或' . $de_raw['message']]); - die(); - break; - case -629: - // 密码错误 - Log::error('登录失败', ['msg' => $de_raw['message']]); - die(); - break; - case -2100: - // 验证手机号 - Log::error('登录失败', ['msg' => '账号启用了设备锁或异地登录需验证手机号']); - die(); - break; - default: - Log::error('登录失败', ['msg' => '未知错误: ' . $de_raw['message']]); - die(); - break; - } + self::loginAfter($mode, $de_raw['code'], $de_raw); } /** @@ -366,8 +269,10 @@ class Login */ private static function smsLogin(string $mode = '短信模式') { - Log::info("尝试{$mode}登录"); - self::checkPhone(self::$username); + Log::info("尝试 {$mode} 登录"); + if (getConf('phone', 'login.check')) { + self::checkPhone(self::$username); + } $captcha = self::sendSms(self::$username); $url = 'https://passport.bilibili.com/x/passport-login/login/sms'; $payload = [ @@ -379,38 +284,7 @@ class Login ]; $raw = Curl::post('app', $url, Sign::login($payload)); $de_raw = json_decode($raw, true); - switch ($de_raw['code']) { - case 0: - // 正常登录 - Log::info("{$mode}登录成功"); - $access_token = $de_raw['data']['token_info']['access_token']; - $refresh_token = $de_raw['data']['token_info']['refresh_token']; - self::saveConfig('ACCESS_TOKEN', $access_token); - self::saveConfig('REFRESH_TOKEN', $refresh_token); - self::saveCookie($de_raw); - Log::info('信息配置完毕'); - break; - case -105: - // 需要验证码 - Log::error('登录失败', ['msg' => '此次登录需要验证码或' . $de_raw['message']]); - die(); - break; - case -629: - // 密码错误 - Log::error('登录失败', ['msg' => $de_raw['message']]); - die(); - break; - case -2100: - // 验证手机号 - Log::error('登录失败', ['msg' => '账号启用了设备锁或异地登录需验证手机号']); - die(); - break; - default: - Log::error('登录失败', ['msg' => '未知错误: ' . $de_raw['message']]); - die(); - break; - } - + self::loginAfter($mode, $de_raw['code'], $de_raw); } /** @@ -437,9 +311,9 @@ class Login { $url = 'https://passport.bilibili.com//x/passport-login/sms/send'; $payload = [ - 'cid' => '86', + 'cid' => getConf('country_code', 'login.country') , 'tel' => $phone, - 'statistics' => '{"appId":1,"platform":3,"version":"6.3.0","abtest":""}', + 'statistics' => '{"appId":1,"platform":3,"version":"6.32.0","abtest":""}', ]; $raw = Curl::post('app', $url, Sign::login($payload)); $de_raw = json_decode($raw, true); @@ -454,6 +328,108 @@ class Login die(); } + /** + * @use 登录之后 + * @param $mode + * @param $code + * @param $data + */ + private static function loginAfter($mode, $code, $data) + { + switch ($code) { + case 0: + // data->data->status number + if (array_key_exists('status', $data['data'])) { + // 二次判断 + switch ($data['data']['status']) { + case 0: + // 正常登录 + self::loginSuccess($mode, $data); + break; + case 2: + // 异常高危 + self::loginFail($mode, $data['data']['message']); + break; + default: + // 未知错误 + self::loginFail($mode, '未知错误: ' . $data['data']['message']); + break; + } + } else { + // 正常登录 + self::loginSuccess($mode, $data); + } + break; + case -105: + // 需要验证码 + self::loginFail($mode, '此次登录需要验证码或' . $data['message']); + break; + case -629: + // 密码错误 + self::loginFail($mode, $data['message']); + break; + case -2100: + // 验证手机号 + self::loginFail($mode, '账号启用了设备锁或异地登录需验证手机号'); + break; + default: + // 未知错误 + self::loginFail($mode, '未知错误: ' . $data['message']); + break; + } + + } + + /** + * @use 登录成功 + * @param $mode + * @param $data + */ + private static function loginSuccess($mode, $data) + { + Log::info("{$mode} 登录成功"); + self::successHandle($data); + Log::info('生成信息配置完毕'); + } + + /** + * @use 刷新成功 + * @param $data + */ + private static function refreshSuccess($data) + { + Log::info('重新令牌生成完毕'); + self::successHandle($data); + Log::info('重置信息配置完毕'); + } + + /** + * @use 成功处理 + * @param $data + */ + private static function successHandle($data) + { + $access_token = $data['data']['token_info']['access_token']; + $refresh_token = $data['data']['token_info']['refresh_token']; + self::saveConfig('access_token', $access_token, 'login.auth'); + self::saveConfig('refresh_token', $refresh_token, 'login.auth'); + self::saveConfig('cookie', self::formatCookie($data), 'login.auth'); + $user = User::parseCookies(); + self::saveConfig('uid', $user['uid'], 'login.auth', false); + self::saveConfig('csrf', $user['csrf'], 'login.auth', false); + } + + /** + * @use 登录失败 + * @param $mode + * @param $data + */ + private static function loginFail($mode, $data) + { + Log::error("{$mode} 登录失败", ['msg' => $data]); + die(); + } + /** * @use 检查手机号格式 * @param string $phone @@ -470,26 +446,31 @@ class Login * @use 保存配置 * @param string $key * @param string $value + * @param string $section + * @param bool $print * @param bool $hide */ - private static function saveConfig(string $key, string $value, $hide = true) + private static function saveConfig(string $key, string $value, string $section, $print = true, $hide = true) { - Config::put($key, $value); - Log::info(" > {$key}: " . ($hide ? Common::replaceStar($value,4,4) : $value)); + setConf($key, $value, $section); + if ($print) { + Log::info(" > {$key}: " . ($hide ? Common::replaceStar($value, 6, 6) : $value)); + } } /** - * @use 保存配置 + * @use @use 格式化COOKIE * @param array $data + * @return string */ - private static function saveCookie(array $data) + private static function formatCookie(array $data): string { $c = ''; $cookies = $data['data']['cookie_info']['cookies']; foreach ($cookies as $cookie) { $c .= $cookie['name'] . '=' . $cookie['value'] . ';'; } - self::saveConfig('COOKIE', $c); + return $c; } /** @@ -497,11 +478,42 @@ class Login */ private static function clearAccount() { - $variables = ['ACCESS_TOKEN', 'REFRESH_TOKEN', 'COOKIE']; + $variables = ['cookie', 'access_token', 'refresh_token']; foreach ($variables as $variable) { - Config::put($variable, ''); + setConf($variable, '', 'login.auth'); } } + /** + * @use 刷新COOKIE + * @return string + */ + private static function refreshCookie(): string + { + $url = 'https://passport.bilibili.com/api/login/sso'; + $payload = [ + 'gourl' => 'https%3A%2F%2Faccount.bilibili.com%2Faccount%2Fhome' + ]; + $response = Curl::headers('app', $url, Sign::common($payload)); + $headers = $response['Set-Cookie']; + $cookies = []; + foreach ($headers as $header) { + preg_match_all('/^(.*);/iU', $header, $cookie); + array_push($cookies, $cookie[0][0]); + } + return implode("", array_reverse($cookies)); + } + + /** + * @use 验证码登录 + * @param string $mode + */ + private static function captchaLogin(string $mode = '验证码模式') + { + $captcha_ori = self::getCaptcha(); + $captcha = self::ocrCaptcha($captcha_ori); + self::accountLogin($captcha['validate'], $captcha['challenge'], $mode); + } + } \ No newline at end of file diff --git a/src/plugin/MainSite.php b/src/plugin/MainSite.php index 20e4e55..c684c05 100644 --- a/src/plugin/MainSite.php +++ b/src/plugin/MainSite.php @@ -20,7 +20,7 @@ class MainSite public static function run() { - if (self::getLock() > time() || getenv('USE_MAIN_SITE') == 'false') { + if (self::getLock() > time() || !getEnable('main_site')) { return; } if (self::watchAid() && self::shareAid() && self::coinAdd()) { @@ -30,7 +30,6 @@ class MainSite self::setLock(3600); } - /** * @use 投币 * @param $aid @@ -38,13 +37,12 @@ class MainSite */ private static function reward($aid): bool { - $user_info = User::parseCookies(); $url = "https://api.bilibili.com/x/web-interface/coin/add"; $payload = [ "aid" => $aid, "multiply" => "1", "cross_domain" => "true", - "csrf" => $user_info['token'] + "csrf" => getCsrf() ]; $headers = [ 'Host' => "api.bilibili.com", @@ -52,18 +50,19 @@ class MainSite 'Referer' => "https://www.bilibili.com/video/av{$aid}", 'User-Agent' => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36", ]; + // {"code":34005,"message":"超过投币上限啦~","ttl":1,"data":{"like":false}} + // {"code":0,"message":"0","ttl":1,"data":{"like":false}} $raw = Curl::post('app', $url, Sign::common($payload), $headers); $de_raw = json_decode($raw, true); if ($de_raw['code'] == 0) { - Log::notice("主站任务: av{$aid}投币成功!"); + Log::notice("主站任务: av{$aid} 投币成功 {$de_raw['code']} MSG -> {$de_raw['message']}"); return true; } else { - Log::warning("主站任务: av{$aid}投币失败!"); + Log::warning("主站任务: av{$aid} 投币失败 CODE -> {$de_raw['code']} MSG -> {$de_raw['message']}"); return false; } } - /** * @use 投币日志 * @return int @@ -75,7 +74,7 @@ class MainSite $raw = Curl::get('pc', $url, $payload); $de_raw = json_decode($raw, true); - $logs = isset($de_raw['data']['list']) ? $de_raw['data']['list'] : []; + $logs = $de_raw['data']['list'] ?? []; $coins = 0; foreach ($logs as $log) { $log_ux = strtotime($log['time']); @@ -106,45 +105,36 @@ class MainSite */ protected static function coinAdd(): bool { - switch (getenv('USE_ADD_COIN')) { - case 'false': - break; - case 'true': - // 预计数量 失败默认0 避免损失 - $estimate_num = intval(getenv('ADD_COIN_NUM') ?? 0); - // 库存数量 - $stock_num = self::getCoin(); - // 实际数量 处理硬币库存少于预计数量 - $actual_num = intval($estimate_num > $stock_num ? $stock_num : $estimate_num) - self::coinLog(); - Log::info("当前硬币库存 {$stock_num} 预计投币 {$estimate_num} 实际投币 {$actual_num}"); - // 上限 - if ($actual_num <= 0) { - Log::info('今日投币上限已满!'); - break; - } - // 稿件列表 - if (gettype('ADD_COIN_MODE') =='random'){ - // 随机热门稿件榜单 - $aids = self::getDayRankingAids($actual_num); - }else{ - // 固定获取关注UP稿件榜单, 不足会随机补全 - $aids = self::getFollowUpAids($actual_num); - } - Log::info("获取稿件列表: ". implode(" ",$aids)); - // 投币 - foreach ($aids as $aid) { - self::reward($aid); - } - break; - default: - Log::warning('当前视频投币设置不正确, 请检查配置文件!'); - die(); - break; + if (!getConf('add_coin', 'main_site')) return true; + + // 预计数量 失败默认0 避免损失 + $estimate_num = getConf('add_coin_num', 'main_site') ?? 0; + // 库存数量 + $stock_num = self::getCoin(); + // 实际数量 处理硬币库存少于预计数量 + $actual_num = intval($estimate_num > $stock_num ? $stock_num : $estimate_num) - self::coinLog(); + Log::info("当前硬币库存 {$stock_num} 预计投币 {$estimate_num} 实际投币 {$actual_num}"); + // 上限 + if ($actual_num <= 0) { + Log::notice('今日投币上限已满'); + return true; + } + // 稿件列表 + if (getConf('add_coin_mode', 'main_site') == 'random') { + // 随机热门稿件榜单 + $aids = self::getTopRCmdAids($actual_num); + } else { + // 固定获取关注UP稿件榜单, 不足会随机补全 + $aids = self::getFollowUpAids($actual_num); + } + Log::info("获取稿件列表: " . implode(" ", $aids)); + // 投币 + foreach ($aids as $aid) { + self::reward($aid); } return true; } - /** * @use 获取随机AID * @return string @@ -161,12 +151,11 @@ class MainSite $de_raw = json_decode($raw, true); // echo "getRandomAid " . count($de_raw['data']['archives']) . PHP_EOL; // $aid = array_rand($de_raw['data']['archives'])['aid']; - } while (count($de_raw['data']['archives']) == 0); + } while (count((array)$de_raw['data']['archives']) == 0); $aid = $de_raw['data']['archives'][0]['aid']; return (string)$aid; } - /** * @use 获取关注UP稿件列表 * @param int $num @@ -175,11 +164,9 @@ class MainSite private static function getFollowUpAids(int $num): array { $aids = []; - $rand_nums = []; $url = 'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new'; - $user_info = User::parseCookies(); $payload = [ - 'uid' => $user_info['uid'], + 'uid' => getUid(), 'type_list' => '8,512,4097,4098,4099,4100,4101' ]; $headers = [ @@ -196,12 +183,11 @@ class MainSite } // 此处补全缺失 if (count($aids) < $num) { - $aids = array_merge($aids, self::getDayRankingAids($num - count($aids))); + $aids = array_merge($aids, self::getTopRCmdAids($num - count($aids))); } return $aids; } - /** * @use 获取榜单稿件列表 * @param int $num @@ -238,6 +224,37 @@ class MainSite return $aids; } + /** + * @use 首页推荐 + * @param int $num + * @param int $ps + * @return array + */ + private static function getTopRCmdAids(int $num, int $ps = 30): array + { + // 动画1 国创168 音乐3 舞蹈129 游戏4 知识36 科技188 汽车223 生活160 美食211 动物圈127 鬼畜119 时尚155 资讯202 娱乐5 影视181 + $rids = [1, 168, 3, 129, 4, 36, 188, 223, 160, 211, 127, 119, 155, 202, 5, 181]; + $aids = []; + $url = 'https://api.bilibili.com/x/web-interface/dynamic/region'; + $payload = [ + 'ps' => $ps, + 'rid' => $rids[array_rand($rids)], + ]; + $raw = Curl::get('other', $url, $payload); + $de_raw = json_decode($raw, true); + if ($de_raw['code'] == 0) { + if ($num == 1) { + $temps = [array_rand($de_raw['data']['archives'], $num)]; + } else { + $temps = array_rand($de_raw['data']['archives'], $num); + } + foreach ($temps as $temp) { + array_push($aids, $de_raw['data']['archives'][$temp]['aid']); + } + return $aids; + } + return self::getDayRankingAids($num); + } /** * @use 分享视频 @@ -245,14 +262,15 @@ class MainSite */ private static function shareAid(): bool { + if (!getConf('share', 'main_site')) return true; + # aid = 稿件av号 $url = "https://api.bilibili.com/x/web-interface/share/add"; $av_info = self::parseAid(); - $user_info = User::parseCookies(); $payload = [ 'aid' => $av_info['aid'], 'jsonp' => "jsonp", - 'csrf' => $user_info['token'], + 'csrf' => getCsrf(), ]; $headers = [ 'Host' => "api.bilibili.com", @@ -263,21 +281,22 @@ class MainSite $raw = Curl::post('pc', $url, $payload, $headers); $de_raw = json_decode($raw, true); if ($de_raw['code'] == 0) { - Log::notice("主站任务: av{$av_info['aid']}分享成功!"); + Log::notice("主站任务: av{$av_info['aid']} 分享成功"); return true; } else { - Log::warning("主站任务: av{$av_info['aid']}分享失败!"); + Log::warning("主站任务: av{$av_info['aid']} 分享失败"); return false; } } - /** * @use 观看视频 * @return bool */ private static function watchAid(): bool { + if (!getConf('watch', 'main_site')) return true; + $url = "https://api.bilibili.com/x/report/click/h5"; $av_info = self::parseAid(); $user_info = User::parseCookies(); @@ -289,8 +308,8 @@ class MainSite 'ftime' => time(), 'jsonp' => "jsonp", 'lv' => "", - 'mid' => $user_info['uid'], - 'csrf' => $user_info['token'], + 'mid' => getUid(), + 'csrf' => getCsrf(), 'stime' => time() ]; @@ -309,7 +328,7 @@ class MainSite "aid" => $av_info['aid'], "cid" => $av_info['cid'], "mid" => $user_info['uid'], - "csrf" => $user_info['token'], + "csrf" => getCsrf(), "jsonp" => "jsonp", "played_time" => "0", "realtime" => $av_info['duration'], @@ -329,16 +348,15 @@ class MainSite $raw = Curl::post('pc', $url, $payload, $headers); $de_raw = json_decode($raw, true); if ($de_raw['code'] == 0) { - Log::notice("主站任务: av{$av_info['aid']}观看成功!"); + Log::notice("主站任务: av{$av_info['aid']} 观看成功"); return true; } } } - Log::warning("主站任务: av{$av_info['aid']}观看失败!"); + Log::warning("主站任务: av{$av_info['aid']} 观看失败"); return false; } - /** * @use 解析AID到CID * @return array diff --git a/src/plugin/ManGa.php b/src/plugin/ManGa.php index 0c5cfdb..1592f30 100644 --- a/src/plugin/ManGa.php +++ b/src/plugin/ManGa.php @@ -20,7 +20,7 @@ class ManGa public static function run() { - if (self::getLock() > time() || getenv('USE_MANGA') == 'false') { + if (self::getLock() > time() || !getEnable('manga')) { return; } if (self::sign() && self::share()) { @@ -31,12 +31,16 @@ class ManGa } + /** + * @use 漫画签到 + * @return bool + */ private static function sign(): bool { sleep(1); $url = 'https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn'; $payload = [ - 'access_key' => getenv('ACCESS_TOKEN'), + 'access_key' => getAccessToken(), 'ts' => time() ]; $raw = Curl::post('app', $url, Sign::common($payload)); @@ -44,14 +48,18 @@ class ManGa # {"code":0,"msg":"","data":{}} # {"code":"invalid_argument","msg":"clockin clockin is duplicate","meta":{"argument":"clockin"}} if (!$de_raw['code']) { - Log::notice('漫画签到: 成功~'); + Log::notice('漫画签到: 成功'); } else { - Log::warning('漫画签到: 失败或者重复操作~'); + Log::warning('漫画签到: 失败或者重复操作'); } return true; } + /** + * @use 漫画分享 + * @return bool + */ private static function share(): bool { sleep(1); @@ -62,9 +70,9 @@ class ManGa # {"code":0,"msg":"","data":{"point":5}} # {"code":1,"msg":"","data":{"point":0}} if (!$de_raw['code']) { - Log::notice('漫画分享: 成功~'); + Log::notice('漫画分享: 成功'); } else { - Log::warning('漫画分享: 失败或者重复操作~'); + Log::warning('漫画分享: 失败或者重复操作'); } return true; } diff --git a/src/plugin/MaterialObject.php b/src/plugin/MaterialObject.php index 0c49331..ec6b753 100644 --- a/src/plugin/MaterialObject.php +++ b/src/plugin/MaterialObject.php @@ -15,7 +15,6 @@ use BiliHelper\Core\Curl; use BiliHelper\Util\TimeLock; use BiliHelper\Util\FilterWords; - class MaterialObject { use TimeLock; @@ -27,13 +26,10 @@ class MaterialObject public static function run() { - if (getenv('USE_LIVE_BOX') == 'false') { + if (self::getLock() > time() || !getEnable('live_box')) { return; } self::setPauseStatus(); - if (self::getLock() > time()) { - return; - } self::calcAid(700, 900); $lottery_list = self::fetchLottery(); self::drawLottery($lottery_list); @@ -57,7 +53,6 @@ class MaterialObject return false; } - /** * @use 抽奖盒子状态 * @param int $aid @@ -92,7 +87,6 @@ class MaterialObject } } - /** * @use 获取抽奖 * @return array @@ -141,7 +135,6 @@ class MaterialObject return $lottery_list; } - /** * @use 过滤轮次 * @param array $rounds @@ -165,7 +158,6 @@ class MaterialObject return 0; } - /** * @use 抽奖 * @param array $lottery_list @@ -194,7 +186,6 @@ class MaterialObject return true; } - /** * @use 计算Aid * @param $min @@ -203,7 +194,7 @@ class MaterialObject */ private static function calcAid($min, $max): bool { - // TODO 优化计算AID算法 + // Todo 优化计算AID算法 if (self::$end_aid != 0 && self::$start_aid != 0) { return false; } diff --git a/src/plugin/Notice.php b/src/plugin/Notice.php index 30b9374..b6392a1 100644 --- a/src/plugin/Notice.php +++ b/src/plugin/Notice.php @@ -25,13 +25,13 @@ class Notice */ public static function push(string $type, string $result = '') { - if (getenv('USE_NOTIFY') == 'false') { + if (!getEnable('notify')) { return; } if (self::filterResultWords($result)) { return; } - $uname = User::userInfo() ? getenv('APP_UNAME') : getenv('APP_USER'); + $uname = getConf('uname', 'print') ?? getConf('username', 'login.account'); self::sendInfoHandle($type, $uname, $result); } @@ -44,9 +44,10 @@ class Notice { self::loadJsonData(); $default_words = self::$store->get("Notice.default");; - $custom_words = empty(getenv('NOTIFY_FILTER_WORDS')) ? [] : explode(',', getenv('NOTIFY_FILTER_WORDS')); + $custom_words = explode(',', getConf('filter_words', 'notify')); $total_words = array_merge($default_words, $custom_words); foreach ($total_words as $word) { + if (empty($word)) continue; if (strpos($result, $word) !== false) { return true; } @@ -54,7 +55,6 @@ class Notice return false; } - /** * @use 处理信息 * @param string $type @@ -156,27 +156,29 @@ class Notice */ private static function sendLog(array $info) { - if (getenv('NOTIFY_SCTKEY')) { + if (getConf('sctkey', 'notify.sct')) { self::sctSend($info); } - if (getenv('NOTIFY_SCKEY')) { + if (getConf('sckey', 'notify.sc')) { self::scSend($info); } - if (getenv('NOTIFY_TELE_BOTTOKEN') && getenv('NOTIFY_TELE_CHATID')) { + if (getConf('bottoken', 'notify.telegram') && getConf('chatid', 'notify.telegram')) { self::teleSend($info); } - if (getenv('NOTIFY_DINGTALK_TOKEN')) { + if (getConf('token', 'notify.dingtalk')) { self::dingTalkSend($info); } - if (getenv('NOTIFY_PUSHPLUS_TOKEN')) { + if (getConf('token', 'notify.pushplus')) { self::pushPlusSend($info); } - if (getenv('NOTIFY_CQ_URL') && getenv('NOTIFY_CQ_TOKEN') && getenv('NOTIFY_CQ_QQ')) { + if (getConf('target_qq', 'notify.gocqhttp') && getConf('token', 'notify.gocqhttp') && getConf('url', 'notify.gocqhttp')) { self::goCqhttp($info); } + if (getConf('token', 'notify.debug') && getConf('url', 'notify.debug')) { + self::debug($info); + } } - /** * @use DingTalkbot推送 * @doc https://developers.dingtalk.com/document/app/document-upgrade-notice#/serverapi2/qf2nxq @@ -185,7 +187,7 @@ class Notice private static function dingTalkSend(array $info) { Log::info('使用DingTalk机器人推送消息'); - $url = 'https://oapi.dingtalk.com/robot/send?access_token=' . getenv('NOTIFY_DINGTALK_TOKEN'); + $url = 'https://oapi.dingtalk.com/robot/send?access_token=' . getConf('token', 'notify.dingtalk'); $payload = [ 'msgtype' => 'markdown', 'markdown' => [ @@ -199,13 +201,12 @@ class Notice $raw = Curl::put('other', $url, $payload, $headers); $de_raw = json_decode($raw, true); if ($de_raw['errcode'] == 0) { - Log::info("推送消息成功: {$de_raw['errmsg']}"); + Log::notice("推送消息成功: {$de_raw['errmsg']}"); } else { Log::warning("推送消息失败: {$raw}"); } } - /** * @use TeleBot推送 * @doc https://core.telegram.org/bots/api#sendmessage @@ -214,22 +215,21 @@ class Notice private static function teleSend(array $info) { Log::info('使用Tele机器人推送消息'); - $url = 'https://api.telegram.org/bot' . getenv('NOTIFY_TELE_BOTTOKEN'); + $url = 'https://api.telegram.org/bot' . getConf('bottoken', 'notify.telegram') . '/sendMessage'; $payload = [ - 'method' => 'sendMessage', - 'chat_id' => getenv('NOTIFY_TELE_CHATID'), + 'chat_id' => getConf('chatid', 'notify.telegram'), 'text' => $info['content'] ]; + // {"ok":true,"result":{"message_id":7,"from":{"id":,"is_bot":true,"first_name":"","username":""},"chat":{"id":,"first_name":"","username":"","type":"private"},"date":,"text":""}} $raw = Curl::post('other', $url, $payload); $de_raw = json_decode($raw, true); - if (array_key_exists('message_id', $de_raw)) { - Log::info("推送消息成功: {$de_raw['message_id']}"); + if ($de_raw['ok'] && array_key_exists('message_id', $de_raw['result'])) { + Log::notice("推送消息成功: MSG_ID->{$de_raw['result']['message_id']}"); } else { - Log::info("推送消息失败: {$raw}"); + Log::warning("推送消息失败: {$raw}"); } } - /** * @use ServerChan推送 * @use https://sc.ftqq.com/ @@ -238,7 +238,7 @@ class Notice private static function scSend(array $info) { Log::info('使用ServerChan推送消息'); - $url = 'https://sc.ftqq.com/' . getenv('NOTIFY_SCKEY') . '.send'; + $url = 'https://sc.ftqq.com/' . getConf('sckey', 'notify.sc') . '.send'; $payload = [ 'text' => $info['title'], 'desp' => $info['content'], @@ -247,13 +247,12 @@ class Notice $de_raw = json_decode($raw, true); if ($de_raw['errno'] == 0) { - Log::info("推送消息成功: {$de_raw['errmsg']}"); + Log::notice("推送消息成功: {$de_raw['errmsg']}"); } else { Log::warning("推送消息失败: {$raw}"); } } - /** * @use ServerChan(Turbo)推送 * @doc https://sct.ftqq.com/ @@ -262,7 +261,7 @@ class Notice private static function sctSend(array $info) { Log::info('使用ServerChan(Turbo)推送消息'); - $url = 'https://sctapi.ftqq.com/' . getenv('NOTIFY_SCTKEY') . '.send'; + $url = 'https://sctapi.ftqq.com/' . getConf('sctkey', 'notify.sct') . '.send'; $payload = [ 'text' => $info['title'], 'desp' => $info['content'], @@ -272,7 +271,7 @@ class Notice // {'message': '[AUTH]用户不存在或者权限不足', 'code': 40001, 'info': '用户不存在或者权限不足', 'args': [None]} // {'code': 0, 'message': '', 'data': {'pushid': 'xxxx', 'readkey': 'xxxxx', 'error': 'SUCCESS', 'errno': 0}} if ($de_raw['code'] == 0) { - Log::info("推送消息成功: {$de_raw['data']['pushid']}"); + Log::notice("推送消息成功: {$de_raw['data']['pushid']}"); } else { Log::warning("推送消息失败: {$raw}"); } @@ -288,7 +287,7 @@ class Notice Log::info('使用PushPlus酱推送消息'); $url = 'http://www.pushplus.plus/send'; $payload = [ - 'token' => getenv('NOTIFY_PUSHPLUS_TOKEN'), + 'token' => getConf('token', 'notify.pushplus'), 'title' => $info['title'], 'content' => $info['content'] ]; @@ -299,13 +298,12 @@ class Notice // {"code":200,"msg":"请求成功","data":"发送消息成功"} $de_raw = json_decode($raw, true); if ($de_raw['code'] == 200) { - Log::info("推送消息成功: {$de_raw['data']}"); + Log::notice("推送消息成功: {$de_raw['data']}"); } else { Log::warning("推送消息失败: {$raw}"); } } - /** * @use GO-CQHTTP推送 * @doc https://docs.go-cqhttp.org/api/ @@ -314,20 +312,46 @@ class Notice private static function goCqhttp(array $info) { Log::info('使用GoCqhttp推送消息'); - $url = getenv('NOTIFY_CQ_URL'); + $url = getConf('url', 'notify.gocqhttp'); $payload = [ - 'access_token' => getenv('NOTIFY_CQ_TOKEN'), - 'user_id' => getenv('NOTIFY_CQ_QQ'), + 'access_token' => getConf('token', 'notify.gocqhttp'), + 'user_id' => getConf('target_qq', 'notify.gocqhttp'), 'message' => $info['content'] ]; $raw = Curl::get('other', $url, $payload); // {"data":{"message_id":123456},"retcode":0,"status":"ok"} $de_raw = json_decode($raw, true); if ($de_raw['retcode'] == 0) { - Log::info("推送消息成功: {$de_raw['status']}"); + Log::notice("推送消息成功: {$de_raw['status']}"); } else { Log::warning("推送消息失败: {$raw}"); } } + /** + * @use 个人调试使用 + * @doc + * @param array $info + */ + private static function debug(array $info) + { + Log::info('使用Debug推送消息'); + $url = getConf('url', 'notify.debug'); + $payload = [ + 'receiver' => getConf('token', 'notify.debug'), + 'title' => $info['title'], + 'body' => $info['content'], + 'url' => '', + ]; + $raw = Curl::post('other', $url, $payload); + $de_raw = json_decode($raw, true); + // {"success": true, "msg": null, "data": {"errcode": 0, "errmsg": "ok", "msgid": 1231, "token": "456"}} + if ($de_raw['success'] == true) { + Log::notice("推送消息成功: {$de_raw['data']['msgid']}"); + } else { + Log::warning("推送消息失败: {$raw}"); + } + + } + } \ No newline at end of file diff --git a/src/plugin/PkRaffle.php b/src/plugin/PkRaffle.php index 3cce163..d523303 100644 --- a/src/plugin/PkRaffle.php +++ b/src/plugin/PkRaffle.php @@ -15,17 +15,15 @@ use BiliHelper\Core\Curl; use BiliHelper\Util\TimeLock; use BiliHelper\Util\BaseRaffle; - class PkRaffle extends BaseRaffle { - const ACTIVE_TITLE = '大乱斗'; - const ACTIVE_SWITCH = 'USE_PK'; + const ACTIVE_TITLE = '主播乱斗'; + const ACTIVE_SWITCH = 'live_pk'; protected static $wait_list = []; protected static $finish_list = []; protected static $all_list = []; - /** * @use 解析数据 * @param int $room_id @@ -65,7 +63,6 @@ class PkRaffle extends BaseRaffle return true; } - /** * @use 创建抽奖任务 * @param array $raffles @@ -75,14 +72,12 @@ class PkRaffle extends BaseRaffle { $url = 'https://api.live.bilibili.com/xlive/lottery-interface/v1/pk/join'; $tasks = []; - $results = []; - $user_info = User::parseCookies(); foreach ($raffles as $raffle) { $payload = [ 'id' => $raffle['raffle_id'], 'roomid' => $raffle['room_id'], - 'csrf_token' => $user_info['token'], - "csrf" => $user_info['token'], + 'csrf_token' => getCsrf(), + "csrf" => getCsrf(), ]; array_push($tasks, [ 'payload' => Sign::common($payload), @@ -93,15 +88,14 @@ class PkRaffle extends BaseRaffle ] ]); } - $results = Curl::async('app', $url, $tasks); // print_r($results); - return $results; + return Curl::async('app', $url, $tasks); } /** * @use 解析抽奖信息 * @param array $results - * @return mixed|void + * @return void */ protected static function parseLottery(array $results) { diff --git a/src/plugin/PolishTheMedal.php b/src/plugin/PolishTheMedal.php new file mode 100644 index 0000000..2498c39 --- /dev/null +++ b/src/plugin/PolishTheMedal.php @@ -0,0 +1,117 @@ + 11000 MSG -> '' + if (in_array($medal['roomid'], [21686237])) return; + + Log::info("开始点亮直播间@{$medal['roomid']}的勋章"); + // 擦亮 + $response = Live::sendBarrageAPP($medal['roomid'], Generator::emoji()); + if (isset($response['code']) && $response['code'] == 0) { + Log::notice("在直播间@{$medal['roomid']}发送点亮弹幕成功"); + } else { + Log::warning("在直播间@{$medal['roomid']}发送点亮弹幕失败, CODE -> {$response['code']} MSG -> {$response['message']} "); + } + } + + + /** + * @use 获取灰色勋章列表(过滤无勋章或已满) + * @param bool $all + */ + private static function fetchGreyMedalList(bool $all = false) + { + $data = Live::fetchMedalList(); + foreach ($data as $vo) { + // 过滤主站勋章 + if (!isset($vo['roomid'])) continue; + // 过滤自己勋章 + if ($vo['target_id'] == getUid()) continue; + // 所有 + self::$fans_medals[] = [ + 'uid' => $vo['target_id'], + 'roomid' => $vo['roomid'], + ]; + // 如果是每天擦亮 ,就不过滤|否则过滤掉,只点亮灰色 + if ($all) { + self::$grey_fans_medals[] = [ + 'uid' => $vo['target_id'], + 'roomid' => $vo['roomid'], + ]; + } else { + // 灰色 + if ($vo['medal_color_start'] == 12632256 && $vo['medal_color_end'] == 12632256 && $vo['medal_color_border'] == 12632256) { + self::$grey_fans_medals[] = [ + 'uid' => $vo['target_id'], + 'roomid' => $vo['roomid'], + ]; + } + } + } + // 乱序 + shuffle(self::$grey_fans_medals); + } +} \ No newline at end of file diff --git a/src/plugin/Schedule.php b/src/plugin/Schedule.php index ce75d22..3a2cbad 100644 --- a/src/plugin/Schedule.php +++ b/src/plugin/Schedule.php @@ -13,17 +13,16 @@ namespace BiliHelper\Plugin; use BiliHelper\Core\Log; use BiliHelper\Util\TimeLock; - class Schedule { use TimeLock; - // TODO 黑白名单|考虑添加到每个插件内部自动添加|优化RUN逻辑代码 + // Todo 黑白名单|考虑添加到每个插件内部自动添加|优化RUN逻辑代码 private static $unlock_hour = 24; private static $unlock_timers = []; private static $sleep_section = []; // 日常类 - private static $fillable = ['Login', 'Schedule', 'Daily', 'Judge', 'MainSite', 'GiftSend', 'DailyTask', 'Silver2Coin', 'ManGa', 'GameMatch', 'GroupSignIn', 'AwardRecord', 'Statistics']; + private static $fillable = ['Login', 'Schedule', 'DailyBag', 'Judge', 'MainSite', 'GiftSend', 'DailyTask', 'Silver2Coin', 'ManGa', 'GroupSignIn', 'AwardRecord', 'Statistics']; // 任务类 private static $guarded_first = ['Barrage', 'GiftHeart', 'Silver', 'MaterialObject']; // 监控类 @@ -31,9 +30,12 @@ class Schedule // 抽奖类 private static $guarded_third = ['StormRaffle', 'GuardRaffle', 'PkRaffle', 'GiftRaffle', 'AnchorRaffle']; // 特殊 老爷处理 - private static $guarded_fourth = ['Heart']; + private static $guarded_fourth = ['DoubleHeart']; // 暂定不做处理,后期看情况再定 - private static $release = ['ActivityLottery', 'SmallHeart', 'Competition', 'SmallHeart', 'Forward', 'CapsuleLottery']; + private static $release = ['ActivityLottery', 'SmallHeart', 'Competition', 'SmallHeart', 'Forward', 'CapsuleLottery', 'PolishTheMedal']; + // 暂定不做处理 大会员类 + private static $guarded_fifth = ['VipPrivilege', 'BpConsumption']; + public static function run() { @@ -48,10 +50,10 @@ class Schedule /** * @use 检查休眠 */ - private static function isSleep() + private static function isSleep(): bool { - if (getenv('USE_SLEEP') != 'false' && self::$unlock_hour != date('H')) { - self::$sleep_section = empty(self::$sleep_section) ? explode(',', getenv('SLEEP_SECTION')) : self::$sleep_section; + if (getEnable('sleep') && self::$unlock_hour != date('H')) { + self::$sleep_section = empty(self::$sleep_section) ? explode(',', getConf('section', 'sleep')) : self::$sleep_section; if (!in_array(date('H'), self::$sleep_section)) { return false; }; @@ -64,7 +66,7 @@ class Schedule /** * @use 特殊暂停 */ - private static function isSpecialPause() + private static function isSpecialPause(): bool { foreach (self::$guarded_second as $classname) { $status = call_user_func(array(__NAMESPACE__ . '\\' . $classname, 'getPauseStatus')); diff --git a/src/plugin/Sign.php b/src/plugin/Sign.php index fca7219..5c92e79 100644 --- a/src/plugin/Sign.php +++ b/src/plugin/Sign.php @@ -27,7 +27,7 @@ class Sign // $appsecret = '59b43e04ad6965f34319062b478f83dd'; // // $default = [ -// 'access_key' => getenv('ACCESS_TOKEN'), +// 'access_key' => getAccessToken() // 'actionKey' => 'appkey', // 'appkey' => $appkey, // 'build' => 101800, @@ -45,17 +45,17 @@ class Sign * @param $payload * @return array */ - public static function login($payload) + public static function login($payload): array { # Android 新 $appkey = 'bca7e84c2d947ac6'; $appsecret = '60698ba2f68e01ce44738920a0ffe768'; $default = [ - 'access_key' => getenv('ACCESS_TOKEN'), + 'access_key' => getAccessToken(), 'actionKey' => 'appkey', 'appkey' => $appkey, - 'build' => 6205500, + 'build' => 6320200, 'channel' => 'bili', 'device' => 'phone', 'mobi_app' => 'android', @@ -71,7 +71,7 @@ class Sign * @param $payload * @return array */ - public static function common($payload) + public static function common($payload): array { # iOS 6680 // $appkey = '27eb53fc9058f8c3'; @@ -81,11 +81,11 @@ class Sign $appsecret = '560c52ccd288fed045859ed18bffd973'; $default = [ - 'access_key' => getenv('ACCESS_TOKEN'), + 'access_key' => getAccessToken(), 'actionKey' => 'appkey', 'appkey' => $appkey, - 'build' => 6205500, - 'device' => 'android', + 'build' => 6320200, + 'device' => 'phone', 'mobi_app' => 'android', 'platform' => 'android', 'ts' => time(), diff --git a/src/plugin/Silver2Coin.php b/src/plugin/Silver2Coin.php index 64a3a9c..89d587f 100644 --- a/src/plugin/Silver2Coin.php +++ b/src/plugin/Silver2Coin.php @@ -20,17 +20,17 @@ class Silver2Coin public static function run() { - if (self::getLock() > time() || getenv('USE_SILVER2COIN') == 'false') { + if (self::getLock() > time() || !getEnable('silver2coin')) { return; } if (self::appSilver2coin() && self::pcSilver2coin()) { - self::setLock(self::timing(10)); + // 定时10点 + 1-60分钟随机 + self::setLock(self::timing(10, 0, 0, true)); return; } self::setLock(3600); } - /** * @use app兑换 * @return bool @@ -40,20 +40,12 @@ class Silver2Coin sleep(0.5); $url = 'https://api.live.bilibili.com/AppExchange/silver2coin'; $payload = []; - $raw = Curl::get('app', $url, Sign::common($payload)); + $raw = Curl::post('app', $url, Sign::common($payload)); $de_raw = json_decode($raw, true); - if (!$de_raw['code'] && $de_raw['msg'] == '兑换成功') { - Log::info('[APP]银瓜子兑换硬币: ' . $de_raw['msg']); - } elseif ($de_raw['code'] == 403) { - Log::warning('[APP]银瓜子兑换硬币: ' . $de_raw['msg']); - } else { - Log::warning('[APP]银瓜子兑换硬币: ' . $de_raw['msg']); - return false; - } - return true; - } + return self::handle('APP', $de_raw); + } /** * @use pc兑换 @@ -62,16 +54,42 @@ class Silver2Coin protected static function pcSilver2coin(): bool { sleep(0.5); - $payload = []; - $url = "https://api.live.bilibili.com/exchange/silver2coin"; - $url = "https://api.live.bilibili.com/pay/v1/Exchange/silver2coin"; - - $raw = Curl::get('pc', $url, $payload); + $payload = [ + 'csrf_token' => getCsrf(), + 'csrf' => getCsrf(), + 'visit_id' => '' + ]; + // $url = "https://api.live.bilibili.com/exchange/silver2coin"; + // $url = "https://api.live.bilibili.com/pay/v1/Exchange/silver2coin"; + $url = "https://api.live.bilibili.com/xlive/revenue/v1/wallet/silver2coin"; + $raw = Curl::post('pc', $url, $payload); $de_raw = json_decode($raw, true); - if ($de_raw['code'] == -403) { - return false; + + return self::handle('PC', $de_raw); + } + + /** + * @use 处理结果 + * @param string $type + * @param array $data + * @return bool + */ + private static function handle(string $type, array $data): bool + { + // {"code":403,"msg":"每天最多能兑换 1 个","message":"每天最多能兑换 1 个","data":[]} + // {"code":403,"msg":"仅主站正式会员以上的用户可以兑换","message":"仅主站正式会员以上的用户可以兑换","data":[]} + // {"code":0,"msg":"兑换成功","message":"兑换成功","data":{"gold":"5074","silver":"36734","tid":"727ab65376a15a6b117cf560a20a21122334","coin":1}} + // {"code":0,"data":{"coin":1,"gold":1234,"silver":4321,"tid":"Silver2Coin21062316490299678123456"},"message":"兑换成功"} + switch ($data['code']) { + case 0: + Log::notice("[{$type}] 银瓜子兑换硬币: {$data['message']}"); + return true; + case 403: + Log::warning("[{$type}] 银瓜子兑换硬币: {$data['message']}"); + return true; + default: + Log::warning("[{$type}] 银瓜子兑换硬币: CODE -> {$data['code']} MSG -> {$data['message']} "); + return false; } - Log::info('[PC]银瓜子兑换硬币: ' . $de_raw['msg']); - return true; } } \ No newline at end of file diff --git a/src/plugin/SmallHeart.php b/src/plugin/SmallHeart.php index 328d5fa..fcdc911 100644 --- a/src/plugin/SmallHeart.php +++ b/src/plugin/SmallHeart.php @@ -10,7 +10,6 @@ namespace BiliHelper\Plugin; - use BiliHelper\Util\TimeLock; use BiliHelper\Util\XliveHeartBeat; @@ -19,9 +18,7 @@ class SmallHeart use TimeLock; use XliveHeartBeat; - private static $fans_medals = []; // 全部勋章 - private static $grey_fans_medals = []; // 灰色勋章 private static $metal_lock = 0; // 勋章时间锁 private static $interval = 60; // 每次跳动时间 private static $total_time = 0; @@ -29,13 +26,12 @@ class SmallHeart public static function run() { - if (getenv('USE_HEARTBEAT') == 'false') { + if (!getEnable('small_heart')) { return; } - if (self::$metal_lock < time()) { - self::polishMetal(); - self::$metal_lock = time() + 8 * 60 * 60; + self::fetchMedalList(); + self::$metal_lock = time() + 12 * 60 * 60; } if (self::getLock() < time()) { self::heartBeat(); @@ -49,35 +45,6 @@ class SmallHeart } } - - /** - * @use 勋章处理 - */ - private static function polishMetal() - { - // 灰色勋章 - self::fetchGreyMedalList(); - if (empty(self::$grey_fans_medals)) { - return; - } - // 小心心 - $bag_list = Live::fetchBagListByGift('小心心', 30607); - if (empty($bag_list)) { - return; - } - // 擦亮勋章 - foreach ($bag_list as $gift) { - for ($num = 1; $num <= $gift['gift_num']; $num++) { - $grey_fans_medal = array_shift(self::$grey_fans_medals); - // 为空 - if (is_null($grey_fans_medal)) break; - // 擦亮 - Live::sendGift($grey_fans_medal, $gift, 1); - } - } - } - - /** * @use 心跳处理 */ @@ -86,7 +53,7 @@ class SmallHeart if (empty(self::$fans_medals)) { return; } - if (is_null(self::$metal)){ + if (is_null(self::$metal)) { self::$metal = self::$fans_medals[array_rand(self::$fans_medals)]; } $interval = self::xliveHeartBeatTask(self::$metal['roomid'], 999, 999); @@ -96,31 +63,22 @@ class SmallHeart self::$interval = $interval == 0 ? 60 : $interval; } - /** * @use 获取灰色勋章列表(过滤无勋章或已满) */ - private static function fetchGreyMedalList() + private static function fetchMedalList() { $data = Live::fetchMedalList(); - $user_info = User::parseCookies(); foreach ($data as $vo) { // 过滤主站勋章 if (!isset($vo['roomid'])) continue; // 过滤自己勋章 - if ($vo['target_id'] == $user_info['uid']) continue; + if ($vo['target_id'] == getUid()) continue; // 所有 self::$fans_medals[] = [ 'uid' => $vo['target_id'], 'roomid' => $vo['roomid'], ]; - // 灰色 - if ($vo['medal_color_start'] == 12632256 && $vo['medal_color_end'] == 12632256 && $vo['medal_color_border'] == 12632256) { - self::$grey_fans_medals[] = [ - 'uid' => $vo['target_id'], - 'roomid' => $vo['roomid'], - ]; - } } } diff --git a/src/plugin/Statistics.php b/src/plugin/Statistics.php index 594014c..3701bfa 100644 --- a/src/plugin/Statistics.php +++ b/src/plugin/Statistics.php @@ -14,7 +14,6 @@ use BiliHelper\Core\Log; use BiliHelper\Util\TimeLock; use MathieuViossat\Util\ArrayToTextTable; - class Statistics { use TimeLock; @@ -24,18 +23,16 @@ class Statistics private static $success_list = []; private static $profit_list = []; - // TODO 统计开关 统计时间间隔 统计类型 + // Todo 统计开关 统计时间间隔 统计类型 public static function run() { if (self::getLock() > time()) { return; } self::outputResult(); - self::setLock(20 * 60); } - /** * @use 添加推送 * @param string $key @@ -49,7 +46,6 @@ class Statistics return true; } - /** * @use 添加参与 * @param string $key @@ -63,7 +59,6 @@ class Statistics return true; } - /** * @use 添加成功 * @param string $key @@ -77,7 +72,6 @@ class Statistics return true; } - /** * @use 添加收益 * @param string $title @@ -94,7 +88,6 @@ class Statistics return true; } - /** * @use 转换时间 * @param int $the_time @@ -142,7 +135,6 @@ class Statistics return true; } - /** * @use 获取结果 * @param array $target @@ -156,7 +148,6 @@ class Statistics return is_null($second_key) ? $target[self::getTodayKey()][$key] : $target[self::getTodayKey()][$key][$second_key]; } - /** * @use 获取所有结果 * @param array $target @@ -164,7 +155,7 @@ class Statistics * @param string $second_key * @return int */ - private static function getResults(array &$target, string $key, $second_key = null) + private static function getResults(array &$target, string $key, $second_key = null): int { $results = 0; is_null($second_key) ? self::initKeyValue($target, $key) : self::initKeyValue($target, $key, 0, $second_key); @@ -177,7 +168,6 @@ class Statistics return $results; } - /** * @use 变量增加 * @param array $target @@ -186,13 +176,12 @@ class Statistics * @param null $second_key * @return bool */ - private static function valIncrease(array &$target, string $key, $num = 1, $second_key = null) + private static function valIncrease(array &$target, string $key, $num = 1, $second_key = null): bool { is_null($second_key) ? $target[self::getTodayKey()][$key] += $num : $target[self::getTodayKey()][$key][$second_key] += $num; return true; } - /** * @use 变量替换 * @param array $target @@ -201,7 +190,7 @@ class Statistics * @param string $second_key * @return bool */ - private static function valReplace(array &$target, string $key, $data = null, $second_key = '') + private static function valReplace(array &$target, string $key, $data = null, $second_key = ''): bool { is_null($second_key) ? $target[self::getTodayKey()][$key] = $data : $target[self::getTodayKey()][$key][$second_key] = $data; return true; @@ -242,10 +231,9 @@ class Statistics return [self::unique_arr($tr_list_count), self::unique_arr($tr_list_profit)]; } - /** * @use 二维数组去重 - * @param $result + * @param array $result * @return array */ private static function unique_arr(array $result): array diff --git a/src/plugin/StormRaffle.php b/src/plugin/StormRaffle.php index ab239f1..2fa1a6b 100644 --- a/src/plugin/StormRaffle.php +++ b/src/plugin/StormRaffle.php @@ -12,13 +12,12 @@ namespace BiliHelper\Plugin; use BiliHelper\Core\Log; use BiliHelper\Core\Curl; -use BiliHelper\Util\TimeLock; use BiliHelper\Util\BaseRaffle; class StormRaffle extends BaseRaffle { const ACTIVE_TITLE = '节奏风暴'; - const ACTIVE_SWITCH = 'USE_STORM'; + const ACTIVE_SWITCH = 'live_storm'; protected static $wait_list = []; protected static $finish_list = []; @@ -27,7 +26,6 @@ class StormRaffle extends BaseRaffle private static $drop_rate = null; private static $attempt = null; - /** * @use 解析数据 * @param int $room_id @@ -49,7 +47,7 @@ class StormRaffle extends BaseRaffle return false; } // 过滤抽奖范围 - self::$drop_rate = getenv('STORM_DROPRATE') !== "" ? (int)getenv('STORM_DROPRATE') : 0; + self::$drop_rate = (int)getConf('drop_rate', 'live_storm'); if (mt_rand(1, 100) <= (int)self::$drop_rate) { return false; } @@ -69,7 +67,6 @@ class StormRaffle extends BaseRaffle return true; } - /** * 格式化日志输出 * @param $id @@ -79,10 +76,9 @@ class StormRaffle extends BaseRaffle */ private static function formatInfo($id, $num, $info): string { - return "风暴 {$id} 请求 {$num} 状态 {$info}"; + return "节奏风暴 {$id} 请求 {$num} 状态 {$info}"; } - /** * @use 创建抽奖任务 * @param array $raffles @@ -91,9 +87,8 @@ class StormRaffle extends BaseRaffle protected static function createLottery(array $raffles): array { $url = 'https://api.live.bilibili.com/lottery/v1/Storm/join'; - $user_info = User::parseCookies(); foreach ($raffles as $raffle) { - self::$attempt = getenv('STORM_ATTEMPT') !== "" ? explode(',', getenv('STORM_ATTEMPT')) : [30, 50]; + self::$attempt = empty($attempt = getConf('attempt', 'live_storm')) ? [5, 10] : explode(',', $attempt); $num = mt_rand((int)self::$attempt[0], (int)self::$attempt[1]); $payload = [ 'id' => $raffle['raffle_id'], @@ -101,8 +96,8 @@ class StormRaffle extends BaseRaffle "color" => "16772431", "captcha_token" => "", "captcha_phrase" => "", - "token" => $user_info['token'], - "csrf_token" => $user_info['token'], + "token" => getCsrf(), + "csrf_token" => getCsrf(), "visit_id" => "" ]; for ($i = 1; $i < $num; $i++) { @@ -158,7 +153,7 @@ class StormRaffle extends BaseRaffle /** * @use 解析抽奖信息 * @param array $results - * @return mixed|void + * @return void */ protected static function parseLottery(array $results) { diff --git a/src/plugin/User.php b/src/plugin/User.php index 21031d0..7e19641 100644 --- a/src/plugin/User.php +++ b/src/plugin/User.php @@ -11,7 +11,8 @@ namespace BiliHelper\Plugin; use BiliHelper\Core\Curl; -use BiliHelper\Core\Config; +use BiliHelper\Core\Log; +use BiliHelper\Tool\Common; class User { @@ -32,7 +33,6 @@ class User return true; } - /** * @use 老爷检测 * @return bool @@ -48,25 +48,6 @@ class User return false; } - - /** - * @use 写入用户名 - * @return bool - */ - public static function userInfo(): bool - { - $data = self::getUserInfo(); - if (getenv('APP_UNAME') != "") { - return true; - } - if ($data['msg'] == 'ok') { - Config::put('APP_UNAME', $data['data']['uname']); - return true; - } - return false; - } - - /** * @use UserInfo * @return array @@ -75,7 +56,7 @@ class User { $url = 'https://api.live.bilibili.com/User/getUserInfo'; $payload = [ - 'ts' => Live::getMillisecond(), + 'ts' => Common::getMillisecond(), ]; $raw = Curl::get('app', $url, Sign::common($payload)); return json_decode($raw, true); @@ -91,7 +72,7 @@ class User { $url = 'https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByUser'; $payload = [ - 'room_id' => $room_id ?? getenv('ROOM_ID') + 'room_id' => $room_id ?? getConf('room_id', 'global_room') ]; $raw = Curl::get('pc', $url, $payload); return json_decode($raw, true); @@ -107,10 +88,10 @@ class User { $url = 'https://api.live.bilibili.com/xlive/app-room/v1/index/getInfoByUser'; $payload = [ - 'room_id' => $room_id ?? getenv('ROOM_ID') + 'room_id' => $room_id ?? getConf('room_id', 'global_room') ]; $raw = Curl::get('app', $url, Sign::common($payload)); - return json_decode($raw, true);; + return json_decode($raw, true); } /** @@ -119,17 +100,14 @@ class User */ public static function parseCookies(): array { - $cookies = getenv('COOKIE'); + $cookies = getCookie(); preg_match('/bili_jct=(.{32})/', $cookies, $token); - $token = isset($token[1]) ? $token[1] : ''; preg_match('/DedeUserID=(\d+)/', $cookies, $uid); - $uid = isset($uid[1]) ? $uid[1] : ''; preg_match('/DedeUserID__ckMd5=(.{16})/', $cookies, $sid); - $sid = isset($sid[1]) ? $sid[1] : ''; return [ - 'token' => $token, - 'uid' => $uid, - 'sid' => $sid, + 'csrf' => $token[1] ?? '', + 'uid' => $uid[1] ?? '', + 'sid' => $sid[1] ?? '', ]; } @@ -139,8 +117,7 @@ class User */ public static function fetchAllFollowings(): array { - $user_info = User::parseCookies(); - $uid = $user_info['uid']; + $uid = getUid(); $followings = []; for ($i = 1; $i < 100; $i++) { $url = "https://api.bilibili.com/x/relation/followings"; @@ -168,7 +145,6 @@ class User return $followings; } - /** * @use 获取分组关注列表 * @param int $tag_id @@ -178,8 +154,7 @@ class User */ public static function fetchTagFollowings(int $tag_id = 0, int $page_num = 100, int $page_size = 50): array { - $user_info = User::parseCookies(); - $uid = $user_info['uid']; + $uid = getUid(); $followings = []; for ($i = 1; $i < $page_num; $i++) { $url = "https://api.bilibili.com/x/relation/tag"; @@ -208,7 +183,6 @@ class User return $followings; } - /** * @use 设置用户关注 * @param int $follow_uid @@ -217,15 +191,14 @@ class User */ public static function setUserFollow(int $follow_uid, $un_follow = false): bool { - $user_info = User::parseCookies(); $url = 'https://api.live.bilibili.com/relation/v1/Feed/SetUserFollow'; $payload = [ - 'uid' => $user_info['uid'], + 'uid' => getUid(), 'type' => $un_follow ? 0 : 1, 'follow' => $follow_uid, 're_src' => 18, - 'csrf_token' => $user_info['token'], - 'csrf' => $user_info['token'], + 'csrf_token' => getCsrf(), + 'csrf' => getCsrf(), 'visit_id' => '' ]; $headers = [ @@ -248,11 +221,10 @@ class User */ public static function createRelationTag(string $tag_name): int { - $user_info = User::parseCookies(); $url = 'https://api.bilibili.com/x/relation/tag/create?cross_domain=true'; $payload = [ 'tag' => $tag_name, - 'csrf' => $user_info['token'], + 'csrf' => getCsrf(), ]; $headers = [ 'content-type' => 'application/x-www-form-urlencoded; charset=UTF-8', @@ -276,12 +248,11 @@ class User */ public static function tagAddUsers(int $fid, int $tid): bool { - $user_info = User::parseCookies(); $url = 'https://api.bilibili.com/x/relation/tags/addUsers?cross_domain=true'; $payload = [ 'fids' => $fid, 'tagids' => $tid, - 'csrf' => $user_info['token'], + 'csrf' => getCsrf(), ]; $headers = [ 'content-type' => 'application/x-www-form-urlencoded; charset=UTF-8', @@ -303,12 +274,11 @@ class User */ public static function fetchTags(): array { - $user_info = User::parseCookies(); $tags = []; $url = 'https://api.bilibili.com/x/relation/tags'; $payload = []; $headers = [ - 'referer' => "https://space.bilibili.com/{$user_info['uid']}/fans/follow", + 'referer' => 'https://space.bilibili.com/' . getUid() . '/fans/follow', ]; $raw = Curl::get('pc', $url, $payload, $headers); $de_raw = json_decode($raw, true); @@ -320,4 +290,51 @@ class User return $tags; } + /** + * @use 是否为有效年度大会员 + * @return bool + */ + public static function isYearVip(): bool + { + $url = 'https://api.bilibili.com/x/vip/web/user/info'; + $headers = [ + 'origin' => 'https://account.bilibili.com', + 'referer' => 'https://account.bilibili.com/account/home' + ]; + $payload = []; + $raw = Curl::get('pc', $url, $payload, $headers); + // {"code":0,"message":"0","ttl":1,"data":{"mid":1234,"vip_type":2,"vip_status":1,"vip_due_date":1667750400000,"vip_pay_type":0,"theme_type":0,"label":{"text":"年度大会员","label_theme":"annual_vip","text_color":"#FFFFFF","bg_style":1,"bg_color":"#FB7299","border_color":""},"avatar_subscript":1,"avatar_subscript_url":"http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png","nickname_color":"#FB7299","is_new_user":false}} + $de_raw = json_decode($raw, true); + if ($de_raw['code'] == 0) { + if ($de_raw['data']['vip_type'] == 2 && $de_raw['data']['vip_due_date'] > Common::getMillisecond()) { + Log::debug("获取会员成功 有效年度大会员"); + return true; + } + Log::debug("获取会员成功 不是年度大会员或已过期"); + } else { + Log::debug("获取会员信息失败 {$raw}"); + } + return false; + } + + /** + * @use 我的钱包 + */ + public static function myWallet() + { + $url = 'https://api.live.bilibili.com/pay/v2/Pay/myWallet'; + $headers = [ + 'origin' => 'https://link.bilibili.com', + 'referer' => 'https://link.bilibili.com/p/center/index' + ]; + $payload = [ + 'need_bp' => 1, + 'need_metal' => 1, + 'platform' => 'pc', + ]; + $raw = Curl::get('pc', $url, $payload, $headers); + // {"code":0,"msg":"succ","message":"succ","data":{"gold":5074,"silver":37434,"bp":"0","metal":1904}} + $de_raw = json_decode($raw, true); + } + } \ No newline at end of file diff --git a/src/plugin/VipPrivilege.php b/src/plugin/VipPrivilege.php new file mode 100644 index 0000000..30809f5 --- /dev/null +++ b/src/plugin/VipPrivilege.php @@ -0,0 +1,96 @@ + '未知奖励', + 1 => 'B币劵', + 2 => '会员购优惠券' + ]; + + public static function run() + { + if (self::getLock() > time() || !getEnable('vip_privilege')) { + return; + } + // 如果为年度大会员 + if (User::isYearVip()) { + $privilege_list = self::myVipPrivilege(); + foreach ($privilege_list as $privilege) { + // 是否领取状态 + if ($privilege['state'] != 0) { + continue; + } + // 领取奖励 + self::myVipPrivilegeReceive($privilege['type']); + } + } + // 定时11点 + 随机120分钟 + self::setLock(self::timing(11) + mt_rand(1, 120) * 60); + } + + /** + * @use 领取我的大会员权益 + * @param int $type + */ + private static function myVipPrivilegeReceive(int $type) + { + $url = 'https://api.bilibili.com/x/vip/privilege/receive'; + $headers = [ + 'origin' => 'https://account.bilibili.com', + 'referer' => 'https://account.bilibili.com/account/big/myPackage', + ]; + $payload = [ + 'type' => $type, + 'csrf' => getCsrf(), + ]; + $raw = Curl::post('pc', $url, $payload, $headers); + // {"code":0,"message":"0","ttl":1} + $de_raw = json_decode($raw, true); + if ($de_raw['code'] == 0) { + Log::notice('大会员权益 ' . self::$privilege[$type] . ' 领取成功'); + } else { + Log::warning('大会员权益 ' . self::$privilege[$type] . " 领取失败, {$raw}"); + } + } + + /** + * @use 获取我的大会员权益列表 + * @return array + */ + private static function myVipPrivilege(): array + { + $url = 'https://api.bilibili.com/x/vip/privilege/my'; + $headers = [ + 'origin' => 'https://account.bilibili.com', + 'referer' => 'https://account.bilibili.com/account/big/myPackage', + ]; + $payload = []; + $raw = Curl::get('pc', $url, $payload, $headers); + // {"code":0,"message":"0","ttl":1,"data":{"list":[{"type":1,"state":0,"expire_time":1622476799},{"type":2,"state":0,"expire_time":1622476799}]}} + $de_raw = json_decode($raw, true); + if ($de_raw['code'] == 0 && isset($de_raw['data']['list'])) { + Log::info('获取大会员权益列表成功'); + return $de_raw['data']['list']; + } else { + Log::warning("获取大会员权益列表失败 {$raw}"); + return []; + } + } +} \ No newline at end of file diff --git a/src/plugin/ZoneTcpClient.php b/src/plugin/ZoneTcpClient.php index 2d6bc8c..555c998 100644 --- a/src/plugin/ZoneTcpClient.php +++ b/src/plugin/ZoneTcpClient.php @@ -39,7 +39,7 @@ class ZoneTcpClient */ public static function run() { - if (self::getLock() > time() || getenv('USE_ZONE_SERVER') == 'false') { + if (self::getLock() > time() || !getEnable('zone_monitor')) { return; } self::setPauseStatus(); @@ -50,13 +50,12 @@ class ZoneTcpClient self::pushHandle(); } - /** * @use 初始化 */ private static function init() { - if (empty(getenv('ZONE_SERVER_ADDR'))) { + if (empty(getConf('server_addr', 'zone_monitor'))) { exit('推送服务器信息不完整, 请检查配置文件!'); } if (!self::$client) { @@ -79,7 +78,6 @@ class ZoneTcpClient } } - /** * @use 触发重连 * @param array $area_data @@ -166,14 +164,13 @@ class ZoneTcpClient return false; } - /** * @use 响应数据 * @param $msg * @param $type * @return bool */ - private static function onMessage($msg, $type) + private static function onMessage($msg, $type): bool { // 心跳后回复人气 if ($type == 3) { @@ -359,9 +356,9 @@ class ZoneTcpClient Log::info("监测到 @分区 {$data['area_id']} @房间 {$data['room_id']} @抽奖 {$data['raffle_title']}"); // print_r($data); } + return true; } - /** * @推送到上游处理 */ @@ -387,12 +384,11 @@ class ZoneTcpClient { } - /** * @use 发送握手包 * @return bool */ - private static function sendHandShake() + private static function sendHandShake(): bool { return self::writer(self::genHandshakePkg(self::$room_id)); } @@ -406,7 +402,6 @@ class ZoneTcpClient return self::packMsg('', 0x0002); } - /** * @use 握手包 * @param $room_id @@ -431,17 +426,16 @@ class ZoneTcpClient * @param $option * @return string */ - private static function packMsg($value, $option) + private static function packMsg($value, $option): string { $head = pack('NnnNN', 0x10 + strlen($value), 0x10, 0x01, $option, 0x0001); return $head . $value; } - /** * @use 解包数据 * @param $value - * @return int|mixed + * @return array|false */ private static function unPackMsg($value) { @@ -449,12 +443,10 @@ class ZoneTcpClient Log::warning("unPackMsg: 包头异常 " . strlen($value)); return []; }; - $head = unpack('Npacklen/nheadlen/nver/Nop/Nseq', $value); // Log::info(json_encode($head, true)); - return $head; + return unpack('Npacklen/nheadlen/nver/Nop/Nseq', $value); } - /** * @use 心跳 */ @@ -479,10 +471,10 @@ class ZoneTcpClient /** * @use 读数据 * @param $length - * @param $is_header - * @return array|bool|false + * @param bool $is_header + * @return array|bool */ - private static function reader($length, $is_header = false) + private static function reader($length, bool $is_header = false) { $data = false; try { @@ -507,7 +499,7 @@ class ZoneTcpClient break; Log::debug("Socket debug: select timeout" . PHP_EOL); } - // TODO unable to read from socket[104]: Connection reset by peer + // Todo unable to read from socket[104]: Connection reset by peer $ret = socket_recv($socket, $buffer, $length, 0); if ($ret < 1) { Log::warning("Socket error: [{$ret}] [{$length}]" . PHP_EOL); @@ -534,7 +526,7 @@ class ZoneTcpClient * @param $data * @return bool */ - private static function writer($data) + private static function writer($data): bool { $status = false; try { @@ -551,7 +543,6 @@ class ZoneTcpClient return $status; } - /** * @use 读取数据 */ @@ -570,8 +561,8 @@ class ZoneTcpClient // 长度为0 ,空信息 continue; } - $length = isset($head['packlen']) ? $head['packlen'] : 16; - $type = isset($head['op']) ? $head['op'] : 0x0000; + $length = $head['packlen'] ?? 16; + $type = $head['op'] ?? 0x0000; $len_body = $length - 16; Log::debug("(AreaId={$client_info['area_id']} -> RoomId={$client_info['room_id']} -> Len={$len_body})"); if (!$len_body) @@ -590,7 +581,13 @@ class ZoneTcpClient } } - private static function v2_split($bin, $total) + /** + * @use V2切割 + * @param $bin + * @param $total + * @return array + */ + private static function v2_split($bin, $total): array { $list = []; $step = 0; @@ -604,7 +601,7 @@ class ZoneTcpClient if ($step == $total) break; $bin = substr($data, $step, 16); $head = self::unPackMsg($bin); - $length = isset($head['packlen']) ? $head['packlen'] : 16; + $length = $head['packlen'] ?? 16; $body = substr($data, $step + 16, $length - 16); $step += $length; array_push($list, $body); @@ -612,12 +609,20 @@ class ZoneTcpClient return $list; } + /** + * @param $object + * @return string + */ private static function getClass($object): string { $class = \get_class($object); return 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class) . '@anonymous' : $class; } + /** + * @param $e + * @return string + */ private static function formatErr($e): string { return sprintf('Uncaught Exception %s: "%s" at %s line %s', self::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()); @@ -626,7 +631,7 @@ class ZoneTcpClient /* * @use replace delay by select */ - public static function Delayed() + public static function Delayed(): Delayed { $r = []; $w = NULL; diff --git a/src/script/BaseTask.php b/src/script/BaseTask.php new file mode 100644 index 0000000..407c479 --- /dev/null +++ b/src/script/BaseTask.php @@ -0,0 +1,63 @@ +choice('Select', $options, $default, true); + static::interactor()->greenBold("You selected: {$options[$option]}", true); + // return $options[$option]; + return $option; + } + + /** + * @use 确认 + * @param string $msg + * @param string $default + * @return bool + */ + public static function confirm(string $msg, string $default = 'n'): bool + { + $confirm = static::interactor()->confirm($msg, $default); // Default: n (no) + if (!$confirm) die(); +// if ($confirm) { // is a boolean +// static::interactor()->greenBold('是 :)', true); // Output green bold text +// } else { +// static::interactor()->redBold('否 :(', true); // Output red bold text +// die(); +// } + return true; + } + + /** + * @return \Ahc\Cli\IO\Interactor + */ + public static function interactor(): Interactor + { + return static::$interactor ?? static::$interactor = new Interactor; + } +} \ No newline at end of file diff --git a/src/script/DelDynamic.php b/src/script/DelDynamic.php new file mode 100644 index 0000000..b12c5d7 --- /dev/null +++ b/src/script/DelDynamic.php @@ -0,0 +1,22 @@ + $up_uname) { + $payload = [ + 'fid' => $up_uid, + 'act' => 2, + 're_src' => 11, + 'csrf' => getCsrf(), + ]; + $headers = [ + 'origin' => 'https://space.bilibili.com', + 'referer' => 'https://space.bilibili.com/' . getUid() . '/fans/follow?tagid=' . $tag_id, + ]; + $raw = Curl::post('pc', $url, $payload, $headers); + // {"code":0,"message":"0","ttl":1} + $data = json_decode($raw, true); + if ($data['code'] == 0) { + Log::notice("UP.{$up_uid} - {$up_uname} 取关成功"); + } else { + Log::error("UP.{$up_uid} - {$up_uname} 取关失败 CODE -> {$data['code']} MSG -> {$data['message']} "); + break; + } + sleep(random_int(5, 10)); + } + } + + + /** + * @use 获取分组关注 + * @param $tag_id + * @param int $max_pn + * @param int $max_ps + * @return array + * @throws \Exception + */ + private static function relationTag($tag_id, int $max_pn = 30, int $max_ps = 20): array + { + $following = []; + $url = 'https://api.bilibili.com/x/relation/tag'; + for ($pn = 1; $pn <= $max_pn; $pn++) { + $payload = [ + 'mid' => getUid(), + 'tagid' => $tag_id, + 'pn' => $pn, + 'ps' => $max_ps, + ]; + $headers = [ + 'referer' => 'https://space.bilibili.com/' . getUid() . '/fans/follow', + ]; + $raw = Curl::get('pc', $url, $payload, $headers); + $data = json_decode($raw, true); + if ($data['code'] == 0 && isset($data['data'])) { + // 循环添加到 following + foreach ($data['data'] as $up) { + $following[$up['mid']] = $up['uname']; + } + // 打印和延迟 + Log::info("已获取分组 {$tag_id} 页码 {$pn}"); + sleep(random_int(4, 8)); + // 如果页面不等于 max_ps 跳出 + if (count($data['data']) != $max_ps) { + break; + } + } else { + Log::error("获取分组关注失败 CODE -> {$data['code']} MSG -> {$data['message']} "); + break; + } + } + $following_num = count($following); + Log::notice("已获取分组 {$tag_id} 有效关注数 {$following_num}"); + return $following; + } + + + /** + * @use 获取分组 + * @return mixed + */ + private static function relationTags() + { + $url = 'https://api.bilibili.com/x/relation/tags'; + $payload = []; + $headers = [ + 'referer' => 'https://space.bilibili.com/', + ]; + $raw = Curl::get('pc', $url, $payload, $headers); + $data = json_decode($raw, true); + if ($data['code'] == 0 && isset($data['data'])) { + $options = []; + foreach ($data['data'] as $tag) { + $options[$tag['tagid']] = "分组:{$tag['name']} - 关注数:{$tag['count']}"; + } + $option = self::choice($options); + Log::notice("已获取分组 {$option} - {$options[$option]}"); + return $option; + } else { + Log::error("获取关注分组失败 CODE -> {$data['code']} MSG -> {$data['message']} "); + die(); + } + } + +} \ No newline at end of file diff --git a/src/script/User.php b/src/script/User.php new file mode 100644 index 0000000..4036c42 --- /dev/null +++ b/src/script/User.php @@ -0,0 +1,57 @@ + {$data['code']} MSG -> {$data['message']} "); + die(); + } + return true; + } + + /** + * @use 用户 + * @return mixed + */ + public static function userInfo() + { + $url = 'https://api.bilibili.com/x/web-interface/nav'; + $payload = []; + $headers = [ + 'origin' => 'https://space.bilibili.com', + 'referer' => 'https://space.bilibili.com/' . getUid(), + ]; + $raw = Curl::get('pc', $url, $payload, $headers); + return json_decode($raw, true); + } + + +} \ No newline at end of file diff --git a/src/tool/BvToAv.php b/src/tool/BvToAv.php index 64f740d..953f367 100644 --- a/src/tool/BvToAv.php +++ b/src/tool/BvToAv.php @@ -20,11 +20,11 @@ class BvToAv protected $add = 8728348608; protected $s = [11, 10, 3, 8, 4, 6]; + /** - * BV 转 AV - * + * @use BV 转 AV * @param $bv - * @return int + * @return int|string */ public function dec($bv) { @@ -36,14 +36,13 @@ class BvToAv return ($r - $this->add) ^ $this->xor; } + /** - * - * AV 转 BV - * + * @use AV 转 BV * @param $av * @return string */ - public function enc($av) + public function enc($av): string { $tr = str_split($this->tr); $bv = 'BV1 4 1 7 '; diff --git a/src/tool/Common.php b/src/tool/Common.php index 0738cd4..09c2b36 100644 --- a/src/tool/Common.php +++ b/src/tool/Common.php @@ -12,6 +12,33 @@ namespace BiliHelper\Tool; class Common { + + /** + * @use 获取十三位时间戳 + * @return int + */ + public static function getMillisecond(): int + { + list($t1, $t2) = explode(' ', microtime()); + // return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000); + return intval(sprintf('%u', (floatval($t1) + floatval($t2)) * 1000)); + } + + /** + * @use 获取当月第一天及最后一天 + * $day[0] 第一天 + * $day[1] 最后一天 + * @return array + */ + public static function getTheMonth(): array + { + $today = date("Y-m-d"); + $first_day = date('Y-m-01', strtotime($today)); + $last_day = date('Y-m-d', strtotime("$first_day +1 month -1 day")); + return array($first_day, $last_day); + } + + /** * @use 替换字符串 * @param $str @@ -21,7 +48,7 @@ class Common * @param string $charset * @return string */ - public static function replaceStar($str, $start, $end = 0, $dot = "*", $charset = "UTF-8") + public static function replaceStar($str, $start, $end = 0, $dot = "*", $charset = "UTF-8"): string { $len = mb_strlen($str, $charset); if ($start == 0 || $start > $len) { @@ -39,9 +66,7 @@ class Common $len = $len - mb_strlen($top, $charset); $len = $len - mb_strlen($bottom, $charset); $newStr = $top; - for ($i = 0; $i < $len; $i++) { - $newStr .= $dot; - } + $newStr .= str_repeat($dot, $len); $newStr .= $bottom; return $newStr; } diff --git a/src/tool/DumpMemory.php b/src/tool/DumpMemory.php index a5615d4..776721c 100644 --- a/src/tool/DumpMemory.php +++ b/src/tool/DumpMemory.php @@ -12,7 +12,6 @@ namespace BiliHelper\Tool; use BiliHelper\Core\Log; -use BiliHelper\Core\Curl; class DumpMemory { diff --git a/src/tool/Faker.php b/src/tool/Faker.php index d1e7c41..63d1775 100644 --- a/src/tool/Faker.php +++ b/src/tool/Faker.php @@ -22,7 +22,7 @@ class Faker * @example 79907610 * */ - public static function numberBetween($int1 = 0, $int2 = 2147483647) + public static function numberBetween($int1 = 0, $int2 = 2147483647): int { $min = $int1 < $int2 ? $int1 : $int2; $max = $int1 < $int2 ? $int2 : $int1; @@ -36,7 +36,7 @@ class Faker * @param int $except * @return int */ - public static function randomDigitNot($except) + public static function randomDigitNot($except): int { $result = self::numberBetween(0, 8); if ($result >= $except) { @@ -53,7 +53,7 @@ class Faker * @param string $string String that needs to bet parsed * @return string */ - public static function asciify($string = '****') + public static function asciify($string = '****'): string { return preg_replace_callback('/\*/u', 'static::randomAscii', $string); } @@ -62,7 +62,7 @@ class Faker /** * @example 'fY4èHdZv68' */ - public function password($minLength = 6, $maxLength = 20) + public function password($minLength = 6, $maxLength = 20): string { $pattern = str_repeat('*', $this->numberBetween($minLength, $maxLength)); @@ -81,7 +81,7 @@ class Faker /** * @example '35cd:186d:3e23:2986:ef9f:5b41:42a4:e6f1' */ - public function ipv6() + public function ipv6(): string { $res = array(); for ($i = 0; $i < 8; $i++) { @@ -108,7 +108,7 @@ class Faker /** * @example '32:F1:39:2F:D6:18' */ - public static function macAddress() + public static function macAddress(): string { for ($i = 0; $i < 6; $i++) { $mac[] = sprintf('%02X', static::numberBetween(0, 0xff)); @@ -118,6 +118,11 @@ class Faker return $mac; } + /** + * @use 转Ascii + * @param $string + * @return array|string|string[] + */ protected static function toAscii($string) { static $arrayFrom, $arrayTo; diff --git a/src/tool/File.php b/src/tool/File.php index 30abcb8..9e24040 100644 --- a/src/tool/File.php +++ b/src/tool/File.php @@ -11,11 +11,9 @@ namespace BiliHelper\Tool; - class File { - /** * @use 创建文件 * @param string $filename diff --git a/src/tool/Generator.php b/src/tool/Generator.php index 3c5a65b..8d7414b 100644 --- a/src/tool/Generator.php +++ b/src/tool/Generator.php @@ -11,7 +11,6 @@ namespace BiliHelper\Tool; - class Generator { /** @@ -53,7 +52,8 @@ class Generator * @use 生成BUVID * @return string */ - public static function buvid():string{ + public static function buvid(): string + { // XYD5B85DA7212341F51C612344A6B8C6C21234 $mac = Faker::macAddress(); $md5 = md5($mac); @@ -61,4 +61,28 @@ class Generator return strtoupper("XY{$md5_arr[2]}{$md5_arr[12]}{$md5_arr[22]}{$md5}"); } + /** + * @use 获取颜文字信息 + * @return string + */ + public static function emoji(): string + { + $emoji_list_all = [ + "(⌒▽⌒)", "( ̄▽ ̄)", "(=・ω・=)", "(`・ω・´)", "(〜 ̄△ ̄)〜", "(・∀・)", + "(°∀°)ノ", "( ̄3 ̄)", "╮( ̄▽ ̄)╭", "_(:3」∠)_", "( ´_ゝ`)", "←_←", "→_→", + "(<_<)", "(>_>)", "(;¬_¬)", '("▔□▔)/', "(゚Д゚≡゚д゚)!?", "Σ(゚д゚;)", "Σ(  ̄□ ̄||)", + "(´;ω;`)", "(/TДT)/", "(^・ω・^ )", "(。・ω・。)", "(● ̄(エ) ̄●)", "ε=ε=(ノ≧∇≦)ノ", + "(´・_・`)", "(-_-#)", "( ̄へ ̄)", "( ̄ε(# ̄) Σ", "ヽ(`Д´)ノ", "(#-_-)┯━┯", + "(╯°口°)╯(┴—┴", "←◡←", "( ♥д♥)", "Σ>―(〃°ω°〃)♡→", "⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄", + "(╬゚д゚)▄︻┻┳═一", "・*・:≡( ε:)", "(打卡)", "(签到)" + ]; + $emoji_list = [ + "(⌒▽⌒)", "( ̄▽ ̄)", "(=・ω・=)", "(`・ω・´)", "(〜 ̄△ ̄)〜", + "╮( ̄▽ ̄)╭", "_(:3」∠)_", "( ´_ゝ`)", "(● ̄(エ) ̄●)", "(・∀・)", + "(´・_・`)", "( ̄へ ̄)", "(打卡)", "(签到)" + ]; + shuffle($emoji_list); + return $emoji_list[array_rand($emoji_list)]; + } + } diff --git a/src/tool/UserAgent.php b/src/tool/UserAgent.php new file mode 100644 index 0000000..30f011f --- /dev/null +++ b/src/tool/UserAgent.php @@ -0,0 +1,401 @@ + [ + 'GT-I9:number2-5:00 Build/JDQ39', + 'Nokia 3:number1-3:[10|15] Build/IMM76D', + '[SAMSUNG |]SM-G3:number1-5:0[R5|I|V|A|T|S] Build/JLS36C', + 'Ascend G3:number0-3:0 Build/JLS36I', + '[SAMSUNG |]SM-G3:number3-6::number1-8::number0-9:[V|A|T|S|I|R5] Build/JLS36C', + 'HUAWEI G6-L:number10-11: Build/HuaweiG6-L:number10-11:', + '[SAMSUNG |]SM-[G|N]:number7-9:1:number0-8:[S|A|V|T] Build/[JLS36C|JSS15J]', + '[SAMSUNG |]SGH-N0:number6-9:5[T|V|A|S] Build/JSS15J', + 'Samsung Galaxy S[4|IV] Mega GT-I:number89-95:00 Build/JDQ39', + 'SAMSUNG SM-T:number24-28:5[s|a|t|v] Build/[JLS36C|JSS15J]', + 'HP :number63-73:5 Notebook PC Build/[JLS36C|JSS15J]', + 'HP Compaq 2:number1-3:10b Build/[JLS36C|JSS15J]', + 'HTC One 801[s|e] Build/[JLS36C|JSS15J]', + 'HTC One max Build/[JLS36C|JSS15J]', + 'HTC Xplorer A:number28-34:0[e|s] Build/GRJ90' + ], + '4.4' => [ + 'XT10:number5-8:0 Build/SU6-7.3', + 'XT10:number12-52: Build/[KXB20.9|KXC21.5]', + 'Nokia :number30-34:10 Build/IMM76D', + 'E:number:20-23::number0-3::number0-4: Build/24.0.[A|B].1.34', + '[SAMSUNG |]SM-E500[F|L] Build/KTU84P', + 'LG Optimus G Build/KRT16M', + 'LG-E98:number7-9: Build/KOT49I', + 'Elephone P:number2-6:000 Build/KTU84P', + 'IQ450:number0-4: Quad Build/KOT49H', + 'LG-F:number2-5:00[K|S|L] Build/KOT49[I|H]', + 'LG-V:number3-7::number0-1:0 Build/KOT49I', + '[SAMSUNG |]SM-J:number1-2::number0-1:0[G|F] Build/KTU84P', + '[SAMSUNG |]SM-N80:number0-1:0 Build/[KVT49L|JZO54K]', + '[SAMSUNG |]SM-N900:number5-8: Build/KOT49H', + '[SAMSUNG-|]SGH-I337[|M] Build/[JSS15J|KOT49H]', + '[SAMSUNG |]SM-G900[W8|9D|FD|H|V|FG|A|T] Build/KOT49H', + '[SAMSUNG |]SM-T5:number30-35: Build/[KOT49H|KTU84P]', + '[Google |]Nexus :number5-7: Build/KOT49H', + 'LG-H2:number0-2:0 Build/KOT49[I|H]', + 'HTC One[_M8|_M9|0P6B|801e|809d|0P8B2|mini 2|S][ dual sim|] Build/[KOT49H|KTU84L]', + '[SAMSUNG |]GT-I9:number3-5:0:number0-6:[V|I|T|N] Build/KOT49H', + 'Lenovo P7:number7-8::number1-6: Build/[Lenovo|JRO03C]', + 'LG-D95:number1-8: Build/KOT49[I|H]', + 'LG-D:number1-8::number0-8:0 Build/KOT49[I|H]', + 'Nexus5 V:number6-7:.1 Build/KOT49H', + 'Nexus[_|] :number4-10: Build/[KOT49H|KTU84P]', + 'Nexus[_S_| S ][4G |]Build/GRJ22', + '[HM NOTE|NOTE-III|NOTE2 1LTE[TD|W|T]', + 'ALCATEL ONE[| ]TOUCH 70:number2-4::number0-9:[X|D|E|A] Build/KOT49H', + 'MOTOROLA [MOTOG|MSM8960|RAZR] Build/KVT49L' + ], + '5.0' => [ + 'Nokia :number10-11:00 [wifi|4G|LTE] Build/GRK39F', + 'HTC 80:number1-2[s|w|e|t] Build/[LRX22G|JSS15J]', + 'Lenovo A7000-a Build/LRX21M;', + 'HTC Butterfly S [901|919][s|d|] Build/LRX22G', + 'HTC [M8|M9|M8 Pro Build/LRX22G', + 'LG-D3:number25-37: Build/LRX22G', + 'LG-D72:number0-9: Build/LRX22G', + '[SAMSUNG |]SM-G4:number0-9:0 Build/LRX22[G|C]', + '[|SAMSUNG ]SM-G9[00|25|20][FD|8|F|F-ORANGE|FG|FQ|H|I|L|M|S|T] Build/[LRX21T|KTU84F|KOT49H]', + '[SAMSUNG |]SM-A:number7-8:00[F|I|T|H|] Build/[LRX22G|LMY47X]', + '[SAMSUNG-|]SM-N91[0|5][A|V|F|G|FY] Build/LRX22C', + '[SAMSUNG |]SM-[T|P][350|550|555|355|805|800|710|810|815] Build/LRX22G', + 'LG-D7:number0-2::number0-9: Build/LRX22G', + '[LG|SM]-[D|G]:number8-9::number0-5::number0-9:[|P|K|T|I|F|T1] Build/[LRX22G|KOT49I|KVT49L|LMY47X]' + ], + '5.1' => [ + 'Nexus :number5-9: Build/[LMY48B|LRX22C]', + '[|SAMSUNG ]SM-G9[28|25|20][X|FD|8|F|F-ORANGE|FG|FQ|H|I|L|M|S|T] Build/[LRX22G|LMY47X]', + '[|SAMSUNG ]SM-G9[35|350][X|FD|8|F|F-ORANGE|FG|FQ|H|I|L|M|S|T] Build/[MMB29M|LMY47X]', + '[MOTOROLA |][MOTO G|MOTO G XT1068|XT1021|MOTO E XT1021|MOTO XT1580|MOTO X FORCE XT1580|MOTO X PLAY XT1562|MOTO XT1562|MOTO XT1575|MOTO X PURE XT1575|MOTO XT1570 MOTO X STYLE] Build/[LXB22|LMY47Z|LPC23|LPK23|LPD23|LPH223]' + ], + '6.0' => [ + '[SAMSUNG |]SM-[G|D][920|925|928|9350][V|F|I|L|M|S|8|I] Build/[MMB29K|MMB29V|MDB08I|MDB08L]', + 'Nexus :number5-7:[P|X|] Build/[MMB29K|MMB29V|MDB08I|MDB08L]', + 'HTC One[_| ][M9|M8|M8 Pro] Build/MRA58K', + 'HTC One[_M8|_M9|0P6B|801e|809d|0P8B2|mini 2|S][ dual sim|] Build/MRA58K' + ], + '7.0' => [ + 'Pixel [XL|C] Build/[NRD90M|NME91E]', + 'Nexus :number5-9:[X|P|] Build/[NPD90G|NME91E]', + '[SAMSUNG |]GT-I:number91-98:00 Build/KTU84P', + 'Xperia [V |]Build/NDE63X', + 'LG-H:number90-93:0 Build/NRD90[C|M]' + ], + '7.1' => [ + 'Pixel [XL|C] Build/[NRD90M|NME91E]', + 'Nexus :number5-9:[X|P|] Build/[NPD90G|NME91E]', + '[SAMSUNG |]GT-I:number91-98:00 Build/KTU84P', + 'Xperia [V |]Build/NDE63X', + 'LG-H:number90-93:0 Build/NRD90[C|M]' + ] + ]; + public $locale = 'en-US'; + /** + * List of "OS" strings used for android + * @var array $android_os + */ + public $android_os = [ + 'Linux; Android :androidVersion:; :androidDevice:', + //Todo: Add a $windowsDevices variable that does the same as androidDevice + //'Windows Phone 10.0; Android :androidVersion:; :windowsDevice:', + 'Linux; U; Android :androidVersion:; :androidDevice:', + 'Android; Android :androidVersion:; :androidDevice:' + ]; + /** + * List of "OS" strings used for iOS + * @var array $mobile_ios + */ + public $mobile_ios = [ + 'iphone' => 'iPhone; CPU iPhone OS :number7-11:_:number0-9:_:number0-9:; like Mac OS X;', + 'ipad' => 'iPad; CPU iPad OS :number7-11:_:number0-9:_:number0-9: like Mac OS X;', + 'ipod' => 'iPod; CPU iPod OS :number7-11:_:number0-9:_:number0-9:; like Mac OS X;' + ]; + + /** + * Get a random operating system + * @param string|null $os + * @return string * + */ + public function getOS(string $os = NULL) + { + $_os = []; + if ($os === NULL || in_array($os, ['chrome', 'firefox', 'explorer'])) { + $_os = $os === 'explorer' ? $this->windows_os : array_merge($this->windows_os, $this->linux_os, $this->mac_os); + } else { + $_os += $this->{$os . '_os'}; + } + // randomly select on operating system + $selected_os = rtrim($_os[random_int(0, count($_os) - 1)], ';'); + + // check for spin syntax + if (strpos($selected_os, '[') !== FALSE) { + $selected_os = self::processSpinSyntax($selected_os); + } + + // check for random number syntax + if (strpos($selected_os, ':number') !== FALSE) { + $selected_os = self::processRandomNumbers($selected_os); + } + + if (random_int(1, 100) > 50) { + $selected_os .= '; ' . $this->locale; + } + return $selected_os; + } + + /** + * Get Mobile OS + * @param string|null $os Can specifiy android, iphone, ipad, ipod, or null/blank for random + * @return string * + */ + public function getMobileOS(string $os = NULL) + { + $os = strtolower($os); + $_os = []; + switch ($os) { + case'android': + $_os += $this->android_os; + break; + case 'iphone': + case 'ipad': + case 'ipod': + $_os[] = $this->mobile_ios[$os]; + break; + default: + $_os = array_merge($this->android_os, array_values($this->mobile_ios)); + } + // select random mobile os + $selected_os = rtrim($_os[random_int(0, count($_os) - 1)], ';'); + if (strpos($selected_os, ':androidVersion:') !== FALSE) { + $selected_os = $this->processAndroidVersion($selected_os); + } + if (strpos($selected_os, ':androidDevice:') !== FALSE) { + $selected_os = $this->addAndroidDevice($selected_os); + } + if (strpos($selected_os, ':number') !== FALSE) { + $selected_os = self::processRandomNumbers($selected_os); + } + return $selected_os; + } + + /** + * static::processRandomNumbers + * @param $selected_os + * @return null|string|string[] * + */ + public static function processRandomNumbers($selected_os) + { + return preg_replace_callback('/:number(\d+)-(\d+):/i', function ($matches) { + return random_int($matches[1], $matches[2]); + }, $selected_os); + } + + /** + * static::processSpinSyntax + * @param $selected_os + * @return null|string|string[] * + */ + public static function processSpinSyntax($selected_os) + { + return preg_replace_callback('/\[([\w\-\s|;]*?)\]/i', function ($matches) { + $shuffle = explode('|', $matches[1]); + return $shuffle[array_rand($shuffle)]; + }, $selected_os); + } + + /** + * processAndroidVersion + * @param $selected_os + * @return null|string|string[] * + */ + public function processAndroidVersion($selected_os) + { + $this->androidVersion = $version = $this->androidVersions[array_rand($this->androidVersions)]; + return preg_replace_callback('/:androidVersion:/i', function ($matches) use ($version) { + return $version; + }, $selected_os); + } + + /** + * addAndroidDevice + * @param $selected_os + * @return null|string|string[] * + */ + public function addAndroidDevice($selected_os) + { + $devices = $this->androidDevices[substr($this->androidVersion, 0, 3)]; + $device = $devices[array_rand($devices)]; + + $device = self::processSpinSyntax($device); + return preg_replace_callback('/:androidDevice:/i', function ($matches) use ($device) { + return $device; + }, $selected_os); + } + + /** + * static::chromeVersion + * @param $version + * @return string * + */ + public static function chromeVersion($version): string + { + return random_int($version['min'], $version['max']) . '.0.' . random_int(1000, 4000) + . '.' . random_int(100, 400); + } + + /** + * static::firefoxVersion + * @param $version + * @return string * + */ + public static function firefoxVersion($version): string + { + return random_int($version['min'], $version['max']) . '.' . random_int(0, 9); + } + + /** + * static::windows + * @param $version + * @return string * + */ + public static function windows($version): string + { + return random_int($version['min'], $version['max']) . '.' . random_int(0, 9); + } + + /** + * generate + * @param null $userAgent + * @return string * + */ + public function generate($userAgent = NULL, $locale = null): string + { + + if (!is_null($locale)) + $this->locale = $locale; + + if ($userAgent === NULL) { + $r = random_int(0, 100); + if ($r >= 44) { + $userAgent = array_rand(['firefox' => 1, 'chrome' => 1, 'explorer' => 1]); + } else { + $userAgent = array_rand(['iphone' => 1, 'android' => 1, 'mobile' => 1]); + } + } elseif ($userAgent == 'windows' || $userAgent == 'mac' || $userAgent == 'linux') { + $agents = ['firefox' => 1, 'chrome' => 1]; + if ($userAgent == 'windows') { + $agents['explorer'] = 1; + } + $userAgent = array_rand($agents); + } + $_SESSION['agent'] = $userAgent; + if ($userAgent == 'chrome') { + return 'Mozilla/5.0 (' . $this->getOS($userAgent) . ') AppleWebKit/' . + (random_int(1, 100) > 50 ? random_int(533, 537) : random_int(600, 603)) + . '.' . random_int(1, 50) . ' (KHTML, like Gecko) Chrome/' . + self::chromeVersion(['min' => 47, 'max' => 55]) . ' Safari/' + . (random_int(1, 100) > 50 ? random_int(533, 537) : random_int(600, 603)); + } elseif ($userAgent == 'firefox') { + + return 'Mozilla/5.0 (' . $this->getOS($userAgent) . ') Gecko/' + . (random_int(1, 100) > 30 ? '20100101' : '20130401') . ' Firefox/' + . self::firefoxVersion(['min' => 45, 'max' => 74]); + } elseif ($userAgent == 'explorer') { + + return 'Mozilla / 5.0 (compatible; MSIE ' . ($int = random_int(7, 11)) + . '.0; ' . $this->getOS('windows') . ' Trident / ' + . ($int == 7 || $int == 8 ? '4' : ($int == 9 ? '5' : ($int == 10 ? '6' : '7'))) + . '.0)'; + } elseif ($userAgent == 'mobile' + || $userAgent == 'android' + || $userAgent == 'iphone' + || $userAgent == 'ipad' + || $userAgent == 'ipod') { + + return 'Mozilla/5.0 (' . $this->getMobileOS($userAgent) . ') AppleWebKit/' + . (random_int(1, 100) > 50 ? random_int(533, 537) : random_int(600, 603)) + . '.' . random_int(1, 50) . ' (KHTML, like Gecko) Chrome/' + . self::chromeVersion(['min' => 47, 'max' => 55]) . ' Mobile Safari/' + . (random_int(1, 100) > 50 ? random_int(533, 537) : random_int(600, 603)) + . '.' . random_int(0, 9); + } else { + new Exception('Unable to determine user agent to generate'); + } + } +} diff --git a/src/util/AllotTasks.php b/src/util/AllotTasks.php index 8602049..283d3f3 100644 --- a/src/util/AllotTasks.php +++ b/src/util/AllotTasks.php @@ -29,7 +29,7 @@ trait AllotTasks * @use 加载json数据 * @return Parser */ - protected static function loadJsonData() + protected static function loadJsonData(): Parser { return Parser::fromFile(static::$repository); } diff --git a/src/util/BaseRaffle.php b/src/util/BaseRaffle.php index 8b904f0..1c80ddb 100644 --- a/src/util/BaseRaffle.php +++ b/src/util/BaseRaffle.php @@ -21,6 +21,7 @@ abstract class BaseRaffle { use TimeLock; use FilterWords; + const ACTIVE_TITLE = ''; const ACTIVE_SWITCH = ''; @@ -31,7 +32,7 @@ abstract class BaseRaffle public static function run() { - if (getenv(static::ACTIVE_SWITCH) == 'false') { + if (!getEnable(static::ACTIVE_SWITCH)) { return; } if (static::getLock() > time()) { @@ -96,14 +97,13 @@ abstract class BaseRaffle $raw = Curl::get('app', $url, Sign::common($payload)); $de_raw = json_decode($raw, true); if (!isset($de_raw['data']) || $de_raw['code']) { - // TODO 请求被拦截 412 + // Todo 请求被拦截 412 Log::error("获取抽奖数据错误,{$de_raw['message']}"); return []; } return $de_raw; } - /** * @use 解析抽奖信息 * @param int $room_id @@ -112,7 +112,6 @@ abstract class BaseRaffle */ abstract protected static function parseLotteryInfo(int $room_id, array $data): bool; - /** * @use 创建抽奖 * @param array $raffles @@ -120,7 +119,6 @@ abstract class BaseRaffle */ abstract protected static function createLottery(array $raffles): array; - /** * @use 解析抽奖返回 * @param array $results @@ -135,7 +133,7 @@ abstract class BaseRaffle * @param string $type * @return array */ - protected static function arrKeySort($arr, $key, $type = 'asc') + protected static function arrKeySort($arr, $key, string $type = 'asc'): array { switch ($type) { case 'desc': @@ -149,14 +147,13 @@ abstract class BaseRaffle } } - /** * @use 去重检测 * @param $lid * @param bool $filter * @return bool */ - protected static function toRepeatLid($lid, $filter = true): bool + protected static function toRepeatLid($lid, bool $filter = true): bool { $lid = (int)$lid; if (in_array($lid, static::$all_list)) { @@ -179,7 +176,7 @@ abstract class BaseRaffle public static function pushToQueue(array $data): bool { // 开关 - if (getenv(static::ACTIVE_SWITCH) == 'false') { + if (!getEnable(static::ACTIVE_SWITCH)) { return false; } // 黑屋 diff --git a/src/util/FilterWords.php b/src/util/FilterWords.php index 2bd744d..faac7b2 100644 --- a/src/util/FilterWords.php +++ b/src/util/FilterWords.php @@ -18,7 +18,7 @@ trait FilterWords { protected static $store; protected static $store_status; - protected static $repository = APP_DATA_PATH . 'filter_words.json'; + protected static $repository = APP_DATA_PATH . 'filter_library.json'; /** * @use 加载配置信息 diff --git a/src/util/TimeLock.php b/src/util/TimeLock.php index 064b59c..eace2fe 100644 --- a/src/util/TimeLock.php +++ b/src/util/TimeLock.php @@ -11,6 +11,7 @@ namespace BiliHelper\Util; use Amp\Delayed; +use BiliHelper\Core\Task; use BiliHelper\Plugin\Schedule; trait TimeLock @@ -25,7 +26,7 @@ trait TimeLock public static function setLock(int $lock) { if (!static::getpauseStatus()) { - static::$lock = time() + $lock; + Task::getInstance()::_setLock(static::getBaseClass(), time() + $lock); } } @@ -35,33 +36,44 @@ trait TimeLock */ public static function getLock(): int { - return static::$lock; + return Task::getInstance()::_getLock(static::getBaseClass()); + } + + /** + * @use 获取基础CLASS NAME + * @return string + */ + public static function getBaseClass(): string + { + return basename(str_replace('\\', '/', __CLASS__)); } /** * @use used in Amp loop Delayed * @return delayed */ - public static function Delayed() + public static function Delayed(): Delayed { return new Delayed(1000); } /** * @use 定时 - * @param int $hour - * @param int $minute - * @param int $seconds + * @param int $hour 时 + * @param int $minute 分 + * @param int $seconds 秒 + * @param bool $random 随机一个小时内 * @return int */ - public static function timing(int $hour, int $minute = 0, int $seconds = 0): int + public static function timing(int $hour, int $minute = 0, int $seconds = 0, bool $random = false): int { $time = strtotime('today') + ($hour * 60 * 60) + ($minute * 60) + ($seconds); if ($time > time()) { - return strtotime('today') + ($hour * 60 * 60) + ($minute * 60) + ($seconds) - time(); + $timing = strtotime('today') + ($hour * 60 * 60) + ($minute * 60) + ($seconds) - time(); } else { - return strtotime('tomorrow') + ($hour * 60 * 60) + ($minute * 60) + ($seconds) - time(); + $timing = strtotime('tomorrow') + ($hour * 60 * 60) + ($minute * 60) + ($seconds) - time(); } + return $random ? $timing + mt_rand(1, 60) * 60 : $timing; } @@ -102,14 +114,14 @@ trait TimeLock */ public static function cancelPause() { - static::$lock = false; + static::$pause_status = false; } /** * @use 暂停状态 * @return bool */ - public static function getPauseStatus() + public static function getPauseStatus(): bool { return static::$pause_status; } diff --git a/src/util/XliveHeartBeat.php b/src/util/XliveHeartBeat.php index 06e5075..a44a381 100644 --- a/src/util/XliveHeartBeat.php +++ b/src/util/XliveHeartBeat.php @@ -13,7 +13,6 @@ namespace BiliHelper\Util; use BiliHelper\Core\Curl; use BiliHelper\Core\Log; use BiliHelper\Plugin\Live; -use BiliHelper\Plugin\User; use BiliHelper\Tool\Generator; trait XliveHeartBeat @@ -32,28 +31,14 @@ trait XliveHeartBeat protected static $_default = 0; // 默认值 - - /** - * @use 重置变量 - * @param false $force - */ - protected static function resetVar($force = false) - { - if ($force) { - static::$_room_info = []; - static::$_current_room_id = 0; - - static::$_retry = 3; - static::$_count_num = 0; - static::$_count_time = 0; - } - $data = [ - 'id' => static::$_data['id'], - ]; - $data["id"][2] = 0; - static::$_data = $data; - } - + // 请求配置 + protected static $_user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36'; + protected static $_headers = [ + 'content-type' => 'application/x-www-form-urlencoded', + 'origin' => 'https://live.bilibili.com', + 'referer' => 'https://live.bilibili.com/', + 'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36' + ]; /** * @use 任务接口 @@ -73,7 +58,7 @@ trait XliveHeartBeat static::resetVar(true); static::$_current_room_id = $room_id; } - // 加载房间信息 + // 获取房间信息 if (empty(static::$_room_info)) { $r_data = Live::webGetRoomInfo($room_id); if ($r_data['code'] != 0) { @@ -92,53 +77,43 @@ trait XliveHeartBeat $r_data = static::heartBeatIterator(); $index = static::$_data['id'][2]; if ($r_data['code'] != 0) { + Log::warning("心跳失败-$index {$r_data['message']}"); + // 失败心跳 if (static::$_retry) { - Log::warning("心跳失败-$index {$r_data['message']}"); - static::resetVar(); + // 重试次数 > 1 , 不全部清除 + static::resetVar(true); static::$_retry -= 1; - return static::$_default; + } else { + // 重试次数 < 1 , 全部清除 + static::resetVar(true); } - } - static::$_count_num += 1; - static::$_count_time += $r_data['heartbeat_interval']; + return static::$_default; + } else { + // 成功心跳 + static::$_count_num += 1; + static::$_count_time += $r_data['heartbeat_interval']; - // 最大次数限制 - if ($max_num <= static::$_count_num) { - // 成功在id为{room_id}的直播间发送完{ii}次心跳,退出直播心跳(达到最大心跳次数) + // 最大次数限制 + if ($max_num <= static::$_count_num) { + // 成功在id为{room_id}的直播间发送完{ii}次心跳,退出直播心跳(达到最大心跳次数) + } + // 最大时间限制 + if ($max_time <= static::$_count_time) { + //成功在id为{room_id}的直播间发送第{ii}次心跳 + } + $minute = round(static::$_count_time / 60) - 1; + Log::notice("已在直播间 $room_id 连续观看了 $minute 分钟"); + return $r_data['heartbeat_interval']; } - // 最大时间限制 - if ($max_time <= static::$_count_time) { - //成功在id为{room_id}的直播间发送第{ii}次心跳 - } - $minute = round(static::$_count_time / 60); - Log::info("已在直播间 $room_id 连续观看了 $minute 分钟"); - return $r_data['heartbeat_interval']; - } - /** - * @use 检查依赖 - * @return bool - */ - protected static function depend(): bool - { - if (getenv('ENC_SERVER') == '') { - return false; - } - // 加载加密服务器 - if (is_null(static::$_enc_server)) { - static::$_enc_server = getenv('ENC_SERVER'); - } - return true; - } - - /** * @use 心跳迭代 * @return array */ protected static function heartBeatIterator(): array { +// print_r(static::$_data); $rdata = []; # 第1次执行 eHeartBeat if (static::$_data['id'][2] == 0) { @@ -147,6 +122,13 @@ trait XliveHeartBeat # 第1次之后执行 xHeartBeat static::$_data['ts'] = time() * 1000; static::$_data['s'] = static::encParamS(static::$_data, static::$_secret_rule); + if (!static::$_data['s']) { + return [ + 'code' => 404, + 'message' => '心跳加密错误', + 'heartbeat_interval' => static::$_default + ]; + } $r_data = static::xHeartBeat(static::$_data['id']); } if ($r_data['code'] == 0) { @@ -161,11 +143,10 @@ trait XliveHeartBeat return [ 'code' => $r_data['code'], 'message' => $r_data['message'], - 'heartbeat_interval' => $rdata['heartbeat_interval'] + 'heartbeat_interval' => array_key_exists('heartbeat_interval', $rdata) ? $rdata['heartbeat_interval'] : static::$_default ]; } - /** * @use E心跳 * @param array $id @@ -174,26 +155,20 @@ trait XliveHeartBeat protected static function eHeartBeat(array $id): array { $url = 'https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/E'; - $headers = [ - 'Content-Type' => 'application/x-www-form-urlencoded', - 'Origin' => 'https://live.bilibili.com', - 'Referer' => 'https://live.bilibili.com/' . $id[3], - ]; - $user_info = User::parseCookies(); $payload = [ 'id' => json_encode([$id[0], $id[1], $id[2], $id[3]], true), 'device' => json_encode([Generator::hash(), Generator::uuid4()], true), 'ts' => time() * 1000, 'is_patch' => 0, 'heart_beat' => [], - 'ua' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0', - 'csrf_token' => $user_info['token'], - 'csrf' => $user_info['token'], + 'ua' => static::$_user_agent, + 'csrf_token' => getCsrf(), + 'csrf' => getCsrf(), 'visit_id' => '' ]; - // print_r($payload); + // print_r($payload); Log::debug(json_encode($payload, true)); - $raw = Curl::post('pc', $url, $payload, $headers); + $raw = Curl::post('pc', $url, $payload, static::$_headers); // {'code':0,'message':'0','ttl':1,'data':{'timestamp':1595342828,'heartbeat_interval':300,'secret_key':'seacasdgyijfhofiuxoannn','secret_rule':[2,5,1,4],'patch_status':2}} unset($payload['id']); @@ -210,12 +185,6 @@ trait XliveHeartBeat protected static function xHeartBeat(array $id): array { $url = 'https://live-trace.bilibili.com/xlive/data-interface/v1/x25Kn/X'; - $user_info = User::parseCookies(); - $headers = [ - 'Content-Type' => 'application/x-www-form-urlencoded', - 'Origin' => 'https://live.bilibili.com', - 'Referer' => 'https://live.bilibili.com/' . $id[3], - ]; $payload = [ 's' => static::$_data['s'], 'id' => json_encode([$id[0], $id[1], $id[2], $id[3]], true), @@ -225,13 +194,14 @@ trait XliveHeartBeat 'time' => static::$_data['time'], 'ts' => static::$_data['ts'], 'ua' => static::$_data['ua'], - 'csrf_token' => $user_info['token'], - 'csrf' => $user_info['token'], + 'csrf_token' => static::$_data['csrf_token'], + 'csrf' => static::$_data['csrf'], 'visit_id' => '' ]; // print_r($payload); Log::debug(json_encode($payload, true)); - $raw = Curl::post('pc', $url, $payload, $headers); + $raw = Curl::post('pc', $url, $payload, static::$_headers); + # {"code":0,"message":"0","ttl":1,"data":{"heartbeat_interval":60,"timestamp":1619419450,"secret_rule":[2,5,1,4],"secret_key":"seacasdgyijfhofiuxoannn"}} # {'code':0,'message':'0','ttl':1,'data':{'heartbeat_interval':300,'timestamp':1595346846,'secret_rule':[2,5,1,4],'secret_key':'seacasdgyijfhofiuxoannn'}} return json_decode($raw, true); } @@ -248,17 +218,91 @@ trait XliveHeartBeat 'Content-Type' => 'application/json', ]; // 加密部分 - $payload = ['t' => $t, 'r' => $r]; + $payload = [ + 't' => static::formatT($t), + 'r' => static::formatR($r) + ]; +// print_r($payload); $data = Curl::put('other', static::$_enc_server, $payload, $headers); $de_raw = json_decode($data, true); if ($de_raw['code'] == 0) { - // Log::info("S加密成功 {$de_raw['s']}"); - return $de_raw['s']; + if (array_key_exists('s', $de_raw)) { + // Log::info("S加密成功 {$de_raw['s']}"); + return $de_raw['s']; + } + Log::warning("参数S加密失败: 加密服务器暂时错误,请检查更换"); } else { - Log::warning("S加密失败 {$de_raw['message']}"); - return false; + Log::warning("参数S加密失败: {$de_raw['message']}"); } + return false; } + /** + * @use 格式T + * @param array $t + * @return array + */ + protected static function formatT(array $t): array + { +// print_r($t); + return [ + 'id' => $t['id'], + 'device' => $t['device'], + 'ets' => $t['ets'], + 'benchmark' => $t['benchmark'], + 'time' => $t['time'], + 'ts' => $t['ts'], + 'ua' => $t['ua'], + ]; + } + + /** + * @use 格式R + * @param array $r + * @return array + */ + protected static function formatR(array $r): array + { + return $r; + } + + /** + * @use 重置变量 + * @param false $force + */ + protected static function resetVar(bool $force = false) + { + if ($force) { + static::$_room_info = []; + static::$_current_room_id = 0; + + static::$_retry = 3; + static::$_count_num = 0; + static::$_count_time = 0; + } + static::$_data = null; + static::$_data = ['id' => []]; + $data = [ + 'id' => static::$_data['id'], + ]; + $data["id"][2] = 0; + static::$_data = $data; + } + + /** + * @use 检查依赖 + * @return bool + */ + protected static function depend(): bool + { + if (getConf('server', 'heartbeat_enc') == '') { + return false; + } + // 加载加密服务器 + if (is_null(static::$_enc_server)) { + static::$_enc_server = getConf('server', 'heartbeat_enc'); + } + return true; + } } \ No newline at end of file diff --git a/task/.gitkeep b/task/.gitkeep new file mode 100644 index 0000000..e69de29