Merge branch 'lkeme:master' into master

This commit is contained in:
DishesDog 2021-07-23 09:53:09 +08:00 committed by GitHub
commit 1122929161
88 changed files with 5402 additions and 2558 deletions

22
.github/workflows/build_image_bhp.yml vendored Normal file
View File

@ -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 }}

23
.gitignore vendored
View File

@ -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/
/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

View File

@ -1,12 +1,198 @@
# Release Notes
# 本项目Log
[comment]: <> (<details>)
[comment]: <> ( <summary><strong>更新历史</strong><kbd>latest</kbd></summary>)
[comment]: <> (</details>)
## 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)

262
DOC.md
View File

@ -1,68 +1,24 @@
<p align="center"><img width="300px" src="https://user-images.githubusercontent.com/19500576/118621710-36428180-b7f9-11eb-891d-3f5697347cef.png"></p>
<p align="center"><img width="300px" src="https://i.loli.net/2018/04/20/5ad97bd395912.jpeg"></p>
[comment]: <> (<p align="center"><img width="300px" src="https://i.loli.net/2018/04/20/5ad97bd395912.jpeg"></p>)
<p align="center">
<img src="https://img.shields.io/badge/version-0.8.1.210423 alpha-green.svg?longCache=true&style=for-the-badge">
<img src="https://img.shields.io/badge/license-mit-blue.svg?longCache=true&style=for-the-badge">
</p>
<div align="center">
[![](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)
> 待添加
## 未完成功能
|待续 |
|-----------|
|多用户 |
</div>
## 环境依赖
通常使用 `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
```
<details>
<summary>其余镜像 展开查看</summary>
<pre><code>
+ 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
```
</code></pre>
</details>
## 使用指南
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 &#40;-o&#41;)
[comment]: <> (composer dumpautoload &#40;-o&#41;)
3. 按照说明修改配置文件 `user.ini`
```
# 默认只需填写帐号密码,按需求开启其他功能即可
```
4. 运行测试
4. 运行测试
```
$ php index.php
```
> 以下是`多账户多开方案`,单个账户可以无视
5. 复制一份example配置文件修改账号密码即可
```
$ php index.php example.conf
```
6. 请保证配置文件存在,否则默认加载`user.conf`配置文件
<p align="center"><img width="680px" src="https://i.loli.net/2018/04/21/5adb497dc3ece.png"></p>
> 以下是`多账户多开方案`,单个账户可以无视
5. 复制一份example配置文件修改账号密码即可
```
$ php index.php example.ini
```
6. 请保证配置文件存在,否则默认加载`user.ini`配置文件
<p align="center"><img width="680px" src="https://user-images.githubusercontent.com/19500576/118621472-f8455d80-b7f8-11eb-9fec-500148a566b4.png"></p>
[comment]: <> (<p align="center"><img width="680px" src="https://i.loli.net/2018/04/21/5adb497dc3ece.png"></p>)
## 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酱
# 自行替换 <SCKEY>
@ -235,10 +281,9 @@ APP_CALLBACK="https://api.telegram.org/bot<TOKEN>/sendMessage?chat_id=<CHAR_ID>&
`{message}` 部分会自动替换成错误信息,接口采用 get 方式发送
## 直播间 ID 问题
文件 `user.conf` 里
文件 `user.ini` 里
`ROOM_ID` 配置,填写此项可以清空临过期礼物给指定直播间。
@ -249,11 +294,13 @@ APP_CALLBACK="https://api.telegram.org/bot<TOKEN>/sendMessage?chat_id=<CHAR_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 文件中的内容为准。

View File

@ -1,38 +0,0 @@
FROM php:alpine
MAINTAINER zsnmwy <szlszl35622@gmail.com>
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

131
README.md
View File

@ -1,31 +1,138 @@
# BiliHelper
B 站直播实用脚本
<p align="center"><img width="300px" src="https://user-images.githubusercontent.com/19500576/118621710-36428180-b7f9-11eb-891d-3f5697347cef.png"></p>
## 交流
[comment]: <> (<p align="center"><img width="300px" src="https://i.loli.net/2018/04/20/5ad97bd395912.jpeg"></p>)
Group: [55308141](https://jq.qq.com/?_wv=1027&k=5AIDaJg) | **仅用于BUG提交反馈**
<div align="center">
## 公告
[![](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**
</div>
<p align="center">
<img src="https://img.shields.io/badge/Version-0.9.7.210714-orange.svg?longCache=true&style=for-the-badge">
<img src="https://img.shields.io/badge/PHP-7.3+-green.svg?longCache=true&style=for-the-badge">
<img src="https://img.shields.io/badge/Composer-latest-blueviolet.svg?longCache=true&style=for-the-badge">
<img src="https://img.shields.io/badge/License-mit-blue.svg?longCache=true&style=for-the-badge">
</p>
## 公告通知
代码开源本地化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)
如果觉得本项目好用,对你有所帮助,欢迎打赏支持本项目哦。
## 效果
<p align="center"><img width="680px" src="https://user-images.githubusercontent.com/19500576/118621834-55d9aa00-b7f9-11eb-9de2-6cfd5e8f20e6.png"></p>
![](https://i.loli.net/2019/07/13/5d296961a4bae41364.png)
[comment]: <> (![Image]&#40;https://i.loli.net/2019/07/13/5d2963e5cc1eb22973.png&#41;)
## 运行效果
效果图不代表当前版本,请以当前最新版本运行结果为准。
<p align="center"><img width="680px" src="https://user-images.githubusercontent.com/19500576/118621918-6853e380-b7f9-11eb-8c73-e041c402a56b.png"></p>
[comment]: <> (![Image]&#40;https://i.loli.net/2019/07/13/5d296961a4bae41364.png&#41;)
## 项目相关
* [BilibiliHelper](https://github.com/metowolf/BilibiliHelper)
* [BiliHelper](https://github.com/lkeme/BiliHelper)
* [Github](https://github.com/)
## 致谢
感谢 `JetBrains` 提供优秀的IDE。
<a href="https://www.jetbrains.com/?from=BiliHelper-personal" target="_blank">
<img src="https://tva1.sinaimg.cn/large/008eGmZEly1gov9g3tzrnj30u00wj0tn.jpg" width="150"/>
</a>
## License 许可证
BiliHelper is under the MIT license.
本项目基于 MIT 协议发布,并增加了 SATA 协议。
当你使用了使用 SATA 的开源软件或文档的时候,在遵守基础许可证的前提下,你必须马不停蹄地给你所使用的开源项目 “点赞” ,比如在 GitHub 上
star然后你必须感谢这个帮助了你的开源项目的作者作者信息可以在许可证头部的版权声明部分找到。
本项目的所有代码文件、配置项,除另有说明外,均基于上述介绍的协议发布,具体请看分支下的 LICENSE。
此处的文字仅用于说明,条款以 LICENSE 文件中的内容为准。

View File

@ -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"
]
}
}

567
composer.lock generated
View File

@ -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"
}

View File

@ -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 成功~";
}
}

View File

@ -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

290
conf/user.ini.example Normal file
View File

@ -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

View File

@ -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"
}
]
}

View File

@ -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"
}
]
}

727
data/filter_library.json Normal file
View File

@ -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
]
}
}

View File

@ -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": [
"谢谢参与",
"未中奖",
"辣条"
]
}
}

11
data/latest_version.json Normal file
View File

@ -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"
}

175
data/reply_words.json Normal file
View File

@ -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]"
]
}
}

45
docker/Dockerfile Normal file
View File

@ -0,0 +1,45 @@
FROM php:alpine
#MAINTAINER zsnmwy <szlszl35622@gmail.com>
LABEL AUTHOR = "Lkeme <Useri@live.cn>"
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"]

43
docker/entrypoint.sh Normal file
View File

@ -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

View File

@ -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();

View File

@ -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();
}
}
}

52
src/core/Command.php Normal file
View File

@ -0,0 +1,52 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Core;
use Garden\Cli\Cli;
use Garden\Cli\Args;
class Command
{
private $argv;
/**
* Command constructor.
* @param $argv
*/
public function __construct($argv)
{
$this->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;
}
}

View File

@ -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()
{
}
}

View File

@ -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);
}
}

View File

@ -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');
}
}

117
src/core/Helpers.php Normal file
View File

@ -0,0 +1,117 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
use BiliHelper\Core\Config;
/**
* @use 读取
* @param $name
* @param int $section
* @param null $key
* @return mixed
*/
function getConf($name, $section = 0, $key = null)
{
return Config::_get($name, $section, $key);
}
/**
* @use 写入
* @param $name
* @param $value
* @param int $section
* @param null $key
*/
function setConf($name, $value, $section = 0, $key = null)
{
Config::_set($name, $value, $section, $key);
}
/**
* @use 更新
*/
function putConf()
{
}
/**
* @use 删除
*/
function delConf()
{
}
/**
* @use 开关
* @param string $plugin
* @return bool
*/
function getEnable(string $plugin): bool
{
return getConf('enable', $plugin);
}
/**
* @use 获取ACCESS_TOKEN
* @return string
*/
function getAccessToken(): string
{
return getConf('access_token', 'login.auth');
}
/**
* @use 获取REFRESH_TOKEN
* @return string
*/
function getRefreshToken(): string
{
return getConf('refresh_token', 'login.auth');
}
/**
* @use 获取COOKIE
* @return string
*/
function getCookie(): string
{
return getConf('cookie', 'login.auth');
}
/**
* @use 获取UID
* @return int
*/
function getUid(): int
{
return getConf('uid', 'login.auth');
}
/**
* @use 获取CSRF
* @return string
*/
function getCsrf(): string
{
return getConf('csrf', 'login.auth');
}
/**
* @use HttpClient
* @param string $url
* @return \HttpClient
*/
function newHttp(string $url): HttpClient
{
return new HttpClient($url);
}

159
src/core/HttpClient.php Normal file
View File

@ -0,0 +1,159 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
* Resource: https://github.com/XcantloadX
*/
namespace BiliHelper\Core;
class HttpClient
{
private $ch;
private $ret;
private $form;
private $headers;
private $url;
private $query;
public function __construct(string $url)
{
$this->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));
}
}

View File

@ -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));

104
src/core/Task.php Normal file
View File

@ -0,0 +1,104 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Core;
class Task
{
private static $init = true;
private static $repository = null;
private static $instance;
/**
* @use 单例
* @return \BiliHelper\Core\Task
*/
public static function getInstance(): Task
{
if (is_null(self::$instance)) {
self::$instance = new static;
}
return self::$instance;
}
/**
* @use 初始化
*/
private static function init()
{
if (self::$init) {
// 赋值仓库地址
if (is_null(self::$repository)) {
self::$repository = APP_TASK_PATH . 'tasks_' . getConf('username', 'login.account') . '.json';
}
// 仓库不存在自动创建
if (!file_exists(self::$repository)) {
$fh = fopen(self::$repository, "w");
fwrite($fh, "{}");
fclose($fh);
Log::info('任务排程文件不存在,初始化所有任务。');
} else {
Log::info('任务排程文件存在,继续执行所有任务。');
}
}
// 限制初始化
self::$init = false;
}
/**
* @use
* @return array
*/
private static function read(): array
{
self::init();
$data = file_get_contents(self::$repository);
return json_decode($data, true);
}
/**
* @use
* @param array $data
* @return bool
*/
private static function write(array $data): bool
{
self::init();
return file_put_contents(self::$repository, json_encode($data));
}
/**
* @use 写入
* @param string $class
* @param int $lock
* @return bool
*/
public static function _setLock(string $class, int $lock): bool
{
$data = self::read();
$data[$class] = $lock;
return self::write($data);
}
/**
* @use 读取
* @param string $class
* @return int
*/
public static function _getLock(string $class): int
{
$data = self::read();
if (array_key_exists($class, $data)) {
return $data[$class];
}
return 0;
}
}

View File

@ -22,9 +22,15 @@ class ActivityLottery
private static $repository = APP_DATA_PATH . 'activity_infos.json';
/**
* @throws \JsonDecodeStream\Exception\TokenizerException
* @throws \JsonDecodeStream\Exception\SelectorException
* @throws \JsonDecodeStream\Exception\CollectorException
* @throws \JsonDecodeStream\Exception\ParserException
*/
public static function run()
{
if (self::getLock() > 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);

View File

@ -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);

View File

@ -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)
{

View File

@ -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 获取活动礼物中奖纪录
*/

View File

@ -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;
}
}

View File

@ -0,0 +1,148 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Plugin;
use BiliHelper\Core\Curl;
use BiliHelper\Core\Log;
use BiliHelper\Tool\Common;
use BiliHelper\Util\TimeLock;
class BpConsumption
{
use TimeLock;
public static function run()
{
if (self::getLock() > 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电池下限 -4B币不足
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']}");
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,90 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Plugin;
use Noodlehaus\Config;
use Noodlehaus\Parser\Json;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
use BiliHelper\Util\TimeLock;
class CheckUpdate
{
use TimeLock;
private static $current_conf;
private static $latest_conf;
private static $repository = APP_DATA_PATH . 'latest_version.json';
public static function run()
{
if (self::getLock() > 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);
}
}

View File

@ -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);

View File

@ -1,47 +0,0 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Plugin;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
use BiliHelper\Util\TimeLock;
class Daily
{
use TimeLock;
public static function run()
{
if (self::getLock() > 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('每日礼包领取成功');
}
}
}

67
src/plugin/DailyBag.php Normal file
View File

@ -0,0 +1,67 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Plugin;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
use BiliHelper\Util\TimeLock;
class DailyBag
{
use TimeLock;
public static function run()
{
if (self::getLock() > 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] 日常/周常礼包领取成功');
}
}
}

View File

@ -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']) {

View File

@ -12,7 +12,7 @@ namespace BiliHelper\Plugin;
class DataTreating
{
// TODO 独立分发 Push||Pull数据
// Todo 独立分发 Push||Pull数据
/**
* @use 抽奖分发
* @param array $data

View File

@ -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] 发送在线心跳成功');
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

File diff suppressed because one or more lines are too long

View File

@ -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);

View File

@ -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)
{

View File

@ -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

View File

@ -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;

View File

@ -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)
{

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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}");
}
}
}

View File

@ -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)
{

View File

@ -0,0 +1,117 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Plugin;
use BiliHelper\Core\Log;
use BiliHelper\Tool\Generator;
use BiliHelper\Util\TimeLock;
class PolishTheMedal
{
use TimeLock;
private static $metal_lock = 0; // 勋章时间锁
private static $fans_medals = []; // 全部勋章
private static $grey_fans_medals = []; // 灰色勋章
/**
*/
public static function run()
{
if (!getEnable('polish_the_medal')) {
return;
}
// 获取灰色勋章
if (self::$metal_lock < time()) {
// 如果勋章过多导致未处理完就1小时一次否则10小时一次。
if (empty(self::$grey_fans_medals)) {
// 处理每日
if (getConf('everyday', 'polish_the_medal')) {
// 如果是 直接定时到第二天7点
self::fetchGreyMedalList(true);
self::$metal_lock = time() + self::timing(7, 0, 0, true);
} else {
// 否则按正常逻辑
self::fetchGreyMedalList();
self::$metal_lock = time() + 10 * 60 * 60;
}
} else {
self::$metal_lock = time() + 1 * 60 * 60;
}
}
// 点亮灰色勋章
if (self::getLock() < time()) {
// 随机4-10分钟处理一次点亮操作
self::polishTheMedal();
self::setLock(mt_rand(4, 10) * 60);
}
}
/**
* @use 点亮勋章
*/
private static function polishTheMedal()
{
$medal = array_pop(self::$grey_fans_medals);
// 为空
if (is_null($medal)) return;
// 特殊房间处理|央视未开播|CODE -> 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);
}
}

View File

@ -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'));

View File

@ -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(),

View File

@ -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;
}
}

View File

@ -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'],
];
}
}
}

View File

@ -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

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -0,0 +1,96 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Plugin;
use BiliHelper\Core\Curl;
use BiliHelper\Core\Log;
use BiliHelper\Util\TimeLock;
class VipPrivilege
{
use TimeLock;
private static $privilege = [
0 => '未知奖励',
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 [];
}
}
}

View File

@ -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;

63
src/script/BaseTask.php Normal file
View File

@ -0,0 +1,63 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Script;
use Ahc\Cli\IO\Interactor;
class BaseTask
{
public static $interactor = null;
public static function init()
{
User::login();
}
/**
* @use 选择
* @param array $options
* @param null $default
* @return mixed
*/
public static function choice(array $options, $default = null)
{
$option = static::interactor()->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;
}
}

22
src/script/DelDynamic.php Normal file
View File

@ -0,0 +1,22 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Script;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
class DelDynamic extends BaseTask
{
public static $description = '批量删除动态默认单次最大清理300个动态.';
public static function run(){
Log::error('当前功能未完成');
}
}

146
src/script/UnFollow.php Normal file
View File

@ -0,0 +1,146 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Script;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
class UnFollow extends BaseTask
{
public static $description = '批量清理选定分组关注默认单次最大清理600个关注.';
/**
* @throws \Exception
*/
public static function run()
{
self::init();
// 获取关注分组
$tag_id = self::relationTags();
// 获取分组关注
$target_ups = self::relationTag($tag_id);
// 取消关注状态
self::relationModify($target_ups, $tag_id);
// Todo 优化
Log::notice('任务执行完毕~');
}
/**
* @use 取消关注
* @param $target_ups
* @param $tag_id
* @throws \Exception
*/
private static function relationModify($target_ups, $tag_id)
{
self::confirm('请确认以上输入信息,是否继续取关操作?');
$url = 'https://api.bilibili.com/x/relation/modify';
foreach ($target_ups as $up_uid => $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();
}
}
}

57
src/script/User.php Normal file
View File

@ -0,0 +1,57 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Updated: 2021 ~ 2022
*/
namespace BiliHelper\Script;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
class User
{
/**
* @use 登录
* @return bool
*/
public static function login(): bool
{
if (getAccessToken() == '' || getCookie() == '' || getUid() == '' || getCsrf() == '') {
Log::error('用户信息不全,请默认模式登录后使用。');
die();
}
$data = User::userInfo();
if ($data['code'] == 0 && $data['data']['isLogin']) {
$nav = $data['data'];
$level = $nav['level_info'];
Log::notice("登录成功 Uname={$nav['uname']} Uid={$nav['mid']} Lv={$level['current_level']} ({$level['current_exp']}/{$level['current_min']})");
} else {
Log::error("登录失败 CODE -> {$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);
}
}

View File

@ -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 ';

View File

@ -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;
}

View File

@ -12,7 +12,6 @@
namespace BiliHelper\Tool;
use BiliHelper\Core\Log;
use BiliHelper\Core\Curl;
class DumpMemory
{

View File

@ -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;

View File

@ -11,11 +11,9 @@
namespace BiliHelper\Tool;
class File
{
/**
* @use 创建文件
* @param string $filename

View File

@ -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)];
}
}

401
src/tool/UserAgent.php Normal file
View File

@ -0,0 +1,401 @@
<?php
/**
* Website: https://mudew.com/
* Author: Lkeme
* License: The MIT License
* Email: Useri@live.cn
* Updated: 2021 ~ 2022
* Source: https://github.com/Deemon47/user-agent-generator/
*/
namespace BiliHelper\Tool;
/** **********************************************************************************
* Generate hundreds of thousands of unique mobile & desktop User Agents that are 100% authentic.
* Supports Hundreds of Android devices, 32 & 64 bit versions of Windows XP-10.5, Linux 540-686, and Mac 7-10.12
* as well as browsers Firefox, Chrome, and Internet Explorer.
*/
class UserAgent
{
/**
* Windows Operating System list with dynamic versioning
* @var array $windows_os
*/
public $windows_os = [
'[Windows; |Windows; U; |]Windows NT 6.:number0-3:;[ Win64; x64| WOW64| x64|]',
'[Windows; |Windows; U; |]Windows NT 10.:number0-5:;[ Win64; x64| WOW64| x64|]'
];
/**
* Linux Operating Systems [limited]
* @var array $linux_os
*/
public $linux_os = [
'[Linux; |][U; |]Linux x86_64',
'[Linux; |][U; |]Linux i:number5-6::number4-8::number0-6: [x86_64|]'
];
/**
* Mac Operating System (OS X) with dynamic versioning
* @var array $mac_os
*/
public $mac_os = [
'Macintosh; [U; |]Intel Mac OS X :number7-9:_:number0-9:_:number0-9:',
'Macintosh; [U; |]Intel Mac OS X 10_:number0-12:_:number0-9:'
];
/**
* Versions of Android to be used
* @var array $androidVersions
*/
public $androidVersions = [
'4.3.1',
'4.4',
'4.4.1',
'4.4.4',
'5.0',
'5.0.1',
'5.0.2',
'5.1',
'5.1.1',
'6.0',
'6.0.1',
'7.0',
'7.1',
'7.1.1'
];
/**
* Holds the version of android for the User Agent being generated
* @property string $androidVersion
*/
public $androidVersion;
/**
* Android devices and for specific android versions
* @var array $androidDevices
*/
public $androidDevices = [
'4.3' => [
'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');
}
}
}

View File

@ -29,7 +29,7 @@ trait AllotTasks
* @use 加载json数据
* @return Parser
*/
protected static function loadJsonData()
protected static function loadJsonData(): Parser
{
return Parser::fromFile(static::$repository);
}

View File

@ -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;
}
// 黑屋

View File

@ -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 加载配置信息

View File

@ -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;
}

View File

@ -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;
}
}

0
task/.gitkeep Normal file
View File